mirror of https://github.com/vitalif/grive2
Added command line option and fixed errors
parent
4409ad764d
commit
fe3c5979b0
|
@ -78,19 +78,19 @@ void InitLog( const po::variables_map& vm )
|
|||
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 ) ;
|
||||
}
|
||||
|
||||
|
||||
if ( vm.count( "debug" ) )
|
||||
{
|
||||
console_log->Enable( log::verbose ) ;
|
||||
|
@ -102,7 +102,7 @@ void InitLog( const po::variables_map& vm )
|
|||
int Main( int argc, char **argv )
|
||||
{
|
||||
InitGCrypt() ;
|
||||
|
||||
|
||||
// construct the program options
|
||||
po::options_description desc( "Grive options" );
|
||||
desc.add_options()
|
||||
|
@ -121,12 +121,13 @@ int Main( int argc, char **argv )
|
|||
( "dry-run", "Only detect which files need to be uploaded/downloaded, "
|
||||
"without actually performing them." )
|
||||
( "ignore", po::value<std::string>(), "Ignore files relative paths of which match this Perl RegExp." )
|
||||
( "move,m", po::value<std::vector<std::string> >()->multitoken(), "Moves or renames a file without reuploading or redownloading." )
|
||||
;
|
||||
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line( argc, argv, desc), vm );
|
||||
po::notify(vm);
|
||||
|
||||
|
||||
// simple commands that doesn't require log or config
|
||||
if ( vm.count("help") )
|
||||
{
|
||||
|
@ -142,9 +143,9 @@ int Main( int argc, char **argv )
|
|||
|
||||
// initialize logging
|
||||
InitLog(vm) ;
|
||||
|
||||
|
||||
Config config(vm) ;
|
||||
|
||||
|
||||
Log( "config file name %1%", config.Filename(), log::verbose );
|
||||
|
||||
std::auto_ptr<http::Agent> http( new http::CurlAgent );
|
||||
|
@ -154,26 +155,26 @@ int Main( int argc, char **argv )
|
|||
if ( vm.count( "auth" ) )
|
||||
{
|
||||
OAuth2 token( http.get(), client_id, client_secret ) ;
|
||||
|
||||
|
||||
std::cout
|
||||
<< "-----------------------\n"
|
||||
<< "Please go to this URL and get an authentication code:\n\n"
|
||||
<< token.MakeAuthURL()
|
||||
<< 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
|
||||
config.Set( "refresh_token", Val( token.RefreshToken() ) ) ;
|
||||
config.Save() ;
|
||||
}
|
||||
|
||||
|
||||
std::string refresh_token ;
|
||||
try
|
||||
{
|
||||
|
@ -185,10 +186,10 @@ int Main( int argc, char **argv )
|
|||
"Please run grive with the \"-a\" option if this is the "
|
||||
"first time you're accessing your Google Drive!",
|
||||
log::critical ) ;
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
OAuth2 token( http.get(), refresh_token, client_id, client_secret ) ;
|
||||
AuthAgent agent( token, http.get() ) ;
|
||||
v2::Syncer2 syncer( &agent );
|
||||
|
@ -196,15 +197,20 @@ int Main( int argc, char **argv )
|
|||
Drive drive( &syncer, config.GetAll() ) ;
|
||||
drive.DetectChanges() ;
|
||||
|
||||
if ( vm.count( "dry-run" ) == 0 )
|
||||
if ( vm.count( "dry-run" ) == 0 && vm.count( "move" ) == 0 )
|
||||
{
|
||||
//drive.Rename("./hello.txt", "./hello_changed.txt");
|
||||
drive.Update() ;
|
||||
drive.SaveState() ;
|
||||
}
|
||||
else if( vm.count( "move" ) > 0 ){
|
||||
bool success = drive.Move();
|
||||
if (!success){
|
||||
Log( "Move failed.", log::critical );
|
||||
}
|
||||
}
|
||||
else
|
||||
drive.DryRun() ;
|
||||
|
||||
|
||||
config.Save() ;
|
||||
Log( "Finished!", log::info ) ;
|
||||
return 0 ;
|
||||
|
|
|
@ -150,9 +150,13 @@ void Drive::DetectChanges()
|
|||
}
|
||||
}
|
||||
|
||||
bool Drive::Move(fs::path old_p, fs::path new_p)
|
||||
bool Drive::Move()
|
||||
{
|
||||
return m_state.Move( m_syncer, old_p, new_p );
|
||||
if (m_options["move"].As<std::vector<std::string> >().size() < 2){
|
||||
Log("Not enough arguments for move!", log::info);
|
||||
return false;
|
||||
}
|
||||
return m_state.Move( m_syncer, m_options["move"].As<std::vector<std::string> >()[0], m_options["move"].As<std::vector<std::string> >()[1] );
|
||||
}
|
||||
|
||||
void Drive::Update()
|
||||
|
|
|
@ -41,7 +41,7 @@ public :
|
|||
Drive( Syncer *syncer, const Val& options ) ;
|
||||
|
||||
void DetectChanges() ;
|
||||
bool Move( fs::path old_p, fs::path new_p);
|
||||
bool Move();
|
||||
void Update() ;
|
||||
void DryRun() ;
|
||||
void SaveState() ;
|
||||
|
|
|
@ -324,13 +324,18 @@ void State::ChangeStamp( long cstamp )
|
|||
bool State::Move( Syncer* syncer, fs::path old_p, fs::path new_p )
|
||||
{
|
||||
Resource* res = m_res.Root();
|
||||
Resource* newParentRes = m_res.Root();
|
||||
for (fs::path::iterator it = old_p.begin(); it != old_p.end(); ++it)
|
||||
{
|
||||
if (*it != ".")
|
||||
res = res->FindChild(it->string());
|
||||
}
|
||||
fs::rename(old_p, new_p);
|
||||
syncer->Move(res, new_p);
|
||||
for (fs::path::iterator it = new_p.begin(); it != new_p.end(); ++it){
|
||||
if (*it != "." && *it != new_p.filename() )
|
||||
newParentRes = newParentRes->FindChild(it->string());
|
||||
}
|
||||
fs::rename(old_p, new_p); //Moves local file
|
||||
syncer->Move(res, newParentRes, new_p.filename().string()); //Moves server file
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public :
|
|||
virtual void Download( Resource *res, const fs::path& file );
|
||||
virtual bool EditContent( Resource *res, bool new_rev ) = 0;
|
||||
virtual bool Create( Resource *res ) = 0;
|
||||
virtual bool Move( Resource *res, fs::path new_p) = 0;
|
||||
virtual bool Move( Resource* res, Resource* newParent, std::string newFilename ) = 0;
|
||||
|
||||
virtual std::auto_ptr<Feed> GetFolders() = 0;
|
||||
virtual std::auto_ptr<Feed> GetAll() = 0;
|
||||
|
|
|
@ -89,7 +89,7 @@ bool Syncer2::Create( Resource *res )
|
|||
return Upload( res );
|
||||
}
|
||||
|
||||
bool Syncer2::Move( Resource *res, fs::path new_p)
|
||||
bool Syncer2::Move( Resource* res, Resource* newParentRes, std::string newFilename )
|
||||
{
|
||||
if ( res->ResourceID().empty() )
|
||||
{
|
||||
|
@ -98,31 +98,32 @@ bool Syncer2::Move( Resource *res, fs::path new_p)
|
|||
}
|
||||
|
||||
Val meta;
|
||||
meta.Add( "title", Val(new_p.filename().string()) );
|
||||
meta.Add( "title", Val(newFilename) );
|
||||
if ( res->IsFolder() )
|
||||
{
|
||||
meta.Add( "mimeType", Val( mime_types::folder ) );
|
||||
}
|
||||
if ( !res->Parent()->IsRoot() )
|
||||
{
|
||||
Val parent;
|
||||
parent.Add( "id", Val( res->Parent()->ResourceID() ) );
|
||||
Val parents( Val::array_type );
|
||||
parents.Add( parent );
|
||||
meta.Add( "parents", parents );
|
||||
}
|
||||
std::string json_meta = WriteJson( meta );
|
||||
|
||||
Val valr ;
|
||||
|
||||
// Issue metadata update request
|
||||
{
|
||||
std::string addRemoveParents("");
|
||||
if (res->Parent()->IsRoot() )
|
||||
addRemoveParents += "&removeParents=root";
|
||||
else
|
||||
addRemoveParents += "&removeParents=" + res->Parent()->ResourceID();
|
||||
if ( newParentRes->IsRoot() )
|
||||
addRemoveParents += "&addParents=root";
|
||||
else
|
||||
addRemoveParents += "&addParents=" + newParentRes->ResourceID();
|
||||
http::Header hdr2 ;
|
||||
hdr2.Add( "Content-Type: application/json" );
|
||||
http::ValResponse vrsp ;
|
||||
long http_code = 0;
|
||||
//Don't want to change the modified date since we're only renaming.
|
||||
http_code = m_http->Put( feeds::files + "/" + res->ResourceID() + "?modifiedDateBehavior=noChange", json_meta, &vrsp, hdr2 ) ;
|
||||
//Don't change modified date because we're only moving
|
||||
http_code = m_http->Put( feeds::files + "/" + res->ResourceID() + "?modifiedDateBehavior=noChange" + addRemoveParents, json_meta, &vrsp, hdr2 ) ;
|
||||
valr = vrsp.Response();
|
||||
assert( !( valr["id"].Str().empty() ) );
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public :
|
|||
void DeleteRemote( Resource *res );
|
||||
bool EditContent( Resource *res, bool new_rev );
|
||||
bool Create( Resource *res );
|
||||
bool Move( Resource *res, fs::path new_p);
|
||||
bool Move( Resource* res, Resource* newParent, std::string newFilename );
|
||||
|
||||
std::auto_ptr<Feed> GetFolders();
|
||||
std::auto_ptr<Feed> GetAll();
|
||||
|
|
|
@ -48,7 +48,8 @@ Val::Val( TypeEnum type )
|
|||
case string_type: m_base.reset( new Impl<std::string> ) ; break ;
|
||||
case array_type: m_base.reset( new Impl<Array> ) ; break ;
|
||||
case object_type: m_base.reset( new Impl<Object> ) ; break ;
|
||||
case null_type:
|
||||
case string_list_type: m_base.reset( new Impl<std::vector<std::string> > ); break ;
|
||||
case null_type:
|
||||
default: m_base.reset( new Impl<void> ) ; break ;
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ const Val& Val::operator[]( const std::string& key ) const
|
|||
Object::const_iterator i = obj.find(key) ;
|
||||
if ( i != obj.end() )
|
||||
return i->second ;
|
||||
|
||||
|
||||
// shut off compiler warning
|
||||
BOOST_THROW_EXCEPTION(Error() << NoKey_(key)) ;
|
||||
throw ;
|
||||
|
@ -96,7 +97,7 @@ const Val& Val::operator[]( std::size_t index ) const
|
|||
const Array& ar = As<Array>() ;
|
||||
if ( index < ar.size() )
|
||||
return ar[index] ;
|
||||
|
||||
|
||||
// shut off compiler warning
|
||||
BOOST_THROW_EXCEPTION(Error() << OutOfRange_(index)) ;
|
||||
throw ;
|
||||
|
@ -179,18 +180,18 @@ void Val::Visit( ValVisitor *visitor ) const
|
|||
case double_type: visitor->Visit( As<double>() ) ; break ;
|
||||
case string_type: visitor->Visit( As<std::string>() ) ; break ;
|
||||
case bool_type: visitor->Visit( As<bool>() ) ; break ;
|
||||
|
||||
|
||||
case object_type:
|
||||
{
|
||||
visitor->StartObject() ;
|
||||
|
||||
|
||||
const Object& obj = As<Object>() ;
|
||||
for ( Object::const_iterator i = obj.begin() ; i != obj.end() ; ++i )
|
||||
{
|
||||
visitor->VisitKey( i->first ) ;
|
||||
i->second.Visit( visitor ) ;
|
||||
}
|
||||
|
||||
|
||||
visitor->EndObject() ;
|
||||
break ;
|
||||
}
|
||||
|
@ -198,11 +199,11 @@ void Val::Visit( ValVisitor *visitor ) const
|
|||
case array_type:
|
||||
{
|
||||
visitor->StartArray() ;
|
||||
|
||||
|
||||
const Array& arr = As<Array>() ;
|
||||
for ( Array::const_iterator i = arr.begin() ; i != arr.end() ; ++i )
|
||||
i->Visit( visitor ) ;
|
||||
|
||||
|
||||
visitor->EndArray() ;
|
||||
break ;
|
||||
}
|
||||
|
@ -218,14 +219,14 @@ void Val::Select( const Object& obj, const std::string& key, std::vector<Val>& r
|
|||
|
||||
/** If \a this is an array of objects, this function returns all values of
|
||||
the objects in the array with the key \a key. If \a this is an object,
|
||||
just return the value with the key \a key.
|
||||
just return the value with the key \a key.
|
||||
*/
|
||||
std::vector<Val> Val::Select( const std::string& key ) const
|
||||
{
|
||||
std::vector<Val> result ;
|
||||
if ( Is<Object>() )
|
||||
Select( As<Object>(), key, result ) ;
|
||||
|
||||
|
||||
else if ( Is<Array>() )
|
||||
{
|
||||
const Array& array = As<Array>() ;
|
||||
|
@ -255,7 +256,7 @@ namespace std
|
|||
{
|
||||
v1.Swap( v2 ) ;
|
||||
}
|
||||
|
||||
|
||||
ostream& operator<<( ostream& os, gr::Val::TypeEnum t )
|
||||
{
|
||||
return os << static_cast<int>(t) ;
|
||||
|
|
|
@ -36,14 +36,14 @@ class ValVisitor ;
|
|||
class Val
|
||||
{
|
||||
public :
|
||||
enum TypeEnum { null_type, bool_type, double_type, int_type, object_type, array_type, string_type } ;
|
||||
enum TypeEnum { null_type, bool_type, double_type, int_type, object_type, array_type, string_type, string_list_type } ;
|
||||
|
||||
struct Error : virtual Exception {} ;
|
||||
typedef boost::error_info<struct SrcType, TypeEnum> SrcType_ ;
|
||||
typedef boost::error_info<struct DestType, TypeEnum> DestType_ ;
|
||||
typedef boost::error_info<struct NoKey, std::string> NoKey_ ;
|
||||
typedef boost::error_info<struct OutOfRange,std::size_t> OutOfRange_ ;
|
||||
|
||||
|
||||
private :
|
||||
template <typename T>
|
||||
struct Type2Enum ;
|
||||
|
@ -71,10 +71,10 @@ public :
|
|||
|
||||
template <typename T>
|
||||
Val& Assign( const T& t ) ;
|
||||
|
||||
|
||||
void Swap( Val& val ) ;
|
||||
Val& operator=( const Val& val ) ;
|
||||
|
||||
|
||||
template <typename T>
|
||||
Val& operator=( const T& t )
|
||||
{
|
||||
|
@ -110,12 +110,12 @@ public :
|
|||
bool Has( const std::string& key ) const ;
|
||||
bool Get( const std::string& key, Val& val ) const ;
|
||||
void Add( const std::string& key, const Val& val ) ;
|
||||
|
||||
|
||||
// shortcuts for array (and array of objects)
|
||||
void Add( const Val& json ) ;
|
||||
|
||||
|
||||
std::vector<Val> Select( const std::string& key ) const ;
|
||||
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& os, const Val& val ) ;
|
||||
void Visit( ValVisitor *visitor ) const ;
|
||||
|
||||
|
@ -124,7 +124,7 @@ private :
|
|||
|
||||
template <typename T>
|
||||
struct Impl ;
|
||||
|
||||
|
||||
std::auto_ptr<Base> m_base ;
|
||||
|
||||
private :
|
||||
|
@ -138,6 +138,7 @@ template <> struct Val::Type2Enum<double> { static const TypeEnum type = double
|
|||
template <> struct Val::Type2Enum<std::string> { static const TypeEnum type = string_type ; } ;
|
||||
template <> struct Val::Type2Enum<Val::Array> { static const TypeEnum type = array_type ; } ;
|
||||
template <> struct Val::Type2Enum<Val::Object> { static const TypeEnum type = object_type ; } ;
|
||||
template <> struct Val::Type2Enum<std::vector<std::string> > { static const TypeEnum type = string_list_type ; } ;
|
||||
|
||||
template <> struct Val::SupportType<int> { typedef long long Type ; } ;
|
||||
template <> struct Val::SupportType<unsigned> { typedef long long Type ; } ;
|
||||
|
@ -154,6 +155,7 @@ template <> struct Val::SupportType<std::string> { typedef std::string Type ; }
|
|||
template <> struct Val::SupportType<const char*> { typedef std::string Type ; } ;
|
||||
template <> struct Val::SupportType<Val::Array> { typedef Val::Array Type ; } ;
|
||||
template <> struct Val::SupportType<Val::Object> { typedef Val::Object Type ; } ;
|
||||
template <> struct Val::SupportType<std::vector<std::string> > { typedef std::vector<std::string> Type ; } ;
|
||||
|
||||
struct Val::Base
|
||||
{
|
||||
|
|
|
@ -49,7 +49,10 @@ Config::Config( const po::variables_map& vm )
|
|||
m_cmd.Add( "ignore", Val(vm.count("ignore") > 0
|
||||
? vm["ignore"].as<std::string>()
|
||||
: "" ) ) ;
|
||||
|
||||
m_cmd.Add( "move", Val(vm.count("move") > 0
|
||||
? vm["move"].as<std::vector<std::string> >()
|
||||
: std::vector<std::string>() ) ) ;
|
||||
|
||||
m_path = GetPath( fs::path(m_cmd["path"].Str()) ) ;
|
||||
m_file = Read( ) ;
|
||||
}
|
||||
|
@ -90,10 +93,10 @@ Val Config::GetAll() const
|
|||
{
|
||||
Val::Object obj = m_file.AsObject() ;
|
||||
Val::Object cmd_obj = m_cmd.AsObject() ;
|
||||
|
||||
|
||||
for ( Val::Object::iterator i = cmd_obj.begin() ; i != cmd_obj.end() ; ++i )
|
||||
obj[i->first] = i->second ;
|
||||
|
||||
|
||||
return Val( obj ) ;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue