Move all protocol interaction into Syncers out of the base code

pull/40/head
Vitaliy Filippov 2015-05-17 16:54:04 +03:00
parent 717a6a4793
commit 862fca035a
24 changed files with 387 additions and 193 deletions

View File

@ -19,7 +19,8 @@
#include "util/Config.hh"
#include "drive/Drive.hh"
#include "base/Drive.hh"
#include "drive/Syncer1.hh"
#include "http/CurlAgent.hh"
#include "protocol/AuthAgent.hh"
@ -185,8 +186,9 @@ int Main( int argc, char **argv )
OAuth2 token( refresh_token, client_id, client_secret ) ;
AuthAgent agent( token, std::auto_ptr<http::Agent>( new http::CurlAgent ) ) ;
Syncer1 syncer( &agent );
Drive drive( &agent, config.GetAll() ) ;
Drive drive( &syncer, config.GetAll() ) ;
drive.DetectChanges() ;
if ( vm.count( "dry-run" ) == 0 )

View File

@ -19,18 +19,13 @@
#include "Drive.hh"
#include "CommonUri.hh"
#include "base/Entry.hh"
#include "Entry.hh"
#include "Feed.hh"
#include "Syncer1.hh"
#include "Syncer.hh"
#include "http/Agent.hh"
#include "http/ResponseLog.hh"
#include "http/XmlResponse.hh"
#include "util/Destroy.hh"
#include "util/log/Log.hh"
#include "xml/Node.hh"
#include "xml/NodeSet.hh"
#include <boost/bind.hpp>
@ -45,20 +40,20 @@
// for debugging only
#include <iostream>
namespace gr { namespace v1 {
namespace gr {
namespace
{
const std::string state_file = ".grive_state" ;
}
Drive::Drive( http::Agent *agent, const Val& options ) :
m_http ( agent ),
Drive::Drive( Syncer *syncer, const Val& options ) :
m_syncer ( syncer ),
m_root ( options["path"].Str() ),
m_state ( m_root / state_file, options ),
m_options ( options )
{
assert( m_http != 0 ) ;
assert( m_syncer ) ;
}
void Drive::FromRemote( const Entry& entry )
@ -95,16 +90,13 @@ void Drive::SaveState()
void Drive::SyncFolders( )
{
assert( m_http != 0 ) ;
Log( "Synchronizing folders", log::info ) ;
Feed feed ;
feed.Start( m_http, feed_base + "/-/folder?max-results=50&showroot=true" ) ;
do
std::auto_ptr<Feed> feed = m_syncer->GetFolders() ;
while ( feed->GetNext( m_syncer->Agent() ) )
{
// first, get all collections from the query result
for ( Feed::iterator i = feed.begin() ; i != feed.end() ; ++i )
for ( Feed::iterator i = feed->begin() ; i != feed->end() ; ++i )
{
const Entry &e = *i ;
if ( e.IsDir() )
@ -119,7 +111,7 @@ void Drive::SyncFolders( )
m_state.FromRemote( e ) ;
}
}
} while ( feed.GetNext( m_http ) ) ;
}
m_state.ResolveEntry() ;
}
@ -135,42 +127,38 @@ void Drive::DetectChanges()
SyncFolders( ) ;
Log( "Reading remote server file list", log::info ) ;
Feed feed ;
std::auto_ptr<Feed> feed = m_syncer->GetAll() ;
if ( m_options["log-xml"].Bool() )
feed.EnableLog( "/tmp/file", ".xml" ) ;
feed->EnableLog( "/tmp/file", ".xml" ) ;
feed.Start( m_http, feed_base + "?showfolders=true&showroot=true" ) ;
do
while ( feed->GetNext( m_syncer->Agent() ) )
{
std::for_each(
feed.begin(), feed.end(),
feed->begin(), feed->end(),
boost::bind( &Drive::FromRemote, this, _1 ) ) ;
} while ( feed.GetNext( m_http ) ) ;
}
// pull the changes feed
if ( prev_stamp != -1 )
{
Log( "Detecting changes from last sync", log::info ) ;
Feed changes ;
feed = m_syncer->GetChanges( prev_stamp+1 ) ;
if ( m_options["log-xml"].Bool() )
feed.EnableLog( "/tmp/changes", ".xml" ) ;
feed.Start( m_http, ChangesFeed(prev_stamp+1) ) ;
std::for_each(
changes.begin(), changes.end(),
boost::bind( &Drive::FromChange, this, _1 ) ) ;
feed->EnableLog( "/tmp/changes", ".xml" ) ;
while ( feed->GetNext( m_syncer->Agent() ) )
{
std::for_each(
feed->begin(), feed->end(),
boost::bind( &Drive::FromChange, this, _1 ) ) ;
}
}
}
void Drive::Update()
{
Syncer1 syncer( m_http );
Log( "Synchronizing files", log::info ) ;
m_state.Sync( &syncer, m_options ) ;
m_state.Sync( m_syncer, m_options ) ;
UpdateChangeStamp( ) ;
}
@ -178,21 +166,14 @@ void Drive::Update()
void Drive::DryRun()
{
Log( "Synchronizing files (dry-run)", log::info ) ;
m_state.Sync( 0, m_options ) ;
m_state.Sync( NULL, m_options ) ;
}
void Drive::UpdateChangeStamp( )
{
assert( m_http != 0 ) ;
// get changed feed
http::XmlResponse xrsp ;
m_http->Get( ChangesFeed(m_state.ChangeStamp()+1), &xrsp, http::Header() ) ;
// we should go through the changes to see if it was really Grive to made that change
// FIXME: we should go through the changes to see if it was really Grive to made that change
// maybe by recording the updated timestamp and compare it?
m_state.ChangeStamp(
std::atoi(xrsp.Response()["docs:largestChangestamp"]["@value"].front().Value().c_str()) ) ;
m_state.ChangeStamp( m_syncer->GetChangeStamp( m_state.ChangeStamp()+1 ) );
}
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -19,9 +19,8 @@
#pragma once
#include "State.hh"
#include "base/State.hh"
#include "http/Header.hh"
#include "json/Val.hh"
#include "util/Exception.hh"
@ -30,19 +29,16 @@
namespace gr {
namespace http
{
class Agent ;
}
class Syncer ;
class Entry ;
namespace v1 {
class State ;
class Drive
{
public :
Drive( http::Agent *agent, const Val& options ) ;
Drive( Syncer *syncer, const Val& options ) ;
void DetectChanges() ;
void Update() ;
@ -58,10 +54,10 @@ private :
void UpdateChangeStamp( ) ;
private :
http::Agent *m_http ;
Syncer *m_syncer ;
fs::path m_root ;
State m_state ;
Val m_options ;
} ;
} } // end of namespace
} // end of namespace gr

