clean up sync code

pull/40/head
Matchman Green 2012-05-20 01:44:46 +08:00
parent 7f2fa95d9a
commit b1589bb181
10 changed files with 89 additions and 64 deletions

View File

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

View File

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

View File

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

View File

@ -38,14 +38,16 @@
namespace gr {
Resource::Resource( const xml::Node& entry ) :
m_entry ( entry ),
m_parent ( 0 )
m_entry ( entry ),
m_parent( 0 ),
m_state ( new_remote )
{
}
Resource::Resource( const Entry& entry, Resource *parent ) :
m_entry ( entry ),
m_parent ( parent )
m_entry ( entry ),
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 ;
}

View File

@ -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 :
@ -45,28 +50,42 @@ public :
void Swap( Resource& coll ) ;
// 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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,7 @@ StateTest::StateTest( )
void StateTest::TestSync( )
{
State s( ".grive_state" ) ;
s.Sync( TEST_DATA ) ;
s.FromLocal( TEST_DATA ) ;
s.Write( "" ) ;
}