diff --git a/libgrive/src/drive/Drive.cc b/libgrive/src/drive/Drive.cc index 5e274bc..df6ec18 100644 --- a/libgrive/src/drive/Drive.cc +++ b/libgrive/src/drive/Drive.cc @@ -162,9 +162,6 @@ void Drive::ConstructDirTree( http::Agent *http ) } m_state.ResolveEntry() ; - - // print the state of the all folders - m_state.ShowFolders() ; } void Drive::Update() diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 3a8b0a1..b61a12c 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -39,6 +39,16 @@ namespace gr { +// hard coded XML file +const std::string xml_meta = + "\n" + "" + "" + "%2%" + "" ; + + /// default constructor creates the root folder Resource::Resource() : m_parent( 0 ), @@ -124,7 +134,12 @@ void Resource::FromRemote( const Entry& remote ) void Resource::FromLocal() { fs::path path = Path() ; - if ( !fs::exists( path ) ) + + // root folder is always rsync + if ( m_parent == 0 ) + m_state = sync ; + + else if ( !fs::exists( path ) ) { m_state = local_deleted ; Log( "%1% in state but not exist on disk: %2%", Name(), m_state ) ; @@ -233,17 +248,18 @@ Resource* Resource::FindChild( const std::string& name ) // try to change the state to "sync" void Resource::Sync( http::Agent *http, const http::Headers& auth ) { - // no need to update for folders -// if ( IsFolder() ) -// return ; - - assert( m_parent != 0 ) ; + // root folder is already synced + if ( IsRoot() ) + { + m_state = sync ; + return ; + } switch ( m_state ) { case local_new : - Log( "sync %1% %2% doesn't exist in server. upload \"%3%\"?", - m_entry.Title(), m_entry.Filename(), m_parent->m_entry.CreateLink(), log::verbose ) ; + Log( "sync %1% doesn't exist in server. upload \"%2%\"?", + Name(), m_parent->m_entry.CreateLink(), log::verbose ) ; if ( Create( http, auth ) ) m_state = sync ; @@ -296,6 +312,12 @@ void Resource::Download( http::Agent* http, const fs::path& file, const http::He bool Resource::EditContent( http::Agent* http, const http::Headers& auth ) { + assert( m_parent != 0 ) ; + + // sync parent first. make sure the parent folder exists in remote + if ( m_parent->m_state != sync ) + m_parent->Sync( http, auth ) ; + // upload link missing means that file is read only if ( m_entry.EditLink().empty() ) { @@ -309,23 +331,43 @@ bool Resource::EditContent( http::Agent* http, const http::Headers& auth ) bool Resource::Create( http::Agent* http, const http::Headers& auth ) { assert( m_parent != 0 ) ; - assert( !m_parent->m_entry.CreateLink().empty() ) ; - return Upload( http, m_parent->m_entry.CreateLink() + "?convert=false", auth, true ) ; + // sync parent first. make sure the parent folder exists in remote + if ( m_parent->m_state != sync ) + m_parent->Sync( http, auth ) ; + + if ( IsFolder() ) + { + std::string uri = feed_base ; + if ( !m_parent->IsRoot() ) + uri += ("/folder%3A" + m_parent->ResourceID() ) ; + + std::string meta = (boost::format(xml_meta) % "folder" % Name() ).str() ; + + http::Headers hdr( auth ) ; + hdr.push_back( "Content-Type: application/atom+xml" ) ; + + http::XmlResponse xml ; + http->Post( uri, meta, &xml, hdr ) ; + m_entry.Update( xml.Response() ) ; + + return true ; + } + else if ( !m_parent->m_entry.CreateLink().empty() ) + { + return Upload( http, m_parent->m_entry.CreateLink() + "?convert=false", auth, true ) ; + } + else + { + Log( "parent of %1% does not exist: cannot upload", Name() ) ; + return false ; + } } bool Resource::Upload( http::Agent* http, const std::string& link, const http::Headers& auth, bool post ) { Log( "Uploading %1%", m_entry.Title() ) ; - std::string meta = - "\n" - "" - "" - "" + m_entry.Filename() + "" - "" ; - StdioFile file( Path() ) ; // TODO: upload in chunks @@ -345,6 +387,8 @@ bool Resource::Upload( http::Agent* http, const std::string& link, const http::H hdr.push_back( "If-Match: " + m_entry.ETag() ) ; hdr.push_back( "Expect:" ) ; + std::string meta = (boost::format( xml_meta ) % m_entry.Kind() % Name()).str() ; + http::StringResponse str ; if ( post ) http->Post( link, meta, &str, hdr ) ; @@ -422,6 +466,11 @@ std::string Resource::StateStr() const return ss.str() ; } +bool Resource::IsRoot() const +{ + return m_parent == 0 ; +} + } // end of namespace namespace std diff --git a/libgrive/src/drive/Resource.hh b/libgrive/src/drive/Resource.hh index 6648f42..bad1a6b 100644 --- a/libgrive/src/drive/Resource.hh +++ b/libgrive/src/drive/Resource.hh @@ -69,6 +69,7 @@ public : fs::path Path() const ; bool IsInRootTree() const ; + bool IsRoot() const ; void FromRemote( const Entry& e ) ; void FromLocal() ; diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index b088323..0ba4e22 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -94,16 +94,6 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder ) } } -void State::ShowFolders() -{ - for ( ResourceTree::iterator i = m_res.begin() ; i != m_res.end() ; ++i ) - { - Resource *r = *i ; - if ( r->IsFolder() ) - Trace( "%1%: %2%", r->Name(), r->StateStr() ) ; - } -} - void State::FromRemote( const Entry& e ) { if ( !Update( e ) ) diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index 2ef625c..3f23f68 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -55,9 +55,6 @@ public : iterator begin() ; iterator end() ; - // for debug - void ShowFolders() ; - private : void FromLocal( const fs::path& p, Resource *folder ) ; bool Update( const Entry& e ) ;