Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to move and rename files #36

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
18c4931
Adding methods to support renaming
dylanwulf Sep 27, 2015
8e98249
Now prefers title over original filename to support renaming
dylanwulf Sep 27, 2015
7e222b9
Renaming no longer changes modified date on server
dylanwulf Sep 27, 2015
bdc5afd
Merge branch 'master' of https://github.com/vitalif/grive2
dylanwulf Oct 10, 2015
4409ad7
Changed rename to move
dylanwulf Oct 11, 2015
fe3c597
Added command line option and fixed errors
dylanwulf Oct 12, 2015
a11d8c7
Merge branch 'master' of https://github.com/vitalif/grive2
dylanwulf Oct 12, 2015
a1dc212
Changed success/failure message on file move
dylanwulf Oct 12, 2015
be8aa02
Added some logic for moving files
dylanwulf Oct 12, 2015
3c699d7
Just added some newlines, nothing to see here.
dylanwulf Oct 12, 2015
4a8cbc0
Changed Drive.Move() to accept paths as arguments, removed string_lis…
dylanwulf Oct 12, 2015
27ce2df
Fixed indents
dylanwulf Oct 12, 2015
db9d11c
Fixed more indents
dylanwulf Oct 12, 2015
0f4b1d5
Couple more slight indent fixes
dylanwulf Oct 12, 2015
3a85c76
Fixed funky indents in Syncer2::Move()
dylanwulf Oct 13, 2015
540a825
Made move option compatible with -p option
dylanwulf Oct 13, 2015
8cbc57b
Now always syncs before moving files.
dylanwulf Oct 13, 2015
c41072c
Extra logic to prevent crashing
dylanwulf Oct 13, 2015
a592721
Converts paths to canonical paths, which makes it work with relative …
dylanwulf Oct 14, 2015
83b730b
Added case when source and destination are equal
dylanwulf Oct 14, 2015
93d44c5
Stopped fs::canonical() from complaining about new_p when it doesn't …
dylanwulf Oct 21, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions grive/src/main.cc
Expand Up @@ -121,6 +121,7 @@ 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(), "Syncs, then moves a file (first argument) to new location (second argument) without reuploading or redownloading." )
;

po::variables_map vm;
Expand Down Expand Up @@ -203,6 +204,21 @@ int Main( int argc, char **argv )
}
else
drive.DryRun() ;

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

config.Save() ;
Log( "Finished!", log::info ) ;
Expand Down
5 changes: 5 additions & 0 deletions libgrive/src/base/Drive.cc
Expand Up @@ -150,6 +150,11 @@ void Drive::DetectChanges()
}
}

bool Drive::Move( fs::path old_p, fs::path new_p )
{
return m_state.Move( m_syncer, old_p, new_p, m_options["path"].Str() );
}

void Drive::Update()
{
Log( "Synchronizing files", log::info ) ;
Expand Down
1 change: 1 addition & 0 deletions libgrive/src/base/Drive.hh
Expand Up @@ -41,6 +41,7 @@ public :
Drive( Syncer *syncer, const Val& options ) ;

void DetectChanges() ;
bool Move( fs::path old_p, fs::path new_p );
void Update() ;
void DryRun() ;
void SaveState() ;
Expand Down
63 changes: 63 additions & 0 deletions libgrive/src/base/State.cc
Expand Up @@ -321,4 +321,67 @@ void State::ChangeStamp( long cstamp )
m_cstamp = cstamp ;
}

