refactored the creation of resources

pull/40/head
Matchman Green 2012-05-31 23:37:47 +08:00
parent 7830136518
commit 6db0b4a7aa
12 changed files with 108 additions and 105 deletions

View File

@ -48,8 +48,10 @@ int main( int argc, char **argv )
DefaultLog nofile_log ;
LogBase::Inst( &nofile_log ) ;
Json options ;
int c ;
while ((c = getopt(argc, argv, "al:vV")) != -1)
while ((c = getopt(argc, argv, "al:vVf")) != -1)
{
switch ( c )
{
@ -72,7 +74,6 @@ int main( int argc, char **argv )
// save to config
config.Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ;
assert( config.Get()["refresh_token"].Str() == token.RefreshToken() ) ;
config.Save() ;
break ;
@ -97,6 +98,12 @@ int main( int argc, char **argv )
LogBase::Inst()->Enable( log::verbose ) ;
break ;
}
case 'f' :
{
options.Add( "force", Json(true) ) ;
break ;
}
}
}
@ -120,7 +127,7 @@ int main( int argc, char **argv )
try
{
OAuth2 token( refresh_token, client_id, client_secret ) ;
Drive drive( token ) ;
Drive drive( token, options ) ;
drive.Update() ;
drive.SaveState() ;

View File

@ -52,9 +52,9 @@ namespace
const std::string state_file = ".grive_state" ;
}
Drive::Drive( OAuth2& auth ) :
Drive::Drive( OAuth2& auth, const Json& options ) :
m_auth( auth ),
m_state( state_file )
m_state( state_file, options )
{
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
m_http_hdr.push_back( "GData-Version: 3.0" ) ;

View File

@ -34,11 +34,12 @@ namespace http
}
class OAuth2 ;
class Json ;
class Drive
{
public :
Drive( OAuth2& auth ) ;
Drive( OAuth2& auth, const Json& options ) ;
void Update() ;
void Sync() ;

View File

@ -48,37 +48,20 @@ Entry::Entry( const xml::Node& n )
}
/// construct an entry from a file or folder in local directory
Entry::Entry( const fs::path& path, const std::string& kind ) :
m_title ( path.filename().string() ),
m_filename ( path.filename().string() ),
m_kind
(
fs::exists(path)
? (fs::is_directory(path) ? "folder" : "file" )
: kind
),
m_md5 ( fs::is_directory(path) ? "" : crypt::MD5( path ) ),
m_mtime ( fs::exists(path) ? os::FileMTime( path ) : DateTime() )
Entry::Entry( const std::string& name, const std::string& kind ) :
m_title ( name ),
m_filename ( name ),
m_kind ( kind )
{
}
Entry::Entry(
const std::string& name,
const std::string& resource_id,
const std::string& href,
const std::string& md5,
const std::string& kind,
const DateTime& mtime,
const std::string& parent_href ) :
m_title ( name ),
m_filename ( name ),
m_kind ( kind ),
m_md5 ( md5 ),
m_resource_id ( resource_id ),
m_parent_hrefs ( 1, parent_href ),
m_self_href ( href ),
m_mtime ( mtime )
void Entry::FromLocal( const fs::path& path )
{
m_title = path.filename().string() ;
m_filename = path.filename().string() ;
m_kind = fs::is_directory(path) ? "folder" : "file" ;
m_md5 = fs::is_directory(path) ? "" : crypt::MD5( path ) ;
m_mtime = fs::exists(path) ? os::FileMTime( path ) : DateTime() ;
}
void Entry::Update( const xml::Node& n )

View File

