added folder init code in state

pull/40/head
Matchman Green 2012-05-18 00:37:11 +08:00
parent 3a33db68b6
commit cf77a2d5c4
6 changed files with 195 additions and 26 deletions

View File

@ -51,6 +51,11 @@ Collection::Collection(
{
}
void Collection::Update( const Entry& e )
{
m_entry = e ;
}
std::string Collection::SelfHref() const
{
return m_entry.SelfHref() ;
@ -61,6 +66,11 @@ std::string Collection::Title() const
return m_entry.Title() ;
}
std::string Collection::ResourceID() const
{
return m_entry.ResourceID() ;
}
const Collection* Collection::Parent() const
{
return m_parent ;
@ -120,7 +130,7 @@ void Collection::ForEachFile(
fs::path Collection::Dir() const
{
assert( m_parent != this ) ;
return m_parent != 0 ? (m_parent->Dir() / m_entry.Title()) : fs::current_path() ;
return m_parent != 0 ? (m_parent->Dir() / m_entry.Title()) : "." ;
}
bool Collection::IsInRootTree() const
@ -128,6 +138,17 @@ bool Collection::IsInRootTree() const
return m_parent == 0 ? (SelfHref() == root_href) : m_parent->IsInRootTree() ;
}
Collection* Collection::FindChild( const std::string& title )
{
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
{
assert( (*i)->m_parent == this ) ;
if ( (*i)->Title() == title )
return *i ;
}
return 0 ;
}
} // end of namespace
namespace std

View File

@ -37,6 +37,7 @@ public :
explicit Collection( const xml::Node& entry ) ;
explicit Collection( const Entry& entry ) ;
Collection( const std::string& title, const std::string& href ) ;
Collection( const std::string& title, Collection *parent ) ;
// default copy ctor & op= are fine
@ -47,6 +48,7 @@ public :
std::string ParentHref() const ;
fs::path Dir() const ;
bool IsInRootTree() const ;
std::string ResourceID() const ;
void AddChild( Collection *child ) ;
void AddLeaf( File *file ) ;
@ -61,6 +63,9 @@ public :
struct Error : virtual Exception {} ;
Collection* FindChild( const std::string& title ) ;
void Update( const Entry& e ) ;
private :
Entry m_entry ;

View File

@ -69,9 +69,10 @@ Drive::Drive( OAuth2& auth ) :
Trace( "change stamp is %1%", change_stamp ) ;
m_state.ChangeStamp( change_stamp ) ;
m_state.Sync( fs::current_path() ) ;
m_state.Sync( "." ) ;
ConstructDirTree( &http ) ;
return ;
std::string uri = feed_base + "?showfolders=true&showroot=true" ;
/* if ( !change_stamp.empty() )
@ -85,15 +86,7 @@ Drive::Drive( OAuth2& auth ) :
m_resume_link = resp["link"].
Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ;
// change_stamp = resp["docs:largestChangestamp"]["@value"] ;
// std::ofstream osfile( ".grive_state" ) ;
// Json state ;
// state.Add( "change_stamp", Json( change_stamp ) ) ;
// osfile << state ;
// osfile.close() ;
bool has_next = false ;
do
{
@ -184,7 +177,10 @@ void Drive::ConstructDirTree( http::Agent *http )
if ( e.Kind() == "folder" )
{
if ( e.ParentHrefs().size() == 1 )
{
m_state.OnEntry( e ) ;
m_coll.push_back( Collection( e ) ) ;
}
else
Log( "folder \"%1%\" has multiple parents, ignored", e.Title(), log::warning ) ;
}
@ -198,11 +194,19 @@ void Drive::ConstructDirTree( http::Agent *http )
resp = xml.Response() ;
}
m_state.ResolveEntry() ;
// second, build up linkage between parent and child
std::sort( m_coll.begin(), m_coll.end(), SortCollectionByHref() ) ;
for ( FolderListIterator i = m_coll.begin() ; i != m_coll.end() ; ++i )
{
FolderListIterator pit = FindFolder( i->ParentHref() ) ;
Collection *scoll = m_state.FindFolderByHref( i->SelfHref() ) ;
if ( scoll )
Trace( "found folder %1% in state", scoll->Title() ) ;
else
Trace( "can't found folder %1% in state", i->Title() ) ;
if ( pit != m_coll.end() )
{
// it shouldn't happen, just in case
@ -217,7 +221,7 @@ void Drive::ConstructDirTree( http::Agent *http )
// lastly, iterating from the root, create the directories in the local file system
assert( Root()->Parent() == 0 ) ;
Root()->CreateSubDir( fs::current_path() ) ;
Root()->CreateSubDir( "." ) ;
}
void Drive::UpdateFile( Entry& entry, Collection& parent, http::Agent *http )
@ -229,9 +233,9 @@ void Drive::UpdateFile( Entry& entry, Collection& parent, http::Agent *http )
m_files.push_back( file ) ;
parent.AddLeaf( file ) ;
Trace( "%1% ID = %2%", file->Path(), file->ResourceID() ) ;
// Trace( "%1% ID = %2%", file->Path(), file->ResourceID() ) ;
m_state.SetId( file->Path(), file->ResourceID() ) ;
// m_state.SetId( file->Path(), file->ResourceID() ) ;
// file->Update( http, m_http_hdr ) ;
}

View File

@ -40,14 +40,15 @@ public :
explicit File( const Entry& e, const Collection *parent ) ;
void Update( http::Agent *http, const http::Headers& auth ) ;
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 ) ;
void Delete( http::Agent* http, const http::Headers& auth ) ;
fs::path Path() const ;
std::string ResourceID() const ;
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 ) ;
private :
Entry m_entry ;
const Collection *m_parent ;

View File

@ -19,6 +19,9 @@
#include "State.hh"
#include "Collection.hh"
#include "CommonUri.hh"
#include "util/Crypt.hh"
#include "util/Log.hh"
#include "protocol/Json.hh"
@ -29,6 +32,7 @@
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <fstream>
@ -79,30 +83,51 @@ namespace
using namespace boost::multi_index ;
struct ById {} ;
struct ByID {} ;
struct ByPath {} ;
typedef multi_index_container<
Resource,
indexed_by<
hashed_non_unique< tag<ById>, member<Resource, std::string, &Resource::id> >,
hashed_non_unique< tag<ByID>, member<Resource, std::string, &Resource::id> >,
hashed_unique< tag<ByPath>,member<Resource, fs::path, &Resource::path>, PathHash >
>
> ResourceSet ;
typedef ResourceSet::index<ById>::type IdIdx ;
typedef ResourceSet::index<ByID>::type IDIdx ;
typedef ResourceSet::index<ByPath>::type PathIdx ;
struct ByHref {} ;
struct ByIdentity {} ;
typedef multi_index_container<
Collection*,
indexed_by<
hashed_non_unique<tag<ByHref>, const_mem_fun<Collection, std::string, &Collection::SelfHref> >,
hashed_non_unique<tag<ByID>, const_mem_fun<Collection, std::string, &Collection::ResourceID> >,
hashed_unique<tag<ByIdentity>, identity<Collection*> >
>
> Folders ;
typedef Folders::index<ByHref>::type FoldersByHref ;
typedef Folders::index<ByIdentity>::type FolderSet ;
}
struct State::Impl
{
ResourceSet rs ;
Folders folders ;
std::string change_stamp ;
std::vector<Entry> unresolved ;
} ;
State::State( const fs::path& filename ) :
m_impl( new Impl )
{
Collection *root = new Collection( ".", root_href ) ;
m_impl->folders.insert( root ) ;
if ( fs::exists( filename ) )
Read( filename );
}
@ -131,12 +156,26 @@ void State::ChangeStamp( const std::string& cs )
void State::Sync( const fs::path& p )
{
Trace( "synchronizing = %1%", p ) ;
FoldersByHref& idx = m_impl->folders.get<ByHref>() ;
FoldersByHref::iterator it = idx.find( root_href ) ;
assert( it != idx.end() ) ;
Sync( p, *it ) ;
}
void State::Sync( const fs::path& p, Collection *folder )
{
// Trace( "synchronizing = %1%", p ) ;
for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i )
{
Trace( "file found = %1%", i->path() ) ;
// Trace( "file found = %2% (%1%)", i->path(), i->path().filename() ) ;
if ( fs::is_directory( i->path() ) )
Sync( *i ) ;
{
Collection *c = new Collection( i->path().filename().string(), "" ) ;
folder->AddChild( c ) ;
Sync( *i, c ) ;
}
else if ( i->path().filename().string()[0] != '.' )
m_impl->rs.insert( Resource( i->path() ) ) ;
}
@ -147,7 +186,7 @@ void State::Write( const fs::path& filename ) const
Json result ;
result.Add( "change_stamp", Json( m_impl->change_stamp ) ) ;
IdIdx& idx = m_impl->rs.get<ById>() ;
IDIdx& idx = m_impl->rs.get<ByID>() ;
std::vector<Json> res ;
std::transform( idx.begin(), idx.end(),
@ -156,7 +195,7 @@ void State::Write( const fs::path& filename ) const
result.Add( "resources", Json(res) ) ;
Trace( "%1%", result ) ;
// Trace( "%1%", result ) ;
std::ofstream fs( filename.string().c_str() ) ;
fs << result ;
@ -178,5 +217,91 @@ void State::SetId( const fs::path& p, const std::string& id )
}
}
void State::OnEntry( const Entry& e )
{
if ( !Update( e ) )
{
Trace( "can't find parent of %1%", e.Title() ) ;
m_impl->unresolved.push_back( e ) ;
}
}
void State::ResolveEntry()
{
Trace( "trying to resolve %1% entries", m_impl->unresolved.size() ) ;
while ( !m_impl->unresolved.empty() )
{
if ( TryResolveEntry() == 0 )
{
Trace( "cannot make progress" ) ;
break ;
}
}
Trace( "entries left = %1%", m_impl->unresolved.size() ) ;
}
std::size_t State::TryResolveEntry()
{
assert( !m_impl->unresolved.empty() ) ;
std::size_t count = 0 ;
std::vector<Entry>& en = m_impl->unresolved ;
for ( std::vector<Entry>::iterator i = en.begin() ; i != en.end() ; )
{
if ( Update( *i ) )
{
i = en.erase( i ) ;
count++ ;
}
else
++i ;
}
return count ;
}
bool State::Update( const Entry& e )
{
FoldersByHref& folders = m_impl->folders.get<ByHref>() ;
FoldersByHref::iterator i = folders.find( e.ParentHref() ) ;
if ( i != folders.end() )
{
Trace( "found parent of folder %1%: %2%", e.Title(), (*i)->Title() ) ;
// see if the entry already exist in local
Collection *child = (*i)->FindChild( e.Title() ) ;
if ( child != 0 )
{
// since we are updating the ID and Href, we need to remove it and re-add it.
FolderSet& fs = m_impl->folders.get<ByIdentity>() ;
FolderSet::iterator c = fs.find( child ) ;
if ( c != fs.end() )
fs.erase( c ) ;
child->Update( e ) ;
folders.insert( child ) ;
}
// folder entry exist in google drive, but not local.
else
{
child = new Collection( e ) ;
(*i)->AddChild( child ) ;
folders.insert( child ) ;
}
return true ;
}
else
return false ;
}
Collection* State::FindFolderByHref( const std::string& href )
{
FoldersByHref& folders = m_impl->folders.get<ByHref>() ;
FoldersByHref::iterator i = folders.find( href ) ;
return i != folders.end() ? *i : 0 ;
}
} // end of namespace

View File

@ -26,6 +26,8 @@
namespace gr {
class Json ;
class Collection ;
class Entry ;
class State
{
@ -34,6 +36,9 @@ public :
void Sync( const fs::path& p ) ;
void OnEntry( const Entry& e ) ;
void ResolveEntry() ;
void SetId( const fs::path& p, const std::string& id ) ;
void Read( const fs::path& filename ) ;
@ -42,6 +47,14 @@ public :
std::string ChangeStamp() const ;
void ChangeStamp( const std::string& cs ) ;
Collection* FindFolderByHref( const std::string& href ) ;
Collection* FindFolderByID( const std::string& id ) ;
private :
void Sync( const fs::path& p, Collection *folder ) ;
bool Update( const Entry& e ) ;
std::size_t TryResolveEntry() ;
private :
struct Impl ;
std::auto_ptr<Impl> m_impl ;