Merge branch 'working'

pull/40/head
Matchman Green 2012-05-10 00:31:02 +08:00
commit 1ae7a18f63
11 changed files with 112 additions and 63 deletions

View File

@ -31,8 +31,7 @@
namespace gr {
Collection::Collection( const Json& entry ) :
m_title ( entry["title"]["$t"].As<std::string>() ),
m_href ( entry["link"].FindInArray( "rel", "self" )["href"].As<std::string>() ),
m_entry ( entry ),
m_parent ( 0 )
{
}
@ -40,8 +39,7 @@ Collection::Collection( const Json& entry ) :
Collection::Collection(
const std::string& title,
const std::string& href ) :
m_title ( title ),
m_href ( href ),
m_entry ( title, href ),
m_parent( 0 )
{
}
@ -53,14 +51,14 @@ std::string Collection::ParentHref( const Json& entry )
node["href"].As<std::string>() : std::string() ;
}
const std::string& Collection::Href() const
std::string Collection::Href() const
{
return m_href ;
return m_entry.SelfHref() ;
}
const std::string& Collection::Title() const
std::string Collection::Title() const
{
return m_title ;
return m_entry.Title() ;
}
const Collection* Collection::Parent() const
@ -73,6 +71,11 @@ Collection* Collection::Parent()
return m_parent ;
}
std::string Collection::ParentHref() const
{
return m_entry.ParentHref() ;
}
void Collection::AddChild( Collection *child )
{
assert( child != 0 ) ;
@ -98,8 +101,7 @@ bool Collection::IsCollection( const Json& entry )
void Collection::Swap( Collection& coll )
{
m_title.swap( coll.m_title ) ;
m_href.swap( coll.m_href ) ;
m_entry.Swap( coll.m_entry ) ;
std::swap( m_parent, coll.m_parent ) ;
m_child.swap( coll.m_child ) ;
m_leaves.swap( coll.m_leaves ) ;
@ -107,7 +109,7 @@ void Collection::Swap( Collection& coll )
void Collection::CreateSubDir( const Path& prefix )
{
Path dir = prefix / m_title ;
Path dir = prefix / m_entry.Title() ;
os::MakeDir( dir ) ;
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
@ -126,7 +128,7 @@ void Collection::ForEachFile(
Path Collection::Dir() const
{
assert( m_parent != this ) ;
return m_parent != 0 ? (m_parent->Dir() / m_title) : Path() ;
return m_parent != 0 ? (m_parent->Dir() / m_entry.Title()) : Path() ;
}
} // end of namespace

View File

@ -19,6 +19,7 @@
#pragma once
#include "Entry.hh"
#include "util/Function.hh"
#include <string>
@ -40,10 +41,11 @@ public :
static bool IsCollection( const Json& entry ) ;
static std::string ParentHref( const Json& entry ) ;
const std::string& Title() const ;
const std::string& Href() const ;
std::string Title() const ;
std::string Href() const ;
const Collection* Parent() const ;
Collection* Parent() ;
std::string ParentHref() const ;
Path Dir() const ;
void AddChild( Collection *child ) ;
@ -58,8 +60,7 @@ public :
const std::string& prefix = "." ) ;
private :
std::string m_title ;
std::string m_href ;
Entry m_entry ;
// not owned
Collection *m_parent ;

View File

@ -22,7 +22,7 @@
#include "CommonUri.hh"
#include "Entry.hh"
#include "http/HTTP.hh"
#include "http/Agent.hh"
#include "http/XmlResponse.hh"
#include "protocol/Json.hh"
#include "protocol/JsonResponse.hh"
@ -71,7 +71,7 @@ Drive::Drive( OAuth2& auth ) :
{
if ( !Collection::IsCollection( *i ) )
{
UpdateFile( *i ) ;
UpdateFile( *i, &http ) ;
}
}
@ -125,7 +125,6 @@ abc << xml.Response()["feed"] ;
assert( m_coll.empty() ) ;
std::map<std::string, std::string> parent_href ;
while ( true )
{
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
@ -134,15 +133,8 @@ abc << xml.Response()["feed"] ;
for ( Json::Array::const_iterator i = entries.begin() ; i != entries.end() ; ++i )
{
if ( Collection::IsCollection( *i ) )
{
m_coll.push_back( Collection( *i ) ) ;
parent_href.insert(
std::make_pair(
m_coll.back().Href(),
Collection::ParentHref( *i ) ) ) ;
}
}
assert( m_coll.size() == parent_href.size() ) ;
Json next ;
if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
@ -156,14 +148,11 @@ abc << xml.Response()["feed"] ;
std::sort( m_coll.begin(), m_coll.end(), SortCollectionByHref() ) ;
for ( FolderListIterator i = m_coll.begin() ; i != m_coll.end() ; ++i )
{
assert( parent_href.find( i->Href() ) != parent_href.end() ) ;
std::string parent = parent_href[i->Href()] ;
if ( parent.empty() )
if ( i->ParentHref().empty() )
m_root.AddChild( &*i ) ;
else
{
FolderListIterator pit = FindFolder( parent ) ;
FolderListIterator pit = FindFolder( i->ParentHref() ) ;
if ( pit != m_coll.end() )
{
// it shouldn't happen, just in case
@ -182,7 +171,7 @@ abc << xml.Response()["feed"] ;
m_root.CreateSubDir( Path() ) ;
}
void Drive::UpdateFile( const Json& entry )
void Drive::UpdateFile( const Json& entry, http::Agent *http )
{
// only handle uploaded files
if ( entry.Has( "docs$suggestedFilename" ) )
@ -193,18 +182,18 @@ void Drive::UpdateFile( const Json& entry )
Path path = Path() / file.Filename() ;
// determine which folder the file belongs to
if ( !file.Parent().empty() )
if ( !file.ParentHref().empty() )
{
FolderListIterator pit = FindFolder( file.Parent() ) ;
FolderListIterator pit = FindFolder( file.ParentHref() ) ;
if ( pit != m_coll.end() )
path = pit->Dir() / file.Filename() ;
}
// compare checksum first if file exists
std::ifstream ifile( path.Str().c_str(), std::ios::binary | std::ios::in ) ;
if ( ifile && file.ServerMD5() == crypt::MD5(ifile.rdbuf()) )
changed = false ;
// if the checksum is different, file is changed and we need to update
if ( changed )
{
@ -215,7 +204,7 @@ void Drive::UpdateFile( const Json& entry )
if ( !ifile || remote > local )
{
std::cout << "downloading " << path << std::endl ;
file.Download( path, m_http_hdr ) ;
file.Download( http, path, m_http_hdr ) ;
}
else
{
@ -223,7 +212,7 @@ std::cout << "local " << path << " is newer" << std::endl ;
// re-reading the file
ifile.seekg(0) ;
if ( !file.Upload( ifile.rdbuf(), m_http_hdr ) )
if ( !file.Upload( http, ifile.rdbuf(), m_http_hdr ) )
std::cout << path << " is read only" << std::endl ;
}
}

View File

@ -45,7 +45,7 @@ public :
~Drive( ) ;
private :
void UpdateFile( const Json& entry ) ;
void UpdateFile( const Json& entry, http::Agent *http ) ;
void ConstructDirTree( http::Agent *http ) ;

View File

@ -46,6 +46,16 @@ Entry::Entry( const Json& entry )
Update( entry ) ;
}
Entry::Entry( const xml::Node& n )
{
}
Entry::Entry( const std::string& title, const std::string& href ) :
m_title( title ),
m_self_href( href )
{
}
void Entry::Update( const Json& entry )
{
m_title = entry["title"]["$t"].Str() ;
@ -53,8 +63,9 @@ void Entry::Update( const Json& entry )
m_filename = entry.Has("docs$suggestedFilename") ?
entry["docs$suggestedFilename"]["$t"].Str() : "" ;
m_href = entry["content"]["src"].Str() ;
m_parent = Parent( entry ) ;
m_content_src = entry["content"]["src"].Str() ;
m_self_href = entry["link"].FindInArray( "rel", "self" )["href"].Str() ;
m_parent_href = Parent( entry ) ;
m_server_modified = DateTime( entry["updated"]["$t"].Str() ) ;
m_etag = entry["gd$etag"].Str() ;
@ -112,26 +123,25 @@ DateTime Entry::ServerModified() const
return m_server_modified ;
}
std::string Entry::Href() const
std::string Entry::SelfHref() const
{
return m_href ;
return m_self_href ;
}
std::string Entry::Parent() const
std::string Entry::ParentHref() const
{
return m_parent ;
return m_parent_href ;
}
void Entry::Download( const Path& file, const http::Headers& auth ) const
void Entry::Download( gr::http::Agent* http, const Path& file, const http::Headers& auth ) const
{
gr::Download dl( file.Str(), Download::NoChecksum() ) ;
http::Agent http ;
long r = http.Get( m_href, &dl, auth ) ;
long r = http->Get( m_content_src, &dl, auth ) ;
if ( r <= 400 )
os::SetFileTime( file, m_server_modified ) ;
}
bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
bool Entry::Upload( gr::http::Agent* http, std::streambuf *file, const http::Headers& auth )
{
// upload link missing means that file is read only
if ( m_upload_link.empty() )
@ -160,10 +170,9 @@ bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
hdr.push_back( "Expect:" ) ;
http::StringResponse str ;
http::Agent http ;
http.Put( m_upload_link, meta, &str, hdr ) ;
http->Put( m_upload_link, meta, &str, hdr ) ;
std::string uplink = http.RedirLocation() ;
std::string uplink = http->RedirLocation() ;
// parse the header and find "Location"
http::Headers uphdr ;
@ -171,7 +180,7 @@ bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
uphdr.push_back( "Accept:" ) ;
http::XmlResponse xml ;
http.Put( uplink, data, &xml, uphdr ) ;
http->Put( uplink, data, &xml, uphdr ) ;
std::cout << xml.Response() << std::endl ;
@ -199,4 +208,21 @@ std::cout << root_url + "/" + m_resource_id + "?delete=true" << std::endl ;
http->Custom( "DELETE", root_url + "/" + m_resource_id + "?delete=true", &str, hdr ) ;
}
void Entry::Swap( Entry& e )
{
m_title.swap( e.m_title ) ;
m_filename.swap( e.m_filename ) ;
m_kind.swap( e.m_kind ) ;
m_server_md5.swap( e.m_server_md5 ) ;
m_etag.swap( e.m_etag ) ;
m_resource_id.swap( e.m_resource_id ) ;
m_self_href.swap( e.m_self_href ) ;
m_parent_href.swap( e.m_parent_href ) ;
m_content_src.swap( e.m_content_src ) ;
m_upload_link.swap( e.m_upload_link ) ;
m_server_modified.Swap( e.m_server_modified ) ;
}
} // end of namespace

View File

@ -21,13 +21,18 @@
#include <string>
#include "http/HTTP.hh"
#include "http/Agent.hh"
#include "util/DateTime.hh"
#include <iosfwd>
namespace gr {
namespace xml
{
class Node ;
}
class Json ;
class OAuth2 ;
class Path ;
@ -37,6 +42,8 @@ class Entry
public :
explicit Entry( const Path& file ) ;
explicit Entry( const Json& entry ) ;
explicit Entry( const xml::Node& n ) ;
Entry( const std::string& title, const std::string& href ) ;
std::string Title() const ;
std::string Filename() const ;
@ -47,13 +54,15 @@ public :
std::string ResourceID() const ;
std::string ETag() const ;
std::string Href() const ;
std::string Parent() const ;
std::string SelfHref() const ;
std::string ParentHref() const ;
void Download( const Path& file, const http::Headers& auth ) const ;
bool Upload( std::streambuf *file, const http::Headers& auth ) ;
void Download( gr::http::Agent* http, const Path& file, const http::Headers& auth ) const ;
bool Upload( gr::http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
void Delete( gr::http::Agent* http, const gr::http::Headers& auth ) ;
void Swap( Entry& e ) ;
private :
void Update( const Json& entry ) ;
static std::string Parent( const Json& entry ) ;
@ -66,8 +75,9 @@ private :
std::string m_etag ;
std::string m_resource_id ;
std::string m_href ;
std::string m_parent ;
std::string m_self_href ;
std::string m_content_src ;
std::string m_parent_href ;
std::string m_upload_link ;
DateTime m_server_modified ;

View File

@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "HTTP.hh"
#include "Agent.hh"
#include "Download.hh"
#include "Exception.hh"
@ -71,6 +71,8 @@ struct Agent::Impl
CURL *curl ;
std::string location ;
char error[CURL_ERROR_SIZE] ;
std::string log_prefix ;
} ;
Agent::Agent() :
@ -90,6 +92,15 @@ Agent::~Agent()
::curl_easy_cleanup( m_pimpl->curl );
}
void Agent::SetLogFile( const std::string& prefix )
{
m_pimpl->log_prefix = prefix ;
}
std::string Agent::LogFilename() const
{
}
std::size_t Agent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Agent *pthis )
{
char *str = reinterpret_cast<char*>(ptr) ;

View File

@ -41,7 +41,8 @@ public :
Agent() ;
~Agent() ;
// TODO: implement put from file, or some callback interface to pull data
void SetLogFile( const std::string& prefix ) ;
long Put(
const std::string& url,
const std::string& data,
@ -75,6 +76,7 @@ private :
static std::size_t Receive( void* ptr, size_t size, size_t nmemb, Receivable *recv ) ;
void SetHeader( const http::Headers& hdr ) ;
std::string LogFilename() const ;
private :
struct Impl ;

View File

@ -22,7 +22,7 @@
#include "JsonResponse.hh"
#include "Json.hh"
#include "http/HTTP.hh"
#include "http/Agent.hh"
// for debugging
#include <iostream>

View File

@ -129,4 +129,10 @@ bool DateTime::operator<=( const DateTime& dt ) const
return !( *this > dt ) ;
}
void DateTime::Swap( DateTime& dt )
{
std::swap( m_sec, dt.m_sec ) ;
std::swap( m_nsec, dt.m_nsec ) ;
}
} // end of namespace

View File

@ -47,6 +47,8 @@ public :
bool operator<( const DateTime& dt ) const ;
bool operator<=( const DateTime& dt ) const ;
void Swap( DateTime& dt ) ;
private :
std::time_t m_sec ;
unsigned long m_nsec ;