@ -43,18 +43,11 @@ class Entry
{
public :
Entry( ) ;
explicit Entry( const fs::path& path, const std::string& kind = "" ) ;
Entry( const std::string& name, const std::string& kind ) ;
explicit Entry( const xml::Node& n ) ;
explicit Entry(
const std::string& name,
const std::string& resource_id,
const std::string& href,
const std::string& md5,
const std::string& kind,
const DateTime& mtime,
const std::string& parent_href ) ;
void AssignID( const Entry& entry ) ;
void FromLocal( const fs::path& path ) ;
std::string Title() const ;
std::string Filename() const ;

View File

@ -57,24 +57,10 @@ Resource::Resource() :
{
}
Resource::Resource( const xml::Node& entry ) :
m_entry ( entry ),
Resource::Resource( const std::string& name, const std::string& kind ) :
m_entry ( name, kind ),
m_parent( 0 ),
m_state ( remote_new )
{
}
Resource::Resource( const Entry& entry, Resource *parent ) :
m_entry ( entry ),
m_parent( parent ),
m_state ( remote_new )
{
}
Resource::Resource( const fs::path& path, const std::string& kind ) :
m_entry ( path, kind ),
m_parent( 0 ),
m_state ( local_new )
m_state ( unknown )
{
}
@ -172,6 +158,7 @@ void Resource::FromRemote( const Entry& remote, const DateTime& last_sync )
}
m_entry.AssignID( remote ) ;
assert( m_state != unknown ) ;
}
/// Update the resource with the attributes of local file or directory. This
@ -181,11 +168,8 @@ void Resource::FromLocal( const DateTime& last_sync )
fs::path path = Path() ;
assert( fs::exists( path ) ) ;
// root folder is always rsync
if ( m_parent == 0 )
m_state = sync ;
else
// root folder is always in sync
if ( !IsRoot() )
{
// if the file is not created after last sync, assume file is
// remote_deleted first, it will be updated to sync/remote_changed
@ -193,8 +177,12 @@ void Resource::FromLocal( const DateTime& last_sync )
DateTime mtime = os::FileMTime( path ) ;
m_state = ( mtime > last_sync ? local_new : remote_deleted ) ;
m_entry.FromLocal( path ) ;
Trace( "%1% found on disk: %2%", Name(), m_state ) ;
}
assert( m_state != unknown ) ;
}
std::string Resource::SelfHref() const
@ -280,10 +268,12 @@ Resource* Resource::FindChild( const std::string& name )
// try to change the state to "sync"
void Resource::Sync( http::Agent *http, const http::Headers& auth )
{
assert( m_state != unknown ) ;
// root folder is already synced
if ( IsRoot() )
{
m_state = sync ;
assert( m_state == sync ) ;
return ;
}

View File

@ -47,13 +47,10 @@ public :
public :
Resource() ;
explicit Resource( const xml::Node& entry ) ;
explicit Resource( const Entry& entry, Resource *parent = 0 ) ;
explicit Resource( const fs::path& path, const std::string& kind = "" ) ;
// explicit Resource( const Json& json, Resource *parent = 0 ) ;
void Swap( Resource& coll ) ;
Resource( const std::string& name, const std::string& kind ) ;
// default copy ctor & op= are fine
void Swap( Resource& coll ) ;
bool IsFolder() const ;
@ -112,7 +109,11 @@ private :
remote_changed,
/// Resource delete in remote, need to delete in local
remote_deleted
remote_deleted,
/// invalid value
unknown
} ;
friend std::ostream& operator<<( std::ostream& os, State s ) ;

View File