bool State::Move( Syncer* syncer, fs::path old_p, fs::path new_p, fs::path grive_root )
{
//Convert paths to canonical representations
//Also seems to remove trailing / at the end of directory paths
old_p = fs::canonical( old_p );
grive_root = fs::canonical( grive_root );

//new_p is a little special because fs::canonical() requires that the path exists
if ( new_p.string()[ new_p.string().size() - 1 ] == '/') //If new_p ends with a /, remove it
new_p = new_p.parent_path();
new_p = fs::canonical( new_p.parent_path() ) / new_p.filename();

//Fails if source file doesn't exist, or if destination file already
//exists and is not a directory, or if the source and destination are exactly the same
if ( (fs::exists(new_p) && !fs::is_directory(new_p) ) || !fs::exists(old_p) || fs::equivalent( old_p, new_p ) )
return false;

//If new path is an existing directory, move the file into the directory
//instead of trying to rename it
if ( fs::is_directory(new_p) ){
new_p = new_p / old_p.filename();
}

//Get the paths relative to grive root.
//Just finds the substring from the end of the grive_root to the end of the path
//+1s are to exclude slash at beginning of relative path
int start = grive_root.string().size() + 1;
int nLen = new_p.string().size() - (grive_root.string().size() + 1);
int oLen = old_p.string().size() - (grive_root.string().size() + 1);
if ( start + nLen != new_p.string().size() || start + oLen != old_p.string().size() )
return false;
fs::path new_p_rootrel( new_p.string().substr( start, nLen ) );
fs::path old_p_rootrel( old_p.string().substr( start, oLen ) );

//Get resources
Resource* res = m_res.Root();
Resource* newParentRes = m_res.Root();
for ( fs::path::iterator it = old_p_rootrel.begin(); it != old_p_rootrel.end(); ++it )
{
if ( *it != "." && *it != ".." && res != 0 )
res = res->FindChild(it->string());
if ( *it == ".." )
res = res->Parent();
}
for ( fs::path::iterator it = new_p_rootrel.begin(); it != new_p_rootrel.end(); ++it )
{
if ( *it != "." && *it != ".." && *it != new_p.filename() && newParentRes != 0 )
newParentRes = newParentRes->FindChild(it->string());
if ( *it == "..")
res = res->Parent();
}

//These conditions should only occur if everything is not up-to-date
if ( res == 0 || newParentRes == 0 || res->GetState() != Resource::sync ||
newParentRes->GetState() != Resource::sync ||
newParentRes->FindChild( new_p.filename().string() ) != 0 )
return false;

fs::rename(old_p, new_p); //Moves local file
syncer->Move(res, newParentRes, new_p.filename().string()); //Moves server file
return true;
}

} // end of namespace gr
3 changes: 2 additions & 1 deletion libgrive/src/base/State.hh
Expand Up @@ -63,7 +63,8 @@ public :

long ChangeStamp() const ;
void ChangeStamp( long cstamp ) ;

bool Move( Syncer* syncer, fs::path old_p, fs::path new_p, fs::path grive_root );

private :
void FromLocal( const fs::path& p, Resource *folder ) ;
void FromChange( const Entry& e ) ;
Expand Down
1 change: 1 addition & 0 deletions libgrive/src/base/Syncer.hh
Expand Up @@ -53,6 +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, Resource* newParent, std::string newFilename ) = 0;

virtual std::auto_ptr<Feed> GetFolders() = 0;
virtual std::auto_ptr<Feed> GetAll() = 0;
Expand Down
41 changes: 41 additions & 0 deletions libgrive/src/drive2/Syncer2.cc
Expand Up @@ -89,6 +89,47 @@ bool Syncer2::Create( Resource *res )
return Upload( res );
}

bool Syncer2::Move( Resource* res, Resource* newParentRes, std::string newFilename )
{
if ( res->ResourceID().empty() )
{
Log("Can't rename file %1%, no server id found", res->Name());
return false;
}

Val meta;
meta.Add( "title", Val(newFilename) );
if ( res->IsFolder() )
{
meta.Add( "mimeType", Val( mime_types::folder ) );
}
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 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() ) );
}
return true;
}

std::string to_string( uint64_t n )
{
std::ostringstream s;
Expand Down
1 change: 1 addition & 0 deletions libgrive/src/drive2/Syncer2.hh
Expand Up @@ -37,6 +37,7 @@ public :
void DeleteRemote( Resource *res );
bool EditContent( Resource *res, bool new_rev );
bool Create( Resource *res );
bool Move( Resource* res, Resource* newParent, std::string newFilename );

std::auto_ptr<Feed> GetFolders();
std::auto_ptr<Feed> GetAll();
Expand Down