2012-04-25 20:13:17 +04:00
/*
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
2012-04-26 19:40:38 +04:00
as published by the Free Software Foundation version 2
2012-04-26 08:21:40 +04:00
of the License .
2012-04-25 20:13:17 +04:00
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 .
*/
2012-07-29 21:17:10 +04:00
# include "util/Config.hh"
2012-05-15 19:07:03 +04:00
2015-05-17 16:54:04 +03:00
# include "base/Drive.hh"
2015-05-17 20:10:03 +03:00
# include "drive2/Syncer2.hh"
2012-05-13 11:27:58 +04:00
2012-07-19 20:39:36 +04:00
# include "http/CurlAgent.hh"
# include "protocol/AuthAgent.hh"
2012-04-27 06:49:33 +04:00
# include "protocol/OAuth2.hh"
2015-05-16 00:27:59 +03:00
# include "json/Val.hh"
2012-04-25 20:13:17 +04:00
2012-05-13 11:27:58 +04:00
# include "bfd/Backtrace.hh"
# include "util/Exception.hh"
2012-06-03 14:31:02 +04:00
# include "util/log/Log.hh"
# include "util/log/CompositeLog.hh"
# include "util/log/DefaultLog.hh"
2012-05-13 11:27:58 +04:00
2012-06-14 20:04:17 +04:00
// boost header
2012-05-13 11:27:58 +04:00
# include <boost/exception/all.hpp>
2012-06-14 20:04:17 +04:00
# include <boost/program_options.hpp>
2012-05-13 11:27:58 +04:00
2012-06-14 20:04:17 +04:00
// initializing libgcrypt, must be done in executable
2012-06-05 18:51:54 +04:00
# include <gcrypt.h>
2012-04-26 05:20:41 +04:00
# include <cassert>
2012-04-25 20:13:17 +04:00
# include <cstdlib>
# include <iostream>
2012-04-29 19:40:13 +04:00
# include <unistd.h>
2012-04-29 02:45:33 +04:00
2012-04-26 08:21:40 +04:00
const std : : string client_id = " 22314510474.apps.googleusercontent.com " ;
const std : : string client_secret = " bl4ufi89h-9MkFlypcI7R785 " ;
2012-06-06 19:21:04 +04:00
using namespace gr ;
2012-07-30 11:24:47 +04:00
namespace po = boost : : program_options ;
2012-06-06 19:21:04 +04:00
2012-06-05 18:51:54 +04:00
// libgcrypt insist this to be done in application, not library
void InitGCrypt ( )
{
if ( ! gcry_check_version ( GCRYPT_VERSION ) )
2013-04-28 19:50:20 +04:00
throw std : : runtime_error ( " libgcrypt version mismatch " ) ;
2012-06-05 18:51:54 +04:00
// disable secure memory
gcry_control ( GCRYCTL_DISABLE_SECMEM , 0 ) ;
// tell Libgcrypt that initialization has completed
gcry_control ( GCRYCTL_INITIALIZATION_FINISHED , 0 ) ;
}
2012-07-30 11:24:47 +04:00
void InitLog ( const po : : variables_map & vm )
2012-04-25 20:13:17 +04:00
{
2012-06-03 14:31:02 +04:00
std : : auto_ptr < log : : CompositeLog > comp_log ( new log : : CompositeLog ) ;
LogBase * console_log = comp_log - > Add ( std : : auto_ptr < LogBase > ( new log : : DefaultLog ) ) ;
2012-07-30 11:24:47 +04:00
if ( vm . count ( " log " ) )
{
std : : auto_ptr < LogBase > file_log ( new log : : DefaultLog ( vm [ " log " ] . as < std : : string > ( ) ) ) ;
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 ) ;
}
2012-05-13 13:27:40 +04:00
2012-07-30 11:24:47 +04:00
if ( vm . count ( " verbose " ) )
{
console_log - > Enable ( log : : verbose ) ;
}
2012-05-31 19:37:47 +04:00
2012-07-30 11:24:47 +04:00
if ( vm . count ( " debug " ) )
{
console_log - > Enable ( log : : verbose ) ;
console_log - > Enable ( log : : debug ) ;
}
LogBase : : Inst ( std : : auto_ptr < LogBase > ( comp_log . release ( ) ) ) ;
}
int Main ( int argc , char * * argv )
{
InitGCrypt ( ) ;
2012-06-14 20:04:17 +04:00
// construct the program options
po : : options_description desc ( " Grive options " ) ;
desc . add_options ( )
( " help,h " , " Produce help message " )
( " version,v " , " Display Grive version " )
( " auth,a " , " Request authorization token " )
2015-12-12 17:22:17 +03:00
( " path,p " , po : : value < std : : string > ( ) , " Root directory to sync " )
( " dir,s " , po : : value < std : : string > ( ) , " Single subdirectory to sync (remembered for next runs) " )
2012-06-14 20:04:17 +04:00
( " verbose,V " , " Verbose mode. Enable more messages than normal. " )
2015-09-30 15:01:50 +03:00
( " log-http " , po : : value < std : : string > ( ) , " Log all HTTP responses in this file for debugging. " )
2012-07-26 20:45:53 +04:00
( " new-rev " , " Create new revisions in server for updated files. " )
2012-06-14 20:04:17 +04:00
( " debug,d " , " Enable debug level messages. Implies -v. " )
( " log,l " , po : : value < std : : string > ( ) , " Set log output filename. " )
( " force,f " , " Force grive to always download a file from Google Drive "
" instead of uploading it. " )
2012-06-17 11:57:47 +04:00
( " dry-run " , " Only detect which files need to be uploaded/downloaded, "
" without actually performing them. " )
2015-12-12 17:22:17 +03:00
( " ignore " , po : : value < std : : string > ( ) , " Perl RegExp to ignore files (matched against relative paths, remembered for next runs). " )
2015-11-10 12:54:47 +03:00
( " move,m " , po : : value < std : : vector < std : : string > > ( ) - > multitoken ( ) , " Syncs, then moves a file (first argument) to new location (second argument) without reuploading or redownloading. " )
2012-06-14 20:04:17 +04:00
;
po : : variables_map vm ;
po : : store ( po : : parse_command_line ( argc , argv , desc ) , vm ) ;
po : : notify ( vm ) ;
2012-07-30 12:52:59 +04:00
// simple commands that doesn't require log or config
2012-06-14 20:04:17 +04:00
if ( vm . count ( " help " ) )
{
std : : cout < < desc < < std : : endl ;
return 0 ;
}
2012-07-30 11:24:47 +04:00
else if ( vm . count ( " version " ) )
2012-06-14 20:04:17 +04:00
{
2012-07-30 11:24:47 +04:00
std : : cout
< < " grive version " < < VERSION < < ' ' < < __DATE__ < < ' ' < < __TIME__ < < std : : endl ;
return 0 ;
2012-06-14 20:04:17 +04:00
}
2012-07-30 11:24:47 +04:00
// initialize logging
InitLog ( vm ) ;
2012-07-26 20:17:44 +04:00
2012-07-30 12:52:59 +04:00
Config config ( vm ) ;
2012-07-30 11:24:47 +04:00
2012-07-30 12:52:59 +04:00
Log ( " config file name %1% " , config . Filename ( ) , log : : verbose ) ;
2012-07-29 21:17:10 +04:00
2015-09-30 15:01:50 +03:00
std : : auto_ptr < http : : Agent > http ( new http : : CurlAgent ) ;
if ( vm . count ( " log-http " ) )
http - > SetLog ( new http : : ResponseLog ( vm [ " log-http " ] . as < std : : string > ( ) , " .txt " ) ) ;
2012-07-29 21:17:10 +04:00
if ( vm . count ( " auth " ) )
{
2015-10-07 01:57:28 +03:00
OAuth2 token ( http . get ( ) , client_id , client_secret ) ;
2015-09-30 15:01:50 +03:00
2012-07-29 21:17:10 +04:00
std : : cout
< < " ----------------------- \n "
< < " Please go to this URL and get an authentication code: \n \n "
2015-09-30 15:01:50 +03:00
< < token . MakeAuthURL ( )
2012-07-29 21:17:10 +04:00
< < std : : endl ;
std : : cout
< < " \n ----------------------- \n "
< < " Please input the authentication code here: " < < std : : endl ;
std : : string code ;
std : : cin > > code ;
token . Auth ( code ) ;
// save to config
2015-05-16 00:27:59 +03:00
config . Set ( " refresh_token " , Val ( token . RefreshToken ( ) ) ) ;
2012-07-30 12:52:59 +04:00
config . Save ( ) ;
2012-07-29 21:17:10 +04:00
}
2012-04-25 20:13:17 +04:00
2012-04-29 07:17:15 +04:00
std : : string refresh_token ;
2012-04-29 02:45:33 +04:00
try
{
2012-07-30 12:52:59 +04:00
refresh_token = config . Get ( " refresh_token " ) . Str ( ) ;
2012-04-29 02:45:33 +04:00
}
2012-05-19 05:03:34 +04:00
catch ( Exception & e )
2012-04-29 02:45:33 +04:00
{
2012-05-13 12:45:27 +04:00
Log (
2012-05-13 12:10:18 +04:00
" Please run grive with the \" -a \" option if this is the "
" first time you're accessing your Google Drive! " ,
2012-05-13 12:45:27 +04:00
log : : critical ) ;
2012-05-13 12:10:18 +04:00
2012-04-29 02:45:33 +04:00
return - 1 ;
}
2012-04-25 20:13:17 +04:00
2015-10-07 01:57:28 +03:00
OAuth2 token ( http . get ( ) , refresh_token , client_id , client_secret ) ;
AuthAgent agent ( token , http . get ( ) ) ;
2015-05-17 20:10:03 +03:00
v2 : : Syncer2 syncer ( & agent ) ;
2012-07-29 21:17:10 +04:00
2015-05-17 16:54:04 +03:00
Drive drive ( & syncer , config . GetAll ( ) ) ;
2012-06-23 14:23:43 +04:00
drive . DetectChanges ( ) ;
2012-06-06 19:21:04 +04:00
2012-06-17 11:57:47 +04:00
if ( vm . count ( " dry-run " ) = = 0 )
{
drive . Update ( ) ;
drive . SaveState ( ) ;
}
2012-06-17 12:33:38 +04:00
else
drive . DryRun ( ) ;
2015-11-10 12:54:47 +03:00
if ( vm . count ( " move " ) > 0 & & vm . count ( " dry-run " ) = = 0 )
{
if ( vm [ " move " ] . as < std : : vector < std : : string > > ( ) . size ( ) < 2 )
Log ( " Not enough arguments for move. Move failed. " , log : : error ) ;
else
{
bool success = drive . Move ( vm [ " move " ] . as < std : : vector < std : : string > > ( ) [ 0 ] ,
vm [ " move " ] . as < std : : vector < std : : string > > ( ) [ 1 ] ) ;
if ( success )
Log ( " Move successful! " , log : : info ) ;
else
Log ( " Move failed. " , log : : error ) ;
}
}
2012-06-06 19:21:04 +04:00
2012-07-30 12:52:59 +04:00
config . Save ( ) ;
2012-06-14 20:55:00 +04:00
Log ( " Finished! " , log : : info ) ;
2012-06-06 19:21:04 +04:00
return 0 ;
}
int main ( int argc , char * * argv )
{
2012-05-13 11:27:58 +04:00
try
{
2012-06-06 19:21:04 +04:00
return Main ( argc , argv ) ;
2012-05-13 11:27:58 +04:00
}
2012-06-06 19:21:04 +04:00
catch ( Exception & e )
2012-05-13 11:27:58 +04:00
{
2012-05-13 12:45:27 +04:00
Log ( " exception: %1% " , boost : : diagnostic_information ( e ) , log : : critical ) ;
2012-06-14 20:55:00 +04:00
}
catch ( std : : exception & e )
{
Log ( " exception: %1% " , e . what ( ) , log : : critical ) ;
2012-05-13 11:27:58 +04:00
}
2012-06-07 14:26:57 +04:00
catch ( . . . )
{
2012-06-14 20:55:00 +04:00
Log ( " unexpected exception " , log : : critical ) ;
2012-06-07 14:26:57 +04:00
}
2012-06-14 20:55:00 +04:00
return - 1 ;
2012-04-25 20:13:17 +04:00
}