diff --git a/grive/src/main.cc b/grive/src/main.cc index b017558..cec9020 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -83,6 +83,7 @@ int Main( int argc, char **argv ) ( "auth,a", "Request authorization token" ) ( "verbose,V", "Verbose mode. Enable more messages than normal.") ( "log-xml", "Log more HTTP responses as XML for debugging.") + ( "new-rev", "Create new revisions in server for updated files.") ( "debug,d", "Enable debug level messages. Implies -v.") ( "log,l", po::value(), "Set log output filename." ) ( "force,f", "Force grive to always download a file from Google Drive " @@ -149,6 +150,7 @@ int Main( int argc, char **argv ) } options.Add( "log-xml", Json(vm.count("log-xml") > 0) ) ; + options.Add( "new-rev", Json(vm.count("new-rev") > 0) ) ; if ( vm.count( "debug" ) ) { diff --git a/libgrive/src/drive/Drive.cc b/libgrive/src/drive/Drive.cc index 5151369..5595fcc 100644 --- a/libgrive/src/drive/Drive.cc +++ b/libgrive/src/drive/Drive.cc @@ -26,7 +26,6 @@ #include "http/Agent.hh" #include "http/ResponseLog.hh" #include "http/XmlResponse.hh" -#include "protocol/Json.hh" #include "util/Destroy.hh" #include "util/log/Log.hh" #include "xml/Node.hh" @@ -55,7 +54,7 @@ namespace Drive::Drive( http::Agent *http, const Json& options ) : m_http ( http ), m_state ( state_file, options ), - m_log_xml ( options["log-xml"].Bool() ) + m_options ( options ) { assert( m_http != 0 ) ; } @@ -137,7 +136,7 @@ void Drive::DetectChanges() Log( "Reading remote server file list", log::info ) ; Feed feed ; - if ( m_log_xml ) + if ( m_options["log-xml"].Bool() ) feed.EnableLog( "/tmp/file", ".xml" ) ; feed.Start( m_http, http::Header(), feed_base + "?showfolders=true&showroot=true" ) ; @@ -158,7 +157,7 @@ void Drive::DetectChanges() { Log( "Detecting changes from last sync", log::info ) ; Feed changes ; - if ( m_log_xml ) + if ( m_options["log-xml"].Bool() ) feed.EnableLog( "/tmp/changes", ".xml" ) ; feed.Start( m_http, http::Header(), ChangesFeed(prev_stamp+1) ) ; @@ -172,7 +171,7 @@ void Drive::DetectChanges() void Drive::Update() { Log( "Synchronizing files", log::info ) ; - m_state.Sync( m_http ) ; + m_state.Sync( m_http, m_options ) ; UpdateChangeStamp( ) ; } @@ -180,7 +179,7 @@ void Drive::Update() void Drive::DryRun() { Log( "Synchronizing files (dry-run)", log::info ) ; - m_state.Sync( 0 ) ; + m_state.Sync( 0, m_options ) ; } void Drive::UpdateChangeStamp( ) diff --git a/libgrive/src/drive/Drive.hh b/libgrive/src/drive/Drive.hh index 11830b5..3409953 100644 --- a/libgrive/src/drive/Drive.hh +++ b/libgrive/src/drive/Drive.hh @@ -22,6 +22,7 @@ #include "State.hh" #include "http/Header.hh" +#include "protocol/Json.hh" #include "util/Exception.hh" #include @@ -35,7 +36,6 @@ namespace http } class Entry ; -class Json ; class Drive { @@ -61,7 +61,7 @@ private : std::string m_resume_link ; State m_state ; - bool m_log_xml ; + Json m_options ; } ; } // end of namespace diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index c044abc..f63f99e 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -365,23 +365,24 @@ Resource* Resource::FindChild( const std::string& name ) } // try to change the state to "sync" -void Resource::Sync( http::Agent *http, DateTime& sync_time ) +void Resource::Sync( http::Agent *http, DateTime& sync_time, const Json& options ) { assert( m_state != unknown ) ; assert( !IsRoot() || m_state == sync ) ; // root folder is already synced - SyncSelf( http ) ; - // we want the server sync time, so we will take the server time of the last file uploaded to store as the sync time - // m_mtime is updated to server modified time when the file is uploaded - sync_time = std::max(sync_time, m_mtime); + SyncSelf( http, options ) ; + + // we want the server sync time, so we will take the server time of the last file uploaded to store as the sync time + // m_mtime is updated to server modified time when the file is uploaded + sync_time = std::max(sync_time, m_mtime); // if myself is deleted, no need to do the childrens if ( m_state != local_deleted && m_state != remote_deleted ) std::for_each( m_child.begin(), m_child.end(), - boost::bind( &Resource::Sync, _1, http, boost::ref(sync_time) ) ) ; + boost::bind( &Resource::Sync, _1, http, boost::ref(sync_time), options ) ) ; } -void Resource::SyncSelf( http::Agent* http ) +void Resource::SyncSelf( http::Agent* http, const Json& options ) { assert( !IsRoot() || m_state == sync ) ; // root is always sync assert( IsRoot() || http == 0 || fs::is_directory( m_parent->Path() ) ) ; @@ -407,7 +408,7 @@ void Resource::SyncSelf( http::Agent* http ) case local_changed : Log( "sync %1% changed in local. uploading", path, log::info ) ; - if ( http != 0 && EditContent( http ) ) + if ( http != 0 && EditContent( http, options["new-rev"].Bool() ) ) m_state = sync ; break ; @@ -520,7 +521,7 @@ void Resource::Download( http::Agent* http, const fs::path& file ) const } } -bool Resource::EditContent( http::Agent* http ) +bool Resource::EditContent( http::Agent* http, bool new_rev ) { assert( http != 0 ) ; assert( m_parent != 0 ) ; @@ -533,10 +534,10 @@ bool Resource::EditContent( http::Agent* http ) return false ; } - return Upload( http, m_edit, false ) ; + return Upload( http, m_edit + (new_rev ? "?new-revision=true" : ""), false ) ; } -bool Resource::Create( http::Agent* http) +bool Resource::Create( http::Agent* http ) { assert( http != 0 ) ; assert( m_parent != 0 ) ; diff --git a/libgrive/src/drive/Resource.hh b/libgrive/src/drive/Resource.hh index b0cb2b8..8b157f7 100644 --- a/libgrive/src/drive/Resource.hh +++ b/libgrive/src/drive/Resource.hh @@ -35,6 +35,7 @@ namespace http } class Entry ; +class Json ; /*! \brief A resource can be a file or a folder in the google drive @@ -76,7 +77,7 @@ public : void FromRemote( const Entry& remote, const DateTime& last_sync ) ; void FromLocal( const DateTime& last_sync ) ; - void Sync( http::Agent* http, DateTime& sync_time ) ; + void Sync( http::Agent* http, DateTime& sync_time, const Json& options ) ; // children access iterator begin() const ; @@ -124,7 +125,7 @@ private : void SetState( State new_state ) ; void Download( http::Agent* http, const fs::path& file ) const ; - bool EditContent( http::Agent* http ) ; + bool EditContent( http::Agent* http, bool new_rev ) ; bool Create( http::Agent* http ) ; bool Upload( http::Agent* http, const std::string& link, bool post ) ; @@ -135,7 +136,7 @@ private : void DeleteRemote( http::Agent* http ) ; void AssignIDs( const Entry& remote ) ; - void SyncSelf( http::Agent* http ) ; + void SyncSelf( http::Agent* http, const Json& options ) ; private : std::string m_name ; diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index afab842..8825f0c 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -261,7 +261,7 @@ void State::Write( const fs::path& filename ) const fs << result ; } -void State::Sync( http::Agent *http ) +void State::Sync( http::Agent *http, const Json& options ) { // set the last sync time from the time returned by the server for the last file synced // if the sync time hasn't changed (i.e. now files have been uploaded) @@ -271,7 +271,8 @@ void State::Sync( http::Agent *http ) // TODO - WARNING - do we use the last sync time to compare to client file times // need to check if this introduces a new problem DateTime last_sync_time = m_last_sync; - m_res.Root()->Sync( http, last_sync_time ) ; + m_res.Root()->Sync( http, last_sync_time, options ) ; + if ( last_sync_time == m_last_sync ) { Trace( "nothing changed? %1%", m_last_sync ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index cd0590d..9ddd435 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -57,7 +57,7 @@ public : Resource* FindByID( const std::string& id ) ; Resource* Find( const fs::path& path ) ; - void Sync( http::Agent *http ) ; + void Sync( http::Agent *http, const Json& options ) ; iterator begin() ; iterator end() ; diff --git a/libgrive/src/http/CurlAgent.cc b/libgrive/src/http/CurlAgent.cc index 640e1eb..09bedee 100644 --- a/libgrive/src/http/CurlAgent.cc +++ b/libgrive/src/http/CurlAgent.cc @@ -150,12 +150,15 @@ long CurlAgent::ExecCurl( dest->Clear() ; CURLcode curl_code = ::curl_easy_perform(curl); + // get the HTTTP response code long http_code = 0; - ::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); - + ::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); Trace( "HTTP response %1%", http_code ) ; - ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, 0 ) ; + // reset the curl buffer to prevent it from touch our "error" buffer + ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, 0 ) ; + + // only throw for libcurl errors if ( curl_code != CURLE_OK ) { BOOST_THROW_EXCEPTION(