mirror of https://github.com/vitalif/grive2
improved logging and fixed exception on MD5 calculation
parent
90bf78e716
commit
99f6e4cc58
|
@ -49,7 +49,7 @@ int main( int argc, char **argv )
|
||||||
LogBase::Inst( &nofile_log ) ;
|
LogBase::Inst( &nofile_log ) ;
|
||||||
|
|
||||||
int c ;
|
int c ;
|
||||||
while ((c = getopt(argc, argv, "al:v")) != -1)
|
while ((c = getopt(argc, argv, "al:vV")) != -1)
|
||||||
{
|
{
|
||||||
switch ( c )
|
switch ( c )
|
||||||
{
|
{
|
||||||
|
@ -91,6 +91,12 @@ int main( int argc, char **argv )
|
||||||
<< "grive version " VERSION " " __DATE__ " " __TIME__ << std::endl ;
|
<< "grive version " VERSION " " __DATE__ " " __TIME__ << std::endl ;
|
||||||
return 0 ;
|
return 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'V' :
|
||||||
|
{
|
||||||
|
LogBase::Inst()->Enable( log::verbose ) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,9 +123,9 @@ int main( int argc, char **argv )
|
||||||
Drive drive( token ) ;
|
Drive drive( token ) ;
|
||||||
|
|
||||||
drive.Update() ;
|
drive.Update() ;
|
||||||
// drive.SaveState() ;
|
drive.SaveState() ;
|
||||||
|
|
||||||
config.Save() ;
|
// config.Save() ;
|
||||||
}
|
}
|
||||||
catch ( gr::Exception& e )
|
catch ( gr::Exception& e )
|
||||||
{
|
{
|
||||||
|
|
|
@ -92,20 +92,20 @@ Drive::Drive( OAuth2& auth ) :
|
||||||
{
|
{
|
||||||
if ( (*i)["content"] == "" )
|
if ( (*i)["content"] == "" )
|
||||||
continue ;
|
continue ;
|
||||||
|
|
||||||
Entry file( *i ) ;
|
Entry file( *i ) ;
|
||||||
if ( file.Kind() != "folder" )
|
if ( file.Kind() != "folder" )
|
||||||
{
|
{
|
||||||
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
|
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
|
||||||
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(), log::info ) ;
|
||||||
|
|
||||||
else if ( file.ParentHref().empty() || p == 0 || !p->IsInRootTree() )
|
else if ( file.ParentHref().empty() || p == 0 || !p->IsInRootTree() )
|
||||||
Log( "file \"%1%\" parent doesn't exist, ignored", file.Title() ) ;
|
Log( "file \"%1%\" parent doesn't exist, ignored", file.Title(), log::info ) ;
|
||||||
|
|
||||||
else if ( p != 0 && !p->IsFolder() )
|
else if ( p != 0 && !p->IsFolder() )
|
||||||
Log( "entry %1% has parent %2% which is not a folder, ignored",
|
Log( "entry %1% has parent %2% which is not a folder, ignored",
|
||||||
file.Title(), p->Name() ) ;
|
file.Title(), p->Name(), log::info ) ;
|
||||||
|
|
||||||
else
|
else
|
||||||
m_state.FromRemote( file ) ;
|
m_state.FromRemote( file ) ;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "http/StringResponse.hh"
|
#include "http/StringResponse.hh"
|
||||||
#include "http/XmlResponse.hh"
|
#include "http/XmlResponse.hh"
|
||||||
#include "protocol/Json.hh"
|
#include "protocol/Json.hh"
|
||||||
|
#include "util/CArray.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"
|
||||||
|
@ -94,14 +95,17 @@ void Resource::FromRemote( const Entry& remote )
|
||||||
{
|
{
|
||||||
// if checksum is equal, no need to compare the mtime
|
// if checksum is equal, no need to compare the mtime
|
||||||
if ( remote.MD5() == m_entry.MD5() )
|
if ( remote.MD5() == m_entry.MD5() )
|
||||||
|
{
|
||||||
|
Log( "MD5 matches: %1% is already in sync", Name(), log::verbose ) ;
|
||||||
m_state = sync ;
|
m_state = sync ;
|
||||||
|
}
|
||||||
// use mtime to check which one is more recent
|
// use mtime to check which one is more recent
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ;
|
assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ;
|
||||||
|
|
||||||
m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ;
|
m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ;
|
||||||
|
Log( "%1% state is %2%", Name(), m_state, log::verbose ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_entry = remote ;
|
m_entry = remote ;
|
||||||
|
@ -111,18 +115,30 @@ void Resource::FromLocal()
|
||||||
{
|
{
|
||||||
fs::path path = Path() ;
|
fs::path path = Path() ;
|
||||||
if ( !fs::exists( path ) )
|
if ( !fs::exists( path ) )
|
||||||
|
{
|
||||||
m_state = local_deleted ;
|
m_state = local_deleted ;
|
||||||
|
Log( "%1% in state but not exist on disk: %2%", Name(), m_state ) ;
|
||||||
|
}
|
||||||
|
|
||||||
// to save time, compare mtime before checksum
|
// to save time, compare mtime before checksum
|
||||||
else if ( m_entry.MTime() > os::FileMTime( path ) )
|
else if ( os::FileMTime( path ) > m_entry.MTime() )
|
||||||
{
|
{
|
||||||
if ( m_entry.MD5() == crypt::MD5( path ) )
|
if ( m_entry.MD5() == crypt::MD5( path ) )
|
||||||
|
{
|
||||||
m_state = local_new ;
|
m_state = local_new ;
|
||||||
|
Log( "%1% mtime newer on disk but unchanged: %2%", Name(), m_state ) ;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_state = local_changed ;
|
m_state = local_changed ;
|
||||||
|
Log( "%1% changed on disk: %2%", Name(), m_state ) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_state = local_changed ;
|
{
|
||||||
|
m_state = local_new ;
|
||||||
|
Log( "%1% unchanged on disk: %2%", Name(), m_state ) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Resource::SelfHref() const
|
std::string Resource::SelfHref() const
|
||||||
|
@ -214,25 +230,30 @@ void Resource::Sync( http::Agent *http, const http::Headers& auth )
|
||||||
switch ( m_state )
|
switch ( m_state )
|
||||||
{
|
{
|
||||||
case local_new :
|
case local_new :
|
||||||
Trace( "file %1% doesn't exist in server. upload?", m_entry.Filename() ) ;
|
Log( "sync %1% doesn't exist in server. upload?", m_entry.Filename(), log::verbose ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case local_deleted :
|
||||||
|
Log( "sync %1% deleted in local. delete?", m_entry.Filename(), log::verbose ) ;
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
case local_changed :
|
case local_changed :
|
||||||
Trace( "file %1% changed in local", m_entry.Filename() ) ;
|
Log( "sync %1% changed in local", m_entry.Filename(), log::verbose ) ;
|
||||||
if ( Upload( http, auth ) )
|
if ( Upload( http, auth ) )
|
||||||
m_state = sync ;
|
m_state = sync ;
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
case remote_new :
|
case remote_new :
|
||||||
case remote_changed :
|
case remote_changed :
|
||||||
Trace( "file %1% changed in remote", m_entry.Filename() ) ;
|
Log( "sync %1% changed in remote. download?", m_entry.Filename(), log::verbose ) ;
|
||||||
Download( http, Path(), auth ) ;
|
Download( http, Path(), auth ) ;
|
||||||
m_state = sync ;
|
m_state = sync ;
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
case sync :
|
case sync :
|
||||||
Trace( "file %1% already in sync", m_entry.Filename() ) ;
|
Log( "sync %1% already in sync", m_entry.Filename(), log::verbose ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
@ -356,6 +377,16 @@ std::size_t Resource::size() const
|
||||||
return m_child.size() ;
|
return m_child.size() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<( std::ostream& os, Resource::State s )
|
||||||
|
{
|
||||||
|
static const char *state[] =
|
||||||
|
{
|
||||||
|
"sync", "local_new", "local_changed", "local_deleted", "remote_new", "remote_changed"
|
||||||
|
} ;
|
||||||
|
assert( s >= 0 && s < Count(state) ) ;
|
||||||
|
return os << state[s] ;
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
|
|
@ -108,12 +108,14 @@ private :
|
||||||
/// Resource exists in both local & remote, but remote is newer.
|
/// Resource exists in both local & remote, but remote is newer.
|
||||||
remote_changed
|
remote_changed
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<( std::ostream& os, State s ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ;
|
void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ;
|
||||||
bool Upload( http::Agent* http, const http::Headers& auth ) ;
|
bool Upload( http::Agent* http, const http::Headers& auth ) ;
|
||||||
bool Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
|
bool Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
Entry m_entry ;
|
Entry m_entry ;
|
||||||
|
|
||||||
|
|
|
@ -74,9 +74,12 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// if the Resource object of the child already exists, it should
|
||||||
|
// have been so no need to do anything here
|
||||||
Resource *c = folder->FindChild( fname ) ;
|
Resource *c = folder->FindChild( fname ) ;
|
||||||
if ( c == 0 )
|
if ( c == 0 )
|
||||||
{
|
{
|
||||||
|
Log( "detected new file %1% in local", fname, log::verbose ) ;
|
||||||
c = new Resource( i->path() ) ;
|
c = new Resource( i->path() ) ;
|
||||||
folder->AddChild( c ) ;
|
folder->AddChild( c ) ;
|
||||||
m_res.Insert( c ) ;
|
m_res.Insert( c ) ;
|
||||||
|
|
|
@ -19,22 +19,30 @@
|
||||||
|
|
||||||
#include "Crypt.hh"
|
#include "Crypt.hh"
|
||||||
|
|
||||||
|
#include "StdioFile.hh"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
// dependent libraries
|
// dependent libraries
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
namespace gr { namespace crypt {
|
namespace gr { namespace crypt {
|
||||||
|
|
||||||
std::string MD5( const boost::filesystem::path& file )
|
std::string MD5( const fs::path& file )
|
||||||
{
|
{
|
||||||
std::ifstream ifile( file.string().c_str(), std::ios::binary | std::ios::in ) ;
|
try
|
||||||
return MD5( ifile.rdbuf() ) ;
|
{
|
||||||
|
StdioFile sfile( file, "rb" ) ;
|
||||||
|
return MD5( sfile ) ;
|
||||||
|
}
|
||||||
|
catch ( StdioFile::Error& )
|
||||||
|
{
|
||||||
|
return "" ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MD5( std::streambuf *file )
|
std::string MD5( StdioFile& file )
|
||||||
{
|
{
|
||||||
char buf[64 * 1024] ;
|
char buf[64 * 1024] ;
|
||||||
EVP_MD_CTX md ;
|
EVP_MD_CTX md ;
|
||||||
|
@ -42,7 +50,7 @@ std::string MD5( std::streambuf *file )
|
||||||
EVP_DigestInit_ex( &md, EVP_md5(), 0 ) ;
|
EVP_DigestInit_ex( &md, EVP_md5(), 0 ) ;
|
||||||
|
|
||||||
std::size_t count = 0 ;
|
std::size_t count = 0 ;
|
||||||
while ( (count = file->sgetn( buf, sizeof(buf) )) > 0 )
|
while ( (count = file.Read( buf, sizeof(buf) )) > 0 )
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate( &md, buf, count ) ;
|
EVP_DigestUpdate( &md, buf, count ) ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
|
class StdioFile ;
|
||||||
|
|
||||||
namespace crypt
|
namespace crypt
|
||||||
{
|
{
|
||||||
std::string MD5( std::streambuf *file ) ;
|
std::string MD5( StdioFile& file ) ;
|
||||||
std::string MD5( const boost::filesystem::path& file ) ;
|
std::string MD5( const boost::filesystem::path& file ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ DefaultLog::DefaultLog() :
|
||||||
m_log( std::cerr )
|
m_log( std::cerr )
|
||||||
{
|
{
|
||||||
m_enabled[log::debug] = false ;
|
m_enabled[log::debug] = false ;
|
||||||
|
m_enabled[log::verbose] = false ;
|
||||||
m_enabled[log::info] = true ;
|
m_enabled[log::info] = true ;
|
||||||
m_enabled[log::warning] = true ;
|
m_enabled[log::warning] = true ;
|
||||||
m_enabled[log::error] = true ;
|
m_enabled[log::error] = true ;
|
||||||
|
@ -39,6 +40,7 @@ DefaultLog::DefaultLog( const std::string& filename ) :
|
||||||
m_log( m_file )
|
m_log( m_file )
|
||||||
{
|
{
|
||||||
m_enabled[log::debug] = true ;
|
m_enabled[log::debug] = true ;
|
||||||
|
m_enabled[log::verbose] = true ;
|
||||||
m_enabled[log::info] = true ;
|
m_enabled[log::info] = true ;
|
||||||
m_enabled[log::warning] = true ;
|
m_enabled[log::warning] = true ;
|
||||||
m_enabled[log::error] = true ;
|
m_enabled[log::error] = true ;
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace gr {
|
||||||
|
|
||||||
namespace log
|
namespace log
|
||||||
{
|
{
|
||||||
enum Serverity { debug, info, warning, error, critical } ;
|
enum Serverity { debug, verbose, info, warning, error, critical } ;
|
||||||
typedef boost::format Fmt ;
|
typedef boost::format Fmt ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,29 @@
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
StdioFile::StdioFile( const std::string& filename, const char *mode ) :
|
StdioFile::StdioFile( const std::string& filename, const char *mode ) : m_file( 0 )
|
||||||
m_file( std::fopen( filename.c_str(), mode ) )
|
|
||||||
{
|
{
|
||||||
|
Open( filename, mode ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdioFile::StdioFile( const fs::path& path, const char *mode ) : m_file( 0 )
|
||||||
|
{
|
||||||
|
Open( path, mode ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdioFile::~StdioFile( )
|
||||||
|
{
|
||||||
|
Close() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioFile::Open( const std::string& filename, const char *mode )
|
||||||
|
{
|
||||||
|
if ( IsOpened() )
|
||||||
|
Close() ;
|
||||||
|
|
||||||
|
assert( m_file == 0 ) ;
|
||||||
|
m_file = std::fopen( filename.c_str(), mode ) ;
|
||||||
|
|
||||||
if ( m_file == 0 )
|
if ( m_file == 0 )
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
|
@ -47,10 +67,23 @@ StdioFile::StdioFile( const std::string& filename, const char *mode ) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StdioFile::~StdioFile( )
|
void StdioFile::Open( const fs::path& path, const char *mode )
|
||||||
{
|
{
|
||||||
assert( m_file != 0 ) ;
|
Open( path.string(), mode ) ;
|
||||||
std::fclose( m_file ) ;
|
}
|
||||||
|
|
||||||
|
void StdioFile::Close()
|
||||||
|
{
|
||||||
|
if ( IsOpened() )
|
||||||
|
{
|
||||||
|
std::fclose( m_file ) ;
|
||||||
|
m_file = 0 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StdioFile::IsOpened() const
|
||||||
|
{
|
||||||
|
return m_file != 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t StdioFile::Read( void *ptr, std::size_t size )
|
std::size_t StdioFile::Read( void *ptr, std::size_t size )
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Exception.hh"
|
#include "Exception.hh"
|
||||||
|
#include "FileSystem.hh"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -33,7 +34,13 @@ public :
|
||||||
|
|
||||||
public :
|
public :
|
||||||
StdioFile( const std::string& filename, const char *mode ) ;
|
StdioFile( const std::string& filename, const char *mode ) ;
|
||||||
|
StdioFile( const fs::path& path, const char *mode ) ;
|
||||||
~StdioFile( ) ;
|
~StdioFile( ) ;
|
||||||
|
|
||||||
|
void Open( const std::string& filename, const char *mode ) ;
|
||||||
|
void Open( const boost::filesystem3::path& path, const char* mode ) ;
|
||||||
|
void Close() ;
|
||||||
|
bool IsOpened() const ;
|
||||||
|
|
||||||
std::size_t Read( void *ptr, std::size_t size ) ;
|
std::size_t Read( void *ptr, std::size_t size ) ;
|
||||||
std::size_t Write( const void *ptr, std::size_t size ) ;
|
std::size_t Write( const void *ptr, std::size_t size ) ;
|
||||||
|
|
Loading…
Reference in New Issue