mirror of https://github.com/vitalif/grive2
clean up sync code
parent
7f2fa95d9a
commit
b1589bb181
|
@ -67,7 +67,7 @@ Drive::Drive( OAuth2& auth ) :
|
|||
Trace( "change stamp is %1%", change_stamp ) ;
|
||||
|
||||
m_state.ChangeStamp( change_stamp ) ;
|
||||
m_state.Sync( "." ) ;
|
||||
m_state.FromLocal( "." ) ;
|
||||
|
||||
ConstructDirTree( &http ) ;
|
||||
|
||||
|
@ -108,7 +108,7 @@ Drive::Drive( OAuth2& auth ) :
|
|||
file.Title(), p->Name() ) ;
|
||||
|
||||
else
|
||||
m_state.OnEntry( file ) ;
|
||||
m_state.FromRemote( file ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,9 +146,8 @@ void Drive::ConstructDirTree( http::Agent *http )
|
|||
if ( e.Kind() == "folder" )
|
||||
{
|
||||
if ( e.ParentHrefs().size() == 1 )
|
||||
{
|
||||
m_state.OnEntry( e ) ;
|
||||
}
|
||||
m_state.FromRemote( e ) ;
|
||||
|
||||
else
|
||||
Log( "folder \"%1%\" has multiple parents, ignored", e.Title(), log::warning ) ;
|
||||
}
|
||||
|
@ -164,26 +163,7 @@ void Drive::ConstructDirTree( http::Agent *http )
|
|||
|
||||
m_state.ResolveEntry() ;
|
||||
}
|
||||
/*
|
||||
void Drive::UpdateFile( Entry& entry, Resource *parent, http::Agent *http )
|
||||
{
|
||||
assert( parent != 0 ) ;
|
||||
|
||||
// only handle uploaded files
|
||||
if ( !entry.Filename().empty() )
|
||||
{
|
||||
Resource *file = new Resource( entry ) ;
|
||||
parent->AddChild( file ) ;
|
||||
m_files.push_back( file ) ;
|
||||
|
||||
Trace( "%1% ID = %2%", file->Path(), file->ResourceID() ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log( "file \"%1%\" is a google document, ignored", entry.Title() ) ;
|
||||
}
|
||||
}
|
||||
*/
|
||||
void Drive::Update()
|
||||
{
|
||||
http::Agent http ;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Entry.hh"
|
||||
#include "CommonUri.hh"
|
||||
|
||||
#include "util/Crypt.hh"
|
||||
#include "util/Log.hh"
|
||||
#include "util/OS.hh"
|
||||
#include "xml/Node.hh"
|
||||
|
@ -30,10 +31,6 @@
|
|||
|
||||
namespace gr {
|
||||
|
||||
Entry::Entry( const Path& file )
|
||||
{
|
||||
}
|
||||
|
||||
Entry::Entry( const xml::Node& n )
|
||||
{
|
||||
Update( n ) ;
|
||||
|
@ -47,6 +44,16 @@ Entry::Entry( const std::string& title, const std::string& kind, const std::stri
|
|||
{
|
||||
}
|
||||
|
||||
/// construct an entry from a file or folder in local directory
|
||||
Entry::Entry( const fs::path& path ) :
|
||||
m_title ( path.filename().string() ),
|
||||
m_filename ( path.filename().string() ),
|
||||
m_kind ( fs::is_directory(path) ? "folder" : "file" ),
|
||||
m_server_md5 ( crypt::MD5( path ) ),
|
||||
m_server_modified( os::FileMTime( path ) )
|
||||
{
|
||||
}
|
||||
|
||||
void Entry::Update( const xml::Node& n )
|
||||
{
|
||||
m_title = n["title"] ;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/DateTime.hh"
|
||||
#include "util/FileSystem.hh"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
@ -32,8 +33,6 @@ namespace xml
|
|||
class Node ;
|
||||
}
|
||||
|
||||
class Path ;
|
||||
|
||||
/*! \brief corresponds to an "entry" in the resource feed
|
||||
|
||||
This class is decodes an entry in the resource feed. It will stored the properties like
|
||||
|
@ -42,7 +41,7 @@ class Path ;
|
|||
class Entry
|
||||
{
|
||||
public :
|
||||
explicit Entry( const Path& file ) ;
|
||||
explicit Entry( const fs::path& path ) ;
|
||||
explicit Entry( const xml::Node& n ) ;
|
||||
Entry( const std::string& title, const std::string& kind, const std::string& href ) ;
|
||||
|
||||
|
|
|
@ -39,13 +39,15 @@ namespace gr {
|
|||
|
||||
Resource::Resource( const xml::Node& entry ) :
|
||||
m_entry ( entry ),
|
||||
m_parent ( 0 )
|
||||
m_parent( 0 ),
|
||||
m_state ( new_remote )
|
||||
{
|
||||
}
|
||||
|
||||
Resource::Resource( const Entry& entry, Resource *parent ) :
|
||||
m_entry ( entry ),
|
||||
m_parent ( parent )
|
||||
m_parent( parent ),
|
||||
m_state ( new_remote )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -54,12 +56,15 @@ Resource::Resource(
|
|||
const std::string& kind,
|
||||
const std::string& href ) :
|
||||
m_entry ( name, kind, href ),
|
||||
m_parent( 0 )
|
||||
m_parent( 0 ),
|
||||
m_state ( new_local )
|
||||
{
|
||||
}
|
||||
|
||||
void Resource::Update( const Entry& e )
|
||||
void Resource::FromRemote( const Entry& e )
|
||||
{
|
||||
Trace( "%1% state is %2%", e.Title(), m_state ) ;
|
||||
m_state = sync ;
|
||||
m_entry = e ;
|
||||
}
|
||||
|
||||
|
@ -201,7 +206,7 @@ bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Head
|
|||
// upload link missing means that file is read only
|
||||
if ( m_entry.UploadLink().empty() )
|
||||
{
|
||||
Log( "Cannot upload %1%: file read-only.", m_entry.Title(), log::warning ) ;
|
||||
Log( "Cannot upload %1%: file read-only. %2%", m_entry.Title(), m_state, log::warning ) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
|
||||
namespace gr {
|
||||
|
||||
/*! \brief A resource can be a file or a folder in the google drive
|
||||
|
||||
The google drive contains a number of resources, which is represented by this class.
|
||||
It also contains linkage to other resources, such as parent and childrens.
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
public :
|
||||
|
@ -46,27 +51,41 @@ public :
|
|||
|
||||
// default copy ctor & op= are fine
|
||||
|
||||
bool IsFolder() const ;
|
||||
|
||||
std::string Name() const ;
|
||||
std::string SelfHref() const ;
|
||||
std::string ResourceID() const ;
|
||||
std::string ParentHref() const ;
|
||||
|
||||
const Resource* Parent() const ;
|
||||
Resource* Parent() ;
|
||||
std::string ParentHref() const ;
|
||||
void AddChild( Resource *child ) ;
|
||||
Resource* FindChild( const std::string& title ) ;
|
||||
|
||||
fs::path Path() const ;
|
||||
bool IsInRootTree() const ;
|
||||
|
||||
bool IsFolder() const ;
|
||||
|
||||
void AddChild( Resource *child ) ;
|
||||
|
||||
Resource* FindChild( const std::string& title ) ;
|
||||
void Update( const Entry& e ) ;
|
||||
|
||||
void FromRemote( const Entry& e ) ;
|
||||
void Update( http::Agent *http, const http::Headers& auth ) ;
|
||||
void Delete( http::Agent* http, const http::Headers& auth ) ;
|
||||
|
||||
private :
|
||||
/// State of the resource. indicating what to do with the resource
|
||||
enum State
|
||||
{
|
||||
/// The best state: the file is the same in google drive and in local.
|
||||
sync,
|
||||
|
||||
/// Resource created in local, but google drive does not have it.
|
||||
/// We should create the resource in google drive and upload new content
|
||||
new_local,
|
||||
|
||||
/// Resource created in google drive, but not exist in local.
|
||||
/// We should download the file.
|
||||
new_remote
|
||||
} ;
|
||||
|
||||
private :
|
||||
void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ;
|
||||
bool Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
|
||||
|
@ -77,6 +96,8 @@ private :
|
|||
// not owned
|
||||
Resource *m_parent ;
|
||||
std::vector<Resource*> m_child ;
|
||||
|
||||
State m_state ;
|
||||
} ;
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -99,6 +99,15 @@ const Resource* ResourceTree::FindByHref( const std::string& href ) const
|
|||
return i != map.end() ? *i : 0 ;
|
||||
}
|
||||
|
||||
/// Unlike other search functions, this one does not depend on the multi-index
|
||||
/// container. It traverses the tree instead.
|
||||
Resource* ResourceTree::FindByPath( const fs::path& path )
|
||||
{
|
||||
// not yet implemented
|
||||
assert( false ) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
/// Reinsert should be called when the ID/HREF were updated
|
||||
bool ResourceTree::ReInsert( Resource *coll )
|
||||
{
|
||||
|
@ -127,7 +136,9 @@ void ResourceTree::Erase( Resource *coll )
|
|||
|
||||
void ResourceTree::Update( Resource *coll, const Entry& e )
|
||||
{
|
||||
coll->Update( e ) ;
|
||||
assert( coll != 0 ) ;
|
||||
|
||||
coll->FromRemote( e ) ;
|
||||
ReInsert( coll ) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,9 +72,9 @@ public :
|
|||
Resource* FindByHref( const std::string& href ) ;
|
||||
const Resource* FindByHref( const std::string& href ) const ;
|
||||
|
||||
Resource* FindByPath( const fs::path& path ) ;
|
||||
|
||||
bool ReInsert( Resource *coll ) ;
|
||||
// void SetID( Collection *coll, const std::string& id ) ;
|
||||
// void SetHref( Collection *coll, const std::string& href ) ;
|
||||
|
||||
void Insert( Resource *coll ) ;
|
||||
void Erase( Resource *coll ) ;
|
||||
|
|
|
@ -59,12 +59,14 @@ void State::ChangeStamp( const std::string& cs )
|
|||
m_change_stamp = cs ;
|
||||
}
|
||||
|
||||
void State::Sync( const fs::path& p )
|
||||
/// Synchronize local directory. Build up the resource tree from files and folders
|
||||
/// of local directory.
|
||||
void State::FromLocal( const fs::path& p )
|
||||
{
|
||||
Sync( p, m_folders.Root() ) ;
|
||||
FromLocal( p, m_folders.Root() ) ;
|
||||
}
|
||||
|
||||
void State::Sync( const fs::path& p, gr::Resource* folder )
|
||||
void State::FromLocal( const fs::path& p, gr::Resource* folder )
|
||||
{
|
||||
assert( folder != 0 ) ;
|
||||
assert( folder->IsFolder() ) ;
|
||||
|
@ -77,11 +79,12 @@ void State::Sync( const fs::path& p, gr::Resource* folder )
|
|||
folder->AddChild( c ) ;
|
||||
m_folders.Insert( c ) ;
|
||||
|
||||
Sync( *i, c ) ;
|
||||
FromLocal( *i, c ) ;
|
||||
}
|
||||
else if ( i->path().filename().string()[0] != '.' )
|
||||
else if ( i->path().filename().string()[0] == '.' )
|
||||
Log( "file %1% is ignored by grive", i->path().filename().string(), log::info ) ;
|
||||
else
|
||||
{
|
||||
// Trace( "file: %1% %2%", i->path().filename().string(), folder->Path() ) ;
|
||||
Resource *c = new Resource( i->path().filename().string(), "file", "" ) ;
|
||||
folder->AddChild( c ) ;
|
||||
m_folders.Insert( c ) ;
|
||||
|
@ -102,7 +105,7 @@ void State::SetId( const fs::path& p, const std::string& id )
|
|||
{
|
||||
}
|
||||
|
||||
void State::OnEntry( const Entry& e )
|
||||
void State::FromRemote( const Entry& e )
|
||||
{
|
||||
if ( !Update( e ) )
|
||||
{
|
||||
|
@ -152,6 +155,8 @@ bool State::Update( const Entry& e )
|
|||
Resource *child = parent->FindChild( e.Title() ) ;
|
||||
if ( child != 0 )
|
||||
{
|
||||
assert( child == m_folders.FindByHref( e.SelfHref() ) ) ;
|
||||
|
||||
// since we are updating the ID and Href, we need to remove it and re-add it.
|
||||
m_folders.Update( child, e ) ;
|
||||
}
|
||||
|
@ -165,8 +170,6 @@ bool State::Update( const Entry& e )
|
|||
m_folders.Insert( child ) ;
|
||||
|
||||
fs::path child_path = child->Path() ;
|
||||
Trace( "added %1%", child_path ) ;
|
||||
|
||||
if ( child->IsFolder() && !fs::is_directory( child_path ) )
|
||||
{
|
||||
Log( "creating %1% directory", child_path, log::info ) ;
|
||||
|
|
|
@ -38,9 +38,8 @@ public :
|
|||
public :
|
||||
explicit State( const fs::path& filename ) ;
|
||||
|
||||
void Sync( const fs::path& p ) ;
|
||||
|
||||
void OnEntry( const Entry& e ) ;
|
||||
void FromLocal( const fs::path& p ) ;
|
||||
void FromRemote( const Entry& e ) ;
|
||||
void ResolveEntry() ;
|
||||
|
||||
void SetId( const fs::path& p, const std::string& id ) ;
|
||||
|
@ -58,7 +57,7 @@ public :
|
|||
iterator end() ;
|
||||
|
||||
private :
|
||||
void Sync( const fs::path& p, Resource *folder ) ;
|
||||
void FromLocal( const fs::path& p, Resource *folder ) ;
|
||||
bool Update( const Entry& e ) ;
|
||||
std::size_t TryResolveEntry() ;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ StateTest::StateTest( )
|
|||
void StateTest::TestSync( )
|
||||
{
|
||||
State s( ".grive_state" ) ;
|
||||
s.Sync( TEST_DATA ) ;
|
||||
s.FromLocal( TEST_DATA ) ;
|
||||
s.Write( "" ) ;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue