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