diff --git a/grive/src/main.cc b/grive/src/main.cc index cec9020..d576001 100644 --- a/grive/src/main.cc +++ b/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 comp_log(new log::CompositeLog) ; LogBase* console_log = comp_log->Add( std::auto_ptr( 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(), "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,6 +105,57 @@ int Main( int argc, char **argv ) std::cout << desc << std::endl ; return 0 ; } + + boost::shared_ptr config ; + + if ( vm.count( "log" ) ) + { + std::auto_ptr file_log(new log::DefaultLog( vm["log"].as() )) ; + file_log->Enable( log::debug ) ; + file_log->Enable( log::verbose ) ; + file_log->Enable( log::info ) ; + file_log->Enable( log::warning ) ; + file_log->Enable( log::error ) ; + file_log->Enable( log::critical ) ; + + // log grive version to log file + file_log->Log( log::Fmt("grive version " VERSION " " __DATE__ " " __TIME__), log::verbose ) ; + file_log->Log( log::Fmt("current time: %1%") % DateTime::Now(), log::verbose ) ; + + comp_log->Add( file_log ) ; + } + if ( vm.count( "verbose" ) ) + { + console_log->Enable( log::verbose ) ; + } + + options.Add( "log-xml", Json(vm.count("log-xml") > 0) ) ; + options.Add( "new-rev", Json(vm.count("new-rev") > 0) ) ; + + if ( vm.count( "debug" ) ) + { + 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(); + 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 @@ -119,24 +174,8 @@ int Main( int argc, char **argv ) token.Auth( code ) ; // save to config - config.Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ; - config.Save() ; - } - if ( vm.count( "log" ) ) - { - std::auto_ptr file_log(new log::DefaultLog( vm["log"].as() )) ; - file_log->Enable( log::debug ) ; - file_log->Enable( log::verbose ) ; - file_log->Enable( log::info ) ; - file_log->Enable( log::warning ) ; - file_log->Enable( log::error ) ; - file_log->Enable( log::critical ) ; - - // log grive version to log file - file_log->Log( log::Fmt("grive version " VERSION " " __DATE__ " " __TIME__), log::verbose ) ; - file_log->Log( log::Fmt("current time: %1%") % DateTime::Now(), log::verbose ) ; - - comp_log->Add( file_log ) ; + config->Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ; + config->Save() ; } if ( vm.count( "version" ) ) { @@ -144,19 +183,6 @@ int Main( int argc, char **argv ) << "grive version " << VERSION << ' ' << __DATE__ << ' ' << __TIME__ << std::endl ; return 0 ; } - if ( vm.count( "verbose" ) ) - { - console_log->Enable( log::verbose ) ; - } - - options.Add( "log-xml", Json(vm.count("log-xml") > 0) ) ; - options.Add( "new-rev", Json(vm.count("new-rev") > 0) ) ; - - if ( vm.count( "debug" ) ) - { - console_log->Enable( log::verbose ) ; - console_log->Enable( log::debug ) ; - } 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( 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 ; } diff --git a/libgrive/src/drive/Drive.cc b/libgrive/src/drive/Drive.cc index 5595fcc..028e62c 100644 --- a/libgrive/src/drive/Drive.cc +++ b/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 ) ; diff --git a/libgrive/src/drive/Drive.hh b/libgrive/src/drive/Drive.hh index 3409953..bcae37c 100644 --- a/libgrive/src/drive/Drive.hh +++ b/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 ; } ; diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index f63f99e..53e4fc4 100644 --- a/libgrive/src/drive/Resource.cc +++ b/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 ), diff --git a/libgrive/src/drive/Resource.hh b/libgrive/src/drive/Resource.hh index 8b157f7..9406c6f 100644 --- a/libgrive/src/drive/Resource.hh +++ b/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 diff --git a/libgrive/src/drive/ResourceTree.cc b/libgrive/src/drive/ResourceTree.cc index 6562ba2..5761579 100644 --- a/libgrive/src/drive/ResourceTree.cc +++ b/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 ) ; } diff --git a/libgrive/src/drive/ResourceTree.hh b/libgrive/src/drive/ResourceTree.hh index c28482f..1edbc8c 100644 --- a/libgrive/src/drive/ResourceTree.hh +++ b/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( ) ; diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 3a6e275..b69b756 100644 --- a/libgrive/src/drive/State.cc +++ b/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 ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index a0e1213..2cc2405 100644 --- a/libgrive/src/drive/State.hh +++ b/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 ) ; diff --git a/grive/src/Config.cc b/libgrive/src/util/Config.cc similarity index 69% rename from grive/src/Config.cc rename to libgrive/src/util/Config.cc index 6a66d56..d74307b 100644 --- a/grive/src/Config.cc +++ b/libgrive/src/util/Config.cc @@ -21,26 +21,28 @@ #include "util/StdioFile.hh" +#include #include -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,11 +51,11 @@ 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 ) { @@ -61,4 +63,3 @@ Json Config::Read( const std::string& filename ) } } -} // end of namespace diff --git a/grive/src/Config.hh b/libgrive/src/util/Config.hh similarity index 85% rename from grive/src/Config.hh rename to libgrive/src/util/Config.hh index 11188fa..63af600 100644 --- a/grive/src/Config.hh +++ b/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 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 ; } ; diff --git a/libgrive/test/UnitTest.cc b/libgrive/test/UnitTest.cc index f599edf..19dcf50 100644 --- a/libgrive/test/UnitTest.cc +++ b/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(); diff --git a/libgrive/test/drive/ResourceTest.cc b/libgrive/test/drive/ResourceTest.cc index 1199561..e819054 100644 --- a/libgrive/test/drive/ResourceTest.cc +++ b/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() ) ; } diff --git a/libgrive/test/util/ConfigTest.cc b/libgrive/test/util/ConfigTest.cc new file mode 100644 index 0000000..33a427d --- /dev/null +++ b/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 + +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()); +} + + diff --git a/libgrive/test/util/ConfigTest.hh b/libgrive/test/util/ConfigTest.hh new file mode 100644 index 0000000..9032574 --- /dev/null +++ b/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 +#include + +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 +