mirror of https://github.com/vitalif/grive2
load and save from .grive_state and build the resource tree
parent
3dd3f544fb
commit
dfbe859531
|
@ -117,6 +117,7 @@ int main( int argc, char **argv )
|
||||||
Drive drive( token ) ;
|
Drive drive( token ) ;
|
||||||
|
|
||||||
drive.Update() ;
|
drive.Update() ;
|
||||||
|
// drive.SaveState() ;
|
||||||
|
|
||||||
config.Save() ;
|
config.Save() ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ Drive::Drive( OAuth2& auth ) :
|
||||||
if ( file.Kind() != "folder" )
|
if ( file.Kind() != "folder" )
|
||||||
{
|
{
|
||||||
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
|
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
|
||||||
|
Trace( "finding parent of %1%: %2%", file.Title(), (void*)p ) ;
|
||||||
if ( file.Filename().empty() )
|
if ( file.Filename().empty() )
|
||||||
Log( "file \"%1%\" is a google document, ignored", file.Title() ) ;
|
Log( "file \"%1%\" is a google document, ignored", file.Title() ) ;
|
||||||
|
|
||||||
|
@ -122,7 +123,10 @@ Drive::Drive( OAuth2& auth ) :
|
||||||
resp = xrsp.Response() ;
|
resp = xrsp.Response() ;
|
||||||
}
|
}
|
||||||
} while ( has_next ) ;
|
} while ( has_next ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::SaveState()
|
||||||
|
{
|
||||||
m_state.Write( state_file ) ;
|
m_state.Write( state_file ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ public :
|
||||||
|
|
||||||
void Update() ;
|
void Update() ;
|
||||||
void Sync() ;
|
void Sync() ;
|
||||||
|
void SaveState() ;
|
||||||
|
|
||||||
struct Error : virtual Exception {} ;
|
struct Error : virtual Exception {} ;
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,25 @@ Entry::Entry( const fs::path& path ) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::Update( const xml::Node& n )
|
void Entry::Update( const xml::Node& n )
|
||||||
{
|
{
|
||||||
m_title = n["title"] ;
|
m_title = n["title"] ;
|
||||||
|
|
|
@ -45,6 +45,14 @@ public :
|
||||||
Entry( ) ;
|
Entry( ) ;
|
||||||
explicit Entry( const fs::path& path ) ;
|
explicit Entry( const fs::path& path ) ;
|
||||||
explicit Entry( const xml::Node& n ) ;
|
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 ) ;
|
||||||
|
|
||||||
std::string Title() const ;
|
std::string Title() const ;
|
||||||
std::string Filename() const ;
|
std::string Filename() const ;
|
||||||
|
@ -78,7 +86,6 @@ private :
|
||||||
|
|
||||||
std::string m_self_href ;
|
std::string m_self_href ;
|
||||||
std::string m_content_src ;
|
std::string m_content_src ;
|
||||||
std::string m_parent_href ;
|
|
||||||
std::string m_upload_link ;
|
std::string m_upload_link ;
|
||||||
|
|
||||||
DateTime m_mtime ;
|
DateTime m_mtime ;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "http/Download.hh"
|
#include "http/Download.hh"
|
||||||
#include "http/StringResponse.hh"
|
#include "http/StringResponse.hh"
|
||||||
#include "http/XmlResponse.hh"
|
#include "http/XmlResponse.hh"
|
||||||
|
#include "protocol/Json.hh"
|
||||||
#include "util/Crypt.hh"
|
#include "util/Crypt.hh"
|
||||||
#include "util/Log.hh"
|
#include "util/Log.hh"
|
||||||
#include "util/OS.hh"
|
#include "util/OS.hh"
|
||||||
|
@ -44,6 +45,21 @@ Resource::Resource() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// construct from previously serialized JSON object
|
||||||
|
Resource::Resource( const Json& json, Resource *parent ) :
|
||||||
|
m_entry (
|
||||||
|
json["name"].Str(),
|
||||||
|
json["id"].Str(),
|
||||||
|
json["href"].Str(),
|
||||||
|
json["md5"].Str(),
|
||||||
|
json["kind"].Str(),
|
||||||
|
DateTime( json["mtime"]["sec"].Int(), json["mtime"]["nsec"].Int() ),
|
||||||
|
parent != 0 ? parent->SelfHref() : "" ),
|
||||||
|
m_parent( parent ),
|
||||||
|
m_state( local_new )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Resource::Resource( const xml::Node& entry ) :
|
Resource::Resource( const xml::Node& entry ) :
|
||||||
m_entry ( entry ),
|
m_entry ( entry ),
|
||||||
m_parent( 0 ),
|
m_parent( 0 ),
|
||||||
|
@ -58,16 +74,6 @@ Resource::Resource( const Entry& entry, Resource *parent ) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resource::Resource(
|
|
||||||
// const std::string& name,
|
|
||||||
// const std::string& kind,
|
|
||||||
// const std::string& href ) :
|
|
||||||
// m_entry ( name, kind, href ),
|
|
||||||
// m_parent( 0 ),
|
|
||||||
// m_state ( local_new )
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
Resource::Resource( const fs::path& path ) :
|
Resource::Resource( const fs::path& path ) :
|
||||||
m_entry ( path ),
|
m_entry ( path ),
|
||||||
m_parent( 0 ),
|
m_parent( 0 ),
|
||||||
|
@ -127,7 +133,7 @@ std::string Resource::ParentHref() const
|
||||||
void Resource::AddChild( Resource *child )
|
void Resource::AddChild( Resource *child )
|
||||||
{
|
{
|
||||||
assert( child != 0 ) ;
|
assert( child != 0 ) ;
|
||||||
assert( child->m_parent == 0 ) ;
|
assert( child->m_parent == 0 || child->m_parent == this ) ;
|
||||||
assert( child != this ) ;
|
assert( child != this ) ;
|
||||||
|
|
||||||
child->m_parent = this ;
|
child->m_parent = this ;
|
||||||
|
@ -285,6 +291,46 @@ bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Head
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json Resource::Serialize() const
|
||||||
|
{
|
||||||
|
Json result ;
|
||||||
|
result.Add( "name", Json(Name()) ) ;
|
||||||
|
result.Add( "id", Json(ResourceID()) ) ;
|
||||||
|
result.Add( "href", Json(SelfHref()) ) ;
|
||||||
|
result.Add( "md5", Json(m_entry.MD5()) ) ;
|
||||||
|
result.Add( "kind", Json(m_entry.Kind()) ) ;
|
||||||
|
|
||||||
|
Json mtime ;
|
||||||
|
mtime.Add( "sec", Json(m_entry.MTime().Sec() ) );
|
||||||
|
mtime.Add( "nsec", Json(m_entry.MTime().NanoSec() ) );
|
||||||
|
|
||||||
|
result.Add( "mtime",mtime ) ;
|
||||||
|
|
||||||
|
std::vector<Json> array ;
|
||||||
|
for ( std::vector<Resource*>::const_iterator i = m_child.begin() ; i != m_child.end() ; ++i )
|
||||||
|
array.push_back( (*i)->Serialize() ) ;
|
||||||
|
|
||||||
|
result.Add( "child", Json(array) ) ;
|
||||||
|
|
||||||
|
return result ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::iterator Resource::begin() const
|
||||||
|
{
|
||||||
|
return m_child.begin() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::iterator Resource::end() const
|
||||||
|
{
|
||||||
|
return m_child.end() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Resource::size() const
|
||||||
|
{
|
||||||
|
return m_child.size() ;
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
|
class Json ;
|
||||||
|
|
||||||
/*! \brief A resource can be a file or a folder in the google drive
|
/*! \brief A resource can be a file or a folder in the google drive
|
||||||
|
|
||||||
The google drive contains a number of resources, which is represented by this class.
|
The google drive contains a number of resources, which is represented by this class.
|
||||||
|
@ -40,15 +42,15 @@ class Resource
|
||||||
public :
|
public :
|
||||||
struct Error : virtual Exception {} ;
|
struct Error : virtual Exception {} ;
|
||||||
|
|
||||||
|
typedef std::vector<Resource*> Children ;
|
||||||
|
typedef Children::const_iterator iterator ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
Resource() ;
|
Resource() ;
|
||||||
explicit Resource( const xml::Node& entry ) ;
|
explicit Resource( const xml::Node& entry ) ;
|
||||||
explicit Resource( const Entry& entry, Resource *parent = 0 ) ;
|
explicit Resource( const Entry& entry, Resource *parent = 0 ) ;
|
||||||
explicit Resource( const fs::path& path ) ;
|
explicit Resource( const fs::path& path ) ;
|
||||||
// Resource(
|
explicit Resource( const Json& json, Resource *parent = 0 ) ;
|
||||||
// const std::string& name,
|
|
||||||
// const std::string& kind,
|
|
||||||
// const std::string& href ) ;
|
|
||||||
void Swap( Resource& coll ) ;
|
void Swap( Resource& coll ) ;
|
||||||
|
|
||||||
// default copy ctor & op= are fine
|
// default copy ctor & op= are fine
|
||||||
|
@ -72,6 +74,13 @@ public :
|
||||||
void Sync( http::Agent *http, const http::Headers& auth ) ;
|
void Sync( http::Agent *http, const http::Headers& auth ) ;
|
||||||
void Delete( http::Agent* http, const http::Headers& auth ) ;
|
void Delete( http::Agent* http, const http::Headers& auth ) ;
|
||||||
|
|
||||||
|
Json Serialize() const ;
|
||||||
|
|
||||||
|
// children access
|
||||||
|
iterator begin() const ;
|
||||||
|
iterator end() const ;
|
||||||
|
std::size_t size() const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
/// State of the resource. indicating what to do with the resource
|
/// State of the resource. indicating what to do with the resource
|
||||||
enum State
|
enum State
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
#include "ResourceTree.hh"
|
#include "ResourceTree.hh"
|
||||||
#include "CommonUri.hh"
|
#include "CommonUri.hh"
|
||||||
|
|
||||||
|
#include "protocol/Json.hh"
|
||||||
#include "util/Destroy.hh"
|
#include "util/Destroy.hh"
|
||||||
|
#include "util/Log.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -52,10 +54,18 @@ ResourceTree::ResourceTree( const ResourceTree& fs ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceTree::~ResourceTree( )
|
ResourceTree::~ResourceTree( )
|
||||||
|
{
|
||||||
|
Clear() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceTree::Clear()
|
||||||
{
|
{
|
||||||
// delete all pointers
|
// delete all pointers
|
||||||
const Set& s = m_set.get<ByIdentity>() ;
|
const Set& s = m_set.get<ByIdentity>() ;
|
||||||
std::for_each( s.begin(), s.end(), Destroy() ) ;
|
std::for_each( s.begin(), s.end(), Destroy() ) ;
|
||||||
|
|
||||||
|
m_set.clear() ;
|
||||||
|
m_root = 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource* ResourceTree::Root()
|
Resource* ResourceTree::Root()
|
||||||
|
@ -152,4 +162,30 @@ ResourceTree::iterator ResourceTree::end()
|
||||||
return m_set.get<ByIdentity>().end() ;
|
return m_set.get<ByIdentity>().end() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResourceTree::Read( const Json& json )
|
||||||
|
{
|
||||||
|
Clear() ;
|
||||||
|
m_root = new Resource( json ) ;
|
||||||
|
AddTree( m_root, json ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceTree::AddTree( Resource *node, const Json& json )
|
||||||
|
{
|
||||||
|
assert( node != 0 ) ;
|
||||||
|
m_set.insert( node ) ;
|
||||||
|
|
||||||
|
std::vector<Json> array = json["child"].AsArray() ;
|
||||||
|
for ( std::vector<Json>::iterator i = array.begin() ; i != array.end() ; ++i )
|
||||||
|
{
|
||||||
|
Resource *c = new Resource( *i, node ) ;
|
||||||
|
node->AddChild( c ) ;
|
||||||
|
AddTree( c, *i ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json ResourceTree::Serialize() const
|
||||||
|
{
|
||||||
|
return m_root->Serialize() ;
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
|
class Json ;
|
||||||
|
|
||||||
namespace details
|
namespace details
|
||||||
{
|
{
|
||||||
using namespace boost::multi_index ;
|
using namespace boost::multi_index ;
|
||||||
|
@ -73,6 +75,7 @@ public :
|
||||||
const Resource* FindByHref( const std::string& href ) const ;
|
const Resource* FindByHref( const std::string& href ) const ;
|
||||||
|
|
||||||
Resource* FindByPath( const fs::path& path ) ;
|
Resource* FindByPath( const fs::path& path ) ;
|
||||||
|
Resource* FindByID( const std::string& id ) ;
|
||||||
|
|
||||||
bool ReInsert( Resource *coll ) ;
|
bool ReInsert( Resource *coll ) ;
|
||||||
|
|
||||||
|
@ -85,7 +88,14 @@ public :
|
||||||
|
|
||||||
iterator begin() ;
|
iterator begin() ;
|
||||||
iterator end() ;
|
iterator end() ;
|
||||||
|
|
||||||
|
void Read( const Json& json ) ;
|
||||||
|
Json Serialize() const ;
|
||||||
|
|
||||||
|
private :
|
||||||
|
void Clear() ;
|
||||||
|
void AddTree( Resource *node, const Json& json ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
details::Folders m_set ;
|
details::Folders m_set ;
|
||||||
Resource* m_root ;
|
Resource* m_root ;
|
||||||
|
|
|
@ -40,8 +40,7 @@ namespace gr {
|
||||||
|
|
||||||
State::State( const fs::path& filename )
|
State::State( const fs::path& filename )
|
||||||
{
|
{
|
||||||
if ( fs::exists( filename ) )
|
Read( filename ) ;
|
||||||
Read( filename );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string State::ChangeStamp() const
|
std::string State::ChangeStamp() const
|
||||||
|
@ -68,15 +67,25 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
|
||||||
|
|
||||||
for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i )
|
for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i )
|
||||||
{
|
{
|
||||||
if ( i->path().filename().string()[0] == '.' )
|
std::string fname = i->path().filename().string() ;
|
||||||
Log( "file %1% is ignored by grive", i->path().filename().string(), log::info ) ;
|
|
||||||
|
if ( fname[0] == '.' )
|
||||||
|
Log( "file %1% is ignored by grive", fname, log::info ) ;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Resource *c = new Resource( i->path() ) ;
|
Resource *c = folder->FindChild( fname ) ;
|
||||||
folder->AddChild( c ) ;
|
if ( c != 0 )
|
||||||
m_res.Insert( c ) ;
|
{
|
||||||
|
Trace( "wow! file %1% is loaded from previous state", fname ) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = new Resource( i->path() ) ;
|
||||||
|
folder->AddChild( c ) ;
|
||||||
|
m_res.Insert( c ) ;
|
||||||
|
}
|
||||||
|
|
||||||
if ( fs::is_directory( i->path() ) )
|
if ( fs::is_directory( i->path() ) )
|
||||||
FromLocal( *i, c ) ;
|
FromLocal( *i, c ) ;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +133,11 @@ bool State::Update( const Entry& e )
|
||||||
{
|
{
|
||||||
assert( !e.ParentHref().empty() ) ;
|
assert( !e.ParentHref().empty() ) ;
|
||||||
|
|
||||||
// Resource *r = m_res.FindByID( e.ResourceID() ) ;
|
Resource *r = m_res.FindByHref( e.SelfHref() ) ;
|
||||||
|
if ( r != 0 )
|
||||||
|
{
|
||||||
|
Trace( "wow! find %1% from state file?", r->Name() ) ;
|
||||||
|
}
|
||||||
|
|
||||||
Resource *parent = m_res.FindByHref( e.ParentHref() ) ;
|
Resource *parent = m_res.FindByHref( e.ParentHref() ) ;
|
||||||
if ( parent != 0 )
|
if ( parent != 0 )
|
||||||
|
@ -183,13 +196,20 @@ State::iterator State::end()
|
||||||
|
|
||||||
void State::Read( const fs::path& filename )
|
void State::Read( const fs::path& filename )
|
||||||
{
|
{
|
||||||
Trace( "reading %1%", filename ) ;
|
if ( fs::exists( filename ) )
|
||||||
|
{
|
||||||
|
Json json = Json::ParseFile( filename.string() ) ;
|
||||||
|
|
||||||
|
m_change_stamp = json["change_stamp"].Str() ;
|
||||||
|
m_res.Read( json["rtree"] ) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void State::Write( const fs::path& filename ) const
|
void State::Write( const fs::path& filename ) const
|
||||||
{
|
{
|
||||||
Json result ;
|
Json result ;
|
||||||
result.Add( "change_stamp", Json( m_change_stamp ) ) ;
|
result.Add( "change_stamp", Json( m_change_stamp ) ) ;
|
||||||
|
result.Add( "rtree", m_res.Serialize() ) ;
|
||||||
|
|
||||||
std::ofstream fs( filename.string().c_str() ) ;
|
std::ofstream fs( filename.string().c_str() ) ;
|
||||||
fs << result ;
|
fs << result ;
|
||||||
|
|
|
@ -34,7 +34,7 @@ Json::Json( ) :
|
||||||
m_json( ::json_object_new_object() )
|
m_json( ::json_object_new_object() )
|
||||||
{
|
{
|
||||||
if ( m_json == 0 )
|
if ( m_json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "cannot create json object" ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json object" ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -42,7 +42,8 @@ Json::Json( const std::string& str ) :
|
||||||
m_json( ::json_object_new_string( str.c_str() ) )
|
m_json( ::json_object_new_string( str.c_str() ) )
|
||||||
{
|
{
|
||||||
if ( m_json == 0 )
|
if ( m_json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "cannot create json string \"" + str + "\"" ) ;
|
BOOST_THROW_EXCEPTION(
|
||||||
|
Error() << expt::ErrMsg( "cannot create json string \"" + str + "\"" ) ) ;
|
||||||
|
|
||||||
// paranoid check
|
// paranoid check
|
||||||
assert( ::json_object_get_string( m_json ) == str ) ;
|
assert( ::json_object_get_string( m_json ) == str ) ;
|
||||||
|
@ -53,7 +54,7 @@ Json::Json( const int& l ) :
|
||||||
m_json( ::json_object_new_int( l ) )
|
m_json( ::json_object_new_int( l ) )
|
||||||
{
|
{
|
||||||
if ( m_json == 0 )
|
if ( m_json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "cannot create json int" ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -61,7 +62,15 @@ Json::Json( const long& l ) :
|
||||||
m_json( ::json_object_new_int( static_cast<int>(l) ) )
|
m_json( ::json_object_new_int( static_cast<int>(l) ) )
|
||||||
{
|
{
|
||||||
if ( m_json == 0 )
|
if ( m_json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "cannot create json int" ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Json::Json( const unsigned long& l ) :
|
||||||
|
m_json( ::json_object_new_int( static_cast<int>(l) ) )
|
||||||
|
{
|
||||||
|
if ( m_json == 0 )
|
||||||
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -69,7 +78,7 @@ Json::Json( const std::vector<Json>& arr ) :
|
||||||
m_json( ::json_object_new_array( ) )
|
m_json( ::json_object_new_array( ) )
|
||||||
{
|
{
|
||||||
if ( m_json == 0 )
|
if ( m_json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "cannot create json int" ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ;
|
||||||
|
|
||||||
for ( std::vector<Json>::const_iterator i = arr.begin() ; i != arr.end() ; ++i )
|
for ( std::vector<Json>::const_iterator i = arr.begin() ; i != arr.end() ; ++i )
|
||||||
Add( *i ) ;
|
Add( *i ) ;
|
||||||
|
@ -79,7 +88,7 @@ Json Json::Parse( const std::string& str )
|
||||||
{
|
{
|
||||||
struct json_object *json = ::json_tokener_parse( str.c_str() ) ;
|
struct json_object *json = ::json_tokener_parse( str.c_str() ) ;
|
||||||
if ( json == 0 )
|
if ( json == 0 )
|
||||||
throw Error() << expt::ErrMsg( "json parse error" ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "json parse error" ) ) ;
|
||||||
|
|
||||||
return Json( json, NotOwned() ) ;
|
return Json( json, NotOwned() ) ;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +107,7 @@ Json Json::ParseFile( const std::string& filename )
|
||||||
json = ::json_tokener_parse_ex( tok, buf, count ) ;
|
json = ::json_tokener_parse_ex( tok, buf, count ) ;
|
||||||
|
|
||||||
if ( json == 0 )
|
if ( json == 0 )
|
||||||
throw Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ) ;
|
||||||
|
|
||||||
::json_tokener_free( tok ) ;
|
::json_tokener_free( tok ) ;
|
||||||
|
|
||||||
|
@ -152,7 +161,10 @@ Json Json::operator[]( const std::string& key ) const
|
||||||
|
|
||||||
struct json_object *j = ::json_object_object_get( m_json, key.c_str() ) ;
|
struct json_object *j = ::json_object_object_get( m_json, key.c_str() ) ;
|
||||||
if ( j == 0 )
|
if ( j == 0 )
|
||||||
throw Error() << expt::ErrMsg( "key: " + key + " is not found in object" ) ;
|
BOOST_THROW_EXCEPTION(
|
||||||
|
Error()
|
||||||
|
<< expt::ErrMsg( "key: " + key + " is not found in object" )
|
||||||
|
<< JsonInfo( *this ) ) ;
|
||||||
|
|
||||||
return Json( j ) ;
|
return Json( j ) ;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +178,10 @@ Json Json::operator[]( const std::size_t& idx ) const
|
||||||
{
|
{
|
||||||
std::ostringstream ss ;
|
std::ostringstream ss ;
|
||||||
ss << "index " << idx << " is not found in array" ;
|
ss << "index " << idx << " is not found in array" ;
|
||||||
throw Error() << expt::ErrMsg( ss.str() ) ;
|
BOOST_THROW_EXCEPTION(
|
||||||
|
Error()
|
||||||
|
<< expt::ErrMsg( ss.str() )
|
||||||
|
<< JsonInfo( *this ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json( j ) ;
|
return Json( j ) ;
|
||||||
|
@ -294,7 +309,8 @@ Json Json::FindInArray( const std::string& key, const std::string& value ) const
|
||||||
if ( item.Has(key) && item[key].Str() == value )
|
if ( item.Has(key) && item[key].Str() == value )
|
||||||
return item ;
|
return item ;
|
||||||
}
|
}
|
||||||
throw Error() << expt::ErrMsg( "cannot find " + key + " = " + value + " in array" ) ;
|
BOOST_THROW_EXCEPTION(
|
||||||
|
Error() << expt::ErrMsg( "cannot find " + key + " = " + value + " in array" ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Json::FindInArray( const std::string& key, const std::string& value, Json& result ) const
|
bool Json::FindInArray( const std::string& key, const std::string& value, Json& result ) const
|
||||||
|
|
|
@ -36,6 +36,7 @@ public :
|
||||||
typedef std::vector<Json> Array ;
|
typedef std::vector<Json> Array ;
|
||||||
|
|
||||||
struct Error : virtual Exception {} ;
|
struct Error : virtual Exception {} ;
|
||||||
|
typedef boost::error_info<struct JsonTag, Json> JsonInfo ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "DateTime.hh"
|
#include "DateTime.hh"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -149,4 +151,11 @@ void DateTime::Swap( DateTime& dt )
|
||||||
std::swap( m_nsec, dt.m_nsec ) ;
|
std::swap( m_nsec, dt.m_nsec ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DateTime::ToString() const
|
||||||
|
{
|
||||||
|
std::ostringstream ss ;
|
||||||
|
ss << *this ;
|
||||||
|
return ss.str() ;
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
|
@ -51,6 +51,7 @@ public :
|
||||||
bool operator<=( const DateTime& dt ) const ;
|
bool operator<=( const DateTime& dt ) const ;
|
||||||
|
|
||||||
void Swap( DateTime& dt ) ;
|
void Swap( DateTime& dt ) ;
|
||||||
|
std::string ToString() const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
std::time_t m_sec ;
|
std::time_t m_sec ;
|
||||||
|
|
|
@ -92,7 +92,7 @@ public :
|
||||||
|
|
||||||
// cannot allow duplicate attribute nodes
|
// cannot allow duplicate attribute nodes
|
||||||
if ( child->m_type == attr && p.first != p.second )
|
if ( child->m_type == attr && p.first != p.second )
|
||||||
throw Error() << expt::ErrMsg( "duplicate attribute " + child->m_name ) ;
|
BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "duplicate attribute " + child->m_name ) ) ;
|
||||||
|
|
||||||
vec.insert( p.second, child ) ;
|
vec.insert( p.second, child ) ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "util/DefaultLog.hh"
|
#include "util/DefaultLog.hh"
|
||||||
|
|
||||||
#include "drive/EntryTest.hh"
|
#include "drive/EntryTest.hh"
|
||||||
|
#include "drive/ResourceTreeTest.hh"
|
||||||
#include "drive/StateTest.hh"
|
#include "drive/StateTest.hh"
|
||||||
#include "util/DateTimeTest.hh"
|
#include "util/DateTimeTest.hh"
|
||||||
#include "util/FunctionTest.hh"
|
#include "util/FunctionTest.hh"
|
||||||
|
@ -40,6 +41,7 @@ int main( int argc, char **argv )
|
||||||
CppUnit::TextUi::TestRunner runner;
|
CppUnit::TextUi::TestRunner runner;
|
||||||
runner.addTest( EntryTest::suite( ) ) ;
|
runner.addTest( EntryTest::suite( ) ) ;
|
||||||
runner.addTest( StateTest::suite( ) ) ;
|
runner.addTest( StateTest::suite( ) ) ;
|
||||||
|
runner.addTest( ResourceTreeTest::suite( ) ) ;
|
||||||
runner.addTest( DateTimeTest::suite( ) ) ;
|
runner.addTest( DateTimeTest::suite( ) ) ;
|
||||||
runner.addTest( FunctionTest::suite( ) ) ;
|
runner.addTest( FunctionTest::suite( ) ) ;
|
||||||
runner.addTest( SignalHandlerTest::suite( ) ) ;
|
runner.addTest( SignalHandlerTest::suite( ) ) ;
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
grive: an GPL program to sync a local directory with Google Drive
|
||||||
|
Copyright (C) 2012 Wan Wai Ho
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation version 2
|
||||||
|
of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ResourceTreeTest.hh"
|
||||||
|
|
||||||
|
#include "Assert.hh"
|
||||||
|
|
||||||
|
#include "drive/ResourceTree.hh"
|
||||||
|
#include "drive/Resource.hh"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace grut {
|
||||||
|
|
||||||
|
using namespace gr ;
|
||||||
|
|
||||||
|
ResourceTreeTest::ResourceTreeTest( )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceTreeTest::TestSerialize( )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace grut
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
grive: an GPL program to sync a local directory with Google Drive
|
||||||
|
Copyright (C) 2012 Wan Wai Ho
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation version 2
|
||||||
|
of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cppunit/TestFixture.h>
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
namespace grut {
|
||||||
|
|
||||||
|
class ResourceTreeTest : public CppUnit::TestFixture
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
ResourceTreeTest( ) ;
|
||||||
|
|
||||||
|
// declare suit function
|
||||||
|
CPPUNIT_TEST_SUITE( ResourceTreeTest ) ;
|
||||||
|
CPPUNIT_TEST( TestSerialize ) ;
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
private :
|
||||||
|
void TestSerialize( ) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
} // end of namespace
|
Loading…
Reference in New Issue