51
libgrive/src/base/Feed.cc Normal file
View File

@ -0,0 +1,51 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Feed.hh"
#include "Entry.hh"
#include "http/Agent.hh"
namespace gr {
Feed::Feed( const std::string &url ):
m_next( url )
{
}
Feed::iterator Feed::begin() const
{
return m_entries.begin() ;
}
Feed::iterator Feed::end() const
{
return m_entries.end() ;
}
void Feed::EnableLog( const std::string& prefix, const std::string& suffix )
{
m_log.reset( new LogInfo ) ;
m_log->prefix = prefix ;
m_log->suffix = suffix ;
m_log->sequence = 0 ;
}
} // end of namespace gr::v1

View File

@ -21,9 +21,6 @@
#include "base/Entry.hh"
#include "xml/Node.hh"
#include "xml/NodeSet.hh"
#include <vector>
#include <string>
@ -35,8 +32,6 @@ namespace http
class Agent ;
}
namespace v1 {
class Feed
{
public :
@ -44,24 +39,22 @@ public :
typedef std::vector<Entry>::const_iterator iterator;
public :
Feed( ) ;
void Start( http::Agent *http, const std::string& url ) ;
bool GetNext( http::Agent *http ) ;
Feed( const std::string& url );
virtual bool GetNext( http::Agent *http ) = 0 ;
iterator begin() const ;
iterator end() const ;
void EnableLog( const std::string& prefix, const std::string& suffix ) ;
private :
virtual void EnableLog( const std::string& prefix, const std::string& suffix ) ;
protected :
struct LogInfo
{
std::string prefix ;
std::string suffix ;
std::size_t sequence ;
std::string prefix ;
std::string suffix ;
std::size_t sequence ;
} ;
std::auto_ptr<LogInfo> m_log ;
xml::Node m_root ;
Entries m_entries ;
std::auto_ptr<LogInfo> m_log ;
Entries m_entries ;
std::string m_next ;
} ;
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -38,7 +38,7 @@
namespace gr {
/// default constructor creates the root folder
Resource::Resource(const fs::path& root_folder) :
Resource::Resource( const fs::path& root_folder ) :
m_name ( root_folder.string() ),
m_kind ( "folder" ),
m_id ( "folder:root" ),
@ -339,7 +339,7 @@ fs::path Resource::Path() const
bool Resource::IsInRootTree() const
{
assert( m_parent == 0 || m_parent->IsFolder() ) ;
return m_parent == 0 ? SelfHref().empty() : m_parent->IsInRootTree() ;
return m_parent == 0 ? IsRoot() : m_parent->IsInRootTree() ;
}
Resource* Resource::FindChild( const std::string& name )
@ -507,6 +507,7 @@ std::string Resource::MD5() const
bool Resource::IsRoot() const
{
// Root entry does not show up in file feeds, so we check for empty parent (and self-href)
return m_parent == 0 ;
}

View File

@ -18,7 +18,6 @@
*/
#include "ResourceTree.hh"
#include "CommonUri.hh"
#include "util/Destroy.hh"
#include "util/log/Log.hh"
@ -26,12 +25,12 @@
#include <algorithm>
#include <cassert>
namespace gr { namespace v1 {
namespace gr {
using namespace details ;
ResourceTree::ResourceTree( const fs::path& rootFolder ) :
m_root(new Resource(rootFolder))
m_root( new Resource( rootFolder ) )
{
m_set.insert( m_root ) ;
}
@ -43,7 +42,7 @@ ResourceTree::ResourceTree( const ResourceTree& fs ) :
for ( Set::const_iterator i = s.begin() ; i != s.end() ; ++i )
{
Resource *c = new Resource( **i ) ;
if ( c->SelfHref() == root_href )
if ( c->IsRoot() )
m_root = c ;
m_set.insert( c ) ;
@ -142,4 +141,4 @@ ResourceTree::iterator ResourceTree::end()
return m_set.get<ByIdentity>().end() ;
}
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -19,7 +19,7 @@
#pragma once
#include "base/Resource.hh"
#include "Resource.hh"
#include "util/FileSystem.hh"
@ -30,8 +30,6 @@
namespace gr {
namespace v1 {
namespace details
{
using namespace boost::multi_index ;
@ -93,4 +91,4 @@ private :
Resource* m_root ;
} ;
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -19,10 +19,9 @@
#include "State.hh"
#include "base/Entry.hh"
#include "base/Resource.hh"
#include "base/Syncer.hh"
#include "CommonUri.hh"
#include "Entry.hh"
#include "Resource.hh"
#include "Syncer.hh"
#include "util/Crypt.hh"
#include "util/File.hh"
@ -32,11 +31,11 @@
#include <fstream>
namespace gr { namespace v1 {
namespace gr {
State::State( const fs::path& filename, const Val& options ) :
m_res ( options["path"].Str() ),
m_dir ( options["dir"].Str() ),
m_res ( options["path"].Str() ),
m_dir ( options["dir"].Str() ),
m_cstamp ( -1 )
{
Read( filename ) ;
@ -308,4 +307,4 @@ void State::ChangeStamp( long cstamp )
m_cstamp = cstamp ;
}
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -36,8 +36,6 @@ class Syncer ;
class Resource ;
namespace v1 {
class State
{
public :
@ -82,4 +80,4 @@ private :
std::vector<Entry> m_unresolved ;
} ;
} } // end of namespace gr::v1
} // end of namespace gr

View File

@ -29,6 +29,11 @@ Syncer::Syncer( http::Agent *http ):
{
}
http::Agent* Syncer::Agent() const
{
return m_http;
}
void Syncer::AssignIDs( Resource *res, const Entry& remote )
{
res->AssignIDs( remote );

View File

@ -38,6 +38,8 @@ class Resource ;
class Entry ;
class Feed ;
/*! \brief A Syncer incapsulates all resource-related upload/download/edit methods */
class Syncer
{
@ -45,11 +47,18 @@ public :
Syncer( http::Agent *http );
http::Agent* Agent() const;
virtual void DeleteRemote( Resource *res ) = 0;
virtual void Download( Resource *res, const fs::path& file ) = 0;
virtual bool EditContent( Resource *res, bool new_rev ) = 0;
virtual bool Create( Resource *res ) = 0;
virtual std::auto_ptr<Feed> GetFolders() = 0;
virtual std::auto_ptr<Feed> GetAll() = 0;
virtual std::auto_ptr<Feed> GetChanges( long min_cstamp ) = 0;
virtual long GetChangeStamp( long min_cstamp ) = 0;
protected:
http::Agent *m_http;

View File

@ -31,6 +31,4 @@ namespace gr { namespace v1
"https://docs.google.com/feeds/default/private/full/folder%3Aroot" ;
const std::string root_create =
"https://docs.google.com/feeds/upload/create-session/default/private/full" ;
std::string ChangesFeed( int changestamp ) ;
} }

View File

@ -70,7 +70,12 @@ void Entry1::Update( const xml::Node& n )
m_parent_hrefs.clear( ) ;
xml::NodeSet parents = n["link"].Find( "@rel", "http://schemas.google.com/docs/2007#parent" ) ;
for ( xml::NodeSet::iterator i = parents.begin() ; i != parents.end() ; ++i )
m_parent_hrefs.push_back( (*i)["@href"] ) ;
{
std::string href = (*i)["@href"];
if ( href == root_href ) // API-independent root href is empty!
href = "";
m_parent_hrefs.push_back( href ) ;
}
// convert to lower case for easy comparison
std::transform( m_md5.begin(), m_md5.end(), m_md5.begin(), tolower ) ;

View File

@ -17,7 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Feed.hh"
#include "CommonUri.hh"
#include "Feed1.hh"
#include "Entry1.hh"
@ -33,62 +34,39 @@
namespace gr { namespace v1 {
Feed::Feed( )
Feed1::Feed1( const std::string &url ):
Feed( url )
{
}
Feed::iterator Feed::begin() const
{
return m_entries.begin() ;
}
Feed::iterator Feed::end() const
{
return m_entries.end() ;
}
void Feed::Start( http::Agent *http, const std::string& url )
bool Feed1::GetNext( http::Agent *http )
{
http::XmlResponse xrsp ;
http::ResponseLog log( &xrsp ) ;
if ( m_next.empty() )
return false;
if ( m_log.get() != 0 )
log.Reset(
m_log->prefix,
(boost::format( "-#%1%%2%" ) % m_log->sequence++ % m_log->suffix ).str(),
&xrsp ) ;
http->Get( url, &log, http::Header() ) ;
http->Get( m_next, &log, http::Header() ) ;
m_root = xrsp.Response() ;
xml::Node m_root = xrsp.Response() ;
xml::NodeSet xe = m_root["entry"] ;
m_entries.clear() ;
for ( xml::NodeSet::iterator i = xe.begin() ; i != xe.end() ; ++i )
{
m_entries.push_back( Entry1( *i ) );
}
}
bool Feed::GetNext( http::Agent *http )
{
assert( http != 0 ) ;
xml::NodeSet nss = m_root["link"].Find( "@rel", "next" ) ;
if ( !nss.empty() )
{
Start( http, nss["@href"] ) ;
return true ;
}
else
return false ;
}
void Feed::EnableLog( const std::string& prefix, const std::string& suffix )
{
m_log.reset( new LogInfo ) ;
m_log->prefix = prefix ;
m_log->suffix = suffix ;
m_log->sequence = 0 ;
m_next = nss.empty() ? std::string( "" ) : nss["@href"];
return true;
}
} } // end of namespace gr::v1

View File

@ -17,15 +17,24 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "CommonUri.hh"
#include <boost/format.hpp>
#pragma once
#include "base/Feed.hh"
#include "xml/Node.hh"
#include "xml/NodeSet.hh"
#include <vector>
#include <string>
namespace gr { namespace v1 {
std::string ChangesFeed( int changestamp )
class Feed1: public Feed
{
boost::format feed( feed_changes + "?start-index=%1%" ) ;
return changestamp > 0 ? (feed%changestamp).str() : feed_changes ;
}
public :
Feed1( const std::string& url ) ;
bool GetNext( http::Agent *http ) ;
} ;
} }
} } // end of namespace gr::v1

View File

@ -20,6 +20,7 @@
#include "base/Resource.hh"
#include "CommonUri.hh"
#include "Entry1.hh"
#include "Feed1.hh"
#include "Syncer1.hh"
#include "http/Agent.hh"
@ -58,6 +59,7 @@ const std::string xml_meta =
Syncer1::Syncer1( http::Agent *http ):
Syncer( http )
{
assert( http != 0 ) ;
}
void Syncer1::DeleteRemote( Resource *res )
@ -252,4 +254,33 @@ bool Syncer1::Upload( Resource *res,
return true ;
}
std::auto_ptr<Feed> Syncer1::GetFolders()
{
return std::auto_ptr<Feed>( new Feed1( feed_base + "/-/folder?max-results=50&showroot=true" ) );
}
std::auto_ptr<Feed> Syncer1::GetAll()
{
return std::auto_ptr<Feed>( new Feed1( feed_base + "?showfolders=true&showroot=true" ) );
}
std::string ChangesFeed( int changestamp )
{
boost::format feed( feed_changes + "?start-index=%1%" ) ;
return changestamp > 0 ? ( feed % changestamp ).str() : feed_changes ;
}
std::auto_ptr<Feed> Syncer1::GetChanges( long min_cstamp )
{
return std::auto_ptr<Feed>( new Feed1( ChangesFeed( min_cstamp ) ) );
}
long Syncer1::GetChangeStamp( long min_cstamp )
{
http::XmlResponse xrsp ;
m_http->Get( ChangesFeed( min_cstamp ), &xrsp, http::Header() ) ;
return std::atoi( xrsp.Response()["docs:largestChangestamp"]["@value"].front().Value().c_str() );
}
} } // end of namespace gr::v1

View File

@ -23,6 +23,8 @@
namespace gr {
class Feed;
namespace v1 {
class Syncer1: public Syncer
@ -37,6 +39,11 @@ public :
bool EditContent( Resource *res, bool new_rev );
bool Create( Resource *res );
std::auto_ptr<Feed> GetFolders();
std::auto_ptr<Feed> GetAll();
std::auto_ptr<Feed> GetChanges( long min_cstamp );
long GetChangeStamp( long min_cstamp );
private :
bool Upload( Resource *res, const std::string& link, bool post);

View File

@ -26,6 +26,7 @@ namespace gr { namespace v2 {
namespace feeds
{
const std::string files = "https://www.googleapis.com/drive/v2/files" ;
const std::string changes = "https://www.googleapis.com/drive/v2/changes" ;
}
namespace mime_types
@ -33,9 +34,4 @@ namespace mime_types
const std::string folder = "application/vnd.google-apps.folder" ;
}
namespace kinds
{
const std::string parent = "drive#parentReference" ;
}
} } // end of namespace gr::v2

View File

@ -69,7 +69,9 @@ void Entry2::Update( const Val& item )
Val::Array parents = file["parents"].AsArray() ;
for ( Val::Array::iterator i = parents.begin() ; i != parents.end() ; ++i )
m_parent_hrefs.push_back( (*i)["parentLink"] ) ; // maybe .id?
{
m_parent_hrefs.push_back( (*i)["isRoot"].Bool() ? std::string() : (*i)["parentLink"] ) ; // maybe .id?
}
// convert to lower case for easy comparison
std::transform( m_md5.begin(), m_md5.end(), m_md5.begin(), tolower ) ;

View File

@ -17,42 +17,42 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Feed.hh"
#include "CommonUri.hh"
#include "Feed2.hh"
#include "Entry2.hh"
#include "http/Agent.hh"
#include "http/Header.hh"
#include "json/Val.hh"
#include "json/ValResponse.hh"
#include <iostream>
#include <boost/format.hpp>
namespace gr { namespace v2 {
Feed::Feed( )
Feed2::Feed2( const std::string& url ):
Feed( url )
{
}
// for example to find dirs: '?q=mimeType%3d%27' + mime_types::folder + '%27'
void Feed::Start( http::Agent *http, const std::string& url )
bool Feed2::GetNext( http::Agent *http )
{
http::ValResponse out ;
http->Get( url, &out, http::Header() ) ;
m_content = out.Response() ;
}
bool Feed::GetNext( http::Agent *http )
{
assert( http != 0 ) ;
Val url ;
if ( m_content.Get( "nextLink", url ) )
{
Start( http, url ) ;
return true ;
}
else
if ( m_next.empty() )
return false ;
http::ValResponse out ;
http->Get( m_next, &out, http::Header() ) ;
Val m_content = out.Response() ;
Val::Array items = m_content["items"].AsArray() ;
m_entries.clear() ;
for ( Val::Array::iterator i = items.begin() ; i != items.end() ; ++i )
m_entries.push_back( Entry2( *i ) );
Val url ;
m_next = m_content.Get( "nextLink", url ) ? url : std::string( "" ) ;
return true ;
}
} } // end of namespace
} } // end of namespace gr::v2

View File

@ -19,31 +19,19 @@
#pragma once
#include "json/Val.hh"
#include "base/Feed.hh"
#include "util/Exception.hh"
#include <string>
namespace gr
{
namespace http
{
class Agent ;
}
namespace gr { namespace v2 {
class Val ;
namespace v2 {
class Feed
class Feed2: public Feed
{
public :
Feed( ) ;
void Start( http::Agent *http, const std::string& url ) ;
Feed2( const std::string& url ) ;
bool GetNext( http::Agent *http ) ;
private :
Val m_content ;
} ;
} } // end of namespace gr::v2

View File

@ -0,0 +1,97 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "base/Resource.hh"
#include "CommonUri.hh"
#include "Entry2.hh"
#include "Feed2.hh"
#include "Syncer2.hh"
#include "http/Agent.hh"
#include "http/Download.hh"
#include "http/Header.hh"
//#include "http/ResponseLog.hh"
#include "json/ValResponse.hh"
#include "util/OS.hh"
#include "util/log/Log.hh"
#include <boost/exception/all.hpp>
#include <cassert>
// for debugging
#include <iostream>
namespace gr { namespace v2 {
Syncer2::Syncer2( http::Agent *http ):
Syncer( http )
{
assert( http != 0 ) ;
}
void Syncer2::DeleteRemote( Resource *res )
{
}
void Syncer2::Download( Resource *res, const fs::path& file )
{
}
bool Syncer2::EditContent( Resource *res, bool new_rev )
{
return false ;
}
bool Syncer2::Create( Resource *res )
{
return false ;
}
std::auto_ptr<Feed> Syncer2::GetFolders()
{
return std::auto_ptr<Feed>( new Feed2( feeds::files + "?maxResults=1000&q=%27me%27+in+readers+and+mimeType%3d%27" + mime_types::folder + "%27" ) );
}
std::auto_ptr<Feed> Syncer2::GetAll()
{
return std::auto_ptr<Feed>( new Feed2( feeds::files + "?maxResults=1000&q=%27me%27+in+readers" ) );
}
std::string ChangesFeed( long changestamp, int maxResults = 1000 )
{
boost::format feed( feeds::changes + "?maxResults=%1%&includeSubscribed=false" + ( changestamp > 0 ? "&startChangeId=%2%" : "" ) ) ;
return ( changestamp > 0 ? feed % maxResults % changestamp : feed % maxResults ).str() ;
}
std::auto_ptr<Feed> Syncer2::GetChanges( long min_cstamp )
{
return std::auto_ptr<Feed>( new Feed2( ChangesFeed( min_cstamp ) ) );
}
long Syncer2::GetChangeStamp( long min_cstamp )
{
http::ValResponse res ;
m_http->Get( ChangesFeed( min_cstamp, 1 ), &res, http::Header() ) ;
return std::atoi( res.Response()["largestChangeId"].Str().c_str() );
}
} } // end of namespace gr::v1

View File

@ -0,0 +1,51 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include "base/Syncer.hh"
namespace gr {
class Feed;
namespace v2 {
class Syncer2: public Syncer
{
public :
Syncer2( http::Agent *http );
void DeleteRemote( Resource *res );
void Download( Resource *res, const fs::path& file );
bool EditContent( Resource *res, bool new_rev );
bool Create( Resource *res );
std::auto_ptr<Feed> GetFolders();
std::auto_ptr<Feed> GetAll();
std::auto_ptr<Feed> GetChanges( long min_cstamp );
long GetChangeStamp( long min_cstamp );
private :
} ;
} } // end of namespace gr::v2