@ -38,9 +38,14 @@
namespace gr {
State::State( const fs::path& filename )
State::State( const fs::path& filename, const Json& options )
{
Read( filename ) ;
// the "-f" option will make grive always thinks remote is newer
Json force ;
if ( options.Get("force", force) && force.Bool() )
m_last_sync = DateTime() ;
}
/// Synchronize local directory. Build up the resource tree from files and folders
@ -72,7 +77,7 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
Resource *c = folder->FindChild( fname ) ;
if ( c == 0 )
{
c = new Resource( i->path() ) ;
c = new Resource( fname, fs::is_directory(i->path()) ? "folder" : "file" ) ;
folder->AddChild( c ) ;
m_res.Insert( c ) ;
}
@ -149,7 +154,7 @@ bool State::Update( const Entry& e )
else if ( e.Kind() == "folder" || !e.Filename().empty() )
{
// first create a dummy resource and update it later
child = new Resource( parent->Path() / e.Filename(), e.Kind() ) ;
child = new Resource( name, e.Kind() ) ;
parent->AddChild( child ) ;
m_res.Insert( child ) ;

View File

@ -39,7 +39,7 @@ public :
typedef ResourceTree::iterator iterator ;
public :
explicit State( const fs::path& filename ) ;
explicit State( const fs::path& filename, const Json& options ) ;
void FromLocal( const fs::path& p ) ;
void FromRemote( const Entry& e ) ;

View File

@ -93,34 +93,12 @@ Json::Json( const std::vector<Json>& arr ) :
Add( *i ) ;
}
Json Json::Parse( const std::string& str )
template <>
Json::Json( const bool& b ) :
m_json( ::json_object_new_boolean( b ) )
{
struct json_object *json = ::json_tokener_parse( str.c_str() ) ;
if ( json == 0 )
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "json parse error" ) ) ;
return Json( json, NotOwned() ) ;
}
Json Json::ParseFile( const std::string& filename )
{
StdioFile file( filename ) ;
struct json_tokener *tok = ::json_tokener_new() ;
struct json_object *json = 0 ;
char buf[1024] ;
std::size_t count = 0 ;
while ( (count = file.Read( buf, sizeof(buf) ) ) > 0 )
json = ::json_tokener_parse_ex( tok, buf, count ) ;
if ( json == 0 )
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ) ;
::json_tokener_free( tok ) ;
return Json( json, NotOwned() ) ;
if ( m_json == 0 )
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json bool" ) ) ;
}
Json::Json( struct json_object *json, NotOwned ) :
@ -202,6 +180,20 @@ bool Json::Has( const std::string& key ) const
return ::json_object_object_get( m_json, key.c_str() ) != 0 ;
}
bool Json::Get( const std::string& key, Json& json ) const
{
assert( m_json != 0 ) ;
struct json_object *j = ::json_object_object_get( m_json, key.c_str() ) ;
if ( j != 0 )
{
Json tmp( j, NotOwned() ) ;
json.Swap( tmp ) ;
return true ;
}
else
return false ;
}
void Json::Add( const std::string& key, const Json& json )
{
assert( m_json != 0 ) ;
@ -341,4 +333,34 @@ bool Json::FindInArray( const std::string& key, const std::string& value, Json&
}
}
Json Json::Parse( const std::string& str )
{
struct json_object *json = ::json_tokener_parse( str.c_str() ) ;
if ( json == 0 )
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "json parse error" ) ) ;
return Json( json, NotOwned() ) ;
}
Json Json::ParseFile( const std::string& filename )
{
StdioFile file( filename ) ;
struct json_tokener *tok = ::json_tokener_new() ;
struct json_object *json = 0 ;
char buf[1024] ;
std::size_t count = 0 ;
while ( (count = file.Read( buf, sizeof(buf) ) ) > 0 )
json = ::json_tokener_parse_ex( tok, buf, count ) ;
if ( json == 0 )
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ) ;
::json_tokener_free( tok ) ;
return Json( json, NotOwned() ) ;
}
}

View File

@ -69,6 +69,7 @@ public :
bool Is() const ;
bool Has( const std::string& key ) const ;
bool Get( const std::string& key, Json& json ) const ;
void Add( const std::string& key, const Json& json ) ;
void Add( const Json& json ) ;
Json FindInArray( const std::string& key, const std::string& value ) const ;

View File

@ -22,6 +22,7 @@
#include "Assert.hh"
#include "drive/State.hh"
#include "protocol/Json.hh"
#include "util/Log.hh"
#include <iostream>
@ -36,7 +37,7 @@ StateTest::StateTest( )
void StateTest::TestSync( )
{
State s( TEST_DATA "/test_dir1.state" ) ;
State s( TEST_DATA "/test_dir1.state", Json() ) ;
Resource *r = s.Find( "./folder1/abc.txt" ) ;
CPPUNIT_ASSERT( r != 0 ) ;
GRUT_ASSERT_EQUAL( r->Name(), "abc.txt" ) ;
@ -45,7 +46,6 @@ void StateTest::TestSync( )
// load directory
s.FromLocal( TEST_DATA "/test_dir1" ) ;
}
} // end of namespace grut