Skip to content
Browse files

Merge pull request #109 from justinharding/issue_86_partial_sync

Issue 86 partial sync
  • Loading branch information...
2 parents d831b8d + 034891a commit cb602052f1afb7f5c49895edb2f0f2c1f05c134a @nestal nestal committed Jul 29, 2012
View
93 grive/src/main.cc
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "Config.hh"
+#include "util/Config.hh"
#include "drive/Drive.hh"
@@ -46,6 +46,9 @@
const std::string client_id = "22314510474.apps.googleusercontent.com" ;
const std::string client_secret = "bl4ufi89h-9MkFlypcI7R785" ;
+const std::string defaultRootFolder = ".";
+const std::string defaultConfigFileName = ".grive";
+const char *configFileEnvironmentVariable = "GR_CONFIG";
using namespace gr ;
@@ -66,8 +69,8 @@ int Main( int argc, char **argv )
{
InitGCrypt() ;
- Config config ;
-
+ std::string rootFolder = defaultRootFolder;
+
std::auto_ptr<log::CompositeLog> comp_log(new log::CompositeLog) ;
LogBase* console_log = comp_log->Add( std::auto_ptr<LogBase>( new log::DefaultLog ) ) ;
@@ -81,6 +84,7 @@ int Main( int argc, char **argv )
( "help,h", "Produce help message" )
( "version,v", "Display Grive version" )
( "auth,a", "Request authorization token" )
+ ( "path,p", po::value<std::string>(), "Path to sync")
( "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.")
@@ -101,27 +105,9 @@ int Main( int argc, char **argv )
std::cout << desc << std::endl ;
return 0 ;
}
- if ( vm.count( "auth" ) )
- {
- std::cout
- << "-----------------------\n"
- << "Please go to this URL and get an authentication code:\n\n"
- << OAuth2::MakeAuthURL( client_id )
- << std::endl ;
-
- std::cout
- << "\n-----------------------\n"
- << "Please input the authentication code here: " << std::endl ;
- std::string code ;
- std::cin >> code ;
-
- OAuth2 token( client_id, client_secret ) ;
- token.Auth( code ) ;
-
- // save to config
- config.Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ;
- config.Save() ;
- }
+
+ boost::shared_ptr<Config> config ;
+
if ( vm.count( "log" ) )
{
std::auto_ptr<LogBase> file_log(new log::DefaultLog( vm["log"].as<std::string>() )) ;
@@ -138,12 +124,6 @@ int Main( int argc, char **argv )
comp_log->Add( file_log ) ;
}
- if ( vm.count( "version" ) )
- {
- std::cout
- << "grive version " << VERSION << ' ' << __DATE__ << ' ' << __TIME__ << std::endl ;
- return 0 ;
- }
if ( vm.count( "verbose" ) )
{
console_log->Enable( log::verbose ) ;
@@ -157,6 +137,52 @@ int Main( int argc, char **argv )
console_log->Enable( log::verbose ) ;
console_log->Enable( log::debug ) ;
}
+
+ // config file will be (in order of preference)
+ // value specified in environment string
+ // value specified in defaultConfigFileName in path from commandline --path
+ // value specified in defaultConfigFileName in current directory
+ const char *envConfigFileName = ::getenv( configFileEnvironmentVariable ) ;
+ if (envConfigFileName) {
+ config.reset(new Config(envConfigFileName));
+
+ } else if ( vm.count( "path" ) ) {
+ rootFolder = vm["path"].as<std::string>();
+ config.reset(new Config( fs::path(rootFolder) / fs::path(defaultConfigFileName) ));
+
+ } else {
+ config.reset(new Config( defaultConfigFileName) );
+ }
+
+ Log( "config file name %1%", config->ConfigFile().string(), log::verbose );
+
+ if ( vm.count( "auth" ) )
+ {
+ std::cout
+ << "-----------------------\n"
+ << "Please go to this URL and get an authentication code:\n\n"
+ << OAuth2::MakeAuthURL( client_id )
+ << std::endl ;
+
+ std::cout
+ << "\n-----------------------\n"
+ << "Please input the authentication code here: " << std::endl ;
+ std::string code ;
+ std::cin >> code ;
+
+ OAuth2 token( client_id, client_secret ) ;
+ token.Auth( code ) ;
+
+ // save to config
+ config->Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ;
+ config->Save() ;
+ }
+ if ( vm.count( "version" ) )
+ {
+ std::cout
+ << "grive version " << VERSION << ' ' << __DATE__ << ' ' << __TIME__ << std::endl ;
+ return 0 ;
+ }
if ( vm.count( "force" ) )
{
options.Add( "force", Json(true) ) ;
@@ -167,7 +193,7 @@ int Main( int argc, char **argv )
std::string refresh_token ;
try
{
- refresh_token = config.Get()["refresh_token"].Str() ;
+ refresh_token = config->Get()["refresh_token"].Str() ;
}
catch ( Exception& e )
{
@@ -181,7 +207,8 @@ 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 ) ) ;
- Drive drive( &agent, options ) ;
+
+ Drive drive( &agent, options, rootFolder ) ;
drive.DetectChanges() ;
if ( vm.count( "dry-run" ) == 0 )
@@ -192,7 +219,7 @@ int Main( int argc, char **argv )
else
drive.DryRun() ;
- config.Save() ;
+ config->Save() ;
Log( "Finished!", log::info ) ;
return 0 ;
}
View
9 libgrive/src/drive/Drive.cc
@@ -51,9 +51,10 @@ namespace
const std::string state_file = ".grive_state" ;
}
-Drive::Drive( http::Agent *http, const Json& options ) :
- m_http ( http ),
- m_state ( state_file, options ),
+Drive::Drive( http::Agent *http, const Json& options, const std::string &rootFolder) :
+ m_http( http ),
+ m_state( fs::path(rootFolder), fs::path(rootFolder) / fs::path(state_file), options ),
+ m_rootFolder(rootFolder),
m_options ( options )
{
assert( m_http != 0 ) ;
@@ -127,7 +128,7 @@ void Drive::SyncFolders( )
void Drive::DetectChanges()
{
Log( "Reading local directories", log::info ) ;
- m_state.FromLocal( "." ) ;
+ m_state.FromLocal( m_rootFolder ) ;
long prev_stamp = m_state.ChangeStamp() ;
Trace( "previous change stamp is %1%", prev_stamp ) ;
View
4 libgrive/src/drive/Drive.hh
@@ -40,7 +40,7 @@ class Entry ;
class Drive
{
public :
- Drive( http::Agent *http, const Json& options ) ;
+ Drive( http::Agent *http, const Json& options, const std::string &rootFolder ) ;
void DetectChanges() ;
void Update() ;
@@ -60,7 +60,7 @@ private :
http::Agent *m_http ;
std::string m_resume_link ;
State m_state ;
-
+ fs::path m_rootFolder;
Json m_options ;
} ;
View
4 libgrive/src/drive/Resource.cc
@@ -58,8 +58,8 @@ const std::string xml_meta =
/// default constructor creates the root folder
-Resource::Resource() :
- m_name ( "." ),
+Resource::Resource(const fs::path& rootFolder) :
+ m_name ( rootFolder.string() ),
m_kind ( "folder" ),
m_id ( "folder:root" ),
m_href ( root_href ),
View
2 libgrive/src/drive/Resource.hh
@@ -51,7 +51,7 @@ public :
typedef Children::const_iterator iterator ;
public :
- Resource() ;
+ Resource(const fs::path& rootFolder) ;
Resource( const std::string& name, const std::string& kind ) ;
// default copy ctor & op= are fine
View
27 libgrive/src/drive/ResourceTree.cc
@@ -31,8 +31,8 @@ namespace gr {
using namespace details ;
-ResourceTree::ResourceTree( ) :
- m_root( new Resource )
+ResourceTree::ResourceTree( const fs::path& rootFolder ) :
+ m_root(new Resource(rootFolder))
{
m_set.insert( m_root ) ;
}
@@ -111,29 +111,6 @@ const Resource* ResourceTree::FindByHref( const std::string& href ) const
return i != map.end() ? *i : 0 ;
}
-/// Unlike other search functions, this one does not depend on the multi-index
-/// container. It traverses the tree instead.
-Resource* ResourceTree::FindByPath( const fs::path& path )
-{
- Resource *current = m_root ;
- for ( fs::path::iterator i = path.begin() ; i != path.end() && current != 0 ; ++i )
- {
- Trace( "path it = %1%", *i ) ;
-
- // current directory
- if ( *i == "." )
- continue ;
-
- else if ( *i == ".." )
- current = current->Parent() ;
-
- else
- current = current->FindChild( Path2Str(*i) ) ;
- }
-
- return current ;
-}
-
/// Reinsert should be called when the ID/HREF were updated
bool ResourceTree::ReInsert( Resource *coll )
{
View
3 libgrive/src/drive/ResourceTree.hh
@@ -64,7 +64,7 @@ public :
typedef details::Set::iterator iterator ;
public :
- ResourceTree( ) ;
+ ResourceTree( const fs::path& rootFolder ) ;
ResourceTree( const ResourceTree& fs ) ;
~ResourceTree( ) ;
@@ -74,7 +74,6 @@ public :
Resource* FindByHref( const std::string& href ) ;
const Resource* FindByHref( const std::string& href ) const ;
- Resource* FindByPath( const fs::path& path ) ;
Resource* FindByID( const std::string& id ) ;
bool ReInsert( Resource *coll ) ;
View
10 libgrive/src/drive/State.cc
@@ -32,8 +32,9 @@
namespace gr {
-State::State( const fs::path& filename, const Json& options ) :
- m_cstamp( -1 )
+State::State( const fs::path& rootFolder, const fs::path& filename, const Json& options ) :
+ m_cstamp( -1 ),
+ m_res(rootFolder)
{
Read( filename ) ;
@@ -213,11 +214,6 @@ Resource* State::FindByHref( const std::string& href )
return m_res.FindByHref( href ) ;
}
-Resource* State::Find( const fs::path& path )
-{
- return m_res.FindByPath( path ) ;
-}
-
State::iterator State::begin()
{
return m_res.begin() ;
View
3 libgrive/src/drive/State.hh
@@ -43,7 +43,7 @@ public :
typedef ResourceTree::iterator iterator ;
public :
- explicit State( const fs::path& filename, const Json& options ) ;
+ explicit State( const fs::path& rootFolder, const fs::path& filename, const Json& options ) ;
~State() ;
void FromLocal( const fs::path& p ) ;
@@ -55,7 +55,6 @@ public :
Resource* FindByHref( const std::string& href ) ;
Resource* FindByID( const std::string& id ) ;
- Resource* Find( const fs::path& path ) ;
void Sync( http::Agent *http, const Json& options ) ;
View
25 grive/src/Config.cc → libgrive/src/util/Config.cc
@@ -21,26 +21,28 @@
#include "util/StdioFile.hh"
+#include <iostream>
#include <iterator>
-namespace gr {
+using namespace gr;
-const std::string& Config::Filename()
+Config::Config(const fs::path& configFile)
+ : m_configFile(configFile)
+ , m_cfg( Read() )
{
- static const char *env_cfg = ::getenv( "GR_CONFIG" ) ;
- static const std::string filename = (env_cfg != 0) ? env_cfg : ".grive" ;
-
- return filename ;
+ if (configFile.empty()) {
+ throw Error() << expt::ErrMsg("Config cannot be initalised with an empty string.");
+ }
}
-Config::Config() :
- m_cfg( Read( Filename() ) )
+const fs::path& Config::ConfigFile() const
{
+ return m_configFile ;
}
void Config::Save( )
{
- StdioFile file( Filename(), 0600 ) ;
+ StdioFile file( m_configFile.string(), 0600 ) ;
m_cfg.Write( file ) ;
}
@@ -49,16 +51,15 @@ Json& Config::Get()
return m_cfg ;
}
-Json Config::Read( const std::string& filename )
+Json Config::Read()
{
try
{
- return Json::ParseFile( filename ) ;
+ return Json::ParseFile( m_configFile.string() ) ;
}
catch ( Exception& e )
{
return Json() ;
}
}
-} // end of namespace
View
11 grive/src/Config.hh → libgrive/src/util/Config.hh
@@ -19,7 +19,8 @@
#pragma once
-#include "util/Exception.hh"
+#include "Exception.hh"
+#include "FileSystem.hh"
#include "protocol/Json.hh"
namespace gr {
@@ -30,17 +31,17 @@ public :
struct Error : virtual Exception {} ;
typedef boost::error_info<struct FileTag, std::string> File ;
- static const std::string& Filename() ;
-
- Config() ;
+ Config(const fs::path& configFile) ;
Json& Get() ;
void Save() ;
+ const fs::path &ConfigFile() const;
private :
- Json Read( const std::string& filename ) ;
+ Json Read() ;
private :
+ const fs::path m_configFile;
Json m_cfg ;
} ;
View
2 libgrive/test/UnitTest.cc
@@ -27,6 +27,7 @@
#include "drive/StateTest.hh"
#include "util/DateTimeTest.hh"
#include "util/FunctionTest.hh"
+#include "util/ConfigTest.hh"
#include "util/SignalHandlerTest.hh"
#include "xml/NodeTest.hh"
@@ -43,6 +44,7 @@ int main( int argc, char **argv )
runner.addTest( ResourceTreeTest::suite( ) ) ;
runner.addTest( DateTimeTest::suite( ) ) ;
runner.addTest( FunctionTest::suite( ) ) ;
+ runner.addTest( ConfigTest::suite( ) ) ;
runner.addTest( SignalHandlerTest::suite( ) ) ;
runner.addTest( NodeTest::suite( ) ) ;
runner.run();
View
7 libgrive/test/drive/ResourceTest.cc
@@ -38,9 +38,10 @@ ResourceTest::ResourceTest( )
void ResourceTest::TestRootPath()
{
- Resource root ;
+ std::string rootFolder = "/home/usr/grive/grive";
+ Resource root(rootFolder) ;
CPPUNIT_ASSERT( root.IsRoot() ) ;
- GRUT_ASSERT_EQUAL( root.Path(), fs::path( "." ) ) ;
+ GRUT_ASSERT_EQUAL( root.Path(), fs::path( rootFolder ) ) ;
}
void ResourceTest::TestNormal( )
@@ -60,7 +61,7 @@ void ResourceTest::TestNormal( )
Entry remote( entry ) ;
subject.FromRemote( remote, DateTime() ) ;
- GRUT_ASSERT_EQUAL( subject.StateStr(), "local_changed" ) ;
+ GRUT_ASSERT_EQUAL( "local_changed", subject.StateStr() ) ;
}
View
57 libgrive/test/util/ConfigTest.cc
@@ -0,0 +1,57 @@
+/*
+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 "ConfigTest.hh"
+
+#include "Assert.hh"
+
+#include "util/Config.hh"
+#include "protocol/Json.hh"
+#include "util/log/Log.hh"
+
+#include <iostream>
+
+using namespace grut;
+using namespace gr ;
+
+ConfigTest::ConfigTest( )
+{
+}
+
+void ConfigTest::TestInitialiseWithEmptyString( )
+{
+ Config config("");
+ GRUT_ASSERT_EQUAL( "/home/.grive", config.ConfigFile().string()) ;
+}
+
+void ConfigTest::TestInitialiseWithString( )
+{
+ Config config("/home/.grive");
+ GRUT_ASSERT_EQUAL( "/home/.grive", config.ConfigFile().string()) ;
+}
+
+void ConfigTest::TestInitialiseWithFileSystemPath( )
+{
+ fs::path path("/home");
+ fs::path file(".grive");
+ Config config(path / file);
+ GRUT_ASSERT_EQUAL( "/home/.grive", config.ConfigFile().string());
+}
+
+
View
47 libgrive/test/util/ConfigTest.hh
@@ -0,0 +1,47 @@
+/*
+ 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 "util/Config.hh"
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace grut {
+
+class ConfigTest : public CppUnit::TestFixture
+{
+public :
+ ConfigTest( ) ;
+
+ // declare suit function
+ CPPUNIT_TEST_SUITE( ConfigTest ) ;
+ CPPUNIT_TEST_EXCEPTION( TestInitialiseWithEmptyString, gr::Config::Error ) ;
+ CPPUNIT_TEST( TestInitialiseWithString ) ;
+ CPPUNIT_TEST( TestInitialiseWithFileSystemPath ) ;
+ CPPUNIT_TEST_SUITE_END();
+
+private :
+ void TestInitialiseWithEmptyString( );
+ void TestInitialiseWithString( );
+ void TestInitialiseWithFileSystemPath( );
+} ;
+
+} // end of namespace
+

0 comments on commit cb60205

Please sign in to comment.
Something went wrong with that request. Please try again.