Added command line option and fixed errors

pull/36/head
Dylan Wulf 2015-10-11 23:19:37 -04:00
parent 4409ad764d
commit fe3c5979b0
10 changed files with 82 additions and 60 deletions

View File

@ -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 ;

View File

@ -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()

View File

@ -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() ;

View File

@ -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;
}

View File

@ -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;

View File

@ -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() ) );
}

View File

@ -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();

View File

@ -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) ;

View File

@ -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
{

View File

@ -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 ) ;
}