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 ) ;
|
||||
|
||||
int c ;
|
||||
while ((c = getopt(argc, argv, "al:v")) != -1)
|
||||
while ((c = getopt(argc, argv, "al:vV")) != -1)
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
@ -91,6 +91,12 @@ int main( int argc, char **argv )
|
|||
<< "grive version " VERSION " " __DATE__ " " __TIME__ << std::endl ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
case 'V' :
|
||||
{
|
||||
LogBase::Inst()->Enable( log::verbose ) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,9 +123,9 @@ int main( int argc, char **argv )
|
|||
Drive drive( token ) ;
|
||||
|
||||
drive.Update() ;
|
||||
// drive.SaveState() ;
|
||||
drive.SaveState() ;
|
||||
|
||||
config.Save() ;
|
||||
// config.Save() ;
|
||||
}
|
||||
catch ( gr::Exception& e )
|
||||
{
|
||||
|
|
|
@ -92,20 +92,20 @@ Drive::Drive( OAuth2& auth ) :
|
|||
{
|
||||
if ( (*i)["content"] == "" )
|
||||
continue ;
|
||||
|
||||
|
||||
Entry file( *i ) ;
|
||||
if ( file.Kind() != "folder" )
|
||||
{
|
||||
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
|
||||
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() )
|
||||
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() )
|
||||
Log( "entry %1% has parent %2% which is not a folder, ignored",
|
||||
file.Title(), p->Name() ) ;
|
||||
file.Title(), p->Name(), log::info ) ;
|
||||
|
||||
else
|
||||
m_state.FromRemote( file ) ;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "http/StringResponse.hh"
|
||||
#include "http/XmlResponse.hh"
|
||||
#include "protocol/Json.hh"
|
||||
#include "util/CArray.hh"
|
||||
#include "util/Crypt.hh"
|
||||
#include "util/Log.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 ( remote.MD5() == m_entry.MD5() )
|
||||
{
|
||||
Log( "MD5 matches: %1% is already in sync", Name(), log::verbose ) ;
|
||||
m_state = sync ;
|
||||
|
||||
}
|
||||
// use mtime to check which one is more recent
|
||||
else
|
||||
{
|
||||
assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ;
|
||||
|
||||
m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ;
|
||||
Log( "%1% state is %2%", Name(), m_state, log::verbose ) ;
|
||||
}
|
||||
|
||||
m_entry = remote ;
|
||||
|
@ -111,18 +115,30 @@ void Resource::FromLocal()
|
|||
{
|
||||
fs::path path = Path() ;
|
||||
if ( !fs::exists( path ) )
|
||||
{
|
||||
m_state = local_deleted ;
|
||||
Log( "%1% in state but not exist on disk: %2%", Name(), m_state ) ;
|
||||
}
|
||||
|
||||
// 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 ) )
|
||||
{
|
||||
m_state = local_new ;
|
||||
Log( "%1% mtime newer on disk but unchanged: %2%", Name(), m_state ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = local_changed ;
|
||||
Log( "%1% changed on disk: %2%", Name(), m_state ) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_state = local_changed ;
|
||||
{
|
||||
m_state = local_new ;
|
||||
Log( "%1% unchanged on disk: %2%", Name(), m_state ) ;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Resource::SelfHref() const
|
||||
|
@ -214,25 +230,30 @@ void Resource::Sync( http::Agent *http, const http::Headers& auth )
|
|||
switch ( m_state )
|
||||
{
|
||||
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 ;
|
||||
|
||||
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 ) )
|
||||
m_state = sync ;
|
||||
break ;
|
||||
|
||||
case remote_new :
|
||||
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 ) ;
|
||||
m_state = sync ;
|
||||
break ;
|
||||
|
||||
case sync :
|
||||
Trace( "file %1% already in sync", m_entry.Filename() ) ;
|
||||
|
||||
Log( "sync %1% already in sync", m_entry.Filename(), log::verbose ) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
@ -356,6 +377,16 @@ std::size_t Resource::size() const
|
|||
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
|
||||
|
||||
namespace std
|
||||
|
|
|
@ -108,12 +108,14 @@ private :
|
|||
/// Resource exists in both local & remote, but remote is newer.
|
||||
remote_changed
|
||||
} ;
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& os, State s ) ;
|
||||
|
||||
private :
|
||||
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, std::streambuf *file, const http::Headers& auth ) ;
|
||||
|
||||
|
||||
private :
|
||||
Entry m_entry ;
|
||||
|
||||
|
|
|
@ -74,9 +74,12 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
|
|||
|
||||
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 ) ;
|
||||
if ( c == 0 )
|
||||
{
|
||||
Log( "detected new file %1% in local", fname, log::verbose ) ;
|
||||
c = new Resource( i->path() ) ;
|
||||
folder->AddChild( c ) ;
|
||||
m_res.Insert( c ) ;
|
||||
|
|
|
@ -19,22 +19,30 @@
|
|||
|
||||
#include "Crypt.hh"
|
||||
|
||||
#include "StdioFile.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
// dependent libraries
|
||||
#include <openssl/evp.h>
|
||||
|
||||
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 ) ;
|
||||
return MD5( ifile.rdbuf() ) ;
|
||||
try
|
||||
{
|
||||
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] ;
|
||||
EVP_MD_CTX md ;
|
||||
|
@ -42,7 +50,7 @@ std::string MD5( std::streambuf *file )
|
|||
EVP_DigestInit_ex( &md, EVP_md5(), 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 ) ;
|
||||
}
|
||||
|
|
|
@ -20,15 +20,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace gr {
|
||||
|
||||
class StdioFile ;
|
||||
|
||||
namespace crypt
|
||||
{
|
||||
std::string MD5( std::streambuf *file ) ;
|
||||
std::string MD5( StdioFile& file ) ;
|
||||
std::string MD5( const boost::filesystem::path& file ) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ DefaultLog::DefaultLog() :
|
|||
m_log( std::cerr )
|
||||
{
|
||||
m_enabled[log::debug] = false ;
|
||||
m_enabled[log::verbose] = false ;
|
||||
m_enabled[log::info] = true ;
|
||||
m_enabled[log::warning] = true ;
|
||||
m_enabled[log::error] = true ;
|
||||
|
@ -39,6 +40,7 @@ DefaultLog::DefaultLog( const std::string& filename ) :
|
|||
m_log( m_file )
|
||||
{
|
||||
m_enabled[log::debug] = true ;
|
||||
m_enabled[log::verbose] = true ;
|
||||
m_enabled[log::info] = true ;
|
||||
m_enabled[log::warning] = true ;
|
||||
m_enabled[log::error] = true ;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace gr {
|
|||
|
||||
namespace log
|
||||
{
|
||||
enum Serverity { debug, info, warning, error, critical } ;
|
||||
enum Serverity { debug, verbose, info, warning, error, critical } ;
|
||||
typedef boost::format Fmt ;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,9 +32,29 @@
|
|||
|
||||
namespace gr {
|
||||
|
||||
StdioFile::StdioFile( const std::string& filename, const char *mode ) :
|
||||
m_file( std::fopen( filename.c_str(), mode ) )
|
||||
StdioFile::StdioFile( const std::string& filename, const char *mode ) : m_file( 0 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 ) ;
|
||||
std::fclose( m_file ) ;
|
||||
Open( path.string(), mode ) ;
|
||||
}
|
||||
|
||||
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 )
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Exception.hh"
|
||||
#include "FileSystem.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
@ -33,7 +34,13 @@ public :
|
|||
|
||||
public :
|
||||
StdioFile( const std::string& filename, const char *mode ) ;
|
||||
StdioFile( const fs::path& path, const char *mode ) ;
|
||||
~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 Write( const void *ptr, std::size_t size ) ;
|
||||
|
|
Loading…
Reference in New Issue