From f4a7577e50a295212874e60089c03acaa5a9a6b9 Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Wed, 2 May 2012 22:34:18 +0200 Subject: [PATCH 01/79] Don't use the SignalFunctor at all (not an efficient solution) --- libgrive/src/util/SignalHandler.hh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libgrive/src/util/SignalHandler.hh b/libgrive/src/util/SignalHandler.hh index 2ef08675..c110f1fb 100644 --- a/libgrive/src/util/SignalHandler.hh +++ b/libgrive/src/util/SignalHandler.hh @@ -32,14 +32,6 @@ public : virtual ~SignalError() throw () ; }; -class SignalFunctor -{ -public : - SignalFunctor() ; - virtual ~SignalFunctor() ; - static void Callback( int signumber ) ; -}; - class SignalHandler { typedef void (*Callback)(int); From a857cc87c3e133c6fc58f3cfe6c7d7ed5358539d Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Wed, 2 May 2012 22:46:12 +0200 Subject: [PATCH 02/79] Fix typo --- libgrive/src/util/SignalHandler.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgrive/src/util/SignalHandler.hh b/libgrive/src/util/SignalHandler.hh index c110f1fb..3f425017 100644 --- a/libgrive/src/util/SignalHandler.hh +++ b/libgrive/src/util/SignalHandler.hh @@ -42,10 +42,11 @@ public : void RegisterSignal ( unsigned int signumber, Callback callback ) ; void UnregisterSignal( unsigned int signumber ); static SignalHandler& GetInstance() ; + private : SignalHandler() ; SignalHandler( const SignalHandler& right ) ; - SignalHandler& operator==( const SignalHandler& right ) ; + SignalHandler& operator=( const SignalHandler& right ) ; signals_t m_signals; signals_t m_signalsOld; From 1986660d919902615a236df068438c0c4d0f03ff Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Wed, 2 May 2012 22:46:52 +0200 Subject: [PATCH 03/79] Use the map properly + remove the singleton unwanted methods --- libgrive/src/util/SignalHandler.cc | 35 +++++++++--------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/libgrive/src/util/SignalHandler.cc b/libgrive/src/util/SignalHandler.cc index 43328ee1..d1d2316d 100644 --- a/libgrive/src/util/SignalHandler.cc +++ b/libgrive/src/util/SignalHandler.cc @@ -42,15 +42,6 @@ SignalHandler::SignalHandler() } -SignalHandler::SignalHandler( const SignalHandler& right ) -{ - -} - -SignalHandler& SignalHandler::operator ==( const SignalHandler& right ) -{ - return (*this); -} SignalHandler::~SignalHandler() { @@ -65,31 +56,25 @@ SignalHandler& SignalHandler::GetInstance() void SignalHandler::UnregisterSignal( unsigned int signumber ) { - m_signals[signumber] = 0 ; - - // Restore the old signal - signal( ( int ) signumber, m_signalsOld[signumber] ); + if ( m_signals.erase( signumber ) ) + { + signal( ( int ) signumber, m_signalsOld[signumber] ); + } } void SignalHandler::RegisterSignal( unsigned int signumber, Callback callback ) { - signals_t::const_iterator anIterator ; - for (anIterator = m_signals.begin(); anIterator != m_signals.end(); ++anIterator) + if ( m_signals.find( signumber ) != m_signals.end() ) { - if (anIterator->first == signumber) - { - if (anIterator->second != 0) - { - std::ostringstream oss; - oss << "Signal " << signumber << " already has a callback!"; - throw SignalError( oss.str() ); ; - } - } + std::ostringstream oss; + oss << "Signal " << signumber << " already has a callback!"; + throw SignalError( oss.str() ); ; } m_signals[signumber] = callback ; - if ( ( m_signalsOld[signumber] = signal( ( int ) signumber, m_signals[signumber] ) ) == SIG_ERR ) { + if ( ( m_signalsOld[signumber] = signal( ( int ) signumber, m_signals[signumber] ) ) == SIG_ERR ) + { throw SignalError( " Error while registering the signal! " ) ; } } From f9c710d8faba1222580042a00b53b7e1dedd02b3 Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Wed, 2 May 2012 23:55:55 +0200 Subject: [PATCH 04/79] Improve the unit test (output a report.xml file) --- libgrive/test/UnitTest.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libgrive/test/UnitTest.cc b/libgrive/test/UnitTest.cc index 4670ced5..2215dbcd 100644 --- a/libgrive/test/UnitTest.cc +++ b/libgrive/test/UnitTest.cc @@ -18,6 +18,10 @@ */ #include +#include +#include + +#include #include "util/DateTimeTest.hh" #include "util/FunctionTest.hh" @@ -34,6 +38,11 @@ int main( int argc, char **argv ) runner.addTest( PathTest::suite( ) ) ; runner.addTest( SignalHandlerTest::suite( ) ) ; runner.run(); + + std::ofstream report_file( "report.xml" ) ; + CppUnit::XmlOutputter xmloutputter ( &runner.result( ), report_file ) ; + xmloutputter.write( ) ; + report_file.close( ) ; return 0 ; } From 8107d081bc47e2cc0ea57532dc4d5d3b658fc9b3 Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Thu, 3 May 2012 19:12:32 +0200 Subject: [PATCH 05/79] Declare the RegisterSignal() as throwing SignalError --- libgrive/src/util/SignalHandler.cc | 2 +- libgrive/src/util/SignalHandler.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgrive/src/util/SignalHandler.cc b/libgrive/src/util/SignalHandler.cc index d1d2316d..34745752 100644 --- a/libgrive/src/util/SignalHandler.cc +++ b/libgrive/src/util/SignalHandler.cc @@ -62,7 +62,7 @@ void SignalHandler::UnregisterSignal( unsigned int signumber ) } } -void SignalHandler::RegisterSignal( unsigned int signumber, Callback callback ) +void SignalHandler::RegisterSignal( unsigned int signumber, Callback callback ) throw ( SignalError ) { if ( m_signals.find( signumber ) != m_signals.end() ) { diff --git a/libgrive/src/util/SignalHandler.hh b/libgrive/src/util/SignalHandler.hh index 3f425017..19f0a97d 100644 --- a/libgrive/src/util/SignalHandler.hh +++ b/libgrive/src/util/SignalHandler.hh @@ -39,7 +39,7 @@ class SignalHandler public : virtual ~SignalHandler() ; - void RegisterSignal ( unsigned int signumber, Callback callback ) ; + void RegisterSignal ( unsigned int signumber, Callback callback ) throw ( SignalError ); void UnregisterSignal( unsigned int signumber ); static SignalHandler& GetInstance() ; From 628cfe4b0f39a08305f224375de1b032dd484485 Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Thu, 3 May 2012 19:23:43 +0200 Subject: [PATCH 06/79] Gracefully fail if an error occurs --- grive/src/main.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/grive/src/main.cc b/grive/src/main.cc index ef14874f..b8910ec6 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -130,8 +130,15 @@ int main( int argc, char **argv ) return -1; } - OAuth2 token( refresh_token, client_id, client_secret ) ; - Drive drive( token ) ; + try + { + OAuth2 token( refresh_token, client_id, client_secret ) ; + Drive drive( token ) ; + } + catch ( const std::exception& exception ) + { + std::cerr << "Exception caught: " << exception.what( ) << std::endl; + } return 0 ; } From 4b35a0dccb2264ef5ffa6e948593060af616d4da Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Sun, 6 May 2012 21:42:39 +0200 Subject: [PATCH 07/79] Slowly start building the GUI (created sources' tree, cmakes, ...) --- CMakeLists.txt | 10 ++++ qgrive/CMakeLists.txt | 29 +++++++++++ qgrive/include/QGriveApplication.hh | 44 ++++++++++++++++ qgrive/include/QGriveMainWindow.hh | 37 +++++++++++++ qgrive/src/QGriveApplication.cc | 81 +++++++++++++++++++++++++++++ qgrive/src/QGriveMainWindow.cc | 57 ++++++++++++++++++++ qgrive/src/main.cc | 23 ++++++++ qgrive/ui/mainwindow.ui | 75 ++++++++++++++++++++++++++ 8 files changed, 356 insertions(+) create mode 100644 qgrive/CMakeLists.txt create mode 100644 qgrive/include/QGriveApplication.hh create mode 100644 qgrive/include/QGriveMainWindow.hh create mode 100644 qgrive/src/QGriveApplication.cc create mode 100644 qgrive/src/QGriveMainWindow.cc create mode 100644 qgrive/src/main.cc create mode 100644 qgrive/ui/mainwindow.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 73103082..fbdcd08c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,3 +2,13 @@ cmake_minimum_required(VERSION 2.8) add_subdirectory( libgrive ) add_subdirectory( grive ) + + +## Check if QT4 exists before trying to build +find_package(Qt4) +if (QT4_FOUND) + message("-- Qt4 found: building QGrive") + add_subdirectory( qgrive ) +else (QT4_FOUND) + message("-- Qt4 not found, the GUI won't be build") +endif(QT4_FOUND) diff --git a/qgrive/CMakeLists.txt b/qgrive/CMakeLists.txt new file mode 100644 index 00000000..56f882ac --- /dev/null +++ b/qgrive/CMakeLists.txt @@ -0,0 +1,29 @@ +## QGrive, Qt interface for libgrive +project ( qgrive ) + +## Declare sources and headers +file( GLOB QGRIVE_SOURCES + src/*.cc +) + +file( GLOB QGRIVE_HEADERS + include/*.hh +) + +include( ${QT_USE_FILE} ) +include_directories( + ${libgrive_SOURCE_DIR}/src + ${qgrive_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_definitions( ${QT_DEFINITIONS} ) + +## Generate moc files +qt4_wrap_cpp ( QGRIVE_HEADERS_MOC ${QGRIVE_HEADERS} ) + +## Generate the .ui file +qt4_wrap_ui ( QGRIVE_HEADERS_UI ui/mainwindow.ui ) + +add_executable( qgrive ${QGRIVE_SOURCES} ${QGRIVE_HEADERS_MOC} ${QGRIVE_HEADERS_UI} ) +target_link_libraries( qgrive ${QT_LIBRARIES} grive ) \ No newline at end of file diff --git a/qgrive/include/QGriveApplication.hh b/qgrive/include/QGriveApplication.hh new file mode 100644 index 00000000..720b836c --- /dev/null +++ b/qgrive/include/QGriveApplication.hh @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include + +class QGriveException : public std::runtime_error +{ +public: + explicit QGriveException( const std::string& exception_msg ) ; + virtual ~QGriveException( ) throw( ) ; + const char* what( ) const throw( ) ; + +private: + std::string _exception_msg; +}; + + +class QGriveApplication : public QApplication +{ +public: + explicit QGriveApplication( int argc, char *argv[] ) ; + virtual ~QGriveApplication( ) ; + + void setup_environment( ) throw ( QGriveException ) ; + int exec( ) ; + + // Logging facility + friend std::ostream& operator<<( std::ostream& os, + const QGriveApplication& application ) ; + +private: + bool _config_by_env; + bool _config_by_file; + std::string _config_file; + std::string _config_env; + QGriveMainWindow _main_window; + gr::Json _configuration; +}; diff --git a/qgrive/include/QGriveMainWindow.hh b/qgrive/include/QGriveMainWindow.hh new file mode 100644 index 00000000..ca02a9b0 --- /dev/null +++ b/qgrive/include/QGriveMainWindow.hh @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include +#include +#include + +// Forward declarations for Qt generated files +namespace Ui { + class QGriveMainWindow; +} + +class QGriveMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit QGriveMainWindow( ); + virtual ~QGriveMainWindow( ); + + void activate_log( ) ; + +signals: + +public slots: + +private slots: + void refresh_tree( ) ; + void sync_directory( ) ; + +private: + Ui::QGriveMainWindow* ui ; + + bool _log_activated ; +}; diff --git a/qgrive/src/QGriveApplication.cc b/qgrive/src/QGriveApplication.cc new file mode 100644 index 00000000..4e0a62b2 --- /dev/null +++ b/qgrive/src/QGriveApplication.cc @@ -0,0 +1,81 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +QGriveException::QGriveException( const std::string& exception_msg ) + : std::runtime_error( exception_msg ), + _exception_msg( exception_msg ) +{ + +} + + +QGriveException::~QGriveException( ) throw ( ) +{ + +} + +const char* QGriveException::what( ) const throw( ) +{ + return _exception_msg.c_str() ; +} + +std::ostream& operator<<( std::ostream& os, + const QGriveApplication& application ) +{ + if ( application._config_by_env ) + { + os << "Using env: " << application._config_env ; + } + + else + { + os << "Using file: " << application._config_file ; + } + + return os ; +} + + +QGriveApplication::QGriveApplication( int argc, char *argv[] ) + : QApplication( argc, argv ), + _config_by_env( false ), + _config_by_file( false ) +{ + +} + +QGriveApplication::~QGriveApplication() +{ + +} + +void QGriveApplication::setup_environment( ) throw ( QGriveException ) +{ + const char* env_cfg = getenv( "GR_CONFIG" ) ; + + if ( env_cfg ) + { + _config_env = getenv( "GR_CONFIG" ) ; + _config_by_env = true ; + } + else + { + _config_file = getenv( "HOME" ) ; + _config_file += "/.grive" ; + _config_by_file = true ; + } +} + +int QGriveApplication::exec( ) +{ + _main_window.show( ) ; + _main_window.activate_log( ) ; + return QApplication::exec( ) ; +} diff --git a/qgrive/src/QGriveMainWindow.cc b/qgrive/src/QGriveMainWindow.cc new file mode 100644 index 00000000..2ef4ee65 --- /dev/null +++ b/qgrive/src/QGriveMainWindow.cc @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include "ui_mainwindow.h" + + +QGriveMainWindow::QGriveMainWindow( ) : + QMainWindow(0), + ui(new Ui::QGriveMainWindow), + _log_activated(false) +{ + ui->setupUi(this); + + QObject::connect( ui->refresh_btn, + SIGNAL(clicked()), + this, + SLOT(refresh_tree()) ) ; + + QObject::connect( ui->launch_sync_btn, + SIGNAL(clicked()), + this, + SLOT(sync_directory()) ) ; + + ui->statusbar->setEnabled( true ) ; + ui->statusbar->addWidget( new QLabel(" Welcome to QGrive!! ") ) ; +} + +QGriveMainWindow::~QGriveMainWindow( ) +{ + +} + +void QGriveMainWindow::activate_log( ) +{ + _log_activated = true ; + std::cout << "LOG ACTIVATED" << std::endl ; +} + +void QGriveMainWindow::refresh_tree( ) +{ + if (_log_activated) + { + std::cout << "refresh_tree()" << std::endl; + } +} + +void QGriveMainWindow::sync_directory( ) +{ + if (_log_activated) + { + std::cout << "sync_directory()" << std::endl; + } + +} diff --git a/qgrive/src/main.cc b/qgrive/src/main.cc new file mode 100644 index 00000000..a55c4722 --- /dev/null +++ b/qgrive/src/main.cc @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +int main ( int argc, char *argv[] ) +{ + QGriveApplication app( argc, argv ) ; + app.setup_environment( ) ; + + std::ofstream log_file( "qgrive.log", std::ios_base::out|std::ios_base::app ) ; + log_file << " ==== starting log ====" << std::endl ; + + log_file << app << std::endl ; + + int ret_value = app.exec( ) ; + + log_file << " ==== closing log ====" << std::endl << std::endl ; + log_file.close( ) ; + + return ret_value; +} diff --git a/qgrive/ui/mainwindow.ui b/qgrive/ui/mainwindow.ui new file mode 100644 index 00000000..f38b701c --- /dev/null +++ b/qgrive/ui/mainwindow.ui @@ -0,0 +1,75 @@ + + + QGriveMainWindow + + + + 0 + 0 + 586 + 407 + + + + QGrive + + + + + + + + + + 1 + + + + + + + + QTextEdit::NoWrap + + + true + + + + + + + + + + + Refresh + + + + + + + Launch sync + + + + + + + + + + + 0 + 0 + 586 + 22 + + + + + + + + From d1fb3781656e102c9dfe31d96dc5d5d13f285a1a Mon Sep 17 00:00:00 2001 From: Massimo Gengarelli Date: Sun, 6 May 2012 21:45:29 +0200 Subject: [PATCH 08/79] Insert license --- qgrive/include/QGriveApplication.hh | 20 ++++++++++++++++++++ qgrive/include/QGriveMainWindow.hh | 20 ++++++++++++++++++++ qgrive/src/QGriveApplication.cc | 20 ++++++++++++++++++++ qgrive/src/QGriveMainWindow.cc | 20 ++++++++++++++++++++ qgrive/src/main.cc | 20 ++++++++++++++++++++ 5 files changed, 100 insertions(+) diff --git a/qgrive/include/QGriveApplication.hh b/qgrive/include/QGriveApplication.hh index 720b836c..6872f41b 100644 --- a/qgrive/include/QGriveApplication.hh +++ b/qgrive/include/QGriveApplication.hh @@ -1,3 +1,23 @@ +/* + qgrive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) + Copyright (C) 2012 Massimo Gengarelli (qgrive) + + 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 diff --git a/qgrive/include/QGriveMainWindow.hh b/qgrive/include/QGriveMainWindow.hh index ca02a9b0..c3c04ef1 100644 --- a/qgrive/include/QGriveMainWindow.hh +++ b/qgrive/include/QGriveMainWindow.hh @@ -1,3 +1,23 @@ +/* + qgrive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) + Copyright (C) 2012 Massimo Gengarelli (qgrive) + + 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 diff --git a/qgrive/src/QGriveApplication.cc b/qgrive/src/QGriveApplication.cc index 4e0a62b2..f5ceda78 100644 --- a/qgrive/src/QGriveApplication.cc +++ b/qgrive/src/QGriveApplication.cc @@ -1,3 +1,23 @@ +/* + qgrive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) + Copyright (C) 2012 Massimo Gengarelli (qgrive) + + 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 #include diff --git a/qgrive/src/QGriveMainWindow.cc b/qgrive/src/QGriveMainWindow.cc index 2ef4ee65..654310d4 100644 --- a/qgrive/src/QGriveMainWindow.cc +++ b/qgrive/src/QGriveMainWindow.cc @@ -1,3 +1,23 @@ +/* + qgrive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) + Copyright (C) 2012 Massimo Gengarelli (qgrive) + + 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 #include #include diff --git a/qgrive/src/main.cc b/qgrive/src/main.cc index a55c4722..0f00709c 100644 --- a/qgrive/src/main.cc +++ b/qgrive/src/main.cc @@ -1,3 +1,23 @@ +/* + qgrive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) + Copyright (C) 2012 Massimo Gengarelli (qgrive) + + 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 #include #include From e2950364da813a5b27eab90c51cbea69fb3fd1f9 Mon Sep 17 00:00:00 2001 From: Christoph Junghans Date: Fri, 2 Nov 2012 21:56:41 -0600 Subject: [PATCH 09/79] Check if bfd.h can be included (fixes #72) --- cmake/Modules/FindBFD.cmake | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindBFD.cmake b/cmake/Modules/FindBFD.cmake index 785e29b6..5fe43c14 100644 --- a/cmake/Modules/FindBFD.cmake +++ b/cmake/Modules/FindBFD.cmake @@ -1,9 +1,15 @@ find_library( DL_LIBRARY NAMES dl PATH /usr/lib /usr/lib64 ) find_library( BFD_LIBRARY NAMES bfd PATH /usr/lib /usr/lib64 ) -if ( DL_LIBRARY AND BFD_LIBRARY ) +include(CheckCSourceCompiles) +check_c_source_compiles( + "#include + int main(void) { + return 0; + }" BFD_WORKS) +if ( DL_LIBRARY AND BFD_LIBRARY AND BFD_WORKS) set( BFD_FOUND TRUE ) -endif (DL_LIBRARY AND BFD_LIBRARY) +endif (DL_LIBRARY AND BFD_LIBRARY AND BFD_WORKS) if ( BFD_FOUND ) From 3f2cc92ce2176864ddec517a32a7de2377a1e858 Mon Sep 17 00:00:00 2001 From: Jarek Sedlacek Date: Thu, 6 Dec 2012 12:52:39 -0500 Subject: [PATCH 10/79] Fix binutils compilation error bfd.h now required PACKAGE and PACKAGE_VERSION to be defined, set these in CMakeList.txt --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index def7ca00..6128ea09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,5 +7,9 @@ set( GRIVE_VERSION "0.3.0-pre" ) add_definitions( -DVERSION="${GRIVE_VERSION}" ) add_definitions( -D_FILE_OFFSET_BITS=64 ) +# Package name and version for libraries depending on autotools +add_definitions( -DPACKAGE="grive" ) +add_definitions( -DPACKAGE_VERSION="${GRIVE_VERSION}" ) + add_subdirectory( libgrive ) add_subdirectory( grive ) From 422fae02c729b0d2d8b130dc8c5fa27dd2c58afd Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Sun, 26 May 2013 11:41:41 +0300 Subject: [PATCH 11/79] YAJL is required to build. --- README | 3 ++- cmake/Modules/FindYAJL.cmake | 30 ++++++++++++++++++++++++++++++ libgrive/CMakeLists.txt | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 cmake/Modules/FindYAJL.cmake diff --git a/README b/README index a713a75c..68af0a73 100644 --- a/README +++ b/README @@ -24,6 +24,7 @@ You need the following libraries: - libstdc++ - libgcrypt - Boost (Boost filesystem and program_option are required) +- yajl There are also some optional dependencies: - CppUnit (for unit tests) @@ -59,4 +60,4 @@ Fixed bugs: New features: #87: support for revisions #86: partial sync (contributed by justin at tierramedia.com) - \ No newline at end of file + diff --git a/cmake/Modules/FindYAJL.cmake b/cmake/Modules/FindYAJL.cmake new file mode 100644 index 00000000..52b0bf10 --- /dev/null +++ b/cmake/Modules/FindYAJL.cmake @@ -0,0 +1,30 @@ +# - Find YAJL +# This module finds an installed YAJL package. +# +# It sets the following variables: +# YAJL_FOUND - Set to false, or undefined, if YAJL isn't found. +# YAJL_INCLUDE_DIR - The YAJL include directory. +# YAJL_LIBRARY - The YAJL library to link against. + +FIND_PATH(YAJL_INCLUDE_DIR yajl/yajl_common.h) +FIND_LIBRARY(YAJL_LIBRARY NAMES yajl) + +IF (YAJL_INCLUDE_DIR AND YAJL_LIBRARY) + SET(YAJL_FOUND TRUE) +ENDIF (YAJL_INCLUDE_DIR AND YAJL_LIBRARY) + +IF (YAJL_FOUND) + + # show which YAJL was found only if not quiet + IF (NOT YAJL_FIND_QUIETLY) + MESSAGE(STATUS "Found YAJL: ${YAJL_LIBRARY}") + ENDIF (NOT YAJL_FIND_QUIETLY) + +ELSE (YAJL_FOUND) + + # fatal error if YAJL is required but not found + IF (YAJL_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find YAJL") + ENDIF (YAJL_FIND_REQUIRED) + +ENDIF (YAJL_FOUND) diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index 3cc15742..111d4be2 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -7,6 +7,7 @@ find_package(JSONC REQUIRED) find_package(CURL REQUIRED) find_package(EXPAT REQUIRED) find_package(Boost 1.40.0 COMPONENTS program_options filesystem unit_test_framework system REQUIRED) +find_package(YAJL REQUIRED) find_package(BFD) find_package(CppUnit) find_package(Iberty) From f6947a35150fe5780d7612899d4ce68c00a7dfb2 Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Sun, 26 May 2013 18:25:12 +0300 Subject: [PATCH 12/79] No man page to install for bgrive. --- bgrive/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..7bb32692 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -40,4 +40,3 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) From c543b989c86890df7d3811b21eeb4c6b7b13a2b1 Mon Sep 17 00:00:00 2001 From: Jarek Sedlacek Date: Tue, 18 Jun 2013 10:37:13 -0400 Subject: [PATCH 13/79] Fixed casting bug --- libgrive/src/drive/State.cc | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..6413ff4b 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -38,12 +38,12 @@ State::State( const fs::path& filename, const Json& options ) : m_cstamp ( -1 ) { Read( filename ) ; - + // the "-f" option will make grive always thinks remote is newer Json force ; if ( options.Get("force", force) && force.Bool() ) m_last_sync = DateTime() ; - + Log( "last sync time: %1%", m_last_sync, log::verbose ) ; } @@ -67,21 +67,21 @@ void State::FromLocal( const fs::path& p, Resource* folder ) { assert( folder != 0 ) ; assert( folder->IsFolder() ) ; - + // sync the folder itself folder->FromLocal( m_last_sync ) ; for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i ) { std::string fname = i->path().filename().string() ; - + if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; - + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; - + else { // if the Resource object of the child already exists, it should @@ -93,9 +93,9 @@ void State::FromLocal( const fs::path& p, Resource* folder ) folder->AddChild( c ) ; m_res.Insert( c ) ; } - - c->FromLocal( m_last_sync ) ; - + + c->FromLocal( m_last_sync ) ; + if ( fs::is_directory( i->path() ) ) FromLocal( *i, c ) ; } @@ -104,7 +104,7 @@ void State::FromLocal( const fs::path& p, Resource* folder ) void State::FromRemote( const Entry& e ) { - std::string fn = e.Filename() ; + std::string fn = e.Filename() ; if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; @@ -112,10 +112,10 @@ void State::FromRemote( const Entry& e ) // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; - + else if ( fn.find('/') != fn.npos ) Log( "%1% \"%2%\" contains a slash in its name, ignored", e.Kind(), e.Name(), log::verbose ) ; - + else if ( !e.IsChange() && e.ParentHrefs().size() != 1 ) Log( "%1% \"%2%\" has multiple parents, ignored", e.Kind(), e.Name(), log::verbose ) ; @@ -143,7 +143,7 @@ std::size_t State::TryResolveEntry() std::size_t count = 0 ; std::vector& en = m_unresolved ; - + for ( std::vector::iterator i = en.begin() ; i != en.end() ; ) { if ( Update( *i ) ) @@ -161,7 +161,7 @@ void State::FromChange( const Entry& e ) { assert( e.IsChange() ) ; assert( !IsIgnore( e.Name() ) ) ; - + // entries in the change feed is always treated as newer in remote, // so we override the last sync time to 0 if ( Resource *res = m_res.FindByHref( e.AltSelf() ) ) @@ -190,7 +190,7 @@ bool State::Update( const Entry& e ) // since we are updating the ID and Href, we need to remove it and re-add it. m_res.Update( child, e, m_last_sync ) ; } - + // folder entry exist in google drive, but not local. we should create // the directory else if ( e.Kind() == "folder" || !e.Filename().empty() ) @@ -199,11 +199,11 @@ bool State::Update( const Entry& e ) child = new Resource( name, e.Kind() ) ; parent->AddChild( child ) ; m_res.Insert( child ) ; - + // update the state of the resource m_res.Update( child, e, m_last_sync ) ; } - + return true ; } else @@ -231,12 +231,12 @@ void State::Read( const fs::path& filename ) { File file( filename ) ; Json json = Json::Parse( &file ) ; - + Json last_sync = json["last_sync"] ; m_last_sync.Assign( last_sync["sec"].Int(), last_sync["nsec"].Int() ) ; - + m_cstamp = json["change_stamp"].Int() ; } catch ( Exception& ) @@ -248,13 +248,13 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; - last_sync.Add( "sec", Json(m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json(m_last_sync.NanoSec() ) ); - + last_sync.Add( "sec", Json((boost::uint64_t) m_last_sync.Sec() ) ); + last_sync.Add( "nsec", Json((boost::uint64_t) m_last_sync.NanoSec() ) ); + Json result ; result.Add( "last_sync", last_sync ) ; - result.Add( "change_stamp", Json(m_cstamp) ) ; - + result.Add( "change_stamp", Json((boost::uint64_t) m_cstamp) ) ; + std::ofstream fs( filename.string().c_str() ) ; fs << result ; } @@ -270,7 +270,7 @@ void State::Sync( http::Agent *http, const Json& options ) // need to check if this introduces a new problem DateTime last_sync_time = m_last_sync; m_res.Root()->Sync( http, last_sync_time, options ) ; - + if ( last_sync_time == m_last_sync ) { Trace( "nothing changed? %1%", m_last_sync ) ; From 49992c3a416f2c95b69621f464abe260bf11f33e Mon Sep 17 00:00:00 2001 From: Jarek Sedlacek Date: Tue, 18 Jun 2013 10:48:20 -0400 Subject: [PATCH 14/79] removed bgrive man1 page, it doesn't exist --- bgrive/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..47841767 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -19,7 +19,7 @@ file (GLOB BGRIVE_UI ) QT4_WRAP_UI(BGRIVE_UI_SRCS ${BGRIVE_UI}) -QT4_WRAP_CPP(BGRIVE_MOC_SRCS +QT4_WRAP_CPP(BGRIVE_MOC_SRCS src/MainWnd.hh ) add_executable( bgrive_executable @@ -40,4 +40,3 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) From 049af024c55959ab806447fdd2ece68b97cb67bf Mon Sep 17 00:00:00 2001 From: vehre Date: Fri, 21 Jun 2013 17:09:09 +0100 Subject: [PATCH 15/79] Fixed make on fedora 17. --- bgrive/CMakeLists.txt | 3 ++- package/fedora16/grive.spec | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..5190e91a 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -40,4 +40,5 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) +# The man package is missing. +#install(FILES doc/grive.1 DESTINATION share/man/man1 )diff --git a/package/fedora16/grive.spec b/package/fedora16/grive.spec diff --git a/package/fedora16/grive.spec b/package/fedora16/grive.spec index 03770b9d..556cdc80 100644 --- a/package/fedora16/grive.spec +++ b/package/fedora16/grive.spec @@ -36,6 +36,7 @@ BuildRequires: expat-devel BuildRequires: openssl-devel BuildRequires: boost-devel BuildRequires: binutils-devel +BuildRequires: yajl-devel %description The purpose of this project is to provide an independent implementation @@ -63,19 +64,24 @@ make %{?_smp_mflags} rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT -%post -p /sbin/ldconfig +# As long as no dynamic libs are build omit ldconfig and the glob for them. +#%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig +#%postun -p /sbin/ldconfig %files -%doc COPYING README +%doc COPYING README %{_bindir}/%{name} -%{_libdir}/libgrive.so.* +%{_bindir}/b%{name} +%{_mandir}/man1/%{name}.1.gz -%files devel -%{_includedir}/%{name}* -%{_libdir}/libgrive.so +#%{_libdir}/libgrive.so.* + +# Files are not installed by cmake currently. +#%files devel +#%{_includedir}/%{name}* +#%{_libdir}/libgrive.so From 9db560006f36ba22305a1d36895d5b98ac436a1a Mon Sep 17 00:00:00 2001 From: Juan Orti Alcaine Date: Wed, 3 Jul 2013 10:05:44 +0200 Subject: [PATCH 16/79] Fix json-c library path --- cmake/Modules/FindJSONC.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index f72e8ea1..8e4f1fc9 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -6,8 +6,8 @@ # JSONC_INCLUDE_DIR - The JSON-C include directory. # JSONC_LIBRARY - The JSON-C library to link against. -FIND_PATH(JSONC_INCLUDE_DIR json/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json) +FIND_PATH(JSONC_INCLUDE_DIR json-c/json.h) +FIND_LIBRARY(JSONC_LIBRARY NAMES json-c) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From 452b130b1baa32275bae211aeeda2a809e22ab58 Mon Sep 17 00:00:00 2001 From: Juan Orti Alcaine Date: Wed, 3 Jul 2013 11:07:13 +0200 Subject: [PATCH 17/79] bgrive tries to install grive man page --- bgrive/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..7bb32692 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -40,4 +40,3 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) From 8d0716cb08b38e1e49b1fe3a14c1dd773f17f369 Mon Sep 17 00:00:00 2001 From: vehre Date: Wed, 10 Jul 2013 15:18:07 +0200 Subject: [PATCH 18/79] Fedora 19 has json-c as library libjson-c and no longer as libjson. Fixed cmake module to respect this change. --- cmake/Modules/FindJSONC.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index f72e8ea1..ed6f0f09 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -7,7 +7,7 @@ # JSONC_LIBRARY - The JSON-C library to link against. FIND_PATH(JSONC_INCLUDE_DIR json/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json) +FIND_LIBRARY(JSONC_LIBRARY NAMES json-c json) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From 752eb3fddaac72f26047ffb46e3e76c4a13908bf Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 8 Sep 2013 02:36:30 +0400 Subject: [PATCH 19/79] Allow to sync just one directory in the root --- grive/src/main.cc | 1 + libgrive/src/drive/State.cc | 9 +++++++++ libgrive/src/drive/State.hh | 1 + libgrive/src/util/Config.cc | 3 +++ 4 files changed, 14 insertions(+) diff --git a/grive/src/main.cc b/grive/src/main.cc index 5209c941..b7b25852 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -110,6 +110,7 @@ int Main( int argc, char **argv ) ( "version,v", "Display Grive version" ) ( "auth,a", "Request authorization token" ) ( "path,p", po::value(), "Path to sync") + ( "dir,s", po::value(), "Subdirectory to sync") ( "verbose,V", "Verbose mode. Enable more messages than normal.") ( "log-xml", "Log more HTTP responses as XML for debugging.") ( "new-rev", "Create new revisions in server for updated files.") diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..cf0c30bd 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -35,6 +35,7 @@ namespace gr { namespace v1 { State::State( const fs::path& filename, const Json& options ) : m_res ( options["path"].Str() ), + m_dir ( options["dir"].Str() ), m_cstamp ( -1 ) { Read( filename ) ; @@ -78,6 +79,10 @@ void State::FromLocal( const fs::path& p, Resource* folder ) if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; + // check if it is ignored + else if ( folder == m_res.Root() && m_dir != "" && fname != m_dir ) + Log( "%1% %2% is ignored", fs::is_directory(i->path()) ? "folder" : "file", fname, log::verbose ); + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; @@ -109,6 +114,10 @@ void State::FromRemote( const Entry& e ) if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; + // check if it is ignored + else if ( e.ParentHref() == m_res.Root()->SelfHref() && m_dir != "" && e.Name() != m_dir ) + Log( "%1% %2% is ignored", e.Kind(), e.Name(), log::verbose ); + // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index 8c641892..98cce39a 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -79,6 +79,7 @@ private : ResourceTree m_res ; DateTime m_last_sync ; long m_cstamp ; + std::string m_dir ; std::vector m_unresolved ; } ; diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index b5a9f15b..12c22c76 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -42,6 +42,9 @@ Config::Config( const po::variables_map& vm ) m_cmd.Add( "path", Json(vm.count("path") > 0 ? vm["path"].as() : default_root_folder ) ) ; + m_cmd.Add( "dir", Json(vm.count("dir") > 0 + ? vm["dir"].as() + : "" ) ) ; m_path = GetPath( fs::path(m_cmd["path"].Str()) ) ; m_file = Read( ) ; From 3fa56d47bc1d573f68320064e70fd50d76a17988 Mon Sep 17 00:00:00 2001 From: Drew Date: Wed, 25 Sep 2013 10:11:53 +0100 Subject: [PATCH 20/79] Update State.cc Added (boost::uint64_t) to State:Write for correct size of int --- libgrive/src/drive/State.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..38e83357 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -248,11 +248,12 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; - last_sync.Add( "sec", Json(m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json(m_last_sync.NanoSec() ) ); - - Json result ; - result.Add( "last_sync", last_sync ) ; + last_sync.Add( "sec", Json((boost::uint64_t)m_last_sync.Sec() ) ); + last_sync.Add( "nsec", Json((boost::uint64_t)m_last_sync.NanoSec() ) ); + + Json result ; + result.Add( "last_sync", last_sync ) ; + result.Add( "change_stamp", Json((boost::uint64_t)m_cstamp) ) ; result.Add( "change_stamp", Json(m_cstamp) ) ; std::ofstream fs( filename.string().c_str() ) ; From 2562c8d3f190a905c5ac267a6b07df890b870397 Mon Sep 17 00:00:00 2001 From: Drew Date: Wed, 23 Oct 2013 14:16:03 +0100 Subject: [PATCH 21/79] Update State.cc --- libgrive/src/drive/State.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 38e83357..f08d4d34 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -252,9 +252,8 @@ void State::Write( const fs::path& filename ) const last_sync.Add( "nsec", Json((boost::uint64_t)m_last_sync.NanoSec() ) ); Json result ; - result.Add( "last_sync", last_sync ) ; - result.Add( "change_stamp", Json((boost::uint64_t)m_cstamp) ) ; - result.Add( "change_stamp", Json(m_cstamp) ) ; + result.Add( "last_sync", last_sync ) ; + result.Add( "change_stamp", Json((boost::uint64_t) m_cstamp) ) ; std::ofstream fs( filename.string().c_str() ) ; fs << result ; From 47c64925ac727be31459703e714ca24fc6616548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20B=C5=82aszczyk?= Date: Tue, 19 Nov 2013 18:48:09 +0100 Subject: [PATCH 22/79] Define PACKAGE & PACKAGE_VERSION for bfd. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f1460b..60a3b09e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ set( GRIVE_VERSION "0.3.0-pre" ) # common compile options add_definitions( -DVERSION="${GRIVE_VERSION}" ) +add_definitions( -DPACKAGE="grive" ) +add_definitions( -DPACKAGE_VERSION="${GRIVE_VERSION}" ) add_definitions( -D_FILE_OFFSET_BITS=64 ) add_subdirectory( libgrive ) From 84aebfe632a4ca6a16d62f2cf0e25e2a52c005c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20B=C5=82aszczyk?= Date: Tue, 19 Nov 2013 18:49:42 +0100 Subject: [PATCH 23/79] Add json-c as primary name for JSONC_LIBRARY. --- cmake/Modules/FindJSONC.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index f72e8ea1..ed6f0f09 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -7,7 +7,7 @@ # JSONC_LIBRARY - The JSON-C library to link against. FIND_PATH(JSONC_INCLUDE_DIR json/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json) +FIND_LIBRARY(JSONC_LIBRARY NAMES json-c json) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From 89506b4162935e529b90f16afa059e36a27c18f0 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Sun, 24 Nov 2013 14:22:49 +0200 Subject: [PATCH 24/79] Add autogenerated stuff to .gitignore --- .gitignore | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index da71e17a..6fa3768d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,13 @@ grive.kdev4 .project .cproject build/ +/CMakeCache.txt +CMakeFiles +moc_*.cxx* +bgrive/ui_MainWindow.h +Makefile +*.a +bgrive/bgrive +grive/grive +libgrive/btest +*.cmake From c15bfbe8bc93e4d59810a0c47225e98fd8269428 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Sun, 24 Nov 2013 14:25:01 +0200 Subject: [PATCH 25/79] Ignore only .grive and .grive_state --- libgrive/src/drive/State.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..124adecc 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -60,7 +60,7 @@ void State::FromLocal( const fs::path& p ) bool State::IsIgnore( const std::string& filename ) { - return filename[0] == '.' ; + return filename == ".grive" || filename == ".grive_state"; } void State::FromLocal( const fs::path& p, Resource* folder ) From 8b434dad144341cc2b49d95a7ab4b048ca2b3a0c Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Sun, 24 Nov 2013 14:34:03 +0200 Subject: [PATCH 26/79] Reduce number of syscalls while scanning local files --- libgrive/src/drive/Resource.cc | 6 +++--- libgrive/src/drive/State.cc | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 4010cab2..f2852115 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -252,7 +252,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) void Resource::FromLocal( const DateTime& last_sync ) { fs::path path = Path() ; - assert( fs::exists( path ) ) ; + //assert( fs::exists( path ) ) ; // root folder is always in sync if ( !IsRoot() ) @@ -270,8 +270,8 @@ void Resource::FromLocal( const DateTime& last_sync ) m_state = ( m_mtime > last_sync ? local_new : remote_deleted ) ; m_name = path.filename().string() ; - m_kind = fs::is_directory(path) ? "folder" : "file" ; - m_md5 = fs::is_directory(path) ? "" : crypt::MD5::Get( path ) ; + //m_kind = fs::is_directory(path) ? "folder" : "file" ; + m_md5 = IsFolder() ? "" : crypt::MD5::Get( path ) ; } assert( m_state != unknown ) ; diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 124adecc..6c2ba611 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -84,19 +84,20 @@ void State::FromLocal( const fs::path& p, Resource* folder ) else { + bool is_dir = fs::is_directory(i->path()); // 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 ) { - c = new Resource( fname, fs::is_directory(i->path()) ? "folder" : "file" ) ; + c = new Resource( fname, is_dir ? "folder" : "file" ) ; folder->AddChild( c ) ; m_res.Insert( c ) ; } c->FromLocal( m_last_sync ) ; - if ( fs::is_directory( i->path() ) ) + if ( is_dir ) FromLocal( *i, c ) ; } } From 986ab4acc6f0274d8d2cf54e52e80e0ce775ddee Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Sun, 24 Nov 2013 14:34:52 +0200 Subject: [PATCH 27/79] Log XML on parse failure --- libgrive/src/xml/TreeBuilder.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libgrive/src/xml/TreeBuilder.cc b/libgrive/src/xml/TreeBuilder.cc index c1ad385a..9d57501b 100644 --- a/libgrive/src/xml/TreeBuilder.cc +++ b/libgrive/src/xml/TreeBuilder.cc @@ -21,6 +21,7 @@ #include "Error.hh" #include "Node.hh" +#include "util/log/Log.hh" #include @@ -72,8 +73,10 @@ void TreeBuilder::ParseData( const char *data, std::size_t count, bool last ) { is_new = false ; - if ( ::XML_Parse( m_impl->psr, data, count, last ) == 0 ) + if ( ::XML_Parse( m_impl->psr, data, count, last ) == 0 ) { + Log("Error parsing XML: %1%", data, log::error); BOOST_THROW_EXCEPTION( Error() << ExpatApiError("XML_Parse") ); + } } Node TreeBuilder::Parse( const std::string& xml ) From 645bb2e7d408718b0b457add629d6d34843cbaef Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Tue, 26 Nov 2013 23:00:42 +0200 Subject: [PATCH 28/79] Add delay before auth token refresh This is sometimes necessary to prevent too frequent requests. --- libgrive/src/protocol/AuthAgent.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 745f274c..6a329ceb 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -152,6 +152,7 @@ bool AuthAgent::CheckRetry( long response ) Log( "resquest failed due to auth token expired: %1%. refreshing token", response, log::warning ) ; + os::Sleep( 5 ) ; m_auth.Refresh() ; return true ; } From 84785ec4731b7a87b844a2339c400ab2e2e9d0ae Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Mon, 25 Nov 2013 00:07:27 +0200 Subject: [PATCH 29/79] Fix hang when upload receives HTTP 500 When an uploading PUT request got a HTTP 500 as reponse, grive hanged forever inside libcurl. This was because the File parameter was not rewound to 0 position on retry. The XmlResponse had to be cleared as well. Rewinding the File and clearing the XmlResponse were not enough to fix the problem, because when retrying after 500, HTTP 410 Gone or 412 Precondition failed is often received, and CheckHttpResponse would throw an exception that crashes grive. Therefore, I implemented a retry logic to Resource::Upload that retries the whole upload transaction if 410 or 412 was received. --- libgrive/src/drive/Resource.cc | 54 +++++++++++++++++++++--------- libgrive/src/http/XmlResponse.cc | 5 +++ libgrive/src/protocol/AuthAgent.cc | 20 +++++++++-- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index f2852115..7a7a2562 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -36,6 +36,7 @@ #include "xml/Node.hh" #include "xml/NodeSet.hh" #include "xml/String.hh" +#include "xml/TreeBuilder.hh" #include #include @@ -599,23 +600,44 @@ bool Resource::Upload( % xml::Escape(m_name) ).str() ; - http::StringResponse str ; - if ( post ) - http->Post( link, meta, &str, hdr ) ; - else - http->Put( link, meta, &str, hdr ) ; - - http::Header uphdr ; - uphdr.Add( "Expect:" ) ; - uphdr.Add( "Accept:" ) ; + bool retrying=false; + while ( true ) { + if ( retrying ) { + file.Seek( 0, SEEK_SET ); + os::Sleep( 5 ); + } - // the content upload URL is in the "Location" HTTP header - std::string uplink = http->RedirLocation() ; - http::XmlResponse xml ; - - http->Put( uplink, &file, &xml, uphdr ) ; - AssignIDs( Entry( xml.Response() ) ) ; - m_mtime = Entry(xml.Response()).MTime(); + http::StringResponse str ; + if ( post ) + http->Post( link, meta, &str, hdr ) ; + else + http->Put( link, meta, &str, hdr ) ; + + http::Header uphdr ; + uphdr.Add( "Expect:" ) ; + uphdr.Add( "Accept:" ) ; + + // the content upload URL is in the "Location" HTTP header + std::string uplink = http->RedirLocation() ; + http::XmlResponse xml ; + + long http_code = 0; + http_code = http->Put( uplink, &file, &xml, uphdr ) ; + + if ( http_code == 410 || http_code == 412 ) { + Log( "request failed with %1%, retrying whole upload in 5s", http_code, + log::warning ) ; + retrying = true; + continue; + } + + if ( retrying ) + Log( "upload succeeded on retry", log::warning ); + Entry responseEntry = Entry( xml.Response() ); + AssignIDs( responseEntry ) ; + m_mtime = responseEntry.MTime(); + break; + } return true ; } diff --git a/libgrive/src/http/XmlResponse.cc b/libgrive/src/http/XmlResponse.cc index b25f1c4d..3df42f94 100644 --- a/libgrive/src/http/XmlResponse.cc +++ b/libgrive/src/http/XmlResponse.cc @@ -28,6 +28,11 @@ XmlResponse::XmlResponse() : m_tb( new xml::TreeBuilder ) { } +void XmlResponse::Clear() +{ + m_tb.reset(new xml::TreeBuilder); +} + std::size_t XmlResponse::Write( const char *data, std::size_t count ) { m_tb->ParseData( data, count ) ; diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 6a329ceb..30a97223 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -21,8 +21,10 @@ #include "http/Error.hh" #include "http/Header.hh" +#include "http/XmlResponse.hh" #include "util/log/Log.hh" #include "util/OS.hh" +#include "util/File.hh" #include @@ -69,8 +71,22 @@ long AuthAgent::Put( Header auth = AppendHeader(hdr) ; long response ; - while ( CheckRetry( - response = m_agent->Put( url, file, dest, AppendHeader(hdr) ) ) ) ; + bool keepTrying = true; + while ( keepTrying ) { + response = m_agent->Put( url, file, dest, auth ); + keepTrying = CheckRetry( response ); + if ( keepTrying ) { + file->Seek( 0, SEEK_SET ); + XmlResponse *xmlResponse = dynamic_cast(dest); + if( xmlResponse ) + xmlResponse->Clear(); + } + } + + // On 410 Gone or 412 Precondition failed, recovery may be possible so don't + // throw an exception + if ( response == 410 || response == 412 ) + return response; return CheckHttpResponse(response, url, auth) ; } From 3775572f4650797e7eeab0ba23e27f1f15f01cd5 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Mon, 25 Nov 2013 00:14:29 +0200 Subject: [PATCH 30/79] Retry upload on XML error instead of crashing Sometimes the Google Drive API sends malformed XML which crashes grive. This patch adds a simple try-catch to Resource::Upload that retries the upload if an XML exception is thrown from AuthAgent::Put. --- libgrive/src/drive/Resource.cc | 36 ++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 7a7a2562..2da7859e 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -607,11 +607,23 @@ bool Resource::Upload( os::Sleep( 5 ); } - http::StringResponse str ; - if ( post ) - http->Post( link, meta, &str, hdr ) ; - else - http->Put( link, meta, &str, hdr ) ; + try { + http::StringResponse str ; + if ( post ) + http->Post( link, meta, &str, hdr ) ; + else + http->Put( link, meta, &str, hdr ) ; + } catch ( Error &e ) { + std::string const *info = boost::get_error_info(e); + if ( info && (*info == "XML_Parse") ) { + Log( "Error parsing pre-upload response XML, retrying whole upload in 5s", + log::warning ); + retrying = true; + continue; + } else { + throw e; + } + } http::Header uphdr ; uphdr.Add( "Expect:" ) ; @@ -622,7 +634,19 @@ bool Resource::Upload( http::XmlResponse xml ; long http_code = 0; - http_code = http->Put( uplink, &file, &xml, uphdr ) ; + try { + http_code = http->Put( uplink, &file, &xml, uphdr ) ; + } catch ( Error &e ) { + std::string const *info = boost::get_error_info(e); + if ( info && (*info == "XML_Parse") ) { + Log( "Error parsing response XML, retrying whole upload in 5s", + log::warning ); + retrying = true; + continue; + } else { + throw e; + } + } if ( http_code == 410 || http_code == 412 ) { Log( "request failed with %1%, retrying whole upload in 5s", http_code, From b0d986a9d956911fc03d6dddc7c96f458c02b875 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Tue, 26 Nov 2013 23:00:42 +0200 Subject: [PATCH 31/79] Add delay before auth token refresh This is sometimes necessary to prevent too frequent requests. --- libgrive/src/protocol/AuthAgent.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 745f274c..6a329ceb 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -152,6 +152,7 @@ bool AuthAgent::CheckRetry( long response ) Log( "resquest failed due to auth token expired: %1%. refreshing token", response, log::warning ) ; + os::Sleep( 5 ) ; m_auth.Refresh() ; return true ; } From a11eae8a875e579c7ad25380512b30084d8c0bb1 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Mon, 25 Nov 2013 00:07:27 +0200 Subject: [PATCH 32/79] Fix hang when upload receives HTTP 500 When an uploading PUT request got a HTTP 500 as reponse, grive hanged forever inside libcurl. This was because the File parameter was not rewound to 0 position on retry. The XmlResponse had to be cleared as well. Rewinding the File and clearing the XmlResponse were not enough to fix the problem, because when retrying after 500, HTTP 410 Gone or 412 Precondition failed is often received, and CheckHttpResponse would throw an exception that crashes grive. Therefore, I implemented a retry logic to Resource::Upload that retries the whole upload transaction if 410 or 412 was received. --- libgrive/src/drive/Resource.cc | 54 +++++++++++++++++++++--------- libgrive/src/http/XmlResponse.cc | 5 +++ libgrive/src/protocol/AuthAgent.cc | 20 +++++++++-- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 4010cab2..fdb6d641 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -36,6 +36,7 @@ #include "xml/Node.hh" #include "xml/NodeSet.hh" #include "xml/String.hh" +#include "xml/TreeBuilder.hh" #include #include @@ -599,23 +600,44 @@ bool Resource::Upload( % xml::Escape(m_name) ).str() ; - http::StringResponse str ; - if ( post ) - http->Post( link, meta, &str, hdr ) ; - else - http->Put( link, meta, &str, hdr ) ; - - http::Header uphdr ; - uphdr.Add( "Expect:" ) ; - uphdr.Add( "Accept:" ) ; + bool retrying=false; + while ( true ) { + if ( retrying ) { + file.Seek( 0, SEEK_SET ); + os::Sleep( 5 ); + } - // the content upload URL is in the "Location" HTTP header - std::string uplink = http->RedirLocation() ; - http::XmlResponse xml ; - - http->Put( uplink, &file, &xml, uphdr ) ; - AssignIDs( Entry( xml.Response() ) ) ; - m_mtime = Entry(xml.Response()).MTime(); + http::StringResponse str ; + if ( post ) + http->Post( link, meta, &str, hdr ) ; + else + http->Put( link, meta, &str, hdr ) ; + + http::Header uphdr ; + uphdr.Add( "Expect:" ) ; + uphdr.Add( "Accept:" ) ; + + // the content upload URL is in the "Location" HTTP header + std::string uplink = http->RedirLocation() ; + http::XmlResponse xml ; + + long http_code = 0; + http_code = http->Put( uplink, &file, &xml, uphdr ) ; + + if ( http_code == 410 || http_code == 412 ) { + Log( "request failed with %1%, retrying whole upload in 5s", http_code, + log::warning ) ; + retrying = true; + continue; + } + + if ( retrying ) + Log( "upload succeeded on retry", log::warning ); + Entry responseEntry = Entry( xml.Response() ); + AssignIDs( responseEntry ) ; + m_mtime = responseEntry.MTime(); + break; + } return true ; } diff --git a/libgrive/src/http/XmlResponse.cc b/libgrive/src/http/XmlResponse.cc index b25f1c4d..3df42f94 100644 --- a/libgrive/src/http/XmlResponse.cc +++ b/libgrive/src/http/XmlResponse.cc @@ -28,6 +28,11 @@ XmlResponse::XmlResponse() : m_tb( new xml::TreeBuilder ) { } +void XmlResponse::Clear() +{ + m_tb.reset(new xml::TreeBuilder); +} + std::size_t XmlResponse::Write( const char *data, std::size_t count ) { m_tb->ParseData( data, count ) ; diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 6a329ceb..30a97223 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -21,8 +21,10 @@ #include "http/Error.hh" #include "http/Header.hh" +#include "http/XmlResponse.hh" #include "util/log/Log.hh" #include "util/OS.hh" +#include "util/File.hh" #include @@ -69,8 +71,22 @@ long AuthAgent::Put( Header auth = AppendHeader(hdr) ; long response ; - while ( CheckRetry( - response = m_agent->Put( url, file, dest, AppendHeader(hdr) ) ) ) ; + bool keepTrying = true; + while ( keepTrying ) { + response = m_agent->Put( url, file, dest, auth ); + keepTrying = CheckRetry( response ); + if ( keepTrying ) { + file->Seek( 0, SEEK_SET ); + XmlResponse *xmlResponse = dynamic_cast(dest); + if( xmlResponse ) + xmlResponse->Clear(); + } + } + + // On 410 Gone or 412 Precondition failed, recovery may be possible so don't + // throw an exception + if ( response == 410 || response == 412 ) + return response; return CheckHttpResponse(response, url, auth) ; } From 307c934ce49f2d51174c315c9e270ebe97e09982 Mon Sep 17 00:00:00 2001 From: Visa Putkinen Date: Mon, 25 Nov 2013 00:14:29 +0200 Subject: [PATCH 33/79] Retry upload on XML error instead of crashing Sometimes the Google Drive API sends malformed XML which crashes grive. This patch adds a simple try-catch to Resource::Upload that retries the upload if an XML exception is thrown from AuthAgent::Put. --- libgrive/src/drive/Resource.cc | 36 ++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index fdb6d641..9a02940b 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -607,11 +607,23 @@ bool Resource::Upload( os::Sleep( 5 ); } - http::StringResponse str ; - if ( post ) - http->Post( link, meta, &str, hdr ) ; - else - http->Put( link, meta, &str, hdr ) ; + try { + http::StringResponse str ; + if ( post ) + http->Post( link, meta, &str, hdr ) ; + else + http->Put( link, meta, &str, hdr ) ; + } catch ( Error &e ) { + std::string const *info = boost::get_error_info(e); + if ( info && (*info == "XML_Parse") ) { + Log( "Error parsing pre-upload response XML, retrying whole upload in 5s", + log::warning ); + retrying = true; + continue; + } else { + throw e; + } + } http::Header uphdr ; uphdr.Add( "Expect:" ) ; @@ -622,7 +634,19 @@ bool Resource::Upload( http::XmlResponse xml ; long http_code = 0; - http_code = http->Put( uplink, &file, &xml, uphdr ) ; + try { + http_code = http->Put( uplink, &file, &xml, uphdr ) ; + } catch ( Error &e ) { + std::string const *info = boost::get_error_info(e); + if ( info && (*info == "XML_Parse") ) { + Log( "Error parsing response XML, retrying whole upload in 5s", + log::warning ); + retrying = true; + continue; + } else { + throw e; + } + } if ( http_code == 410 || http_code == 412 ) { Log( "request failed with %1%, retrying whole upload in 5s", http_code, From 90ef29a8211cdc3b081731ac9603d7b9e6173363 Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Sun, 22 Dec 2013 20:08:01 +0200 Subject: [PATCH 34/79] Fix json-c library name. --- cmake/Modules/FindJSONC.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index f72e8ea1..5548c719 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -7,7 +7,7 @@ # JSONC_LIBRARY - The JSON-C library to link against. FIND_PATH(JSONC_INCLUDE_DIR json/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json) +FIND_LIBRARY(JSONC_LIBRARY NAMES json-c) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From 7bf7416126a535aed0202667c561ff285793f1a9 Mon Sep 17 00:00:00 2001 From: ChesterBishop Date: Sun, 12 Jan 2014 16:29:28 +0000 Subject: [PATCH 35/79] Added description of doc,g modifier --- grive/src/main.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/grive/src/main.cc b/grive/src/main.cc index 5209c941..73ec9cb9 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -119,6 +119,7 @@ int Main( int argc, char **argv ) "instead of uploading it." ) ( "dry-run", "Only detect which files need to be uploaded/downloaded, " "without actually performing them." ) + ("docs,g", "Synchronises Google Docs, Sheets and Slides.") ; po::variables_map vm; From 1c94cd9861a5d8268211bc6580cbf7acdc3ee6f4 Mon Sep 17 00:00:00 2001 From: Jerome Maloberti Date: Sun, 9 Mar 2014 22:26:30 +0000 Subject: [PATCH 36/79] Remove . restrictions. Signed-off-by: Jerome Maloberti --- build.sh | 1 + libgrive/CMakeLists.txt | 2 +- libgrive/src/drive/State.cc | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..cf0c49b9 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_EXE_LINKER_FLAGS=-ljson-c diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index 3cc15742..acef830c 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -7,7 +7,7 @@ find_package(JSONC REQUIRED) find_package(CURL REQUIRED) find_package(EXPAT REQUIRED) find_package(Boost 1.40.0 COMPONENTS program_options filesystem unit_test_framework system REQUIRED) -find_package(BFD) +#find_package(BFD) find_package(CppUnit) find_package(Iberty) find_package(ZLIB) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..5b7c159d 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -58,9 +58,11 @@ void State::FromLocal( const fs::path& p ) FromLocal( p, m_res.Root() ) ; } + const std::string prefix = ".grive"; bool State::IsIgnore( const std::string& filename ) { - return filename[0] == '.' ; + // return filename[0] == '.' ; + return filename.size() <= prefix.size() && filename.compare(0, prefix.size(), prefix) == 0; } void State::FromLocal( const fs::path& p, Resource* folder ) From dee75f955756eac196304d181fd6581262c6c7a8 Mon Sep 17 00:00:00 2001 From: Jerome Maloberti Date: Mon, 10 Mar 2014 00:07:26 +0000 Subject: [PATCH 37/79] Fix a stupid bug. --- libgrive/src/drive/State.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 5b7c159d..5185247b 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -62,7 +62,7 @@ void State::FromLocal( const fs::path& p ) bool State::IsIgnore( const std::string& filename ) { // return filename[0] == '.' ; - return filename.size() <= prefix.size() && filename.compare(0, prefix.size(), prefix) == 0; + return filename.size() >= prefix.size() && filename.compare(0, prefix.size(), prefix) == 0; } void State::FromLocal( const fs::path& p, Resource* folder ) From 4f2a6aa08d7a561be64230854e1793858fc9683a Mon Sep 17 00:00:00 2001 From: ColinKinloch Date: Tue, 25 Mar 2014 16:34:38 +0000 Subject: [PATCH 38/79] Yajl loaded with PkgConfig --- libgrive/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index 3cc15742..ea2d07e1 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -12,6 +12,9 @@ find_package(CppUnit) find_package(Iberty) find_package(ZLIB) +include(FindPkgConfig) +pkg_search_module(YAJL REQUIRED yajl) + # additional headers if build unit tests IF ( CPPUNIT_FOUND ) set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} ) @@ -42,6 +45,7 @@ include_directories( ${libgrive_SOURCE_DIR}/test ${GDBM_INCLUDE_DIR} ${OPT_INCS} + ${YAJL_INCLUDE_DIRS} ) file(GLOB DRIVE_HEADERS @@ -80,7 +84,6 @@ add_definitions( add_library( grive STATIC ${LIBGRIVE_SRC} ${OPT_SRC} ) target_link_libraries( grive - yajl ${CURL_LIBRARIES} ${JSONC_LIBRARY} ${LIBGCRYPT_LIBRARIES} @@ -89,6 +92,7 @@ target_link_libraries( grive ${IBERTY_LIBRARY} ${EXPAT_LIBRARY} ${OPT_LIBS} + ${YAJL_LIBRARIES} ) #set_target_properties(grive PROPERTIES From bcd8dbdc2429205f500dd5429f4b133c695e2cb9 Mon Sep 17 00:00:00 2001 From: Juan Orti Alcaine Date: Wed, 3 Jul 2013 10:05:44 +0200 Subject: [PATCH 39/79] Fix json-c library path --- cmake/Modules/FindJSONC.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index f72e8ea1..8e4f1fc9 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -6,8 +6,8 @@ # JSONC_INCLUDE_DIR - The JSON-C include directory. # JSONC_LIBRARY - The JSON-C library to link against. -FIND_PATH(JSONC_INCLUDE_DIR json/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json) +FIND_PATH(JSONC_INCLUDE_DIR json-c/json.h) +FIND_LIBRARY(JSONC_LIBRARY NAMES json-c) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From 6598f363a810cd080245c8e65812eded978ad38b Mon Sep 17 00:00:00 2001 From: Juan Orti Alcaine Date: Wed, 3 Jul 2013 11:07:13 +0200 Subject: [PATCH 40/79] bgrive tries to install grive man page --- bgrive/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..7bb32692 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -40,4 +40,3 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) From 23a47c1ce881c671bd0f14abe015a6fca1224cae Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Thu, 17 Apr 2014 18:53:08 +0300 Subject: [PATCH 41/79] Skip bgrive, install docs. --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60a3b09e..d8ccac10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,4 +11,6 @@ add_definitions( -D_FILE_OFFSET_BITS=64 ) add_subdirectory( libgrive ) add_subdirectory( grive ) -add_subdirectory( bgrive ) +#add_subdirectory( bgrive ) + +install(FILES COPYING README DESTINATION share/doc/grive) From be1bc5a2e0ed83d696d33e0412fadcc1e72f6cad Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Thu, 17 Apr 2014 18:55:05 +0300 Subject: [PATCH 42/79] Spec file for building directly from github. --- grive.spec | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 grive.spec diff --git a/grive.spec b/grive.spec new file mode 100644 index 00000000..828f3f93 --- /dev/null +++ b/grive.spec @@ -0,0 +1,49 @@ +%define rev %(git ls-remote https://github.com/jar1karp/grive.git refs/heads/master|awk '{print $1}') + +Name: grive +Version: 0.3.0-pre_git%{rev} +Release: 1%{?dist} + +Summary: An open source Linux client for Google Drive + +License: GPLv2 +URL: http://grive.github.com/grive/ + +BuildRequires: git +BuildRequires: gawk +BuildRequires: cmake +BuildRequires: libstdc++-devel +BuildRequires: libcurl-devel +BuildRequires: json-c-devel +BuildRequires: expat-devel +BuildRequires: openssl-devel +BuildRequires: boost-devel +BuildRequires: binutils-devel +BuildRequires: yajl-devel +BuildRequires: libgcrypt-devel + +%description +The purpose of this project is to provide an independent implementation +of Google Drive client. It uses the Google Document List API to talk to +the servers in Google. The code is written in standard C++. + +%prep +rm -rf grive-%{version} +git clone https://github.com/jar1karp/grive.git -b master grive-%{version} +cd grive-%{version} + +%build +cd grive-%{version} +%cmake . +make %{?_smp_mflags} + +%install +cd grive-%{version} +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT +rm -rf $RPM_BUILD_ROOT/%{_bindir}/bgrive + +%files +%doc COPYING README +%{_bindir}/%{name} +%{_mandir}/man1/%{name}.1.gz From 508cd7e2b7263c020cc5c1dbccf1269a706fce05 Mon Sep 17 00:00:00 2001 From: Jari Karppinen Date: Thu, 17 Apr 2014 19:00:30 +0300 Subject: [PATCH 43/79] Fix version string and doc packaging. --- grive.spec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grive.spec b/grive.spec index 828f3f93..d1b87f3f 100644 --- a/grive.spec +++ b/grive.spec @@ -1,7 +1,7 @@ %define rev %(git ls-remote https://github.com/jar1karp/grive.git refs/heads/master|awk '{print $1}') Name: grive -Version: 0.3.0-pre_git%{rev} +Version: 0.3.0pre_git%{rev} Release: 1%{?dist} Summary: An open source Linux client for Google Drive @@ -44,6 +44,7 @@ make install DESTDIR=$RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT/%{_bindir}/bgrive %files -%doc COPYING README +%{_docdir}/%{name}/COPYING +%{_docdir}/%{name}/README %{_bindir}/%{name} %{_mandir}/man1/%{name}.1.gz From 0e0691e8b1142b49cec3c958cabf5c3df3b6e60e Mon Sep 17 00:00:00 2001 From: Falk Howar Date: Mon, 12 May 2014 19:21:37 -0700 Subject: [PATCH 44/79] added hard-coded filter for top-level folders --- CMakeLists.txt | 2 +- libgrive/src/drive/State.cc | 38 ++++++++++++++++++++++++++++++++++++- libgrive/src/drive/State.hh | 5 ++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f1460b..fbdc065d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,4 +9,4 @@ add_definitions( -D_FILE_OFFSET_BITS=64 ) add_subdirectory( libgrive ) add_subdirectory( grive ) -add_subdirectory( bgrive ) +# add_subdirectory( bgrive ) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..bde681d0 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -38,6 +38,8 @@ State::State( const fs::path& filename, const Json& options ) : m_cstamp ( -1 ) { Read( filename ) ; + + m_filter = "GDrive"; // the "-f" option will make grive always thinks remote is newer Json force ; @@ -58,9 +60,37 @@ void State::FromLocal( const fs::path& p ) FromLocal( p, m_res.Root() ) ; } +/// returns true if a file should be ignored based +/// on the configured filter +bool State::IsFiltered( const std::string& filename ) +{ + if (filename.length() < m_filter.length()) { + return true ; + } + + std::string prefix = filename.substr(0, m_filter.length()); + + return prefix.compare(m_filter) != 0; +} + +bool State::IsFiltered( const Entry& e ) +{ + if (Resource *parent = m_res.FindByHref( e.ParentHref() ) ) + { + assert( parent->IsFolder() ) ; + if (!parent->IsRoot()) + return false; + } + else + return false ; + + return IsFiltered( e.Name() ); +} + + bool State::IsIgnore( const std::string& filename ) { - return filename[0] == '.' ; + return (filename[0] == '.') ; } void State::FromLocal( const fs::path& p, Resource* folder ) @@ -78,6 +108,9 @@ void State::FromLocal( const fs::path& p, Resource* folder ) if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; + else if ( folder->IsRoot() && this->IsFiltered(fname)) + Log( "file %1% is filtered by grive", fname, log::verbose ) ; + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; @@ -109,6 +142,9 @@ void State::FromRemote( const Entry& e ) if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; + else if ( this->IsFiltered(e) ) + Log( "file %1% is filtered by grive", e.Name(), log::verbose ) ; + // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index 8c641892..bfd679a3 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -74,13 +74,16 @@ private : std::size_t TryResolveEntry() ; static bool IsIgnore( const std::string& filename ) ; - + bool IsFiltered( const Entry& e ); + bool IsFiltered( const std::string& filename ); private : ResourceTree m_res ; DateTime m_last_sync ; long m_cstamp ; std::vector m_unresolved ; + + std::string m_filter; } ; } } // end of namespace gr::v1 From 1301d4e81d6033759a2e034210aef1cd774732d6 Mon Sep 17 00:00:00 2001 From: Davide Del Grande Date: Tue, 1 Jul 2014 23:28:43 +0200 Subject: [PATCH 45/79] Fix compilation on Debian 7 i686 due to 3 missing boost::uint64_t casts in State.cc --- libgrive/src/drive/State.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..292a750f 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -248,12 +248,12 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; - last_sync.Add( "sec", Json(m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json(m_last_sync.NanoSec() ) ); + last_sync.Add( "sec", Json((boost::uint64_t) m_last_sync.Sec() ) ); + last_sync.Add( "nsec", Json((boost::uint64_t) m_last_sync.NanoSec() ) ); Json result ; result.Add( "last_sync", last_sync ) ; - result.Add( "change_stamp", Json(m_cstamp) ) ; + result.Add( "change_stamp", Json((boost::uint64_t) m_cstamp) ) ; std::ofstream fs( filename.string().c_str() ) ; fs << result ; From 459313ecf502ae8b95e791dea552b46774c0a48d Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 23 Jul 2014 14:41:40 +0400 Subject: [PATCH 46/79] Find YAJL via pkg-config --- libgrive/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index 3cc15742..28c3cbd3 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -12,6 +12,9 @@ find_package(CppUnit) find_package(Iberty) find_package(ZLIB) +find_package(PkgConfig) +pkg_check_modules(YAJL REQUIRED yajl) + # additional headers if build unit tests IF ( CPPUNIT_FOUND ) set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} ) @@ -42,6 +45,7 @@ include_directories( ${libgrive_SOURCE_DIR}/test ${GDBM_INCLUDE_DIR} ${OPT_INCS} + ${YAJL_INCLUDE_DIRS} ) file(GLOB DRIVE_HEADERS @@ -80,7 +84,7 @@ add_definitions( add_library( grive STATIC ${LIBGRIVE_SRC} ${OPT_SRC} ) target_link_libraries( grive - yajl + ${YAJL_LIBRARIES} ${CURL_LIBRARIES} ${JSONC_LIBRARY} ${LIBGCRYPT_LIBRARIES} From 400d9e0c0ff150347aa043209d11afce5337b72e Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 23 Jul 2014 14:47:16 +0400 Subject: [PATCH 47/79] Fix long/int cast errors --- libgrive/src/drive/State.cc | 4 ++-- libgrive/src/drive/State.hh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index cf0c30bd..de53a88e 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -257,8 +257,8 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; - last_sync.Add( "sec", Json(m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json(m_last_sync.NanoSec() ) ); + last_sync.Add( "sec", Json( (int)m_last_sync.Sec() ) ); + last_sync.Add( "nsec", Json( (unsigned)m_last_sync.NanoSec() ) ); Json result ; result.Add( "last_sync", last_sync ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index 98cce39a..af79f8da 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -78,7 +78,7 @@ private : private : ResourceTree m_res ; DateTime m_last_sync ; - long m_cstamp ; + int m_cstamp ; std::string m_dir ; std::vector m_unresolved ; From 94efea11dd1735786d63ec1de3aaa385b2fd3c1d Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 23 Jul 2014 14:48:22 +0400 Subject: [PATCH 48/79] Do not try to install doc/grive.1 from bgrive cmake --- bgrive/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt index 074ab383..7bb32692 100644 --- a/bgrive/CMakeLists.txt +++ b/bgrive/CMakeLists.txt @@ -40,4 +40,3 @@ set_target_properties( bgrive_executable ) install(TARGETS bgrive_executable RUNTIME DESTINATION bin) -install(FILES doc/grive.1 DESTINATION share/man/man1 ) From 81a4cf0bdb3929a76f16511bc98207804e4d6a87 Mon Sep 17 00:00:00 2001 From: Bryan Richter Date: Sun, 27 Jul 2014 22:36:11 -0700 Subject: [PATCH 49/79] Put yajl dependency in Cmake --- cmake/Modules/FindYAJL.cmake | 31 +++++++++++++++++++++++++++++++ libgrive/CMakeLists.txt | 4 +++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 cmake/Modules/FindYAJL.cmake diff --git a/cmake/Modules/FindYAJL.cmake b/cmake/Modules/FindYAJL.cmake new file mode 100644 index 00000000..65e15693 --- /dev/null +++ b/cmake/Modules/FindYAJL.cmake @@ -0,0 +1,31 @@ +# - Find YAJL +# This module finds an installed YAJL package. +# +# It sets the following variables: +# YAJL_FOUND - Set to false, or undefined, if YAJL isn't found. +# YAJL_INCLUDE_DIR - The YAJL include directory. +# YAJL_LIBRARY - The YAJL library to link against. + +FIND_PATH(YAJL_INCLUDE_DIR yajl/yajl_gen.h) +FIND_LIBRARY(YAJL_LIBRARY NAMES yajl) + +IF (YAJL_INCLUDE_DIR AND YAJL_LIBRARY) + SET(YAJL_FOUND TRUE) +ENDIF (YAJL_INCLUDE_DIR AND YAJL_LIBRARY) + +IF (YAJL_FOUND) + + # show which YAJL was found only if not quiet + IF (NOT YAJL_FIND_QUIETLY) + MESSAGE(STATUS "Found YAJL: ${YAJL_LIBRARY}") + ENDIF (NOT YAJL_FIND_QUIETLY) + +ELSE (YAJL_FOUND) + + # fatal error if YAJL is required but not found + IF (YAJL_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find YAJL") + ENDIF (YAJL_FIND_REQUIRED) + +ENDIF (YAJL_FOUND) + diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index 3cc15742..62186017 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -6,6 +6,7 @@ find_package(LibGcrypt REQUIRED) find_package(JSONC REQUIRED) find_package(CURL REQUIRED) find_package(EXPAT REQUIRED) +find_package(YAJL REQUIRED) find_package(Boost 1.40.0 COMPONENTS program_options filesystem unit_test_framework system REQUIRED) find_package(BFD) find_package(CppUnit) @@ -41,6 +42,7 @@ include_directories( ${libgrive_SOURCE_DIR}/src ${libgrive_SOURCE_DIR}/test ${GDBM_INCLUDE_DIR} + ${YAJL_INCLUDE_DIR} ${OPT_INCS} ) @@ -80,7 +82,7 @@ add_definitions( add_library( grive STATIC ${LIBGRIVE_SRC} ${OPT_SRC} ) target_link_libraries( grive - yajl + ${YAJL_LIBRARY} ${CURL_LIBRARIES} ${JSONC_LIBRARY} ${LIBGCRYPT_LIBRARIES} From 1cef976cf4589c4495902702ecea6b8a3337a4a3 Mon Sep 17 00:00:00 2001 From: Bryan Richter Date: Sun, 27 Jul 2014 22:37:00 -0700 Subject: [PATCH 50/79] Typo fix in log message --- libgrive/src/protocol/AuthAgent.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 745f274c..b878ea0a 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -139,7 +139,7 @@ bool AuthAgent::CheckRetry( long response ) // HTTP 500 and 503 should be temperory. just wait a bit and retry if ( response == 500 || response == 503 ) { - Log( "resquest failed due to temperory error: %1%. retrying in 5 seconds", + Log( "request failed due to temperory error: %1%. retrying in 5 seconds", response, log::warning ) ; os::Sleep( 5 ) ; @@ -149,7 +149,7 @@ bool AuthAgent::CheckRetry( long response ) // HTTP 401 Unauthorized. the auth token has been expired. refresh it else if ( response == 401 ) { - Log( "resquest failed due to auth token expired: %1%. refreshing token", + Log( "request failed due to auth token expired: %1%. refreshing token", response, log::warning ) ; m_auth.Refresh() ; From 01f457d0bb1ba46bdeee552ae5fccc06612f01fa Mon Sep 17 00:00:00 2001 From: Al Williams Date: Mon, 1 Sep 2014 14:51:50 -0500 Subject: [PATCH 51/79] Adds a few useful scripts for auto upload and periodic download sync --- scripts/crontab.txt | 5 +++++ scripts/grive-incron | 34 ++++++++++++++++++++++++++++++++++ scripts/incron.txt | 3 +++ scripts/readme.txt | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 scripts/crontab.txt create mode 100755 scripts/grive-incron create mode 100644 scripts/incron.txt create mode 100644 scripts/readme.txt diff --git a/scripts/crontab.txt b/scripts/crontab.txt new file mode 100644 index 00000000..029d6597 --- /dev/null +++ b/scripts/crontab.txt @@ -0,0 +1,5 @@ +# This example runs grive on /home/USER/gdrive +# See man crontab for format +# This line runs at 5 after the hour and 35 after the hour + +5,35 * * * * /usr/bin/grive -p /home/USER/gdrive diff --git a/scripts/grive-incron b/scripts/grive-incron new file mode 100755 index 00000000..40ed76d6 --- /dev/null +++ b/scripts/grive-incron @@ -0,0 +1,34 @@ +#!/bin/bash + +# Allow grive to be called from incron +# if your path is /home/User/gdrivef and this file is in /usr/local/bin then use the following incrontab line: +# /home/User/gdrive IN_CREATE,IN_DELETE,IN_CLOSE_WRITE,IN_MOVE /usr/local/bin/grive-incron $# /home/User/gdrive + +# grive-incron a bash script to allow automatic push to gdrive from a directory +# It is made to be called by # incron +# +# Copyright (C) 2014 Al Williams (al.williams@awce.com) +# +# 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, either version 3 of the License, or (at your option) any later version. +# 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, see http://www.gnu.org/licenses/. + +if [ $# != 2 ] +then + >&2 echo Call from incron: \$# directory + exit 1 +fi +if [ "$1" == .grive -o "$1" == .grive_state ] +then + exit 0 # ignore grive housekeeping files +fi +# Don't run multiple copies at once +N=2 +while [ "$N" != 1 ] +do + N=$( pgrep -c -u "$USER" grive-? ) # assume if 1 it is me! + if [ "$N" != 1 ] + then sleep 1 + fi +done +exec grive -p "$2" diff --git a/scripts/incron.txt b/scripts/incron.txt new file mode 100644 index 00000000..99806945 --- /dev/null +++ b/scripts/incron.txt @@ -0,0 +1,3 @@ +# Fix path below (2 places) and location of grive-incron script +/home/USER/gdrive IN_CREATE,IN_DELETE,IN_CLOSE_WRITE,IN_MOVE /usr/bin/grive-incron $# /home/USER/gdrive + diff --git a/scripts/readme.txt b/scripts/readme.txt new file mode 100644 index 00000000..ea661d6a --- /dev/null +++ b/scripts/readme.txt @@ -0,0 +1,40 @@ +This directory contains a simple script that allows calling +grive from incron. This will cause any changes you make +to the local directory to automatically call grive to +update Google Drive. You can copy the script to a location on your +path: + +sudo cp grive-incron /usr/local/bin + +To make this work, you also need to insert the contents of incrontab.txt +into your incrontab (after changing the paths to suit your +installation). + +To do this run: +incrontab -e + +Then use the editor that appears to insert the line with your custom +paths. You can ignore lines that start with # -- they are just comments +although you can paste them into the incrontab if you like. + +To get the reverse, you can do a similar command in your crontab (see +crontab.txt). The example syncs at 5 and 35 minutes after each hour +but you can customize that by changing the crontab line. + +crontab -e + +will bring up an editor. Copy the line without the # in front from +crontab.txt after fixing it for your specific path names. You can +skip the # lines or include them, as before. + +You probably don't want to do a crontab sync every minute because +grive takes some time to run. The grive-incron script stalls if +another copy of it or grive is running for the current user to +prevent overrun, but the crontab entry has on such protection. If you +prefer, you could use the same script with a dummy file name in crontab. +Then your crontab line would look something like this: + +5,35 * * * * /usr/local/bin/grive-incron DUMMY /home/USER/gdrive + +The word DUMMY is just a placeholder. It does not have to refer to a real +file. From 1f5c6d4172a25638f497473984989bb3facdc294 Mon Sep 17 00:00:00 2001 From: Al Williams Date: Mon, 1 Sep 2014 15:47:06 -0500 Subject: [PATCH 52/79] Fixes deadlock problem but still possible for more than one grive to start --- scripts/grive-incron | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/grive-incron b/scripts/grive-incron index 40ed76d6..6c55cca3 100755 --- a/scripts/grive-incron +++ b/scripts/grive-incron @@ -24,11 +24,13 @@ then fi # Don't run multiple copies at once N=2 -while [ "$N" != 1 ] +DLY=1 +while [ "$N" != 0 ] do - N=$( pgrep -c -u "$USER" grive-? ) # assume if 1 it is me! - if [ "$N" != 1 ] - then sleep 1 + N=$( pgrep -c -u "$USER" ^grive$ ) # assume if 1 it is me! + if [ "$N" != 0 ] + then sleep $DLY + DLY=$((DLY+5)) fi done exec grive -p "$2" From 00e998694d7e2f6e14e716aab1944f8779422875 Mon Sep 17 00:00:00 2001 From: Al Williams Date: Mon, 1 Sep 2014 16:16:58 -0500 Subject: [PATCH 53/79] Better fix for interlock using PID file --- scripts/grive-incron | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/grive-incron b/scripts/grive-incron index 6c55cca3..cdebc201 100755 --- a/scripts/grive-incron +++ b/scripts/grive-incron @@ -13,6 +13,8 @@ # 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, see http://www.gnu.org/licenses/. +PIDFILE=/tmp/grive-incron.lock + if [ $# != 2 ] then >&2 echo Call from incron: \$# directory @@ -23,14 +25,28 @@ then exit 0 # ignore grive housekeeping files fi # Don't run multiple copies at once -N=2 + DLY=1 -while [ "$N" != 0 ] -do - N=$( pgrep -c -u "$USER" ^grive$ ) # assume if 1 it is me! - if [ "$N" != 0 ] - then sleep $DLY - DLY=$((DLY+5)) - fi + +while true + do + while [ -f "$PIDFILE" ] && kill -0 `cat "$PIDFILE"` 2>/dev/null + do + sleep $DLY + DLY=$((DLY+1)) + DLY=$((DLY % 10 )) # no more than 10 seconds + done + if ! kill -0 `cat "$PIDFILE" 2>/dev/null` 2>/dev/null + then + rm -f "$PIDFILE" + fi + if (set -o noclobber; echo $$>"$PIDFILE" ) >/dev/null + then + trap 'rm -f "$PIDFILE"' INT TERM EXIT + break + fi done -exec grive -p "$2" +grive -p "$2" +rm -f "$PIDFILE" +trap - INT TERM EXIT +exit 0 From 73fc8d20dcd1d56da8d883ce533b26c13084d77d Mon Sep 17 00:00:00 2001 From: linwiz Date: Fri, 19 Sep 2014 12:38:40 -0400 Subject: [PATCH 54/79] Added -u/-uploadonly flag. This will only Upload files. --- grive/doc/grive.1 | 5 +++ grive/src/main.cc | 2 + libgrive/src/drive/Resource.cc | 73 +++++++++++++++++++--------------- libgrive/src/drive/State.cc | 6 +-- libgrive/src/util/Config.cc | 1 + 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/grive/doc/grive.1 b/grive/doc/grive.1 index 57b2e9cc..017cef14 100644 --- a/grive/doc/grive.1 +++ b/grive/doc/grive.1 @@ -33,6 +33,11 @@ Forces .I grive to always download a file from Google Drive instead uploading it .TP +\fB\-u, \-\-upload\fR +Forces +.I grive +to only upload a file from Google Drive instead downloading it +.TP \fB\-h\fR, \fB\-\-help\fR Produces help message .TP diff --git a/grive/src/main.cc b/grive/src/main.cc index 5209c941..e93f627b 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -117,6 +117,8 @@ int Main( int argc, char **argv ) ( "log,l", po::value(), "Set log output filename." ) ( "force,f", "Force grive to always download a file from Google Drive " "instead of uploading it." ) + ( "uploadonly,u", "Force grive to always upload a file from Google Drive " + "instead of downloading it." ) ( "dry-run", "Only detect which files need to be uploaded/downloaded, " "without actually performing them." ) ; diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 4010cab2..cfd8bff5 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -84,7 +84,7 @@ void Resource::SetState( State new_state ) new_state == remote_new || new_state == remote_deleted || new_state == local_new || new_state == local_deleted ) ; - + m_state = new_state ; std::for_each( m_child.begin(), m_child.end(), boost::bind( &Resource::SetState, _1, new_state ) ) ; @@ -93,17 +93,17 @@ void Resource::SetState( State new_state ) void Resource::FromRemoteFolder( const Entry& remote, const DateTime& last_sync ) { fs::path path = Path() ; - + if ( remote.CreateLink().empty() ) Log( "folder %1% is read-only", path, log::verbose ) ; - + // already sync if ( fs::is_directory( path ) ) { Log( "folder %1% is in sync", path, log::verbose ) ; m_state = sync ; } - + // remote file created after last sync, so remote is newer else if ( remote.MTime() > last_sync ) { @@ -146,11 +146,11 @@ void Resource::FromRemote( const Entry& remote, const DateTime& last_sync ) FromRemoteFolder( remote, last_sync ) ; else FromRemoteFile( remote, last_sync ) ; - + AssignIDs( remote ) ; - + assert( m_state != unknown ) ; - + if ( m_state == remote_new || m_state == remote_changed ) { m_md5 = remote.MD5() ; @@ -175,7 +175,7 @@ void Resource::AssignIDs( const Entry& remote ) void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) { assert( m_parent != 0 ) ; - + fs::path path = Path() ; // recursively create/delete folder @@ -186,7 +186,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) ( m_parent->m_state == remote_new || m_parent->m_state == local_new ) ? "created" : "deleted", ( m_parent->m_state == remote_new || m_parent->m_state == remote_deleted ) ? "remote" : "local", m_parent->m_state, log::verbose ) ; - + m_state = m_parent->m_state ; } @@ -194,12 +194,12 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) else if ( !fs::exists( path ) ) { Trace( "file %1% change stamp = %2%", Path(), remote.ChangeStamp() ) ; - + if ( remote.MTime() > last_sync || remote.ChangeStamp() > 0 ) { Log( "file %1% is created in remote (change %2%)", path, remote.ChangeStamp(), log::verbose ) ; - + m_state = remote_new ; } else @@ -208,7 +208,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) m_state = local_deleted ; } } - + // remote checksum unknown, assume the file is not changed in remote else if ( remote.MD5().empty() ) { @@ -216,7 +216,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) Path(), log::verbose ) ; m_state = sync ; } - + // if checksum is equal, no need to compare the mtime else if ( remote.MD5() == m_md5 ) { @@ -235,7 +235,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync ) Log( "file %1% is changed in remote", path, log::verbose ) ; m_state = remote_changed ; } - + // remote also has the file, so it's not new in local else if ( m_state == local_new || m_state == remote_deleted ) { @@ -262,18 +262,18 @@ void Resource::FromLocal( const DateTime& last_sync ) // follow parent recursively if ( m_parent->m_state == local_new || m_parent->m_state == local_deleted ) m_state = local_new ; - + // if the file is not created after last sync, assume file is // remote_deleted first, it will be updated to sync/remote_changed // in FromRemote() else m_state = ( m_mtime > last_sync ? local_new : remote_deleted ) ; - + m_name = path.filename().string() ; m_kind = fs::is_directory(path) ? "folder" : "file" ; m_md5 = fs::is_directory(path) ? "" : crypt::MD5::Get( path ) ; } - + assert( m_state != unknown ) ; } @@ -323,12 +323,12 @@ void Resource::Swap( Resource& coll ) m_id.swap( coll.m_id ) ; m_href.swap( coll.m_href ) ; - m_content.swap( coll.m_content ) ; + m_content.swap( coll.m_content ) ; m_edit.swap( coll.m_edit ) ; m_create.swap( coll.m_create ) ; - + m_mtime.Swap( coll.m_mtime ) ; - + std::swap( m_parent, coll.m_parent ) ; m_child.swap( coll.m_child ) ; std::swap( m_state, coll.m_state ) ; @@ -369,13 +369,13 @@ void Resource::Sync( http::Agent *http, DateTime& sync_time, const Json& options { assert( m_state != unknown ) ; assert( !IsRoot() || m_state == sync ) ; // root folder is already synced - + SyncSelf( http, options ) ; - + // we want the server sync time, so we will take the server time of the last file uploaded to store as the sync time // m_mtime is updated to server modified time when the file is uploaded sync_time = std::max(sync_time, m_mtime); - + // if myself is deleted, no need to do the childrens if ( m_state != local_deleted && m_state != remote_deleted ) std::for_each( m_child.begin(), m_child.end(), @@ -391,28 +391,33 @@ void Resource::SyncSelf( http::Agent* http, const Json& options ) const fs::path path = Path() ; + Json uploadonly ; + switch ( m_state ) { case local_new : Log( "sync %1% doesn't exist in server, uploading", path, log::info ) ; - if ( http != 0 && Create( http ) ) m_state = sync ; break ; - + case local_deleted : + if ( options.Get("uploadonly", uploadonly) && uploadonly.Bool() ) + break ; Log( "sync %1% deleted in local. deleting remote", path, log::info ) ; if ( http != 0 ) DeleteRemote( http ) ; break ; - + case local_changed : Log( "sync %1% changed in local. uploading", path, log::info ) ; if ( http != 0 && EditContent( http, options["new-rev"].Bool() ) ) m_state = sync ; break ; - + case remote_new : + if ( options.Get("uploadonly", uploadonly) && uploadonly.Bool() ) + break ; Log( "sync %1% created in remote. creating local", path, log::info ) ; if ( http != 0 ) { @@ -420,12 +425,14 @@ void Resource::SyncSelf( http::Agent* http, const Json& options ) fs::create_directories( path ) ; else Download( http, path ) ; - + m_state = sync ; } break ; - + case remote_changed : + if ( options.Get("uploadonly", uploadonly) && uploadonly.Bool() ) + break ; assert( !IsFolder() ) ; Log( "sync %1% changed in remote. downloading", path, log::info ) ; if ( http != 0 ) @@ -434,13 +441,15 @@ void Resource::SyncSelf( http::Agent* http, const Json& options ) m_state = sync ; } break ; - + case remote_deleted : + if ( options.Get("uploadonly", uploadonly) && uploadonly.Bool() ) + break ; Log( "sync %1% deleted in remote. deleting local", path, log::info ) ; if ( http != 0 ) DeleteLocal() ; break ; - + case sync : Log( "sync %1% already in sync", path, log::verbose ) ; break ; @@ -449,7 +458,7 @@ void Resource::SyncSelf( http::Agent* http, const Json& options ) case unknown : assert( false ) ; break ; - + default : break ; } diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 2d1dc943..c2dc6c40 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -248,12 +248,12 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; - last_sync.Add( "sec", Json(m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json(m_last_sync.NanoSec() ) ); + last_sync.Add( "sec", Json((boost::uint64_t)m_last_sync.Sec() ) ); + last_sync.Add( "nsec", Json((boost::uint64_t)m_last_sync.NanoSec() ) ); Json result ; result.Add( "last_sync", last_sync ) ; - result.Add( "change_stamp", Json(m_cstamp) ) ; + result.Add( "change_stamp", Json((boost::uint64_t)m_cstamp) ) ; std::ofstream fs( filename.string().c_str() ) ; fs << result ; diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index b5a9f15b..6f944a59 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -39,6 +39,7 @@ Config::Config( const po::variables_map& vm ) m_cmd.Add( "log-xml", Json(vm.count("log-xml") > 0) ) ; m_cmd.Add( "new-rev", Json(vm.count("new-rev") > 0) ) ; m_cmd.Add( "force", Json(vm.count("force") > 0 ) ) ; + m_cmd.Add( "uploadonly", Json(vm.count("uploadonly") > 0 ) ) ; m_cmd.Add( "path", Json(vm.count("path") > 0 ? vm["path"].as() : default_root_folder ) ) ; From 5914cef5f253b62e4cb05b02f3533bfa2514448b Mon Sep 17 00:00:00 2001 From: linwiz Date: Fri, 19 Sep 2014 12:51:13 -0400 Subject: [PATCH 55/79] Ignore only .grive and .grive_state --- libgrive/src/drive/State.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index c2dc6c40..7b041030 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -60,7 +60,7 @@ void State::FromLocal( const fs::path& p ) bool State::IsIgnore( const std::string& filename ) { - return filename[0] == '.' ; + return filename == ".grive" || filename == ".grive_state"; } void State::FromLocal( const fs::path& p, Resource* folder ) From f8dff44102dbebc8bc7920a33746f84e729c3f00 Mon Sep 17 00:00:00 2001 From: linwiz Date: Fri, 19 Sep 2014 13:15:55 -0400 Subject: [PATCH 56/79] Add autogenerated stuff to .gitignore --- .gitignore | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index da71e17a..6fa3768d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,13 @@ grive.kdev4 .project .cproject build/ +/CMakeCache.txt +CMakeFiles +moc_*.cxx* +bgrive/ui_MainWindow.h +Makefile +*.a +bgrive/bgrive +grive/grive +libgrive/btest +*.cmake From aa040bc1d28b325361421d3e4e22121facbe7457 Mon Sep 17 00:00:00 2001 From: linwiz Date: Fri, 19 Sep 2014 13:49:43 -0400 Subject: [PATCH 57/79] Ignore .trash from sync --- libgrive/src/drive/State.cc | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 7b041030..bbeb69ea 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -38,12 +38,12 @@ State::State( const fs::path& filename, const Json& options ) : m_cstamp ( -1 ) { Read( filename ) ; - + // the "-f" option will make grive always thinks remote is newer Json force ; if ( options.Get("force", force) && force.Bool() ) m_last_sync = DateTime() ; - + Log( "last sync time: %1%", m_last_sync, log::verbose ) ; } @@ -60,28 +60,28 @@ void State::FromLocal( const fs::path& p ) bool State::IsIgnore( const std::string& filename ) { - return filename == ".grive" || filename == ".grive_state"; + return filename == ".grive" || filename == ".grive_state" || filename == ".trash"; } void State::FromLocal( const fs::path& p, Resource* folder ) { assert( folder != 0 ) ; assert( folder->IsFolder() ) ; - + // sync the folder itself folder->FromLocal( m_last_sync ) ; for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i ) { std::string fname = i->path().filename().string() ; - + if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; - + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; - + else { // if the Resource object of the child already exists, it should @@ -93,9 +93,9 @@ void State::FromLocal( const fs::path& p, Resource* folder ) folder->AddChild( c ) ; m_res.Insert( c ) ; } - - c->FromLocal( m_last_sync ) ; - + + c->FromLocal( m_last_sync ) ; + if ( fs::is_directory( i->path() ) ) FromLocal( *i, c ) ; } @@ -104,7 +104,7 @@ void State::FromLocal( const fs::path& p, Resource* folder ) void State::FromRemote( const Entry& e ) { - std::string fn = e.Filename() ; + std::string fn = e.Filename() ; if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; @@ -112,10 +112,10 @@ void State::FromRemote( const Entry& e ) // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; - + else if ( fn.find('/') != fn.npos ) Log( "%1% \"%2%\" contains a slash in its name, ignored", e.Kind(), e.Name(), log::verbose ) ; - + else if ( !e.IsChange() && e.ParentHrefs().size() != 1 ) Log( "%1% \"%2%\" has multiple parents, ignored", e.Kind(), e.Name(), log::verbose ) ; @@ -143,7 +143,7 @@ std::size_t State::TryResolveEntry() std::size_t count = 0 ; std::vector& en = m_unresolved ; - + for ( std::vector::iterator i = en.begin() ; i != en.end() ; ) { if ( Update( *i ) ) @@ -161,7 +161,7 @@ void State::FromChange( const Entry& e ) { assert( e.IsChange() ) ; assert( !IsIgnore( e.Name() ) ) ; - + // entries in the change feed is always treated as newer in remote, // so we override the last sync time to 0 if ( Resource *res = m_res.FindByHref( e.AltSelf() ) ) @@ -190,7 +190,7 @@ bool State::Update( const Entry& e ) // since we are updating the ID and Href, we need to remove it and re-add it. m_res.Update( child, e, m_last_sync ) ; } - + // folder entry exist in google drive, but not local. we should create // the directory else if ( e.Kind() == "folder" || !e.Filename().empty() ) @@ -199,11 +199,11 @@ bool State::Update( const Entry& e ) child = new Resource( name, e.Kind() ) ; parent->AddChild( child ) ; m_res.Insert( child ) ; - + // update the state of the resource m_res.Update( child, e, m_last_sync ) ; } - + return true ; } else @@ -231,12 +231,12 @@ void State::Read( const fs::path& filename ) { File file( filename ) ; Json json = Json::Parse( &file ) ; - + Json last_sync = json["last_sync"] ; m_last_sync.Assign( last_sync["sec"].Int(), last_sync["nsec"].Int() ) ; - + m_cstamp = json["change_stamp"].Int() ; } catch ( Exception& ) @@ -250,11 +250,11 @@ void State::Write( const fs::path& filename ) const Json last_sync ; last_sync.Add( "sec", Json((boost::uint64_t)m_last_sync.Sec() ) ); last_sync.Add( "nsec", Json((boost::uint64_t)m_last_sync.NanoSec() ) ); - + Json result ; result.Add( "last_sync", last_sync ) ; result.Add( "change_stamp", Json((boost::uint64_t)m_cstamp) ) ; - + std::ofstream fs( filename.string().c_str() ) ; fs << result ; } @@ -270,7 +270,7 @@ void State::Sync( http::Agent *http, const Json& options ) // need to check if this introduces a new problem DateTime last_sync_time = m_last_sync; m_res.Root()->Sync( http, last_sync_time, options ) ; - + if ( last_sync_time == m_last_sync ) { Trace( "nothing changed? %1%", m_last_sync ) ; From 3c25cb553c069a02c995bc15c866fb64960c7ccf Mon Sep 17 00:00:00 2001 From: linwiz Date: Fri, 19 Sep 2014 14:05:29 -0400 Subject: [PATCH 58/79] Cleaned up whitespace --- bgrive/src/DriveModel.cc | 4 +- bgrive/src/DriveModel.hh | 2 +- bgrive/src/MainWnd.cc | 2 +- bgrive/src/main.cc | 6 +-- grive/src/main.cc | 32 ++++++------- libgrive/src/bfd/Backtrace.hh | 6 +-- libgrive/src/bfd/Debug.cc | 8 ++-- libgrive/src/bfd/SymbolInfo.cc | 24 +++++----- libgrive/src/bfd/SymbolInfo.hh | 8 ++-- libgrive/src/drive/CommonUri.hh | 4 +- libgrive/src/drive/Drive.cc | 38 +++++++-------- libgrive/src/drive/Drive.hh | 6 +-- libgrive/src/drive/Entry.hh | 22 ++++----- libgrive/src/drive/Feed.cc | 6 +-- libgrive/src/drive/Feed.hh | 14 +++--- libgrive/src/drive/Resource.cc | 34 +++++++------- libgrive/src/drive/Resource.hh | 46 +++++++++--------- libgrive/src/drive/ResourceTree.cc | 6 +-- libgrive/src/drive/ResourceTree.hh | 14 +++--- libgrive/src/drive/State.hh | 14 +++--- libgrive/src/drive2/Drive.cc | 18 +++---- libgrive/src/drive2/Drive.hh | 10 ++-- libgrive/src/drive2/Feed.cc | 4 +- libgrive/src/drive2/Feed.hh | 4 +- libgrive/src/drive2/Resource.hh | 6 +-- libgrive/src/http/Agent.hh | 10 ++-- libgrive/src/http/CurlAgent.cc | 38 +++++++-------- libgrive/src/http/CurlAgent.hh | 18 +++---- libgrive/src/http/Download.cc | 4 +- libgrive/src/http/Download.hh | 8 ++-- libgrive/src/http/Header.hh | 4 +- libgrive/src/http/ResponseLog.cc | 12 ++--- libgrive/src/http/ResponseLog.hh | 8 ++-- libgrive/src/http/StringResponse.hh | 2 +- libgrive/src/http/XmlResponse.hh | 2 +- libgrive/src/json/JsonParser.cc | 52 ++++++++++----------- libgrive/src/json/JsonParser.hh | 6 +-- libgrive/src/json/JsonWriter.cc | 2 +- libgrive/src/json/Val.cc | 22 ++++----- libgrive/src/json/Val.hh | 14 +++--- libgrive/src/json/ValBuilder.cc | 8 ++-- libgrive/src/json/ValBuilder.hh | 2 +- libgrive/src/json/ValResponse.hh | 2 +- libgrive/src/protocol/AuthAgent.cc | 22 ++++----- libgrive/src/protocol/AuthAgent.hh | 14 +++--- libgrive/src/protocol/Json.cc | 38 +++++++-------- libgrive/src/protocol/Json.hh | 24 +++++----- libgrive/src/protocol/JsonResponse.hh | 2 +- libgrive/src/protocol/OAuth2.cc | 8 ++-- libgrive/src/protocol/OAuth2.hh | 12 ++--- libgrive/src/util/CArray.hh | 8 ++-- libgrive/src/util/Config.cc | 6 +-- libgrive/src/util/Config.hh | 8 ++-- libgrive/src/util/Crypt.cc | 4 +- libgrive/src/util/Crypt.hh | 2 +- libgrive/src/util/DataStream.hh | 2 +- libgrive/src/util/DateTime.cc | 6 +-- libgrive/src/util/DateTime.hh | 12 ++--- libgrive/src/util/Exception.hh | 2 +- libgrive/src/util/File.cc | 16 +++---- libgrive/src/util/File.hh | 8 ++-- libgrive/src/util/Function.hh | 30 ++++++------ libgrive/src/util/MemMap.cc | 2 +- libgrive/src/util/MemMap.hh | 2 +- libgrive/src/util/OS.cc | 4 +- libgrive/src/util/OS.hh | 6 +-- libgrive/src/util/StringStream.hh | 8 ++-- libgrive/src/util/Types.hh | 2 +- libgrive/src/util/log/CommonLog.cc | 4 +- libgrive/src/util/log/CommonLog.hh | 4 +- libgrive/src/util/log/CompositeLog.cc | 2 +- libgrive/src/util/log/CompositeLog.hh | 2 +- libgrive/src/util/log/DefaultLog.cc | 2 +- libgrive/src/util/log/DefaultLog.hh | 2 +- libgrive/src/util/log/Log.cc | 6 +-- libgrive/src/util/log/Log.hh | 18 +++---- libgrive/src/xml/Node.cc | 62 ++++++++++++------------- libgrive/src/xml/Node.hh | 22 ++++----- libgrive/src/xml/NodeSet.cc | 4 +- libgrive/src/xml/NodeSet.hh | 8 ++-- libgrive/src/xml/TreeBuilder.cc | 22 ++++----- libgrive/src/xml/TreeBuilder.hh | 6 +-- libgrive/test/Assert.hh | 6 +-- libgrive/test/UnitTest.cc | 6 +-- libgrive/test/btest/JsonValTest.cc | 8 ++-- libgrive/test/btest/ValTest.cc | 2 +- libgrive/test/drive/EntryTest.cc | 8 ++-- libgrive/test/drive/ResourceTest.cc | 8 ++-- libgrive/test/drive/ResourceTreeTest.cc | 2 +- libgrive/test/http/MockAgent.hh | 10 ++-- libgrive/test/util/DateTimeTest.cc | 6 +-- libgrive/test/util/FunctionTest.cc | 2 +- libgrive/test/xml/NodeTest.cc | 16 +++---- 93 files changed, 519 insertions(+), 519 deletions(-) diff --git a/bgrive/src/DriveModel.cc b/bgrive/src/DriveModel.cc index bc3bcf43..d2ee81ae 100644 --- a/bgrive/src/DriveModel.cc +++ b/bgrive/src/DriveModel.cc @@ -49,7 +49,7 @@ QVariant DriveModel::data( const QModelIndex& index, int role ) const default: break ; } } - + return QVariant() ; } @@ -75,7 +75,7 @@ bool DriveModel::hasChildren( const QModelIndex& parent ) const QModelIndex DriveModel::index( int row, int column, const QModelIndex& parent_idx ) const { - const Resource *parent = Res(parent_idx) ; + const Resource *parent = Res(parent_idx) ; // check out-of-bound if ( parent != 0 && static_cast(row) >= parent->ChildCount() ) diff --git a/bgrive/src/DriveModel.hh b/bgrive/src/DriveModel.hh index f39847f4..9885aedb 100644 --- a/bgrive/src/DriveModel.hh +++ b/bgrive/src/DriveModel.hh @@ -40,7 +40,7 @@ public : public : DriveModel( http::Agent *agent ) ; - + // QAbstractItemModel overrides Qt::ItemFlags flags( const QModelIndex & index ) const ; QVariant data( const QModelIndex& index, int role ) const ; diff --git a/bgrive/src/MainWnd.cc b/bgrive/src/MainWnd.cc index 28d4e088..a440efab 100644 --- a/bgrive/src/MainWnd.cc +++ b/bgrive/src/MainWnd.cc @@ -35,7 +35,7 @@ MainWnd::MainWnd( http::Agent *agent ) : { m_ui.setupUi(this) ; m_ui.m_dir->setModel( &m_drive ) ; - + connect( m_ui.m_dir, SIGNAL(activated(const QModelIndex&)), this, SLOT(OnClick(const QModelIndex&)) diff --git a/bgrive/src/main.cc b/bgrive/src/main.cc index ea578ec9..3e24ebcb 100644 --- a/bgrive/src/main.cc +++ b/bgrive/src/main.cc @@ -48,15 +48,15 @@ int main( int argc, char **argv ) { File file( ".grive" ) ; Json cfg = Json::Parse( &file ) ; - + std::string refresh_token = cfg["refresh_token"].Str() ; OAuth2 token( refresh_token, client_id, client_secret ) ; - + AuthAgent agent( token, std::auto_ptr( new http::CurlAgent ) ) ; QApplication app( argc, argv ) ; MainWnd wnd( &agent ) ; wnd.show(); - + return app.exec() ; } diff --git a/grive/src/main.cc b/grive/src/main.cc index e93f627b..e300cd4e 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -78,19 +78,19 @@ void InitLog( const po::variables_map& vm ) file_log->Enable( log::warning ) ; file_log->Enable( log::error ) ; file_log->Enable( log::critical ) ; - + // log grive version to log file file_log->Log( log::Fmt("grive version " VERSION " " __DATE__ " " __TIME__), log::verbose ) ; file_log->Log( log::Fmt("current time: %1%") % DateTime::Now(), log::verbose ) ; - + comp_log->Add( file_log ) ; } - + if ( vm.count( "verbose" ) ) { console_log->Enable( log::verbose ) ; } - + if ( vm.count( "debug" ) ) { console_log->Enable( log::verbose ) ; @@ -102,7 +102,7 @@ void InitLog( const po::variables_map& vm ) int Main( int argc, char **argv ) { InitGCrypt() ; - + // construct the program options po::options_description desc( "Grive options" ); desc.add_options() @@ -122,11 +122,11 @@ int Main( int argc, char **argv ) ( "dry-run", "Only detect which files need to be uploaded/downloaded, " "without actually performing them." ) ; - + po::variables_map vm; po::store(po::parse_command_line( argc, argv, desc), vm ); po::notify(vm); - + // simple commands that doesn't require log or config if ( vm.count("help") ) { @@ -142,9 +142,9 @@ int Main( int argc, char **argv ) // initialize logging InitLog(vm) ; - + Config config(vm) ; - + Log( "config file name %1%", config.Filename(), log::verbose ); if ( vm.count( "auth" ) ) @@ -154,21 +154,21 @@ int Main( int argc, char **argv ) << "Please go to this URL and get an authentication code:\n\n" << OAuth2::MakeAuthURL( client_id ) << std::endl ; - + std::cout << "\n-----------------------\n" << "Please input the authentication code here: " << std::endl ; std::string code ; std::cin >> code ; - + OAuth2 token( client_id, client_secret ) ; token.Auth( code ) ; - + // save to config config.Set( "refresh_token", Json( token.RefreshToken() ) ) ; config.Save() ; } - + std::string refresh_token ; try { @@ -180,10 +180,10 @@ int Main( int argc, char **argv ) "Please run grive with the \"-a\" option if this is the " "first time you're accessing your Google Drive!", log::critical ) ; - + return -1; } - + OAuth2 token( refresh_token, client_id, client_secret ) ; AuthAgent agent( token, std::auto_ptr( new http::CurlAgent ) ) ; @@ -197,7 +197,7 @@ int Main( int argc, char **argv ) } else drive.DryRun() ; - + config.Save() ; Log( "Finished!", log::info ) ; return 0 ; diff --git a/libgrive/src/bfd/Backtrace.hh b/libgrive/src/bfd/Backtrace.hh index aab906d9..8673a388 100644 --- a/libgrive/src/bfd/Backtrace.hh +++ b/libgrive/src/bfd/Backtrace.hh @@ -30,11 +30,11 @@ namespace gr { /** \internal The sole reason for this class to exists is to provide the operator<< overload to allow: - + \code std::cout << Backtrace() << std::endl ; \endcode - + \sa SymbolInfo */ class Backtrace @@ -42,7 +42,7 @@ class Backtrace public : explicit Backtrace( std::size_t skip = 2 ) ; Backtrace( const Backtrace& bt ) ; - + friend std::ostream& operator<<( std::ostream& os, const gr::Backtrace& bt ) ; diff --git a/libgrive/src/bfd/Debug.cc b/libgrive/src/bfd/Debug.cc index f00c4829..0225cc27 100644 --- a/libgrive/src/bfd/Debug.cc +++ b/libgrive/src/bfd/Debug.cc @@ -52,16 +52,16 @@ std::string Demangle( const char *name ) std::ostream& PrintHex( std::ostream& os, const void *buf, std::size_t size ) { const unsigned char *raw = static_cast( buf ) ; - + for ( std::size_t i = 0 ; i < size ; i++ ) { if ( i % 8 == 0 && i > 0 ) os << std::endl ; - + if ( i % 8 == 0 ) os << std::hex << std::setw(8) << std::setfill('0') << i << " " ; - - os << "0x" << std::hex << std::setw(2) << std::setfill('0') + + os << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)raw[i] << ", " ; } os << std::endl ; diff --git a/libgrive/src/bfd/SymbolInfo.cc b/libgrive/src/bfd/SymbolInfo.cc index afd3ba14..568c0b04 100644 --- a/libgrive/src/bfd/SymbolInfo.cc +++ b/libgrive/src/bfd/SymbolInfo.cc @@ -48,9 +48,9 @@ SymbolInfo::SymbolInfo( ) m_impl->m_bfd = 0 ; m_impl->m_symbols = 0 ; m_impl->m_symbol_count = 0 ; - + bfd_init( ) ; - + // opening itself bfd *b = bfd_openr( "/proc/self/exe", 0 ) ; if ( b == NULL ) @@ -59,13 +59,13 @@ SymbolInfo::SymbolInfo( ) << bfd_errmsg( bfd_get_error() ) << std::endl ; return ; } - + if ( bfd_check_format( b, bfd_archive ) ) { bfd_close( b ) ; return ; } - + char **matching ; if ( !bfd_check_format_matches( b, bfd_object, &matching ) ) { @@ -77,7 +77,7 @@ SymbolInfo::SymbolInfo( ) std::cerr << bfd_get_filename( b ) << ": Matching formats: " ; for ( char **p = matching ; *p != 0 ; p++ ) std::cerr << " " << *p ; - + std::cerr << std::endl ; std::free( matching ) ; } @@ -106,7 +106,7 @@ struct SymbolInfo::BacktraceInfo const char *m_func_name ; unsigned int m_lineno ; unsigned int m_is_found ; - + static void Callback( bfd *abfd, asection *section, void* addr ) ; } ; @@ -116,17 +116,17 @@ void SymbolInfo::BacktraceInfo::Callback( bfd *abfd, asection *section, BacktraceInfo *info = (BacktraceInfo *)data ; if ((section->flags & SEC_ALLOC) == 0) return ; - + bfd_vma vma = bfd_get_section_vma(abfd, section); - + unsigned long address = (unsigned long)(info->m_addr); if ( address < vma ) return; - + bfd_size_type size = bfd_section_size(abfd, section); if ( address > (vma + size)) return ; - + const SymbolInfo *pthis = info->m_pthis ; info->m_is_found = bfd_find_nearest_line( abfd, section, pthis->m_impl->m_symbols, @@ -148,7 +148,7 @@ void SymbolInfo::PrintTrace( void *addr, std::ostream& os, std::size_t idx ) { this, addr, 0, 0, 0, false } ; - + Dl_info sym ; bfd_map_over_sections( m_impl->m_bfd, &SymbolInfo::BacktraceInfo::Callback, @@ -164,7 +164,7 @@ if ( btinfo.m_is_found ) filename.erase( pos, std::strlen( SRC_DIR ) ) ; #endif os << "#" << idx << " " << addr << " " - << filename << ":" << btinfo.m_lineno + << filename << ":" << btinfo.m_lineno << " " << (btinfo.m_func_name != 0 ? Demangle(btinfo.m_func_name) : "" ) << std::endl ; diff --git a/libgrive/src/bfd/SymbolInfo.hh b/libgrive/src/bfd/SymbolInfo.hh index bcbc3b14..8854691d 100644 --- a/libgrive/src/bfd/SymbolInfo.hh +++ b/libgrive/src/bfd/SymbolInfo.hh @@ -28,7 +28,7 @@ namespace gr { /// ource code symbolic information /** \internal - + This class represents symbolic information about the source code, e.g. function names and line numbers. It provides an interface to lookup these informations by address. @@ -41,7 +41,7 @@ public : /*! \brief singleton function \internal - + Returns the SymbolInfo singleton. Normally only one object of SymbolInfo is enough for one application, so a singleton is enough. This function will create the SymbolInfo object @@ -51,11 +51,11 @@ public : std::size_t Backtrace( addr_t *stack, std::size_t count ) ; void PrintTrace( addr_t addr, std::ostream& os, std::size_t idx = 0 ) ; - + private : struct Impl ; const std::auto_ptr m_impl ; - + struct BacktraceInfo ; friend struct BacktraceInfo ; } ; diff --git a/libgrive/src/drive/CommonUri.hh b/libgrive/src/drive/CommonUri.hh index b0e06f7f..4a06e299 100644 --- a/libgrive/src/drive/CommonUri.hh +++ b/libgrive/src/drive/CommonUri.hh @@ -26,11 +26,11 @@ namespace gr { namespace v1 const std::string feed_base = "https://docs.google.com/feeds/default/private/full" ; const std::string feed_changes = "https://docs.google.com/feeds/default/private/changes" ; const std::string feed_metadata = "https://docs.google.com/feeds/metadata/default" ; - + const std::string root_href = "https://docs.google.com/feeds/default/private/full/folder%3Aroot" ; const std::string root_create = "https://docs.google.com/feeds/upload/create-session/default/private/full" ; - + std::string ChangesFeed( int changestamp ) ; } } diff --git a/libgrive/src/drive/Drive.cc b/libgrive/src/drive/Drive.cc index 39354484..d2f20f71 100644 --- a/libgrive/src/drive/Drive.cc +++ b/libgrive/src/drive/Drive.cc @@ -65,14 +65,14 @@ void Drive::FromRemote( const Entry& entry ) // entries from change feed does not have the parent HREF, // so these checkings are done in normal entries only Resource *parent = m_state.FindByHref( entry.ParentHref() ) ; - + if ( parent != 0 && !parent->IsFolder() ) Log( "warning: entry %1% has parent %2% which is not a folder, ignored", entry.Title(), parent->Name(), log::verbose ) ; - + else if ( parent == 0 || !parent->IsInRootTree() ) Log( "file \"%1%\" parent doesn't exist, ignored", entry.Title(), log::verbose ) ; - + else m_state.FromRemote( entry ) ; } @@ -81,7 +81,7 @@ void Drive::FromChange( const Entry& entry ) { if ( entry.IsRemoved() ) Log( "file \"%1%\" represents a deletion, ignored", entry.Title(), log::verbose ) ; - + // folders go directly else m_state.FromRemote( entry ) ; @@ -100,7 +100,7 @@ void Drive::SyncFolders( ) http::XmlResponse xml ; m_http->Get( feed_base + "/-/folder?max-results=50&showroot=true", &xml, http::Header() ) ; - + Feed feed( xml.Response() ) ; do { @@ -112,10 +112,10 @@ void Drive::SyncFolders( ) { if ( e.ParentHrefs().size() != 1 ) Log( "folder \"%1%\" has multiple parents, ignored", e.Title(), log::verbose ) ; - + else if ( e.Title().find('/') != std::string::npos ) Log( "folder \"%1%\" contains a slash in its name, ignored", e.Title(), log::verbose ) ; - + else m_state.FromRemote( e ) ; } @@ -129,30 +129,30 @@ void Drive::DetectChanges() { Log( "Reading local directories", log::info ) ; m_state.FromLocal( m_root ) ; - + long prev_stamp = m_state.ChangeStamp() ; Trace( "previous change stamp is %1%", prev_stamp ) ; - + SyncFolders( ) ; Log( "Reading remote server file list", log::info ) ; Feed feed ; if ( m_options["log-xml"].Bool() ) feed.EnableLog( "/tmp/file", ".xml" ) ; - + feed.Start( m_http, feed_base + "?showfolders=true&showroot=true" ) ; - + m_resume_link = feed.Root()["link"]. Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ; - + do { std::for_each( feed.begin(), feed.end(), boost::bind( &Drive::FromRemote, this, _1 ) ) ; - + } while ( feed.GetNext( m_http ) ) ; - + // pull the changes feed if ( prev_stamp != -1 ) { @@ -160,9 +160,9 @@ void Drive::DetectChanges() Feed changes ; if ( m_options["log-xml"].Bool() ) feed.EnableLog( "/tmp/changes", ".xml" ) ; - + feed.Start( m_http, ChangesFeed(prev_stamp+1) ) ; - + std::for_each( changes.begin(), changes.end(), boost::bind( &Drive::FromChange, this, _1 ) ) ; @@ -173,7 +173,7 @@ void Drive::Update() { Log( "Synchronizing files", log::info ) ; m_state.Sync( m_http, m_options ) ; - + UpdateChangeStamp( ) ; } @@ -190,10 +190,10 @@ void Drive::UpdateChangeStamp( ) // get changed feed http::XmlResponse xrsp ; m_http->Get( ChangesFeed(m_state.ChangeStamp()+1), &xrsp, http::Header() ) ; - + // we should go through the changes to see if it was really Grive to made that change // maybe by recording the updated timestamp and compare it? - m_state.ChangeStamp( + m_state.ChangeStamp( std::atoi(xrsp.Response()["docs:largestChangestamp"]["@value"].front().Value().c_str()) ) ; } diff --git a/libgrive/src/drive/Drive.hh b/libgrive/src/drive/Drive.hh index 0490d5c1..32797ff9 100644 --- a/libgrive/src/drive/Drive.hh +++ b/libgrive/src/drive/Drive.hh @@ -48,16 +48,16 @@ public : void Update() ; void DryRun() ; void SaveState() ; - + struct Error : virtual Exception {} ; - + private : void SyncFolders( ) ; void file(); void FromRemote( const Entry& entry ) ; void FromChange( const Entry& entry ) ; void UpdateChangeStamp( ) ; - + private : http::Agent *m_http ; std::string m_resume_link ; diff --git a/libgrive/src/drive/Entry.hh b/libgrive/src/drive/Entry.hh index b7e9293a..4c5e2449 100644 --- a/libgrive/src/drive/Entry.hh +++ b/libgrive/src/drive/Entry.hh @@ -46,18 +46,18 @@ class Entry public : Entry( ) ; explicit Entry( const xml::Node& n ) ; - + std::string Title() const ; std::string Filename() const ; std::string Kind() const ; std::string MD5() const ; DateTime MTime() const ; - + std::string Name() const ; - + std::string ResourceID() const ; std::string ETag() const ; - + std::string SelfHref() const ; std::string AltSelf() const ; std::string ParentHref() const ; @@ -65,16 +65,16 @@ public : std::string EditLink() const ; std::string CreateLink() const ; long ChangeStamp() const ; - + bool IsChange() const ; bool IsRemoved() const ; - + const std::vector& ParentHrefs() const ; - + void Swap( Entry& e ) ; - + void Update( const xml::Node& entry ) ; - + private : std::string m_title ; std::string m_filename ; @@ -84,7 +84,7 @@ private : std::string m_resource_id ; std::vector m_parent_hrefs ; - + std::string m_self_href ; std::string m_alt_self ; std::string m_content_src ; @@ -92,7 +92,7 @@ private : std::string m_create_link ; long m_change_stamp ; - + DateTime m_mtime ; bool m_is_removed ; } ; diff --git a/libgrive/src/drive/Feed.cc b/libgrive/src/drive/Feed.cc index b227e520..6c7fb8bf 100644 --- a/libgrive/src/drive/Feed.cc +++ b/libgrive/src/drive/Feed.cc @@ -67,15 +67,15 @@ void Feed::Start( http::Agent *http, const std::string& url ) { http::XmlResponse xrsp ; http::ResponseLog log( &xrsp ) ; - + if ( m_log.get() != 0 ) log.Reset( m_log->prefix, (boost::format( "-#%1%%2%" ) % m_log->sequence++ % m_log->suffix ).str(), &xrsp ) ; - + http->Get( url, &log, http::Header() ) ; - + m_root = xrsp.Response() ; m_entries = m_root["entry"] ; } diff --git a/libgrive/src/drive/Feed.hh b/libgrive/src/drive/Feed.hh index 92e62345..8772a051 100644 --- a/libgrive/src/drive/Feed.hh +++ b/libgrive/src/drive/Feed.hh @@ -47,18 +47,18 @@ public : explicit Feed( const xml::Node& root ) ; Feed( ) ; void Start( http::Agent *http, const std::string& url ) ; - + void Assign( const xml::Node& root ) ; const xml::Node& Root() const ; - + iterator begin() const ; iterator end() const ; - + std::string Next() const ; bool GetNext( http::Agent *http ) ; - + void EnableLog( const std::string& prefix, const std::string& suffix ) ; - + private : struct LogInfo { @@ -82,11 +82,11 @@ class Feed::iterator : public boost::iterator_adaptor< { public : iterator() ; - explicit iterator( xml::Node::iterator i ) ; + explicit iterator( xml::Node::iterator i ) ; private : friend class boost::iterator_core_access; - + reference dereference() const ; } ; diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index cfd8bff5..eb0e8745 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -472,11 +472,11 @@ void Resource::DeleteLocal() assert( m_parent != 0 ) ; fs::path parent = m_parent->Path() ; fs::path dest = ".trash" / parent / Name() ; - + std::size_t idx = 1 ; while ( fs::exists( dest ) && idx != 0 ) dest = ".trash" / parent / (boost::format(trash_file) % Name() % idx++).str() ; - + // wrap around! just remove the file if ( idx == 0 ) fs::remove_all( Path() ) ; @@ -491,17 +491,17 @@ void Resource::DeleteRemote( http::Agent *http ) { assert( http != 0 ) ; http::StringResponse str ; - + try { http::Header hdr ; hdr.Add( "If-Match: " + m_etag ) ; - + // doesn't know why, but an update before deleting seems to work always http::XmlResponse xml ; http->Get( m_href, &xml, hdr ) ; AssignIDs( Entry( xml.Response() ) ) ; - + http->Custom( "DELETE", m_href, &str, hdr ) ; } catch ( Exception& e ) @@ -518,7 +518,7 @@ void Resource::DeleteRemote( http::Agent *http ) void Resource::Download( http::Agent* http, const fs::path& file ) const { assert( http != 0 ) ; - + http::Download dl( file.string(), http::Download::NoChecksum() ) ; long r = http->Get( m_content, &dl, http::Header() ) ; if ( r <= 400 ) @@ -542,7 +542,7 @@ bool Resource::EditContent( http::Agent* http, bool new_rev ) Log( "Cannot upload %1%: file read-only. %2%", m_name, m_state, log::warning ) ; return false ; } - + return Upload( http, m_edit + (new_rev ? "?new-revision=true" : ""), false ) ; } @@ -552,13 +552,13 @@ bool Resource::Create( http::Agent* http ) assert( m_parent != 0 ) ; assert( m_parent->IsFolder() ) ; assert( m_parent->m_state == sync ) ; - + if ( IsFolder() ) { std::string uri = feed_base ; if ( !m_parent->IsRoot() ) uri += ("/" + http->Escape(m_parent->m_id) + "/contents") ; - + std::string meta = (boost::format( xml_meta ) % "folder" % xml::Escape(m_name) @@ -566,7 +566,7 @@ bool Resource::Create( http::Agent* http ) http::Header hdr ; hdr.Add( "Content-Type: application/atom+xml" ) ; - + http::XmlResponse xml ; // http::ResponseLog log( "create", ".xml", &xml ) ; http->Post( uri, meta, &xml, hdr ) ; @@ -591,29 +591,29 @@ bool Resource::Upload( bool post) { assert( http != 0 ) ; - + File file( Path() ) ; std::ostringstream xcontent_len ; xcontent_len << "X-Upload-Content-Length: " << file.Size() ; - + http::Header hdr ; hdr.Add( "Content-Type: application/atom+xml" ) ; hdr.Add( "X-Upload-Content-Type: application/octet-stream" ) ; hdr.Add( xcontent_len.str() ) ; hdr.Add( "If-Match: " + m_etag ) ; hdr.Add( "Expect:" ) ; - + std::string meta = (boost::format( xml_meta ) % m_kind % xml::Escape(m_name) ).str() ; - + http::StringResponse str ; if ( post ) http->Post( link, meta, &str, hdr ) ; else http->Put( link, meta, &str, hdr ) ; - + http::Header uphdr ; uphdr.Add( "Expect:" ) ; uphdr.Add( "Accept:" ) ; @@ -621,11 +621,11 @@ bool Resource::Upload( // the content upload URL is in the "Location" HTTP header std::string uplink = http->RedirLocation() ; http::XmlResponse xml ; - + http->Put( uplink, &file, &xml, uphdr ) ; AssignIDs( Entry( xml.Response() ) ) ; m_mtime = Entry(xml.Response()).MTime(); - + return true ; } diff --git a/libgrive/src/drive/Resource.hh b/libgrive/src/drive/Resource.hh index 46096807..775884f8 100644 --- a/libgrive/src/drive/Resource.hh +++ b/libgrive/src/drive/Resource.hh @@ -52,11 +52,11 @@ public : typedef std::vector Children ; typedef Children::const_iterator iterator ; - + public : Resource(const fs::path& root_folder) ; Resource( const std::string& name, const std::string& kind ) ; - + // default copy ctor & op= are fine void Swap( Resource& coll ) ; @@ -65,12 +65,12 @@ public : std::string Name() const ; std::string SelfHref() const ; std::string ResourceID() const ; - + const Resource* Parent() const ; Resource* Parent() ; void AddChild( Resource *child ) ; Resource* FindChild( const std::string& title ) ; - + fs::path Path() const ; bool IsInRootTree() const ; bool IsRoot() const ; @@ -79,51 +79,51 @@ public : void FromRemote( const Entry& remote, const DateTime& last_sync ) ; void FromLocal( const DateTime& last_sync ) ; - + void Sync( http::Agent* http, DateTime& sync_time, const Json& options ) ; // children access iterator begin() const ; iterator end() const ; std::size_t size() const ; - + std::string StateStr() const ; - + private : /// State of the resource. indicating what to do with the resource enum State { /// The best state: the file is the same in remote and in local. sync, - + /// Resource created in local, but remote does not have it. /// We should create the resource in google drive and upload new content local_new, - + /// Resource exists in both local & remote, but changes in local is newer /// than remote. We should upload local copy to overwrite remote. local_changed, - + /// Resource deleted from local since last time grive has checked. local_deleted, - + /// Resource created in google drive, but not exist in local. /// We should download the file. remote_new, - - /// Resource exists in both local & remote, but remote is newer. + + /// Resource exists in both local & remote, but remote is newer. remote_changed, - + /// Resource delete in remote, need to delete in local remote_deleted, - - + + /// invalid value unknown } ; friend std::ostream& operator<<( std::ostream& os, State s ) ; - + private : void SetState( State new_state ) ; @@ -131,22 +131,22 @@ private : bool EditContent( http::Agent* http, bool new_rev ) ; bool Create( http::Agent* http ) ; bool Upload( http::Agent* http, const std::string& link, bool post ) ; - + void FromRemoteFolder( const Entry& remote, const DateTime& last_sync ) ; void FromRemoteFile( const Entry& remote, const DateTime& last_sync ) ; - + void DeleteLocal() ; void DeleteRemote( http::Agent* http ) ; - + void AssignIDs( const Entry& remote ) ; void SyncSelf( http::Agent* http, const Json& options ) ; - + private : std::string m_name ; std::string m_kind ; std::string m_md5 ; DateTime m_mtime ; - + std::string m_id ; std::string m_href ; std::string m_edit ; @@ -157,7 +157,7 @@ private : // not owned Resource *m_parent ; std::vector m_child ; - + State m_state ; } ; diff --git a/libgrive/src/drive/ResourceTree.cc b/libgrive/src/drive/ResourceTree.cc index 4a8a6daf..e3933c97 100644 --- a/libgrive/src/drive/ResourceTree.cc +++ b/libgrive/src/drive/ResourceTree.cc @@ -46,10 +46,10 @@ ResourceTree::ResourceTree( const ResourceTree& fs ) : Resource *c = new Resource( **i ) ; if ( c->SelfHref() == root_href ) m_root = c ; - + m_set.insert( c ) ; } - + assert( m_root != 0 ) ; } @@ -63,7 +63,7 @@ void ResourceTree::Clear() // delete all pointers const Set& s = m_set.get() ; std::for_each( s.begin(), s.end(), Destroy() ) ; - + m_set.clear() ; m_root = 0 ; } diff --git a/libgrive/src/drive/ResourceTree.hh b/libgrive/src/drive/ResourceTree.hh index 212141a8..b9673e91 100644 --- a/libgrive/src/drive/ResourceTree.hh +++ b/libgrive/src/drive/ResourceTree.hh @@ -49,7 +49,7 @@ namespace details hashed_unique, identity > > > Folders ; - + typedef Folders::index::type IDMap ; typedef Folders::index::type HrefMap ; typedef Folders::index::type Set ; @@ -69,24 +69,24 @@ public : ResourceTree( const fs::path& rootFolder ) ; ResourceTree( const ResourceTree& fs ) ; ~ResourceTree( ) ; - + void Swap( ResourceTree& fs ) ; ResourceTree& operator=( const ResourceTree& fs ) ; - + Resource* FindByHref( const std::string& href ) ; const Resource* FindByHref( const std::string& href ) const ; Resource* FindByID( const std::string& id ) ; - + bool ReInsert( Resource *coll ) ; - + void Insert( Resource *coll ) ; void Erase( Resource *coll ) ; void Update( Resource *coll, const Entry& e, const DateTime& last_sync ) ; - + Resource* Root() ; const Resource* Root() const ; - + iterator begin() ; iterator end() ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index 8c641892..60281ad3 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -48,11 +48,11 @@ public : public : explicit State( const fs::path& filename, const Json& options ) ; ~State() ; - + void FromLocal( const fs::path& p ) ; void FromRemote( const Entry& e ) ; void ResolveEntry() ; - + void Read( const fs::path& filename ) ; void Write( const fs::path& filename ) const ; @@ -60,13 +60,13 @@ public : Resource* FindByID( const std::string& id ) ; void Sync( http::Agent *http, const Json& options ) ; - + iterator begin() ; iterator end() ; - + long ChangeStamp() const ; void ChangeStamp( long cstamp ) ; - + private : void FromLocal( const fs::path& p, Resource *folder ) ; void FromChange( const Entry& e ) ; @@ -74,12 +74,12 @@ private : std::size_t TryResolveEntry() ; static bool IsIgnore( const std::string& filename ) ; - + private : ResourceTree m_res ; DateTime m_last_sync ; long m_cstamp ; - + std::vector m_unresolved ; } ; diff --git a/libgrive/src/drive2/Drive.cc b/libgrive/src/drive2/Drive.cc index feaa84be..761a772f 100644 --- a/libgrive/src/drive2/Drive.cc +++ b/libgrive/src/drive2/Drive.cc @@ -46,12 +46,12 @@ void Drive::Refresh( http::Agent *agent ) // find root node ID assert( m_root == 0 ) ; m_root = NewResource( agent, "root" ) ; - + // get all folders first Feed folders( feeds::files ) ; folders.Query( "mimeType", mime_types::folder ) ; NewResource( agent, folders ) ; - + // get all files Feed files( feeds::files ) ; NewResource( agent, files ) ; @@ -61,7 +61,7 @@ void Drive::Refresh( http::Agent *agent ) { Resource *parent = Find( (*i)->Parent() ), *child = *i ; assert( child != 0 ) ; - + if ( parent != 0 ) { // initialize parent IDs @@ -74,7 +74,7 @@ void Drive::Refresh( http::Agent *agent ) void Drive::NewResource( http::Agent *agent, Feed& items ) { assert( agent != 0 ) ; - + while ( items.Next( agent ) ) { std::vector item_json = items.Content()["items"].AsArray() ; @@ -88,7 +88,7 @@ Resource* Drive::NewResource( http::Agent *agent, const std::string& id ) { Feed feed( feeds::files + "/" + id ) ; feed.Next( agent ) ; - + return NewResource( feed.Content() ) ; } @@ -96,7 +96,7 @@ Resource* Drive::NewResource( const Val& item ) { // assume resource is directly under root std::string parent_id = m_root != 0 ? m_root->ID() : "" ; - + Val parents ; if ( item.Get( "parents", parents ) ) { @@ -116,10 +116,10 @@ Resource* Drive::NewResource( const Val& item ) item["mimeType"].Str(), item["title"].Str(), parent_id ) ; - + m_db.insert(r) ; assert( Find(r->ID()) == r ) ; - + return r ; } @@ -151,7 +151,7 @@ const Resource* Drive::Child( const Resource *parent, std::size_t idx ) const BOOST_THROW_EXCEPTION( Exception() ) ; - + return Find( parent->At(idx) ) ; } diff --git a/libgrive/src/drive2/Drive.hh b/libgrive/src/drive2/Drive.hh index 33014b03..f858ecf0 100644 --- a/libgrive/src/drive2/Drive.hh +++ b/libgrive/src/drive2/Drive.hh @@ -52,7 +52,7 @@ namespace details hashed_non_unique, const_mem_fun > > > DB ; - + typedef DB::index::type ID ; typedef DB::index::type Set ; } @@ -63,7 +63,7 @@ class Drive { public : Drive( ) ; - + void Refresh( http::Agent *agent ) ; Resource* Find( const std::string& id ) ; @@ -71,7 +71,7 @@ public : Resource* Root() ; const Resource* Root() const ; - + const Resource* Child( const Resource *parent, std::size_t idx ) const ; const Resource* Parent( const Resource *child ) const ; @@ -79,10 +79,10 @@ private : Resource* NewResource( const Val& item ) ; Resource* NewResource( http::Agent *agent, const std::string& id ) ; void NewResource( http::Agent *agent, Feed& items ) ; - + private : details::DB m_db ; - + Resource *m_root ; } ; diff --git a/libgrive/src/drive2/Feed.cc b/libgrive/src/drive2/Feed.cc index 78f67f06..8d07b1c4 100644 --- a/libgrive/src/drive2/Feed.cc +++ b/libgrive/src/drive2/Feed.cc @@ -45,7 +45,7 @@ bool Feed::Next( http::Agent *agent ) Val url ; if ( !m_content.Get("nextLink", url) ) return false ; - + http::ValResponse out ; try { @@ -57,7 +57,7 @@ bool Feed::Next( http::Agent *agent ) throw ; } m_content = out.Response() ; - + return true ; } diff --git a/libgrive/src/drive2/Feed.hh b/libgrive/src/drive2/Feed.hh index ad1f294a..d46e7bd2 100644 --- a/libgrive/src/drive2/Feed.hh +++ b/libgrive/src/drive2/Feed.hh @@ -45,8 +45,8 @@ public : public : Feed( const std::string& base ) ; void Query( const std::string& field, const std::string& value ) ; - - + + bool Next( http::Agent *agent ) ; Val Content() const ; diff --git a/libgrive/src/drive2/Resource.hh b/libgrive/src/drive2/Resource.hh index 8513c604..d5acf5cf 100644 --- a/libgrive/src/drive2/Resource.hh +++ b/libgrive/src/drive2/Resource.hh @@ -38,7 +38,7 @@ public : std::string ID() const ; std::string Mime() const ; std::string Title() const ; - + bool IsFolder() const ; void AddChild( const std::string& child ) ; @@ -53,9 +53,9 @@ private : std::string m_id ; std::string m_mime ; std::string m_title ; - + std::vector m_children ; - + std::string m_parent ; } ; diff --git a/libgrive/src/http/Agent.hh b/libgrive/src/http/Agent.hh index a1903ce9..20ed9b31 100644 --- a/libgrive/src/http/Agent.hh +++ b/libgrive/src/http/Agent.hh @@ -46,26 +46,26 @@ public : File *file, DataStream *dest, const Header& hdr ) = 0 ; - + virtual long Get( const std::string& url, DataStream *dest, const Header& hdr ) = 0 ; - + virtual long Post( const std::string& url, const std::string& data, DataStream *dest, const Header& hdr ) = 0 ; - + virtual long Custom( const std::string& method, const std::string& url, DataStream *dest, const Header& hdr ) = 0 ; - + virtual std::string RedirLocation() const = 0 ; - + virtual std::string Escape( const std::string& str ) = 0 ; virtual std::string Unescape( const std::string& str ) = 0 ; } ; diff --git a/libgrive/src/http/CurlAgent.cc b/libgrive/src/http/CurlAgent.cc index d725e86c..7a1dee54 100644 --- a/libgrive/src/http/CurlAgent.cc +++ b/libgrive/src/http/CurlAgent.cc @@ -57,7 +57,7 @@ std::size_t ReadStringCallback( void *ptr, std::size_t size, std::size_t nmemb, std::memcpy( ptr, &(*data)[0], count ) ; data->erase( 0, count ) ; } - + return count ; } @@ -70,10 +70,10 @@ std::size_t ReadFileCallback( void *ptr, std::size_t size, std::size_t nmemb, Fi static_cast(size * nmemb), static_cast(file->Size() - file->Tell()) ) ; assert( count <= std::numeric_limits::max() ) ; - + if ( count > 0 ) file->Read( static_cast(ptr), static_cast(count) ) ; - + return count ; } @@ -96,7 +96,7 @@ CurlAgent::CurlAgent() : void CurlAgent::Init() { ::curl_easy_reset( m_pimpl->curl ) ; - ::curl_easy_setopt( m_pimpl->curl, CURLOPT_SSL_VERIFYPEER, 0L ) ; + ::curl_easy_setopt( m_pimpl->curl, CURLOPT_SSL_VERIFYPEER, 0L ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_SSL_VERIFYHOST, 0L ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_HEADERFUNCTION, &CurlAgent::HeaderCallback ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_WRITEHEADER , this ) ; @@ -112,7 +112,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur { char *str = reinterpret_cast(ptr) ; std::string line( str, str + size*nmemb ) ; - + static const std::string loc = "Location: " ; std::size_t pos = line.find( loc ) ; if ( pos != line.npos ) @@ -120,7 +120,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur std::size_t end_pos = line.find( "\r\n", pos ) ; pthis->m_pimpl->location = line.substr( loc.size(), end_pos - loc.size() ) ; } - + return size*nmemb ; } @@ -153,10 +153,10 @@ long CurlAgent::ExecCurl( long http_code = 0; ::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); Trace( "HTTP response %1%", http_code ) ; - + // reset the curl buffer to prevent it from touch our "error" buffer ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, 0 ) ; - + // only throw for libcurl errors if ( curl_code != CURLE_OK ) { @@ -179,7 +179,7 @@ long CurlAgent::Put( const Header& hdr ) { Trace("HTTP PUT \"%1%\"", url ) ; - + Init() ; CURL *curl = m_pimpl->curl ; @@ -190,7 +190,7 @@ long CurlAgent::Put( ::curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadStringCallback ) ; ::curl_easy_setopt(curl, CURLOPT_READDATA , &put_data ) ; ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, put_data.size() ) ; - + return ExecCurl( url, dest, hdr ) ; } @@ -200,10 +200,10 @@ long CurlAgent::Put( DataStream *dest, const Header& hdr ) { - assert( file != 0 ) ; + assert( file != 0 ) ; Trace("HTTP PUT \"%1%\"", url ) ; - + Init() ; CURL *curl = m_pimpl->curl ; @@ -212,7 +212,7 @@ long CurlAgent::Put( ::curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadFileCallback ) ; ::curl_easy_setopt(curl, CURLOPT_READDATA , file ) ; ::curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, static_cast(file->Size()) ) ; - + return ExecCurl( url, dest, hdr ) ; } @@ -243,7 +243,7 @@ long CurlAgent::Post( // make a copy because the parameter is const std::string post_data = data ; - + // set post specific options ::curl_easy_setopt(curl, CURLOPT_POST, 1L); ::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &post_data[0] ) ; @@ -274,7 +274,7 @@ void CurlAgent::SetHeader( const Header& hdr ) struct curl_slist *curl_hdr = 0 ; for ( Header::iterator i = hdr.begin() ; i != hdr.end() ; ++i ) curl_hdr = curl_slist_append( curl_hdr, i->c_str() ) ; - + ::curl_easy_setopt( m_pimpl->curl, CURLOPT_HTTPHEADER, curl_hdr ) ; } @@ -286,23 +286,23 @@ std::string CurlAgent::RedirLocation() const std::string CurlAgent::Escape( const std::string& str ) { CURL *curl = m_pimpl->curl ; - + char *tmp = curl_easy_escape( curl, str.c_str(), str.size() ) ; std::string result = tmp ; curl_free( tmp ) ; - + return result ; } std::string CurlAgent::Unescape( const std::string& str ) { CURL *curl = m_pimpl->curl ; - + int r ; char *tmp = curl_easy_unescape( curl, str.c_str(), str.size(), &r ) ; std::string result = tmp ; curl_free( tmp ) ; - + return result ; } diff --git a/libgrive/src/http/CurlAgent.hh b/libgrive/src/http/CurlAgent.hh index c142c3b1..e85838d4 100644 --- a/libgrive/src/http/CurlAgent.hh +++ b/libgrive/src/http/CurlAgent.hh @@ -31,7 +31,7 @@ class DataStream ; namespace http { /*! \brief agent to provide HTTP access - + This class provides functions to send HTTP request in many methods (e.g. get, post and put). Normally the HTTP response is returned in a Receivable. */ @@ -40,13 +40,13 @@ class CurlAgent : public Agent public : CurlAgent() ; ~CurlAgent() ; - + long Put( const std::string& url, const std::string& data, DataStream *dest, const Header& hdr ) ; - + long Put( const std::string& url, File *file, @@ -57,28 +57,28 @@ public : const std::string& url, DataStream *dest, const Header& hdr ) ; - + long Post( const std::string& url, const std::string& data, DataStream *dest, const Header& hdr ) ; - + long Custom( const std::string& method, const std::string& url, DataStream *dest, const Header& hdr ) ; - + std::string RedirLocation() const ; - + std::string Escape( const std::string& str ) ; std::string Unescape( const std::string& str ) ; private : static std::size_t HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis ) ; static std::size_t Receive( void* ptr, size_t size, size_t nmemb, DataStream *recv ) ; - + void SetHeader( const Header& hdr ) ; long ExecCurl( const std::string& url, @@ -86,7 +86,7 @@ private : const Header& hdr ) ; void Init() ; - + private : struct Impl ; std::auto_ptr m_pimpl ; diff --git a/libgrive/src/http/Download.cc b/libgrive/src/http/Download.cc index 885187ef..e74fe34d 100644 --- a/libgrive/src/http/Download.cc +++ b/libgrive/src/http/Download.cc @@ -68,10 +68,10 @@ std::string Download::Finish() const std::size_t Download::Write( const char *data, std::size_t count ) { assert( data != 0 ) ; - + if ( m_crypt.get() != 0 ) m_crypt->Write( data, count ) ; - + return m_file.Write( data, count ) ; } diff --git a/libgrive/src/http/Download.hh b/libgrive/src/http/Download.hh index 77cc1ae8..e556538f 100644 --- a/libgrive/src/http/Download.hh +++ b/libgrive/src/http/Download.hh @@ -39,13 +39,13 @@ public : Download( const std::string& filename ) ; Download( const std::string& filename, NoChecksum ) ; ~Download() ; - + std::string Finish() const ; - + void Clear() ; std::size_t Write( const char *data, std::size_t count ) ; - std::size_t Read( char *, std::size_t ) ; - + std::size_t Read( char *, std::size_t ) ; + private : File m_file ; std::auto_ptr m_crypt ; diff --git a/libgrive/src/http/Header.hh b/libgrive/src/http/Header.hh index 2486cd0c..d0e16035 100644 --- a/libgrive/src/http/Header.hh +++ b/libgrive/src/http/Header.hh @@ -35,9 +35,9 @@ public : public : Header() ; - + void Add( const std::string& str ) ; - + iterator begin() const ; iterator end() const ; diff --git a/libgrive/src/http/ResponseLog.cc b/libgrive/src/http/ResponseLog.cc index 9de4ac04..a9bfb982 100644 --- a/libgrive/src/http/ResponseLog.cc +++ b/libgrive/src/http/ResponseLog.cc @@ -50,7 +50,7 @@ std::size_t ResponseLog::Write( const char *data, std::size_t count ) assert( m_log.rdbuf() != 0 ) ; m_log.rdbuf()->sputn( data, count ) ; } - + return m_next->Write( data, count ) ; } @@ -73,16 +73,16 @@ void ResponseLog::Enable( bool enable ) void ResponseLog::Reset( const std::string& prefix, const std::string& suffix, DataStream *next ) { assert( next != 0 ) ; - + if ( m_log.is_open() ) m_log.close() ; - + const std::string fname = Filename(prefix, suffix) ; - + // reset previous stream state. don't care if file can be opened // successfully previously m_log.clear() ; - + // re-open the file m_log.open( fname.c_str() ) ; if ( m_log ) @@ -92,7 +92,7 @@ void ResponseLog::Reset( const std::string& prefix, const std::string& suffix, D } else Trace( "cannot open log file %1%", fname ) ; - + m_next = next ; } diff --git a/libgrive/src/http/ResponseLog.hh b/libgrive/src/http/ResponseLog.hh index 046b5c97..b37cb2fe 100644 --- a/libgrive/src/http/ResponseLog.hh +++ b/libgrive/src/http/ResponseLog.hh @@ -34,16 +34,16 @@ public : const std::string& suffix, DataStream *next ) ; ResponseLog( DataStream *next ) ; - + std::size_t Write( const char *data, std::size_t count ) ; std::size_t Read( char *data, std::size_t count ) ; - + void Enable( bool enable = true ) ; void Reset( const std::string& prefix, const std::string& suffix, DataStream *next ) ; - + private : static std::string Filename( const std::string& prefix, const std::string& suffix ) ; - + private : bool m_enabled ; std::ofstream m_log ; diff --git a/libgrive/src/http/StringResponse.hh b/libgrive/src/http/StringResponse.hh index 3f262a94..0b1d2ede 100644 --- a/libgrive/src/http/StringResponse.hh +++ b/libgrive/src/http/StringResponse.hh @@ -35,7 +35,7 @@ public : void Clear() ; const std::string& Response() const ; - + private : std::string m_resp ; } ; diff --git a/libgrive/src/http/XmlResponse.hh b/libgrive/src/http/XmlResponse.hh index b1505097..80f93a21 100644 --- a/libgrive/src/http/XmlResponse.hh +++ b/libgrive/src/http/XmlResponse.hh @@ -42,7 +42,7 @@ public : void Finish() ; xml::Node Response() const ; - + private : std::auto_ptr m_tb ; } ; diff --git a/libgrive/src/json/JsonParser.cc b/libgrive/src/json/JsonParser.cc index 9ae63f48..78fa07ee 100644 --- a/libgrive/src/json/JsonParser.cc +++ b/libgrive/src/json/JsonParser.cc @@ -35,63 +35,63 @@ namespace b->VisitNull() ; return true ; } - + int OnBool( void *ctx, int value ) { ValVisitor *b = reinterpret_cast(ctx) ; b->Visit( static_cast(value) ) ; return true ; } - + int OnInt( void *ctx, long long value ) { ValVisitor *b = reinterpret_cast(ctx) ; b->Visit(value) ; return true ; } - + int OnDouble( void *ctx, double value ) { ValVisitor *b = reinterpret_cast(ctx) ; b->Visit(value) ; return true ; } - + int OnStr( void *ctx, const unsigned char *str, std::size_t len ) { ValVisitor *b = reinterpret_cast(ctx) ; b->Visit( std::string(reinterpret_cast(str), len) ) ; return true ; } - + int StartMap( void *ctx ) { ValVisitor *b = reinterpret_cast(ctx) ; b->StartObject() ; return true ; } - + int OnMapKey( void *ctx, const unsigned char *str, std::size_t len ) { ValVisitor *b = reinterpret_cast(ctx) ; b->VisitKey( std::string(reinterpret_cast(str), len) ) ; return true ; } - + int EndMap( void *ctx ) { ValVisitor *b = reinterpret_cast(ctx) ; b->EndObject() ; return true ; } - + int StartArray( void *ctx ) { ValVisitor *b = reinterpret_cast(ctx) ; b->StartArray() ; return true ; } - + int EndArray( void *ctx ) { ValVisitor *b = reinterpret_cast(ctx) ; @@ -99,19 +99,19 @@ namespace return true ; } - const yajl_callbacks callbacks = { - OnNull, - OnBool, - OnInt, - OnDouble, - 0, - OnStr, - StartMap, - OnMapKey, - EndMap, - StartArray, - EndArray, - }; + const yajl_callbacks callbacks = { + OnNull, + OnBool, + OnInt, + OnDouble, + 0, + OnStr, + StartMap, + OnMapKey, + EndMap, + StartArray, + EndArray, + }; } void JsonParser::Parse( const std::string& json, ValVisitor *callback ) @@ -142,15 +142,15 @@ JsonParser::~JsonParser() void JsonParser::Parse( const char *str, std::size_t size ) { const unsigned char *ustr = reinterpret_cast(str) ; - + yajl_status r = yajl_parse( m_impl->hand, ustr, size ) ; - + if ( r != yajl_status_ok ) { unsigned char *msg = yajl_get_error( m_impl->hand, true, ustr, size ) ; std::string msg_str(reinterpret_cast(msg)) ; yajl_free_error(m_impl->hand, msg) ; - + BOOST_THROW_EXCEPTION( Error() << ParseErr_(msg_str) @@ -166,7 +166,7 @@ void JsonParser::Finish() unsigned char *msg = yajl_get_error( m_impl->hand, false, 0, 0 ) ; std::string msg_str(reinterpret_cast(msg)) ; yajl_free_error(m_impl->hand, msg) ; - + BOOST_THROW_EXCEPTION( Error() << ParseErr_(msg_str) ) ; } } diff --git a/libgrive/src/json/JsonParser.hh b/libgrive/src/json/JsonParser.hh index 27d6a4c8..37250cf9 100644 --- a/libgrive/src/json/JsonParser.hh +++ b/libgrive/src/json/JsonParser.hh @@ -37,13 +37,13 @@ public : typedef boost::error_info JsonText_ ; static void Parse( const std::string& json, ValVisitor *callback ) ; - + explicit JsonParser( ValVisitor *callback ) ; ~JsonParser() ; - + void Parse( const char *str, std::size_t size ) ; void Finish() ; - + private : struct Impl ; std::auto_ptr m_impl ; diff --git a/libgrive/src/json/JsonWriter.cc b/libgrive/src/json/JsonWriter.cc index 9fbcc2bb..3a3648b9 100644 --- a/libgrive/src/json/JsonWriter.cc +++ b/libgrive/src/json/JsonWriter.cc @@ -104,7 +104,7 @@ void JsonWriter::WriteCallback( void *ctx, const char *str, std::size_t size ) JsonWriter *pthis = reinterpret_cast(ctx) ; assert( pthis != 0 ) ; assert( pthis->m_impl->out != 0 ) ; - + pthis->m_impl->out->Write( str, size ) ; } diff --git a/libgrive/src/json/Val.cc b/libgrive/src/json/Val.cc index 79c0b5e1..f21e52ec 100644 --- a/libgrive/src/json/Val.cc +++ b/libgrive/src/json/Val.cc @@ -48,7 +48,7 @@ Val::Val( TypeEnum type ) case string_type: m_base.reset( new Impl ) ; break ; case array_type: m_base.reset( new Impl ) ; break ; case object_type: m_base.reset( new Impl ) ; break ; - case null_type: + case null_type: default: m_base.reset( new Impl ) ; break ; } } @@ -85,7 +85,7 @@ const Val& Val::operator[]( const std::string& key ) const Object::const_iterator i = obj.find(key) ; if ( i != obj.end() ) return i->second ; - + // shut off compiler warning BOOST_THROW_EXCEPTION(Error() << NoKey_(key)) ; throw ; @@ -96,7 +96,7 @@ const Val& Val::operator[]( std::size_t index ) const const Array& ar = As() ; if ( index < ar.size() ) return ar[index] ; - + // shut off compiler warning BOOST_THROW_EXCEPTION(Error() << OutOfRange_(index)) ; throw ; @@ -165,18 +165,18 @@ void Val::Visit( ValVisitor *visitor ) const case double_type: visitor->Visit( As() ) ; break ; case string_type: visitor->Visit( As() ) ; break ; case bool_type: visitor->Visit( As() ) ; break ; - + case object_type: { visitor->StartObject() ; - + const Object& obj = As() ; for ( Object::const_iterator i = obj.begin() ; i != obj.end() ; ++i ) { visitor->VisitKey( i->first ) ; i->second.Visit( visitor ) ; } - + visitor->EndObject() ; break ; } @@ -184,11 +184,11 @@ void Val::Visit( ValVisitor *visitor ) const case array_type: { visitor->StartArray() ; - + const Array& arr = As() ; for ( Array::const_iterator i = arr.begin() ; i != arr.end() ; ++i ) i->Visit( visitor ) ; - + visitor->EndArray() ; break ; } @@ -204,14 +204,14 @@ void Val::Select( const Object& obj, const std::string& key, std::vector& r /** If \a this is an array of objects, this function returns all values of the objects in the array with the key \a key. If \a this is an object, - just return the value with the key \a key. + just return the value with the key \a key. */ std::vector Val::Select( const std::string& key ) const { std::vector result ; if ( Is() ) Select( As(), key, result ) ; - + else if ( Is() ) { const Array& array = As() ; @@ -241,7 +241,7 @@ namespace std { v1.Swap( v2 ) ; } - + ostream& operator<<( ostream& os, gr::Val::TypeEnum t ) { return os << static_cast(t) ; diff --git a/libgrive/src/json/Val.hh b/libgrive/src/json/Val.hh index 25478860..3d791f2a 100644 --- a/libgrive/src/json/Val.hh +++ b/libgrive/src/json/Val.hh @@ -43,7 +43,7 @@ public : typedef boost::error_info DestType_ ; typedef boost::error_info NoKey_ ; typedef boost::error_info OutOfRange_ ; - + private : template struct Type2Enum ; @@ -71,10 +71,10 @@ public : template Val& Assign( const T& t ) ; - + void Swap( Val& val ) ; Val& operator=( const Val& val ) ; - + template Val& operator=( const T& t ) { @@ -108,14 +108,14 @@ public : bool Has( const std::string& key ) const ; bool Get( const std::string& key, Val& val ) const ; void Add( const std::string& key, const Val& val ) ; - + // shortcuts for array (and array of objects) void Add( const Val& json ) ; Val FindInArray( const std::string& key, const std::string& value ) const ; bool FindInArray( const std::string& key, const std::string& value, Val& result ) const ; - + std::vector Select( const std::string& key ) const ; - + friend std::ostream& operator<<( std::ostream& os, const Val& val ) ; void Visit( ValVisitor *visitor ) const ; @@ -124,7 +124,7 @@ private : template struct Impl ; - + std::auto_ptr m_base ; private : diff --git a/libgrive/src/json/ValBuilder.cc b/libgrive/src/json/ValBuilder.cc index c5658ff2..211f4701 100644 --- a/libgrive/src/json/ValBuilder.cc +++ b/libgrive/src/json/ValBuilder.cc @@ -64,7 +64,7 @@ void ValBuilder::Build( const Val& t ) Level l = { Val::Null(), t } ; m_ctx.push( l ) ; } - + else if ( m_ctx.top().val.Is() ) { Val::Array& ar = m_ctx.top().val.As() ; @@ -74,7 +74,7 @@ void ValBuilder::Build( const Val& t ) { if ( !m_ctx.top().key.Is() ) BOOST_THROW_EXCEPTION( Error() << NoKey_(t) ) ; - + else { Val::Object& obj = m_ctx.top().val.As() ; @@ -107,12 +107,12 @@ void ValBuilder::End( Val::TypeEnum type ) if ( m_ctx.top().val.Type() == type ) { assert( m_ctx.top().key.Is() ) ; - + // get top Val from stack Val current ; current.Swap( m_ctx.top().val ) ; m_ctx.pop() ; - + Build(current) ; } } diff --git a/libgrive/src/json/ValBuilder.hh b/libgrive/src/json/ValBuilder.hh index efbe5b2a..b9dd4f03 100644 --- a/libgrive/src/json/ValBuilder.hh +++ b/libgrive/src/json/ValBuilder.hh @@ -37,7 +37,7 @@ public : typedef boost::error_info Mismatch_ ; typedef boost::error_info Unexpected_ ; typedef boost::error_info NoKey_ ; - + public : ValBuilder( ) ; ~ValBuilder() ; diff --git a/libgrive/src/json/ValResponse.hh b/libgrive/src/json/ValResponse.hh index cdeca6af..a0881357 100644 --- a/libgrive/src/json/ValResponse.hh +++ b/libgrive/src/json/ValResponse.hh @@ -42,7 +42,7 @@ public : void Finish() ; Val Response() const ; - + private : ValBuilder m_val ; JsonParser m_parser ; diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 745f274c..4e23cd2e 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -56,7 +56,7 @@ long AuthAgent::Put( long response ; while ( CheckRetry( response = m_agent->Put(url, data, dest, auth) ) ) ; - + return CheckHttpResponse(response, url, auth) ; } @@ -67,11 +67,11 @@ long AuthAgent::Put( const Header& hdr ) { Header auth = AppendHeader(hdr) ; - + long response ; while ( CheckRetry( response = m_agent->Put( url, file, dest, AppendHeader(hdr) ) ) ) ; - + return CheckHttpResponse(response, url, auth) ; } @@ -85,7 +85,7 @@ long AuthAgent::Get( long response ; while ( CheckRetry( response = m_agent->Get( url, dest, AppendHeader(hdr) ) ) ) ; - + return CheckHttpResponse(response, url, auth) ; } @@ -96,11 +96,11 @@ long AuthAgent::Post( const Header& hdr ) { Header auth = AppendHeader(hdr) ; - + long response ; while ( CheckRetry( response = m_agent->Post( url, data, dest, AppendHeader(hdr) ) ) ) ; - + return CheckHttpResponse(response, url, auth) ; } @@ -115,7 +115,7 @@ long AuthAgent::Custom( long response ; while ( CheckRetry( response = m_agent->Custom( method, url, dest, AppendHeader(hdr) ) ) ) ; - + return CheckHttpResponse(response, url, auth) ; } @@ -141,17 +141,17 @@ bool AuthAgent::CheckRetry( long response ) { Log( "resquest failed due to temperory error: %1%. retrying in 5 seconds", response, log::warning ) ; - + os::Sleep( 5 ) ; return true ; } - + // HTTP 401 Unauthorized. the auth token has been expired. refresh it else if ( response == 401 ) { Log( "resquest failed due to auth token expired: %1%. refreshing token", response, log::warning ) ; - + m_auth.Refresh() ; return true ; } @@ -173,7 +173,7 @@ long AuthAgent::CheckHttpResponse( << Url( url ) << HttpHeader( hdr ) ) ; } - + return response ; } diff --git a/libgrive/src/protocol/AuthAgent.hh b/libgrive/src/protocol/AuthAgent.hh index ec939a8d..bd41c63c 100644 --- a/libgrive/src/protocol/AuthAgent.hh +++ b/libgrive/src/protocol/AuthAgent.hh @@ -27,7 +27,7 @@ namespace gr { /*! \brief An HTTP agent with support OAuth2 - + This is a HTTP agent that provide support for OAuth2. It will also perform retries on certain HTTP errors. */ @@ -41,7 +41,7 @@ public : const std::string& data, DataStream *dest, const http::Header& hdr ) ; - + long Put( const std::string& url, File* file, @@ -52,21 +52,21 @@ public : const std::string& url, DataStream *dest, const http::Header& hdr ) ; - + long Post( const std::string& url, const std::string& data, DataStream *dest, const http::Header& hdr ) ; - + long Custom( const std::string& method, const std::string& url, DataStream *dest, const http::Header& hdr ) ; - + std::string RedirLocation() const ; - + std::string Escape( const std::string& str ) ; std::string Unescape( const std::string& str ) ; @@ -77,7 +77,7 @@ private : long response, const std::string& url, const http::Header& hdr ) ; - + private : OAuth2 m_auth ; const std::auto_ptr m_agent ; diff --git a/libgrive/src/protocol/Json.cc b/libgrive/src/protocol/Json.cc index 4c115d6a..dfee446c 100644 --- a/libgrive/src/protocol/Json.cc +++ b/libgrive/src/protocol/Json.cc @@ -149,7 +149,7 @@ Json::Json( const std::vector& arr ) : { if ( m_json == 0 ) BOOST_THROW_EXCEPTION( Error() << JsonCApi_( "json_object_new_array" ) ) ; - + for ( std::vector::const_iterator i = arr.begin() ; i != arr.end() ; ++i ) Add( *i ) ; } @@ -221,7 +221,7 @@ void Json::Swap( Json& other ) Json Json::operator[]( const std::string& key ) const { assert( m_json != 0 ) ; - + struct json_object *j = 0 ; if ( !::json_object_object_get_ex( m_json, key.c_str(), &j ) ) BOOST_THROW_EXCEPTION( @@ -229,7 +229,7 @@ Json Json::operator[]( const std::string& key ) const << JsonCApi_( "json_object_object_get" ) << KeyNotFound_( key ) << Json_( ::json_object_to_json_string(m_json) ) ) ; - + assert( j != 0 ) ; return Json( j ) ; } @@ -247,7 +247,7 @@ Json Json::operator[]( const std::size_t& idx ) const << OutOfRange_( idx ) << Json_( ::json_object_to_json_string(m_json) ) ) ; } - + return Json( j ) ; } @@ -264,7 +264,7 @@ bool Json::Get( const std::string& key, Json& json ) const if ( ::json_object_object_get_ex( m_json, key.c_str(), &j ) ) { assert( j != 0 ) ; - + Json tmp( j ) ; json.Swap( tmp ) ; return true ; @@ -286,7 +286,7 @@ void Json::Add( const Json& json ) { assert( m_json != 0 ) ; assert( json.m_json != 0 ) ; - + ::json_object_get( json.m_json ) ; ::json_object_array_add( m_json, json.m_json ) ; } @@ -389,12 +389,12 @@ Json::Type Json::DataType() const Json::Object Json::AsObject() const { Object result ; - + json_object_object_foreach( m_json, key, val ) { result.insert( Object::value_type( key, Json( val ) ) ) ; } - + return result ; } @@ -415,10 +415,10 @@ Json::Array Json::AsArray() const { std::size_t count = ::json_object_array_length( m_json ) ; Array result ; - + for ( std::size_t i = 0 ; i < count ; ++i ) result.push_back( Json( ::json_object_array_get_idx( m_json, i ) ) ) ; - + return result ; } @@ -441,21 +441,21 @@ Json::Array Json::As() const Json Json::FindInArray( const std::string& key, const std::string& value ) const { std::size_t count = ::json_object_array_length( m_json ) ; - + for ( std::size_t i = 0 ; i < count ; ++i ) { Json item( ::json_object_array_get_idx( m_json, i ) ) ; if ( item.Has(key) && item[key].Str() == value ) return item ; } - + BOOST_THROW_EXCEPTION( Error() << JsonCApi_( "Json::FindInArray" ) << KeyNotFound_( key ) << Value_(value) ) ; - + // shut off compiler warnings return Json() ; } @@ -482,7 +482,7 @@ Json Json::Parse( const std::string& str ) << JsonCApi_( "json_tokener_parse" ) << ValueErr( str ) ) ; - + return Json( json, NotOwned() ) ; } @@ -495,23 +495,23 @@ Json Json::Parse( DataStream *in ) struct json_tokener *tok = ::json_tokener_new() ; struct json_object *json = 0 ; - + char buf[1024] ; std::size_t count = 0 ; while ( (count = in->Read( buf, sizeof(buf) ) ) > 0 ) { json = ::json_tokener_parse_ex( tok, buf, count ) ; - + // check for parse error if ( ::json_tokener_get_error(tok) == ::json_tokener_continue ) break ; } - + // save the error code and free the tokener before throwing exceptions ::json_tokener_error err = ::json_tokener_get_error(tok) ; ::json_tokener_free( tok ) ; tok = 0 ; - + if ( err != json_tokener_success || json == 0 ) { BOOST_THROW_EXCEPTION( @@ -520,7 +520,7 @@ Json Json::Parse( DataStream *in ) << ErrMsg_( ::json_tokener_error_desc(err) ) ) ; } - + return Json( json, NotOwned() ) ; } diff --git a/libgrive/src/protocol/Json.hh b/libgrive/src/protocol/Json.hh index 320f9d71..bf193863 100644 --- a/libgrive/src/protocol/Json.hh +++ b/libgrive/src/protocol/Json.hh @@ -59,25 +59,25 @@ public : public : template explicit Json( const T& val ) ; - + template explicit Json( const char (&str)[n] ) : m_json( InitStr( str, n ) ) { } - + Json() ; Json( const Json& rhs ) ; Json( const char *str ) ; ~Json() ; - + static Json Parse( const std::string& str ) ; static Json Parse( DataStream *in ) ; - + Json operator[]( const std::string& key ) const ; Json operator[]( const std::size_t& idx ) const ; Json& operator=( const Json& rhs ) ; - + void Swap( Json& other ) ; std::string Str() const ; @@ -89,17 +89,17 @@ public : template bool Is() const ; - + template T As() const ; - + bool Has( const std::string& key ) const ; bool Get( const std::string& key, Json& json ) const ; void Add( const std::string& key, const Json& json ) ; void Add( const Json& json ) ; Json FindInArray( const std::string& key, const std::string& value ) const ; bool FindInArray( const std::string& key, const std::string& value, Json& result ) const ; - + /** Expect *this is a JSON array of objects. Select all "key" values inside each objects in the array and copies them in the output iterator \a out. */ @@ -115,17 +115,17 @@ public : } return out ; } - + friend std::ostream& operator<<( std::ostream& os, const Json& json ) ; void Write( DataStream *out ) const ; enum Type { null_type, bool_type, double_type, int_type, object_type, array_type, string_type } ; - + Type DataType() const ; - + private : Json( struct json_object *json ) ; - + struct NotOwned {} ; Json( struct json_object *json, NotOwned ) ; diff --git a/libgrive/src/protocol/JsonResponse.hh b/libgrive/src/protocol/JsonResponse.hh index 2b6322f7..8768bb69 100644 --- a/libgrive/src/protocol/JsonResponse.hh +++ b/libgrive/src/protocol/JsonResponse.hh @@ -38,7 +38,7 @@ public : std::size_t Read( char *data, std::size_t count ) ; Json Response() const ; - + private : StringResponse m_resp ; } ; diff --git a/libgrive/src/protocol/OAuth2.cc b/libgrive/src/protocol/OAuth2.cc index 5d2c1727..bd738fee 100644 --- a/libgrive/src/protocol/OAuth2.cc +++ b/libgrive/src/protocol/OAuth2.cc @@ -80,10 +80,10 @@ std::string OAuth2::MakeAuthURL( return "https://accounts.google.com/o/oauth2/auth" "?scope=" + - h.Escape( "https://www.googleapis.com/auth/userinfo.email" ) + "+" + + h.Escape( "https://www.googleapis.com/auth/userinfo.email" ) + "+" + h.Escape( "https://www.googleapis.com/auth/userinfo.profile" ) + "+" + - h.Escape( "https://docs.google.com/feeds/" ) + "+" + - h.Escape( "https://docs.googleusercontent.com/" ) + "+" + + h.Escape( "https://docs.google.com/feeds/" ) + "+" + + h.Escape( "https://docs.googleusercontent.com/" ) + "+" + h.Escape( "https://spreadsheets.google.com/feeds/" ) + "&redirect_uri=urn:ietf:wg:oauth:2.0:oob" "&response_type=code" @@ -100,7 +100,7 @@ void OAuth2::Refresh( ) http::JsonResponse resp ; http::CurlAgent http ; - + DisableLog dlog( log::debug ) ; http.Post( token_url, post, &resp, http::Header() ) ; diff --git a/libgrive/src/protocol/OAuth2.hh b/libgrive/src/protocol/OAuth2.hh index e8713f3e..93bba9e6 100644 --- a/libgrive/src/protocol/OAuth2.hh +++ b/libgrive/src/protocol/OAuth2.hh @@ -35,26 +35,26 @@ public : const std::string& client_secret ) ; std::string Str() const ; - + static std::string MakeAuthURL( const std::string& client_id, const std::string& state = std::string() ) ; void Auth( const std::string& auth_code ) ; void Refresh( ) ; - + std::string RefreshToken( ) const ; std::string AccessToken( ) const ; - + // adding HTTP auth header std::string HttpHeader( ) const ; - + private : std::string m_access ; std::string m_refresh ; - + const std::string m_client_id ; const std::string m_client_secret ; } ; - + } // end of namespace diff --git a/libgrive/src/util/CArray.hh b/libgrive/src/util/CArray.hh index d48e89bf..baba9d30 100644 --- a/libgrive/src/util/CArray.hh +++ b/libgrive/src/util/CArray.hh @@ -25,10 +25,10 @@ namespace gr { /*! \brief get the begin iterator from an array \internal - + This function returns the begin "iterator" of an array. It is useful to treat an array like an STL container. - + For example: \code int array[10] = { 1, 2, 3, 4, 5 } ; @@ -48,10 +48,10 @@ T* Begin( T (&array)[n] ) /*! \brief get the end iterator from an array \internal - + This function returns the end "iterator" of an array. It is useful to treat an array like an STL container. - + \param array reference to the array \return the end iterator of the array. i.e. \a array+n \sa Begin(), Count() diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index 6f944a59..40509d73 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -43,7 +43,7 @@ Config::Config( const po::variables_map& vm ) m_cmd.Add( "path", Json(vm.count("path") > 0 ? vm["path"].as() : default_root_folder ) ) ; - + m_path = GetPath( fs::path(m_cmd["path"].Str()) ) ; m_file = Read( ) ; } @@ -83,10 +83,10 @@ Json Config::GetAll() const { Json::Object obj = m_file.AsObject() ; Json::Object cmd_obj = m_cmd.AsObject() ; - + for ( Json::Object::iterator i = cmd_obj.begin() ; i != cmd_obj.end() ; ++i ) obj[i->first] = i->second ; - + return Json( obj ) ; } diff --git a/libgrive/src/util/Config.hh b/libgrive/src/util/Config.hh index e2c0423f..b4e83e32 100644 --- a/libgrive/src/util/Config.hh +++ b/libgrive/src/util/Config.hh @@ -42,7 +42,7 @@ public : Config( const boost::program_options::variables_map& vm ) ; const fs::path Filename() const ; - + void Set( const std::string& key, const Json& value ) ; Json Get( const std::string& key ) const ; @@ -56,12 +56,12 @@ private : private : //! config file path fs::path m_path; - + //! config values loaded from config file Json m_file ; - + //! config values from command line Json m_cmd ; } ; - + } // end of namespace diff --git a/libgrive/src/util/Crypt.cc b/libgrive/src/util/Crypt.cc index 5fb8ebe8..66b496ba 100644 --- a/libgrive/src/util/Crypt.cc +++ b/libgrive/src/util/Crypt.cc @@ -66,7 +66,7 @@ std::string MD5::Get() const { unsigned char *md5 = ::gcry_md_read( m_impl->hd, GCRY_MD_MD5 ) ; unsigned int len = ::gcry_md_get_algo_dlen(GCRY_MD_MD5) ; - + // format the MD5 string std::ostringstream ss ; for ( unsigned int i = 0 ; i < len ; i++ ) @@ -91,7 +91,7 @@ std::string MD5::Get( const fs::path& file ) std::string MD5::Get( File& file ) { MD5 crypt ; - + u64_t size = file.Size() ; for ( u64_t i = 0 ; i < size ; i += read_size ) { diff --git a/libgrive/src/util/Crypt.hh b/libgrive/src/util/Crypt.hh index dcd8dd34..3db4637e 100644 --- a/libgrive/src/util/Crypt.hh +++ b/libgrive/src/util/Crypt.hh @@ -44,7 +44,7 @@ public : static std::string Get( File& file ) ; static std::string Get( const boost::filesystem::path& file ) ; - + void Write( const void *data, std::size_t size ) ; std::string Get() const ; diff --git a/libgrive/src/util/DataStream.hh b/libgrive/src/util/DataStream.hh index 819c8f8a..e6623b7a 100644 --- a/libgrive/src/util/DataStream.hh +++ b/libgrive/src/util/DataStream.hh @@ -30,7 +30,7 @@ class DataStream { protected : virtual ~DataStream() {} - + public : /** Reading from the stream. The caller indicates that it wants to read `size` bytes and must provide enough space pointed diff --git a/libgrive/src/util/DateTime.cc b/libgrive/src/util/DateTime.cc index ffb4ec57..a2803699 100644 --- a/libgrive/src/util/DateTime.cc +++ b/libgrive/src/util/DateTime.cc @@ -86,7 +86,7 @@ DateTime DateTime::Now() << boost::errinfo_errno(errno) ) ; } - + return DateTime( tv.tv_sec, tv.tv_usec * 1000 ) ; } @@ -96,7 +96,7 @@ std::string DateTime::Format( const std::string& format ) const char tmp[1024] ; std::size_t count = ::strftime( tmp, sizeof(tmp), format.c_str(), &tp ) ; - return count > 0 ? std::string( tmp, count ) : "" ; + return count > 0 ? std::string( tmp, count ) : "" ; } struct tm DateTime::Tm() const @@ -129,7 +129,7 @@ std::ostream& operator<<( std::ostream& os, const DateTime& dt ) struct timeval DateTime::Tv() const { assert( m_nsec < 1000000000 ) ; - + timeval result ; result.tv_sec = m_sec ; result.tv_usec = m_nsec / 1000 ; diff --git a/libgrive/src/util/DateTime.hh b/libgrive/src/util/DateTime.hh index eb19f318..d017e0b9 100644 --- a/libgrive/src/util/DateTime.hh +++ b/libgrive/src/util/DateTime.hh @@ -35,26 +35,26 @@ public : explicit DateTime( std::time_t sec, unsigned long nsec = 0 ) ; void Assign( std::time_t sec, unsigned long nsec = 0 ) ; - + static DateTime Now() ; - + std::time_t Sec( ) const ; unsigned long NanoSec( ) const ; std::string Format( const std::string& format ) const ; - + tm Tm() const ; timeval Tv() const ; - + bool operator==( const DateTime& dt ) const ; bool operator!=( const DateTime& dt ) const ; bool operator>( const DateTime& dt ) const ; bool operator>=( const DateTime& dt ) const ; bool operator<( const DateTime& dt ) const ; bool operator<=( const DateTime& dt ) const ; - + void Swap( DateTime& dt ) ; std::string ToString() const ; - + private : std::time_t m_sec ; unsigned long m_nsec ; diff --git a/libgrive/src/util/Exception.hh b/libgrive/src/util/Exception.hh index f1515841..803fd511 100644 --- a/libgrive/src/util/Exception.hh +++ b/libgrive/src/util/Exception.hh @@ -42,7 +42,7 @@ struct Exception : virtual public boost::exception { Exception( ) ; - + virtual const char* what() const throw() ; } ; diff --git a/libgrive/src/util/File.cc b/libgrive/src/util/File.cc index 375cd625..a2367a52 100644 --- a/libgrive/src/util/File.cc +++ b/libgrive/src/util/File.cc @@ -48,7 +48,7 @@ using namespace gr ; off_t LSeek( int fd, off_t offset, int whence ) { assert( fd >= 0 ) ; - + off_t r = ::lseek( fd, offset, whence ) ; if ( r == static_cast(-1) ) { @@ -58,7 +58,7 @@ off_t LSeek( int fd, off_t offset, int whence ) << boost::errinfo_errno(errno) ) ; } - + return r ; } @@ -104,7 +104,7 @@ File::File( const fs::path& path, int mode ) : m_fd( -1 ) OpenForWrite( path, mode ) ; } -/** The destructor will close the file. +/** The destructor will close the file. */ File::~File( ) { @@ -115,7 +115,7 @@ void File::Open( const fs::path& path, int flags, int mode ) { if ( IsOpened() ) Close() ; - + assert( m_fd == -1 ) ; m_fd = ::open( path.string().c_str(), flags, mode ) ; if ( m_fd == -1 ) @@ -209,9 +209,9 @@ off_t File::Tell() const u64_t File::Size() const { assert( IsOpened() ) ; - + struct stat s = FStat(m_fd) ; - + assert( s.st_size >= 0 ) ; return static_cast( s.st_size ) ; } @@ -219,7 +219,7 @@ u64_t File::Size() const void File::Chmod( int mode ) { assert( IsOpened() ) ; -#ifndef WIN32 +#ifndef WIN32 if ( ::fchmod( m_fd, mode ) != 0 ) { BOOST_THROW_EXCEPTION( @@ -235,7 +235,7 @@ void File::Chmod( int mode ) void* File::Map( off_t offset, std::size_t length ) { assert( IsOpened() ) ; - + #ifdef WIN32 assert( false ) ; return 0 ; diff --git a/libgrive/src/util/File.hh b/libgrive/src/util/File.hh index 041c5998..355781b7 100644 --- a/libgrive/src/util/File.hh +++ b/libgrive/src/util/File.hh @@ -57,14 +57,14 @@ public : void OpenForWrite( const fs::path& path, int mode = 0600 ) ; void Close() ; bool IsOpened() const ; - + std::size_t Read( char *ptr, std::size_t size ) ; std::size_t Write( const char *ptr, std::size_t size ) ; off_t Seek( off_t offset, int whence ) ; off_t Tell() const ; u64_t Size() const ; - + void Chmod( int mode ) ; void* Map( off_t offset, std::size_t length ) ; @@ -74,9 +74,9 @@ public : private : void Open( const fs::path& path, int flags, int mode ) ; - + private : int m_fd ; } ; - + } // end of namespace diff --git a/libgrive/src/util/Function.hh b/libgrive/src/util/Function.hh index 197418f0..3dcd02e3 100644 --- a/libgrive/src/util/Function.hh +++ b/libgrive/src/util/Function.hh @@ -27,7 +27,7 @@ namespace gr { namespace impl { template class FuncImpl ; - + template class FuncImpl { public : @@ -43,7 +43,7 @@ namespace impl virtual FuncImpl* Clone() const = 0 ; virtual ~FuncImpl() {} } ; - + template class FuncImpl { public : @@ -54,23 +54,23 @@ namespace impl template struct FuncTrait ; - + struct NullType {} ; - + template struct FuncTrait { typedef R ReturnType ; typedef NullType Param1Type ; typedef NullType Param2Type ; } ; - + template struct FuncTrait { typedef R ReturnType ; typedef P1 Param1Type ; typedef NullType Param2Type ; } ; - + template struct FuncTrait { typedef R ReturnType ; @@ -83,11 +83,11 @@ namespace impl public : explicit FuncHolder( const F& f ) : m_func( f ) { } FuncHolder* Clone() const { return new FuncHolder( *this ) ; } - + typedef typename FuncTrait::ReturnType ReturnType ; - + ReturnType operator()() { return m_func(); } - + ReturnType operator()( typename FuncTrait::Param1Type p1) { return m_func(p1); @@ -103,7 +103,7 @@ namespace impl private : F m_func ; } ; - + template struct NullFunc { @@ -123,7 +123,7 @@ namespace impl return ReturnType() ; } } ; - + template FuncHolder* MakeFuncHolder( F func ) { @@ -148,7 +148,7 @@ public : m_pimpl( impl::MakeFuncHolder( f ) ) { } - + Function& operator=( const Function& f ) { Function tmp( f ) ; @@ -160,17 +160,17 @@ public : } typedef typename impl::FuncTrait::ReturnType ReturnType ; - + ReturnType operator()( ) { return (*m_pimpl)() ; } - + template ReturnType operator()( P1 p1 ) { return (*m_pimpl)( p1 ) ; } - + template ReturnType operator()( P1 p1, P2 p2 ) { return (*m_pimpl)( p1, p2 ) ; diff --git a/libgrive/src/util/MemMap.cc b/libgrive/src/util/MemMap.cc index 12b1f780..005eeaa0 100644 --- a/libgrive/src/util/MemMap.cc +++ b/libgrive/src/util/MemMap.cc @@ -32,7 +32,7 @@ MemMap::~MemMap() { File::UnMap( m_addr, m_length ) ; } - + void* MemMap::Addr() const { return m_addr ; diff --git a/libgrive/src/util/MemMap.hh b/libgrive/src/util/MemMap.hh index b8ca5a26..143e710d 100644 --- a/libgrive/src/util/MemMap.hh +++ b/libgrive/src/util/MemMap.hh @@ -35,7 +35,7 @@ public : public : MemMap( File& file, off_t offset, std::size_t length ) ; ~MemMap() ; - + void* Addr() const ; std::size_t Length() const ; diff --git a/libgrive/src/util/OS.cc b/libgrive/src/util/OS.cc index 5bf2f663..ed1cb247 100644 --- a/libgrive/src/util/OS.cc +++ b/libgrive/src/util/OS.cc @@ -56,7 +56,7 @@ DateTime FileCTime( const std::string& filename ) << boost::errinfo_file_name(filename) ) ; } - + #if defined __APPLE__ && defined __DARWIN_64_BIT_INO_T return DateTime( s.st_ctimespec.tv_sec, s.st_ctimespec.tv_nsec ) ; #else @@ -84,7 +84,7 @@ void SetFileTime( const std::string& filename, const DateTime& t ) void Sleep( unsigned int sec ) { struct timespec ts = { sec, 0 } ; - + int result = 0 ; do { diff --git a/libgrive/src/util/OS.hh b/libgrive/src/util/OS.hh index 31ab51de..a91d72ec 100644 --- a/libgrive/src/util/OS.hh +++ b/libgrive/src/util/OS.hh @@ -32,13 +32,13 @@ class Path ; namespace os { struct Error : virtual Exception {} ; - + DateTime FileCTime( const std::string& filename ) ; DateTime FileCTime( const fs::path& filename ) ; - + void SetFileTime( const std::string& filename, const DateTime& t ) ; void SetFileTime( const fs::path& filename, const DateTime& t ) ; - + void Sleep( unsigned int sec ) ; } diff --git a/libgrive/src/util/StringStream.hh b/libgrive/src/util/StringStream.hh index 600f24c3..a17a38f5 100644 --- a/libgrive/src/util/StringStream.hh +++ b/libgrive/src/util/StringStream.hh @@ -26,16 +26,16 @@ namespace gr { /** \brief DataStream base on `std::string`s - + StringStream is a DataStream back-end that uses std::string for storage. It is useful for unit tests and text parsing, especially when used with StreamParser. - + StringStream has a limit on the maximum number of byte it stores. This is to prevent DOS attacks in which the client sends a lot of bytes before the delimiter (e.g. new-line characters) and the server is forced to hold all of them in memory. - + The limit is current 1024 bytes. */ class StringStream : public DataStream @@ -48,7 +48,7 @@ public : const std::string& Str() const ; void Str( const std::string& str ) ; - + private : std::string m_str ; } ; diff --git a/libgrive/src/util/Types.hh b/libgrive/src/util/Types.hh index a981c6d3..b80fb138 100644 --- a/libgrive/src/util/Types.hh +++ b/libgrive/src/util/Types.hh @@ -25,7 +25,7 @@ namespace gr { using ::off_t ; - + // should use boost/cstdint typedef unsigned long long u64_t ; } diff --git a/libgrive/src/util/log/CommonLog.cc b/libgrive/src/util/log/CommonLog.cc index d9cab059..70ff90b1 100644 --- a/libgrive/src/util/log/CommonLog.cc +++ b/libgrive/src/util/log/CommonLog.cc @@ -34,10 +34,10 @@ CommonLog::CommonLog() bool CommonLog::Enable( log::Serverity s, bool enable ) { assert( s >= debug && s < serverity_count ) ; - + bool prev = m_enabled[s] ; m_enabled[s] = enable ; - + return prev ; } diff --git a/libgrive/src/util/log/CommonLog.hh b/libgrive/src/util/log/CommonLog.hh index a8e910e4..0bb2f359 100644 --- a/libgrive/src/util/log/CommonLog.hh +++ b/libgrive/src/util/log/CommonLog.hh @@ -29,10 +29,10 @@ class CommonLog : public LogBase { public : CommonLog() ; - + bool Enable( log::Serverity s, bool enable = true ) ; bool IsEnabled( log::Serverity s ) const ; - + private : std::bitset m_enabled ; } ; diff --git a/libgrive/src/util/log/CompositeLog.cc b/libgrive/src/util/log/CompositeLog.cc index 6c9140ab..306d6a7e 100644 --- a/libgrive/src/util/log/CompositeLog.cc +++ b/libgrive/src/util/log/CompositeLog.cc @@ -38,7 +38,7 @@ CompositeLog::~CompositeLog() { std::for_each( m_logs.begin(), m_logs.end(), Destroy() ) ; } - + LogBase* CompositeLog::Add( std::auto_ptr log ) { m_logs.push_back( log.get() ) ; diff --git a/libgrive/src/util/log/CompositeLog.hh b/libgrive/src/util/log/CompositeLog.hh index 6efe3be0..3a533849 100644 --- a/libgrive/src/util/log/CompositeLog.hh +++ b/libgrive/src/util/log/CompositeLog.hh @@ -31,7 +31,7 @@ class CompositeLog : public CommonLog public : CompositeLog() ; ~CompositeLog() ; - + LogBase* Add( std::auto_ptr log ) ; void Log( const log::Fmt& msg, log::Serverity s ) ; diff --git a/libgrive/src/util/log/DefaultLog.cc b/libgrive/src/util/log/DefaultLog.cc index 6f4c64d0..5c17387c 100644 --- a/libgrive/src/util/log/DefaultLog.cc +++ b/libgrive/src/util/log/DefaultLog.cc @@ -47,7 +47,7 @@ void DefaultLog::Log( const log::Fmt& msg, log::Serverity s ) case log::info: m_log << msg << std::endl ; break ; - + default: m_log << msg << std::endl ; break ; diff --git a/libgrive/src/util/log/DefaultLog.hh b/libgrive/src/util/log/DefaultLog.hh index 60e92e16..03917449 100644 --- a/libgrive/src/util/log/DefaultLog.hh +++ b/libgrive/src/util/log/DefaultLog.hh @@ -33,7 +33,7 @@ public : explicit DefaultLog( const std::string& filename ) ; void Log( const log::Fmt& msg, log::Serverity s ) ; - + private : std::ofstream m_file ; std::ostream& m_log ; diff --git a/libgrive/src/util/log/Log.cc b/libgrive/src/util/log/Log.cc index b93e1b7f..84a3d530 100644 --- a/libgrive/src/util/log/Log.cc +++ b/libgrive/src/util/log/Log.cc @@ -29,7 +29,7 @@ public : void Log( const log::Fmt&, log::Serverity ) { } - + bool Enable( log::Serverity, bool enable ) { return enable ; @@ -43,10 +43,10 @@ public : LogBase* LogBase::Inst( std::auto_ptr log ) { static std::auto_ptr inst( new MockLog ) ; - + if ( log.get() != 0 ) inst = log ; - + assert( inst.get() != 0 ) ; return inst.get() ; } diff --git a/libgrive/src/util/log/Log.hh b/libgrive/src/util/log/Log.hh index 0d43adbb..0480865e 100644 --- a/libgrive/src/util/log/Log.hh +++ b/libgrive/src/util/log/Log.hh @@ -31,28 +31,28 @@ namespace log { /// user unfriendly messages. only meant for developers. debug, - + /// enabled only if -V is specified. grive tries to tell you every /// single thing it tries to do. verbose, - + /// notification messages indicates nothing is going wrong info, - + /// potential error messages warning, - + /// an error has occurs but grive doesn't need to quit error, - + /// grive cannot proceed critical, - - + + /// must be put at the end, equal to number of serverities serverity_count } ; - + typedef boost::format Fmt ; } @@ -64,7 +64,7 @@ public : virtual void Log( const log::Fmt& msg, log::Serverity s = log::info ) = 0 ; virtual bool Enable( log::Serverity s, bool enable = true ) = 0 ; virtual bool IsEnabled( log::Serverity s ) const = 0 ; - + static LogBase* Inst( std::auto_ptr log = std::auto_ptr() ) ; ~LogBase() ; diff --git a/libgrive/src/xml/Node.cc b/libgrive/src/xml/Node.cc index abed0c4e..b7e4d925 100644 --- a/libgrive/src/xml/Node.cc +++ b/libgrive/src/xml/Node.cc @@ -45,7 +45,7 @@ public : Impl() : m_ref(1), m_type( element ) { } - + Impl( const std::string& str, Type type, const std::string& value = "" ) : m_ref(1), m_type( type ), @@ -53,7 +53,7 @@ public : m_value( value ) { } - + ~Impl() { std::for_each( m_children.begin(), m_children.end(), std::mem_fun( &Impl::Release ) ) ; @@ -64,13 +64,13 @@ public : ++m_ref ; return this ; } - + void Release() { if ( --m_ref == 0 ) delete this ; } - + std::size_t RefCount() const { assert( m_ref > 0 ) ; @@ -81,9 +81,9 @@ public : { assert( child != 0 ) ; assert( child->m_type >= element && child->m_type <= text ) ; - + ImplVec *map[] = { &m_element, &m_attr, 0 } ; - + if ( map[child->m_type] != 0 ) { ImplVec& vec = *map[child->m_type] ; @@ -93,10 +93,10 @@ public : // cannot allow duplicate attribute nodes if ( child->m_type == attr && p.first != p.second ) BOOST_THROW_EXCEPTION( Error() << DupAttr_( child->m_name ) ) ; - + vec.insert( p.second, child ) ; } - + m_children.push_back( child ) ; } @@ -105,67 +105,67 @@ public : assert( !name.empty() ) ; return name[0] == '@' - ? Find( m_attr, name.substr(1) ) + ? Find( m_attr, name.substr(1) ) : Find( m_element, name ) ; } - + Impl* FindAttr( const std::string& name ) { std::pair r = Find( m_attr, name ) ; return r.first != r.second ? *r.first : 0 ; } - + iterator Begin() { return m_children.begin() ; } - + iterator End() { return m_children.end() ; } - + const_iterator Begin() const { return m_children.begin() ; } - + const_iterator End() const { return m_children.end() ; } - + std::size_t Size() const { return m_children.size() ; } - + Range Attr() { return std::make_pair( m_attr.begin(), m_attr.end() ) ; } - + const std::string& Name() const { return m_name ; } - + std::string Value() const { assert( m_type != element || m_value.empty() ) ; - + std::string value = m_value ; for ( const_iterator i = Begin() ; i != End() ; ++i ) value += (*i)->Value() ; return value ; } - + void Value( const std::string& val ) { m_value = val ; } - + Type GetType() const { return m_type ; @@ -188,7 +188,7 @@ private : private : std::size_t m_ref ; - + Type m_type ; std::string m_name ; std::string m_value ; @@ -211,7 +211,7 @@ Node::iterator::reference Node::iterator::dereference() const { Impl *p = *base_reference() ; assert( p != 0 ) ; - + return Node( p->AddRef() ) ; } @@ -264,7 +264,7 @@ bool Node::IsCompatible( Type parent, Type child ) { false, false, true }, // attribute { false, false, false } // text } ; - + assert( parent >= element && parent <= text ) ; assert( child >= element && child <= text ) ; return map[parent][child] ; @@ -274,7 +274,7 @@ Node Node::AddElement( const std::string& name ) { assert( m_ptr != 0 ) ; assert( IsCompatible( GetType(), element) ) ; - + Impl *child = new Impl( name, element ) ; m_ptr->Add( child->AddRef() ) ; return Node( child ) ; @@ -302,7 +302,7 @@ void Node::AddNode( const Node& node ) assert( m_ptr != 0 ) ; assert( node.m_ptr != 0 ) ; assert( IsCompatible( GetType(), node.GetType() ) ) ; - + m_ptr->Add( node.m_ptr->AddRef() ) ; } @@ -316,7 +316,7 @@ NodeSet Node::operator[]( const std::string& name ) const { assert( m_ptr != 0 ) ; assert( !name.empty() ) ; - + Range is = m_ptr->Find( name ) ; return NodeSet( iterator(is.first), iterator(is.second) ) ; } @@ -342,7 +342,7 @@ const std::string& Node::Name() const std::string Node::Value() const { assert( m_ptr != 0 ) ; - + return m_ptr->Value() ; } @@ -361,13 +361,13 @@ std::ostream& operator<<( std::ostream& os, const Node& node ) if ( node.GetType() == Node::element ) { os << '<' << node.Name() ; - + // print attributes NodeSet attrs = node.Attr() ; if ( !attrs.empty() ) os << ' ' << attrs ; os << '>' ; - + // recursively print children for ( Node::iterator i = node.begin() ; i != node.end() ; ++i ) { @@ -386,7 +386,7 @@ std::ostream& operator<<( std::ostream& os, const Node& node ) { Node::PrintString( os, node.Value() ) ; } - + return os ; } diff --git a/libgrive/src/xml/Node.hh b/libgrive/src/xml/Node.hh index fb4b6c43..916a1dc8 100644 --- a/libgrive/src/xml/Node.hh +++ b/libgrive/src/xml/Node.hh @@ -37,7 +37,7 @@ class Node private : class Impl ; typedef std::vector ImplVec ; - + public : class iterator ; @@ -50,10 +50,10 @@ public : static Node Element( const std::string& name ) ; static Node Text( const std::string& name ) ; - + Node& operator=( const Node& node ) ; void Swap( Node& node ) ; - + Node AddElement( const std::string& name ) ; Node AddText( const std::string& text ) ; void AddNode( const Node& node ) ; @@ -63,13 +63,13 @@ public : NodeSet operator[]( const std::string& name ) const ; operator std::string() const ; bool operator==( const std::string& value ) const ; - + const std::string& Name() const ; std::string Value() const ; - + // read-only access to the reference counter. for checking. std::size_t RefCount() const ; - + enum Type { element, attr, text } ; Type GetType() const ; @@ -81,16 +81,16 @@ public : iterator end() const ; std::size_t size() const ; NodeSet Children() const ; - + NodeSet Attr() const ; std::string Attr( const std::string& attr ) const ; bool HasAttr( const std::string& attr ) const ; - + private : explicit Node( Impl *impl ) ; typedef std::pair Range ; - + private : Impl *m_ptr ; } ; @@ -105,11 +105,11 @@ class Node::iterator : public boost::iterator_adaptor< { public : iterator( ) ; - explicit iterator( ImplVec::iterator i ) ; + explicit iterator( ImplVec::iterator i ) ; private : friend class boost::iterator_core_access; - + reference dereference() const ; } ; diff --git a/libgrive/src/xml/NodeSet.cc b/libgrive/src/xml/NodeSet.cc index 42d5c488..f2c18822 100644 --- a/libgrive/src/xml/NodeSet.cc +++ b/libgrive/src/xml/NodeSet.cc @@ -108,7 +108,7 @@ void NodeSet::Add( const Node& n ) } m_tmp.AddNode( n ) ; - + // the iterators may be invalidated after adding the node m_first = m_tmp.begin() ; m_last = m_tmp.end() ; @@ -129,7 +129,7 @@ Node NodeSet::front() const { if ( empty() ) BOOST_THROW_EXCEPTION( Error() << EmptyNodeSet_(0) ) ; - + return *m_first ; } diff --git a/libgrive/src/xml/NodeSet.hh b/libgrive/src/xml/NodeSet.hh index 8820a8fd..768e5fb0 100644 --- a/libgrive/src/xml/NodeSet.hh +++ b/libgrive/src/xml/NodeSet.hh @@ -43,22 +43,22 @@ public : NodeSet& operator=( const NodeSet& ns ) ; void Swap( NodeSet& ns ) ; - + void Add( const Node& n ) ; - + iterator begin() const ; iterator end() const ; bool empty() const ; std::size_t size() const ; Node front() const ; - + NodeSet Find( const std::string& name, const std::string& value ) const ; // forwarding common Node operations to Node operator std::string() const ; NodeSet operator[]( const std::string& name ) const ; bool operator==( const std::string& value ) const ; - + private : Node m_tmp ; iterator m_first ; diff --git a/libgrive/src/xml/TreeBuilder.cc b/libgrive/src/xml/TreeBuilder.cc index c1ad385a..1ea58da9 100644 --- a/libgrive/src/xml/TreeBuilder.cc +++ b/libgrive/src/xml/TreeBuilder.cc @@ -40,11 +40,11 @@ TreeBuilder::TreeBuilder() : m_impl( new Impl ) { m_impl->stack.push_back( Node() ) ; m_impl->psr = ::XML_ParserCreate( 0 ) ; - + ::XML_SetElementHandler( m_impl->psr, &TreeBuilder::StartElement, &TreeBuilder::EndElement ) ; ::XML_SetCharacterDataHandler( m_impl->psr, &TreeBuilder::OnCharData ) ; ::XML_SetUserData( m_impl->psr , this ) ; - + is_new = true ; } @@ -56,15 +56,15 @@ Node TreeBuilder::ParseFile( const std::string& file ) { TreeBuilder tb ; ::XML_Parser p = tb.m_impl->psr ; - + std::ifstream f( file.c_str() ) ; - + const std::size_t block_size = 10 ; std::size_t count = 0 ; while ( (count = f.rdbuf()->sgetn( (char*)::XML_GetBuffer( p, block_size ), block_size ) ) > 0 ) XML_ParseBuffer( p, count, false ) ; XML_ParseBuffer( p, 0, true ) ; - + return tb.Result() ; } @@ -87,10 +87,10 @@ Node TreeBuilder::Result() const { // the node on the stack should be the dummy node with only one child assert( m_impl->stack.size() == 1 ) ; - + if ( m_impl->stack.front().size() != 1 ) BOOST_THROW_EXCEPTION( Error() << LogicError(0) ) ; - + return *m_impl->stack.front().begin() ; } @@ -101,22 +101,22 @@ void TreeBuilder::StartElement( void *pvthis, const char *name, const char **att assert( attr != 0 ) ; TreeBuilder *pthis = reinterpret_cast(pvthis) ; - + Node n = pthis->m_impl->stack.back().AddElement( name ) ; - + for ( std::size_t i = 0 ; attr[i] != 0 ; i += 2 ) { assert( attr[i+1] != 0 ) ; n.AddAttribute( attr[i], attr[i+1] ) ; } - + pthis->m_impl->stack.push_back( n ) ; } void TreeBuilder::EndElement( void* pvthis, const char* name ) { TreeBuilder *pthis = reinterpret_cast(pvthis) ; - + assert( pthis->m_impl->stack.back().Name() == name ) ; pthis->m_impl->stack.pop_back() ; } diff --git a/libgrive/src/xml/TreeBuilder.hh b/libgrive/src/xml/TreeBuilder.hh index fe71a996..15548088 100644 --- a/libgrive/src/xml/TreeBuilder.hh +++ b/libgrive/src/xml/TreeBuilder.hh @@ -37,10 +37,10 @@ public : public : TreeBuilder() ; ~TreeBuilder() ; - + void ParseData( const char *data, std::size_t count, bool last = false ) ; Node Result( ) const ; - + // one shot helpers static Node ParseFile( const std::string& file ) ; static Node Parse( const std::string& xml ) ; @@ -48,7 +48,7 @@ public : bool is_new ; private : - + static void StartElement( void* pvthis, const char* name, const char** attr ) ; static void EndElement( void* pvthis, const char* name ) ; static void OnCharData( void *pvthis, const char *s, int len ) ; diff --git a/libgrive/test/Assert.hh b/libgrive/test/Assert.hh index 6863ce16..ac9b1881 100644 --- a/libgrive/test/Assert.hh +++ b/libgrive/test/Assert.hh @@ -56,7 +56,7 @@ namespace grut { act << *actualFirst++ << " " ; exp << *expectFirst++ << " " ; } - + CPPUNIT_NS::Asserter::failNotEqual( exp.str(), act.str(), @@ -64,7 +64,7 @@ namespace grut { message ); } } - + inline void AssertEquals( const std::wstring& expected, const std::wstring& actual, @@ -77,7 +77,7 @@ namespace grut { sourceLine, message ) ; } - + } // end of namespace #define GRUT_ASSERT_RANGE_EQUAL(actualFirst, actualLast, expectFirst) \ diff --git a/libgrive/test/UnitTest.cc b/libgrive/test/UnitTest.cc index 19dcf503..00fdc371 100644 --- a/libgrive/test/UnitTest.cc +++ b/libgrive/test/UnitTest.cc @@ -34,9 +34,9 @@ int main( int argc, char **argv ) { using namespace grut ; - + gr::LogBase::Inst( std::auto_ptr(new gr::log::DefaultLog) ) ; - + CppUnit::TextUi::TestRunner runner; runner.addTest( EntryTest::suite( ) ) ; runner.addTest( StateTest::suite( ) ) ; @@ -48,6 +48,6 @@ int main( int argc, char **argv ) runner.addTest( SignalHandlerTest::suite( ) ) ; runner.addTest( NodeTest::suite( ) ) ; runner.run(); - + return 0 ; } diff --git a/libgrive/test/btest/JsonValTest.cc b/libgrive/test/btest/JsonValTest.cc index d5087cdf..3a81c57c 100644 --- a/libgrive/test/btest/JsonValTest.cc +++ b/libgrive/test/btest/JsonValTest.cc @@ -41,16 +41,16 @@ BOOST_AUTO_TEST_CASE( Test ) ValBuilder b ; JsonParser::Parse( "{\"key\": 100 }", &b ) ; Val json = b.Result() ; - + BOOST_CHECK( json.Is() ) ; BOOST_CHECK_EQUAL( json["key"].As(), 100 ) ; - + StringStream ss ; JsonWriter wr( &ss ) ; json.Visit( &wr ) ; - + BOOST_CHECK_EQUAL( ss.Str(), "{\"key\":100}" ) ; - + // std::cout << ss.Str() << std::endl ; } diff --git a/libgrive/test/btest/ValTest.cc b/libgrive/test/btest/ValTest.cc index 5514825e..19d22b96 100644 --- a/libgrive/test/btest/ValTest.cc +++ b/libgrive/test/btest/ValTest.cc @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( TestSimpleTypes ) Val null ; BOOST_CHECK_EQUAL( null.Type(), Val::null_type ) ; BOOST_CHECK( null.Is() ) ; - + Val i( 100 ) ; BOOST_CHECK_EQUAL( i.As(), 100 ) ; BOOST_CHECK_EQUAL( i.Type(), Val::int_type ) ; diff --git a/libgrive/test/drive/EntryTest.cc b/libgrive/test/drive/EntryTest.cc index 48dfa5c7..041f9085 100644 --- a/libgrive/test/drive/EntryTest.cc +++ b/libgrive/test/drive/EntryTest.cc @@ -40,19 +40,19 @@ EntryTest::EntryTest( ) void EntryTest::TestXml( ) { xml::Node root = xml::TreeBuilder::ParseFile( TEST_DATA "entry.xml" ) ; - + CPPUNIT_ASSERT( !root["entry"].empty() ) ; - + Entry subject( root["entry"].front() ) ; GRUT_ASSERT_EQUAL( "snes", subject.Title() ) ; GRUT_ASSERT_EQUAL( "\"WxYPGE8CDyt7ImBk\"", subject.ETag() ) ; GRUT_ASSERT_EQUAL( "https://docs.google.com/feeds/default/private/full/folder%3A0B5KhdsbryVeGMl83OEV1ZVc3cUE", subject.SelfHref() ) ; - + GRUT_ASSERT_EQUAL( 1U, subject.ParentHrefs().size() ) ; GRUT_ASSERT_EQUAL( "https://docs.google.com/feeds/default/private/full/folder%3A0B5KhdsbryVeGNEZjdUxzZHl3Sjg", subject.ParentHrefs().front() ) ; - + GRUT_ASSERT_EQUAL( "folder", subject.Kind() ) ; } diff --git a/libgrive/test/drive/ResourceTest.cc b/libgrive/test/drive/ResourceTest.cc index 5f69c427..a506a9ce 100644 --- a/libgrive/test/drive/ResourceTest.cc +++ b/libgrive/test/drive/ResourceTest.cc @@ -50,16 +50,16 @@ void ResourceTest::TestNormal( ) Resource root( TEST_DATA, "folder" ) ; Resource subject( "entry.xml", "file" ) ; root.AddChild( &subject ) ; - + GRUT_ASSERT_EQUAL( subject.Path(), fs::path( TEST_DATA ) / "entry.xml" ) ; - + subject.FromLocal( DateTime() ) ; GRUT_ASSERT_EQUAL( subject.MD5(), "c0742c0a32b2c909b6f176d17a6992d0" ) ; GRUT_ASSERT_EQUAL( subject.StateStr(), "local_new" ) ; - + xml::Node entry = xml::Node::Element( "entry" ) ; entry.AddElement( "updated" ).AddText( "2012-05-09T16:13:22.401Z" ) ; - + Entry remote( entry ) ; subject.FromRemote( remote, DateTime() ) ; GRUT_ASSERT_EQUAL( "local_changed", subject.StateStr() ) ; diff --git a/libgrive/test/drive/ResourceTreeTest.cc b/libgrive/test/drive/ResourceTreeTest.cc index 22285ade..ad26f35b 100644 --- a/libgrive/test/drive/ResourceTreeTest.cc +++ b/libgrive/test/drive/ResourceTreeTest.cc @@ -37,7 +37,7 @@ ResourceTreeTest::ResourceTreeTest( ) void ResourceTreeTest::TestSerialize( ) { - + } } // end of namespace grut diff --git a/libgrive/test/http/MockAgent.hh b/libgrive/test/http/MockAgent.hh index d348e62d..7a9f94b5 100644 --- a/libgrive/test/http/MockAgent.hh +++ b/libgrive/test/http/MockAgent.hh @@ -31,7 +31,7 @@ class MockAgent : public Agent { public : MockAgent() ; - + long Put( const std::string& url, const std::string& data, @@ -42,21 +42,21 @@ public : const std::string& url, Receivable *dest, const Header& hdr ) ; - + long Post( const std::string& url, const std::string& data, Receivable *dest, const Header& hdr ) ; - + long Custom( const std::string& method, const std::string& url, Receivable *dest, const Header& hdr ) ; - + std::string RedirLocation() const ; - + std::string Escape( const std::string& str ) ; std::string Unescape( const std::string& str ) ; } ; diff --git a/libgrive/test/util/DateTimeTest.cc b/libgrive/test/util/DateTimeTest.cc index 341c3a85..3cb30541 100644 --- a/libgrive/test/util/DateTimeTest.cc +++ b/libgrive/test/util/DateTimeTest.cc @@ -63,17 +63,17 @@ void DateTimeTest::TestOffByOne( ) void DateTimeTest::TestCompare( ) { DateTime s1( 1000, 2000 ), s2( 1001, 2000 ), s3( 1000, 2001 ), s4( 1001, 2000 ) ; - + CPPUNIT_ASSERT( s1 < s3 ) ; CPPUNIT_ASSERT( s1 <= s3 ) ; CPPUNIT_ASSERT( s3 > s1 ) ; CPPUNIT_ASSERT( s3 >= s1 ) ; - + CPPUNIT_ASSERT( s1 < s2 ) ; CPPUNIT_ASSERT( s1 <= s2 ) ; CPPUNIT_ASSERT( s2 > s1 ) ; CPPUNIT_ASSERT( s2 >= s1 ) ; - + CPPUNIT_ASSERT( s2 == s4 ) ; CPPUNIT_ASSERT( s2 >= s4 ) ; CPPUNIT_ASSERT( s2 <= s4 ) ; diff --git a/libgrive/test/util/FunctionTest.cc b/libgrive/test/util/FunctionTest.cc index 2b24d2d8..a7d0fd6c 100644 --- a/libgrive/test/util/FunctionTest.cc +++ b/libgrive/test/util/FunctionTest.cc @@ -38,7 +38,7 @@ void FunctionTest::TestRun( ) { Function f = &TestFunction ; Function f2 ; - + CPPUNIT_ASSERT_EQUAL( 3, f(3) ) ; CPPUNIT_ASSERT_EQUAL( std::string(), f2() ) ; } diff --git a/libgrive/test/xml/NodeTest.cc b/libgrive/test/xml/NodeTest.cc index 14e973ba..167b29de 100644 --- a/libgrive/test/xml/NodeTest.cc +++ b/libgrive/test/xml/NodeTest.cc @@ -40,18 +40,18 @@ void NodeTest::TestTree( ) Node node = Node::Element( "root" ) ; GRUT_ASSERT_EQUAL( 1UL, node.RefCount() ) ; GRUT_ASSERT_EQUAL( Node::element, node.GetType() ) ; - + Node c1 = node.AddElement( "child1" ) ; c1.AddText( "this is a line" ) ; Node c11 = c1.AddElement( "b" ) ; GRUT_ASSERT_EQUAL( 2UL, c1.RefCount() ) ; - + Node c2 = node.AddElement( "child2" ) ; Node c0 = node.AddElement( "child0" ) ; - + Node c1_ = node["child1"].front() ; Node c11_ = node["child1"]["b"].front() ; - + GRUT_ASSERT_EQUAL( 3UL, c1_.RefCount() ) ; GRUT_ASSERT_EQUAL( "child1", c1_.Name() ) ; } @@ -60,13 +60,13 @@ void NodeTest::TestParseFile( ) { Node n ; n.AddNode( TreeBuilder::Parse( "abc" ) ) ; - - + + GRUT_ASSERT_EQUAL( "entry", n["entry"].front().Name() ) ; GRUT_ASSERT_EQUAL( "link", n["entry"]["link"].front().Name() ) ; GRUT_ASSERT_EQUAL( "q", n["entry"]["link"]["@href"].front().Value() ) ; GRUT_ASSERT_EQUAL( Node::element, n["entry"]["link"]["href"].front().GetType() ) ; - + GRUT_ASSERT_EQUAL( "abc", n["entry"]["link"]["href"].front().Value() ) ; Node el = n["entry"]["link"].front() ; @@ -76,7 +76,7 @@ void NodeTest::TestParseFile( ) CPPUNIT_ASSERT_EQUAL( std::string("href"), (*i).Name() ) ; ++i ; } - + NodeSet r = n["entry"]["link"] ; GRUT_ASSERT_EQUAL( 2U, r.size() ) ; } From 43bf0e7858db822f85a1581156673f8168cfc56a Mon Sep 17 00:00:00 2001 From: linwiz Date: Sun, 28 Sep 2014 20:30:56 -0400 Subject: [PATCH 59/79] merge with chreekat/grive --- cmake/Modules/FindYAJL.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmake/Modules/FindYAJL.cmake b/cmake/Modules/FindYAJL.cmake index 82520625..0dc425c0 100644 --- a/cmake/Modules/FindYAJL.cmake +++ b/cmake/Modules/FindYAJL.cmake @@ -28,7 +28,3 @@ ELSE (YAJL_FOUND) ENDIF (YAJL_FIND_REQUIRED) ENDIF (YAJL_FOUND) -<<<<<<< HEAD -======= - ->>>>>>> 1cef976cf4589c4495902702ecea6b8a3337a4a3 From a8d87d2fef94922e3834090eb3c9f5dbb6428cbe Mon Sep 17 00:00:00 2001 From: linwiz Date: Sun, 28 Sep 2014 21:10:39 -0400 Subject: [PATCH 60/79] Fixed merge conflict --- libgrive/src/drive/State.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index df08f875..1f52df67 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -255,15 +255,8 @@ void State::Read( const fs::path& filename ) void State::Write( const fs::path& filename ) const { Json last_sync ; -<<<<<<< HEAD last_sync.Add( "sec", Json((boost::uint64_t)m_last_sync.Sec() ) ); last_sync.Add( "nsec", Json((boost::uint64_t)m_last_sync.NanoSec() ) ); - -======= - last_sync.Add( "sec", Json( (int)m_last_sync.Sec() ) ); - last_sync.Add( "nsec", Json( (unsigned)m_last_sync.NanoSec() ) ); - ->>>>>>> 94efea11dd1735786d63ec1de3aaa385b2fd3c1d Json result ; result.Add( "last_sync", last_sync ) ; result.Add( "change_stamp", Json((boost::uint64_t)m_cstamp) ) ; From 71c9d7f002c5ebc9a811bf9f5b17901b39d7d307 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 09:20:20 -0400 Subject: [PATCH 61/79] Reverted merge of http://github.com/fhowar/grive --- CMakeLists.txt | 2 +- libgrive/src/drive/State.cc | 36 +----------------------------------- libgrive/src/drive/State.hh | 5 ----- 3 files changed, 2 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 529456de..60a3b09e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,4 +11,4 @@ add_definitions( -D_FILE_OFFSET_BITS=64 ) add_subdirectory( libgrive ) add_subdirectory( grive ) -# add_subdirectory( bgrive ) +add_subdirectory( bgrive ) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index ef6fbc7e..7c673cc3 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -40,8 +40,6 @@ State::State( const fs::path& filename, const Json& options ) : { Read( filename ) ; - m_filter = "GDrive"; - // the "-f" option will make grive always thinks remote is newer Json force ; if ( options.Get("force", force) && force.Bool() ) @@ -61,34 +59,6 @@ void State::FromLocal( const fs::path& p ) FromLocal( p, m_res.Root() ) ; } -/// returns true if a file should be ignored based -/// on the configured filter -bool State::IsFiltered( const std::string& filename ) -{ - if (filename.length() < m_filter.length()) { - return true ; - } - - std::string prefix = filename.substr(0, m_filter.length()); - - return prefix.compare(m_filter) != 0; -} - -bool State::IsFiltered( const Entry& e ) -{ - if (Resource *parent = m_res.FindByHref( e.ParentHref() ) ) - { - assert( parent->IsFolder() ) ; - if (!parent->IsRoot()) - return false; - } - else - return false ; - - return IsFiltered( e.Name() ); -} - - bool State::IsIgnore( const std::string& filename ) { return filename == ".grive" || filename == ".grive_state" || filename == ".trash"; @@ -108,8 +78,7 @@ void State::FromLocal( const fs::path& p, Resource* folder ) if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; - else if ( folder->IsRoot() && this->IsFiltered(fname)) - Log( "file %1% is filtered by grive", fname, log::verbose ) ; + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; @@ -142,9 +111,6 @@ void State::FromRemote( const Entry& e ) if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; - else if ( this->IsFiltered(e) ) - Log( "file %1% is filtered by grive", e.Name(), log::verbose ) ; - // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh index cb9b04af..dd3da552 100644 --- a/libgrive/src/drive/State.hh +++ b/libgrive/src/drive/State.hh @@ -75,17 +75,12 @@ private : static bool IsIgnore( const std::string& filename ) ; - bool IsFiltered( const Entry& e ); - bool IsFiltered( const std::string& filename ); - private : ResourceTree m_res ; DateTime m_last_sync ; int m_cstamp ; std::string m_dir ; std::vector m_unresolved ; - - std::string m_filter; } ; } } // end of namespace gr::v1 From 5ac4ae8a0241f0895ba63360b296c9faf7e0d58c Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 09:24:22 -0400 Subject: [PATCH 62/79] Revert merge of http://github.com/fhowar/grive --- libgrive/src/drive/State.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 7c673cc3..7a7681af 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -79,6 +79,10 @@ void State::FromLocal( const fs::path& p, Resource* folder ) if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; + // check if it is ignored + else if ( folder == m_res.Root() && m_dir != "" && fname != m_dir ) + Log( "%1% %2% is ignored", fs::is_directory(i->path()) ? "folder" : "file", fname, log::verbose ); + // check for broken symblic links else if ( !fs::exists( i->path() ) ) Log( "file %1% doesn't exist (broken link?), ignored", i->path(), log::verbose ) ; @@ -111,6 +115,10 @@ void State::FromRemote( const Entry& e ) if ( IsIgnore( e.Name() ) ) Log( "%1% %2% is ignored by grive", e.Kind(), e.Name(), log::verbose ) ; + // check if it is ignored + else if ( e.ParentHref() == m_res.Root()->SelfHref() && m_dir != "" && e.Name() != m_dir ) + Log( "%1% %2% is ignored", e.Kind(), e.Name(), log::verbose ); + // common checkings else if ( e.Kind() != "folder" && (fn.empty() || e.ContentSrc().empty()) ) Log( "%1% \"%2%\" is a google document, ignored", e.Kind(), e.Name(), log::verbose ) ; From c587ffcca17fa1fe5bc9a686b1b77f07ca126aef Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 09:53:06 -0400 Subject: [PATCH 63/79] Corrected directory specific code --- libgrive/src/util/Config.cc | 10 +++++----- qgrive/src/QGriveApplication.cc | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index ca5ac164..dfdbd430 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -31,16 +31,16 @@ namespace po = boost::program_options; namespace gr { const std::string default_filename = ".grive"; -const char *env_name = "GR_CONFIG"; -const std::string default_root_folder = "."; +const char *env_name = "GR_CONFIG"; +const std::string default_root_folder = "."; Config::Config( const po::variables_map& vm ) { m_cmd.Add( "log-xml", Json(vm.count("log-xml") > 0) ) ; m_cmd.Add( "new-rev", Json(vm.count("new-rev") > 0) ) ; - m_cmd.Add( "force", Json(vm.count("force") > 0 ) ) ; - m_cmd.Add( "uploadonly", Json(vm.count("uploadonly") > 0 ) ) ; - m_cmd.Add( "path", Json(vm.count("path") > 0 + m_cmd.Add( "force", Json(vm.count("force") > 0 ) ) ; + m_cmd.Add( "uploadonly",Json(vm.count("uploadonly") > 0 ) ) ; + m_cmd.Add( "path", Json(vm.count("path") > 0 ? vm["path"].as() : default_root_folder ) ) ; m_cmd.Add( "dir", Json(vm.count("dir") > 0 diff --git a/qgrive/src/QGriveApplication.cc b/qgrive/src/QGriveApplication.cc index f5ceda78..99893897 100644 --- a/qgrive/src/QGriveApplication.cc +++ b/qgrive/src/QGriveApplication.cc @@ -87,8 +87,7 @@ void QGriveApplication::setup_environment( ) throw ( QGriveException ) } else { - _config_file = getenv( "HOME" ) ; - _config_file += "/.grive" ; + _config_file = "./.grive" ; _config_by_file = true ; } } From 0a29c2c352ecf57f0d31dcdfaa92bc5e5b010ecc Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 13:28:04 -0400 Subject: [PATCH 64/79] Added install_menifest.txt to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6fa3768d..d0c63324 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ bgrive/bgrive grive/grive libgrive/btest *.cmake +install_manifest.txt From 51a3d80de8009d1c92c12d4dcd0d57028305d202 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 14:59:10 -0400 Subject: [PATCH 65/79] Fixed location of json.h --- cmake/Modules/FindJSONC.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index 8e4f1fc9..9c6d6c8a 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -6,8 +6,8 @@ # JSONC_INCLUDE_DIR - The JSON-C include directory. # JSONC_LIBRARY - The JSON-C library to link against. -FIND_PATH(JSONC_INCLUDE_DIR json-c/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json-c) +FIND_PATH(JSONC_INCLUDE_DIR json/json.h json-c/json.h) +FIND_LIBRARY(JSONC_LIBRARY NAMES json json-c) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) From bf6467e820911920e3a1e060ced6777c6d4617c4 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 16:26:29 -0400 Subject: [PATCH 66/79] Fixes #1 --- CMakeLists.txt | 2 +- {bgrive => old/bgrive}/CMakeLists.txt | 0 {bgrive => old/bgrive}/src/DriveModel.cc | 0 {bgrive => old/bgrive}/src/DriveModel.hh | 0 {bgrive => old/bgrive}/src/MainWnd.cc | 0 {bgrive => old/bgrive}/src/MainWnd.hh | 0 {bgrive => old/bgrive}/src/main.cc | 0 {bgrive => old/bgrive}/ui/MainWindow.ui | 0 {qgrive => old/qgrive}/CMakeLists.txt | 0 {qgrive => old/qgrive}/include/QGriveApplication.hh | 0 {qgrive => old/qgrive}/include/QGriveMainWindow.hh | 0 {qgrive => old/qgrive}/src/QGriveApplication.cc | 0 {qgrive => old/qgrive}/src/QGriveMainWindow.cc | 0 {qgrive => old/qgrive}/src/main.cc | 0 {qgrive => old/qgrive}/ui/mainwindow.ui | 0 15 files changed, 1 insertion(+), 1 deletion(-) rename {bgrive => old/bgrive}/CMakeLists.txt (100%) rename {bgrive => old/bgrive}/src/DriveModel.cc (100%) rename {bgrive => old/bgrive}/src/DriveModel.hh (100%) rename {bgrive => old/bgrive}/src/MainWnd.cc (100%) rename {bgrive => old/bgrive}/src/MainWnd.hh (100%) rename {bgrive => old/bgrive}/src/main.cc (100%) rename {bgrive => old/bgrive}/ui/MainWindow.ui (100%) rename {qgrive => old/qgrive}/CMakeLists.txt (100%) rename {qgrive => old/qgrive}/include/QGriveApplication.hh (100%) rename {qgrive => old/qgrive}/include/QGriveMainWindow.hh (100%) rename {qgrive => old/qgrive}/src/QGriveApplication.cc (100%) rename {qgrive => old/qgrive}/src/QGriveMainWindow.cc (100%) rename {qgrive => old/qgrive}/src/main.cc (100%) rename {qgrive => old/qgrive}/ui/mainwindow.ui (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54cd97cd..45c80093 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,4 +15,4 @@ add_definitions( -DPACKAGE_VERSION="${GRIVE_VERSION}" ) add_subdirectory( libgrive ) add_subdirectory( grive ) -add_subdirectory( bgrive ) + diff --git a/bgrive/CMakeLists.txt b/old/bgrive/CMakeLists.txt similarity index 100% rename from bgrive/CMakeLists.txt rename to old/bgrive/CMakeLists.txt diff --git a/bgrive/src/DriveModel.cc b/old/bgrive/src/DriveModel.cc similarity index 100% rename from bgrive/src/DriveModel.cc rename to old/bgrive/src/DriveModel.cc diff --git a/bgrive/src/DriveModel.hh b/old/bgrive/src/DriveModel.hh similarity index 100% rename from bgrive/src/DriveModel.hh rename to old/bgrive/src/DriveModel.hh diff --git a/bgrive/src/MainWnd.cc b/old/bgrive/src/MainWnd.cc similarity index 100% rename from bgrive/src/MainWnd.cc rename to old/bgrive/src/MainWnd.cc diff --git a/bgrive/src/MainWnd.hh b/old/bgrive/src/MainWnd.hh similarity index 100% rename from bgrive/src/MainWnd.hh rename to old/bgrive/src/MainWnd.hh diff --git a/bgrive/src/main.cc b/old/bgrive/src/main.cc similarity index 100% rename from bgrive/src/main.cc rename to old/bgrive/src/main.cc diff --git a/bgrive/ui/MainWindow.ui b/old/bgrive/ui/MainWindow.ui similarity index 100% rename from bgrive/ui/MainWindow.ui rename to old/bgrive/ui/MainWindow.ui diff --git a/qgrive/CMakeLists.txt b/old/qgrive/CMakeLists.txt similarity index 100% rename from qgrive/CMakeLists.txt rename to old/qgrive/CMakeLists.txt diff --git a/qgrive/include/QGriveApplication.hh b/old/qgrive/include/QGriveApplication.hh similarity index 100% rename from qgrive/include/QGriveApplication.hh rename to old/qgrive/include/QGriveApplication.hh diff --git a/qgrive/include/QGriveMainWindow.hh b/old/qgrive/include/QGriveMainWindow.hh similarity index 100% rename from qgrive/include/QGriveMainWindow.hh rename to old/qgrive/include/QGriveMainWindow.hh diff --git a/qgrive/src/QGriveApplication.cc b/old/qgrive/src/QGriveApplication.cc similarity index 100% rename from qgrive/src/QGriveApplication.cc rename to old/qgrive/src/QGriveApplication.cc diff --git a/qgrive/src/QGriveMainWindow.cc b/old/qgrive/src/QGriveMainWindow.cc similarity index 100% rename from qgrive/src/QGriveMainWindow.cc rename to old/qgrive/src/QGriveMainWindow.cc diff --git a/qgrive/src/main.cc b/old/qgrive/src/main.cc similarity index 100% rename from qgrive/src/main.cc rename to old/qgrive/src/main.cc diff --git a/qgrive/ui/mainwindow.ui b/old/qgrive/ui/mainwindow.ui similarity index 100% rename from qgrive/ui/mainwindow.ui rename to old/qgrive/ui/mainwindow.ui From 5fc43a248fe5a3654c73539ed84f5f71a3efdc18 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 16:35:27 -0400 Subject: [PATCH 67/79] Not used for grive --- old/icon/128x128/128x128.png | Bin 0 -> 18608 bytes old/icon/16x16/16x16.png | Bin 0 -> 966 bytes old/icon/22x22/22x22.png | Bin 0 -> 1369 bytes old/icon/256x256/256x256.png | Bin 0 -> 53136 bytes old/icon/32x32/32x32.png | Bin 0 -> 2355 bytes old/icon/48x48/48x48.png | Bin 0 -> 4186 bytes old/icon/64x64/64x64.png | Bin 0 -> 6534 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 old/icon/128x128/128x128.png create mode 100644 old/icon/16x16/16x16.png create mode 100644 old/icon/22x22/22x22.png create mode 100644 old/icon/256x256/256x256.png create mode 100644 old/icon/32x32/32x32.png create mode 100644 old/icon/48x48/48x48.png create mode 100644 old/icon/64x64/64x64.png diff --git a/old/icon/128x128/128x128.png b/old/icon/128x128/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..5914ad64a5bb56e24c0a38037d82ae51671ec4c7 GIT binary patch literal 18608 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 Hu0mjft9SHl literal 0 HcmV?d00001 diff --git a/old/icon/16x16/16x16.png b/old/icon/16x16/16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6949b3a6a9d48a6b1442ee51b7740073e86bd1 GIT binary patch literal 966 zcmV;%13CPOP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vo0H_CX>@2HM@dakSAh-}0009aNkljSutf&o*(w0XcDpG}1B)Sl(AVv@>0}>Jo1Dy~H zY#kUF*cdCZ1O%u^AR$2NP+HWGQnhsobsXH-@%6QRAHL7;`!j(kuQML~&Tl(}|4H}K z({!)VLdP0l^&N}Wv&$8uVKbW=}0engI=kdrX7gfve`3Sw=hjPn3~`Gc2#9l!MXg}sjFzMZP%x!x#+ z@OqdHci{RVl2kzwA8pyZ+pxrsuCJ1R2y)909d$hKgEWpamKU+-4rwN81A&hyNtv}K zBC2L3e|e*!tOo?uw^j|$^WO9W|5Oyl9E^Nw+rBD#7Ekj~go%dIOk+8o>-BwM{3!L{c5PaVsYSnCDFOj-j*j;3snerBQ#0RUq%zb{In z*R|3}lLSc|Bks8)ZrPXbbmFx{i?34!Uu!^XVo8ko3ccp~sx0=ryh46BdO<5a#agpg znsl5%^_|VA-u?nWY-R@^6Vj`aGz6stR+uiOPoAiW)0r@e2*4r)Kmar}*h4CV)(CMyG%G zUXLGJs%US}E;-J?ltM_Y6*wNI;r4g$O4PfcIkQVd%Pdf<6eoGvcvO7#?RDeuA=5m* zFl|=%8|8!LLZM}|FijKl)q|)VFoNcn135P|Sm?lSHw%izgPwxs(s=zSXV^0N|f?n7i9Q;69(zJEe_?B+XTd)ND4;AG&b; z2ZfldZ>e#luMGriwG$qEy=jJ8lUQwD}gfTg*#aNbfl&G-Z&IH@* ov2*{^1N+Tuqme)FIL_VQ0q|?bwe}FZ2LJ#707*qoM6N<$f(CE7!vFvP literal 0 HcmV?d00001 diff --git a/old/icon/22x22/22x22.png b/old/icon/22x22/22x22.png new file mode 100644 index 0000000000000000000000000000000000000000..d005088ac4b5872a8f31dba7feef0104153847c3 GIT binary patch literal 1369 zcmV-f1*ZCmP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1v(0#yOKiy000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000EENkl3l<7D!xG(W|1!mBKWBkM-fR#ww!bC=Vj;pJkN7K_jBJ@A2!X2mIPg&uj|L3|Mdp^ zPeFH+6l>e!NsYz=v5BN7naSHd6Q*(Ch@t-z_!#$jF7$S7p3G#oz3Xjl%8m@rnux`H znQYD~6s(b=<(yCE`Rje}8)t4;@4gdw_KtN&9M*5yQZ9#Ctgd$wA;UC-LRev~b)Ad! z+JIL#NA3-DxA%%(0DN=3>vqsre*G*Qi^q27vpGo9!pTe!k~LTpmMoRQe3in&SAs0Rw&1Tumnc4HmaN?B4QFn(}t81j?&PI;rF7ldkEbVY1R3U;Pvn9 zojaTy|5z&xVG9V;f@KtOI!1WhI}FnjkWxV@4b2RIQCsC*+}dFu1z_9}EEZP0A#8h< zBPDEM!?FY{!{Dr8P*pK&Rifaw9YtDc=qXD$6wnbv`3A0x$&Tw@&+z!MH}`r9#p08O zVQ?;&M>dm1CY?eylOd!H^Q$igTBMewlxC$FiWyonISN?Q$a|O(zRvR84DJ}Xd`Q?L zva2@G&;1+5MQyz2}@em6t$yceFR z%$T|7Su-o8VB0oqAs|eP?O3)@98FvR(0Oq<@U&tAYldcqW6-s_q`5GslEXo zPbYS0&CHso{Zmj%K{}G?T4oT869969!?{aBQM;N}t9i;)r3iHq)zmb%Wc>`VqtyY{ zOsq9nYp`NyrQnlrjP|Ri0JHE6f{qK!`;*f8QpoySCtU=HqFx7hV3)ExIE zO`02NAh&xJ0n7|4^_Ae|N1AEN+Esp^-(UHAe>^H|jsg_jw{uzaL|b2QQq^$W2vOV& zAz=g&%X>LFdgUz4*q1jJglfu1$m`w-mn*=`{My!L`sw?AeDL8>Y}>F9iOCc;J-ig9 zeiww9LpbPxWov4v4T7|T1^1U@>&lQl(tGCfLO$Daqj~(}mESmHy$Y#pVy19O84r&P z;iVUMA(eL!tt>-RwTb@D)7ZG83h}W4G}W4TbZHsesct;AVU`-d+L3Lsj>b(y!}xdKQJ#0nIFgH{z0T=07lWk=vV^F8f#GEu}N8ZQ%l1k zR(&lkEdv0mZ@m>7iS#*-HS3Rao%Zt056-XHzHtE^KluydsRCTYJebf_9r5CP*EKZG zpM&#fT8+MrpTC*YP=9sNqD4yzg~I8co}Sh_eGsBRw2=|n1#)ddSw)>YSW~K`>Gt{q zjw~cix15|%>Cp~2vX{_W>^0aU`}X&{e(HrN$nEftiN0x$$%5Wpk= bd28WcbNA9Q<1SB+00000NkvXXu0mjfRU2=; literal 0 HcmV?d00001 diff --git a/old/icon/256x256/256x256.png b/old/icon/256x256/256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a6b5fd271a52316ffc2c70fecac5f2579a2c93 GIT binary patch literal 53136 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 literal 0 HcmV?d00001 From f5b84331013f6b61cfad5f7925a613bcb5cabb3e Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 16:37:04 -0400 Subject: [PATCH 68/79] Fixes merge issues --- grive.spec | 4 ++-- icon/128x128/128x128.png | Bin 18608 -> 0 bytes icon/16x16/16x16.png | Bin 966 -> 0 bytes icon/22x22/22x22.png | Bin 1369 -> 0 bytes icon/256x256/256x256.png | Bin 53136 -> 0 bytes icon/32x32/32x32.png | Bin 2355 -> 0 bytes icon/48x48/48x48.png | Bin 4186 -> 0 bytes icon/64x64/64x64.png | Bin 6534 -> 0 bytes 8 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 icon/128x128/128x128.png delete mode 100644 icon/16x16/16x16.png delete mode 100644 icon/22x22/22x22.png delete mode 100644 icon/256x256/256x256.png delete mode 100644 icon/32x32/32x32.png delete mode 100644 icon/48x48/48x48.png delete mode 100644 icon/64x64/64x64.png diff --git a/grive.spec b/grive.spec index d1b87f3f..3cec116c 100644 --- a/grive.spec +++ b/grive.spec @@ -1,4 +1,4 @@ -%define rev %(git ls-remote https://github.com/jar1karp/grive.git refs/heads/master|awk '{print $1}') +%define rev %(git ls-remote https://github.com/linwiz/grive.git refs/heads/master|awk '{print $1}') Name: grive Version: 0.3.0pre_git%{rev} @@ -29,7 +29,7 @@ the servers in Google. The code is written in standard C++. %prep rm -rf grive-%{version} -git clone https://github.com/jar1karp/grive.git -b master grive-%{version} +git clone https://github.com/linwiz/grive.git -b master grive-%{version} cd grive-%{version} %build diff --git a/icon/128x128/128x128.png b/icon/128x128/128x128.png deleted file mode 100644 index 5914ad64a5bb56e24c0a38037d82ae51671ec4c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18608 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 Hu0mjft9SHl diff --git a/icon/16x16/16x16.png b/icon/16x16/16x16.png deleted file mode 100644 index 2e6949b3a6a9d48a6b1442ee51b7740073e86bd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 966 zcmV;%13CPOP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vo0H_CX>@2HM@dakSAh-}0009aNkljSutf&o*(w0XcDpG}1B)Sl(AVv@>0}>Jo1Dy~H zY#kUF*cdCZ1O%u^AR$2NP+HWGQnhsobsXH-@%6QRAHL7;`!j(kuQML~&Tl(}|4H}K z({!)VLdP0l^&N}Wv&$8uVKbW=}0engI=kdrX7gfve`3Sw=hjPn3~`Gc2#9l!MXg}sjFzMZP%x!x#+ z@OqdHci{RVl2kzwA8pyZ+pxrsuCJ1R2y)909d$hKgEWpamKU+-4rwN81A&hyNtv}K zBC2L3e|e*!tOo?uw^j|$^WO9W|5Oyl9E^Nw+rBD#7Ekj~go%dIOk+8o>-BwM{3!L{c5PaVsYSnCDFOj-j*j;3snerBQ#0RUq%zb{In z*R|3}lLSc|Bks8)ZrPXbbmFx{i?34!Uu!^XVo8ko3ccp~sx0=ryh46BdO<5a#agpg znsl5%^_|VA-u?nWY-R@^6Vj`aGz6stR+uiOPoAiW)0r@e2*4r)Kmar}*h4CV)(CMyG%G zUXLGJs%US}E;-J?ltM_Y6*wNI;r4g$O4PfcIkQVd%Pdf<6eoGvcvO7#?RDeuA=5m* zFl|=%8|8!LLZM}|FijKl)q|)VFoNcn135P|Sm?lSHw%izgPwxs(s=zSXV^0N|f?n7i9Q;69(zJEe_?B+XTd)ND4;AG&b; z2ZfldZ>e#luMGriwG$qEy=jJ8lUQwD}gfTg*#aNbfl&G-Z&IH@* ov2*{^1N+Tuqme)FIL_VQ0q|?bwe}FZ2LJ#707*qoM6N<$f(CE7!vFvP diff --git a/icon/22x22/22x22.png b/icon/22x22/22x22.png deleted file mode 100644 index d005088ac4b5872a8f31dba7feef0104153847c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1369 zcmV-f1*ZCmP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1v(0#yOKiy000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000EENkl3l<7D!xG(W|1!mBKWBkM-fR#ww!bC=Vj;pJkN7K_jBJ@A2!X2mIPg&uj|L3|Mdp^ zPeFH+6l>e!NsYz=v5BN7naSHd6Q*(Ch@t-z_!#$jF7$S7p3G#oz3Xjl%8m@rnux`H znQYD~6s(b=<(yCE`Rje}8)t4;@4gdw_KtN&9M*5yQZ9#Ctgd$wA;UC-LRev~b)Ad! z+JIL#NA3-DxA%%(0DN=3>vqsre*G*Qi^q27vpGo9!pTe!k~LTpmMoRQe3in&SAs0Rw&1Tumnc4HmaN?B4QFn(}t81j?&PI;rF7ldkEbVY1R3U;Pvn9 zojaTy|5z&xVG9V;f@KtOI!1WhI}FnjkWxV@4b2RIQCsC*+}dFu1z_9}EEZP0A#8h< zBPDEM!?FY{!{Dr8P*pK&Rifaw9YtDc=qXD$6wnbv`3A0x$&Tw@&+z!MH}`r9#p08O zVQ?;&M>dm1CY?eylOd!H^Q$igTBMewlxC$FiWyonISN?Q$a|O(zRvR84DJ}Xd`Q?L zva2@G&;1+5MQyz2}@em6t$yceFR z%$T|7Su-o8VB0oqAs|eP?O3)@98FvR(0Oq<@U&tAYldcqW6-s_q`5GslEXo zPbYS0&CHso{Zmj%K{}G?T4oT869969!?{aBQM;N}t9i;)r3iHq)zmb%Wc>`VqtyY{ zOsq9nYp`NyrQnlrjP|Ri0JHE6f{qK!`;*f8QpoySCtU=HqFx7hV3)ExIE zO`02NAh&xJ0n7|4^_Ae|N1AEN+Esp^-(UHAe>^H|jsg_jw{uzaL|b2QQq^$W2vOV& zAz=g&%X>LFdgUz4*q1jJglfu1$m`w-mn*=`{My!L`sw?AeDL8>Y}>F9iOCc;J-ig9 zeiww9LpbPxWov4v4T7|T1^1U@>&lQl(tGCfLO$Daqj~(}mESmHy$Y#pVy19O84r&P z;iVUMA(eL!tt>-RwTb@D)7ZG83h}W4G}W4TbZHsesct;AVU`-d+L3Lsj>b(y!}xdKQJ#0nIFgH{z0T=07lWk=vV^F8f#GEu}N8ZQ%l1k zR(&lkEdv0mZ@m>7iS#*-HS3Rao%Zt056-XHzHtE^KluydsRCTYJebf_9r5CP*EKZG zpM&#fT8+MrpTC*YP=9sNqD4yzg~I8co}Sh_eGsBRw2=|n1#)ddSw)>YSW~K`>Gt{q zjw~cix15|%>Cp~2vX{_W>^0aU`}X&{e(HrN$nEftiN0x$$%5Wpk= bd28WcbNA9Q<1SB+00000NkvXXu0mjfRU2=; diff --git a/icon/256x256/256x256.png b/icon/256x256/256x256.png deleted file mode 100644 index c6a6b5fd271a52316ffc2c70fecac5f2579a2c93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53136 zcmb4p(|aAx^YA$*wr$%+W7}?Qwy|y7Xq=qbHX6IJ?KD=C{661{_YZiV-MQG=y_k8% zI}@d%B#i`*4-WtUkYr^f)Bpe=-hV&>3;iF)O}6oW7eE&^X)!?U4B^>-2WV4yX$ipB z|JJXb@|6EDa6e>pT>tn@R#6gW6A}*-7K8d0R{uW~o~xvetGJVc zgN36jK-}5F#MQ!_)WgQrnp9d=QAIll83zC$1;|Q>YIv?+_SnTT+UQX~b?@Myc~yd4 zl>T&hC_g{UaUc%$PXU@XZx9io(@pv(8@XXAD6k3a{i}y38hdo?bQ|r*)18t%m||K2 zp>%sAv65TTGrl)uf1eukj>yXkIy*a??07g+U#Xsu-|T(9O<*DCAZI6MxNt>z;G^j) z=1oh>N=wtk+QFE8@4k8O?zePU{{P)6edhNJp5DvjU+>@dR(0GN~?W|S3>x`N7ZGEy#pQPe;&;U-k?fz|fmaa}zy zYuX!>{yClyz2QDKL&)jUuPAb3UPJ*io!ee0<^lW7y$C#KP-upgL019)1jiMsgf%5t z(e28EolFWW4NfnMz1WLbHf_ts)O|J^Y`QvS&f^k^jV{y3NLfv162#LDKKZ@|a^TVG3v z!yv)sRc`vRVyH%!!Rtiw!{CR(2Wo_6S+U6ls;KPg#*uN7a%r-vqQXjL#*MhcLRo>cTA}311I;(1F~fO}a+T zDtmn_BJfFHNrx=(N@buF2n?79SRMFLOod$IW5`Mj98_CPPSu~4DLg2q5GSGWV#P&b zbCq+I73y=UOQ>Mv5_ru40}DZQAg!Dj5s)6U1co?y?3pH6uJQhfug8H4g_+5k`yH}W*rfIz`>Ui7}09T{eN`f=zd+FImPt4 zGx{)(@EB%~Klfdr7V=>emP1!^sK7hZj5$LTJ3ABVtKzCgSKyE50j(=-bJa0uvZ!ow z?@7fU0TSg>y1v&=#qCBKc@@}gdo8$N@@dTqM#?>qG@_mnrpmWQ5xNroFFrUF zlTdz5%|R&Wc;a>qEZ6w#5HNfh-5=c_=M}P2qveOClSLFzM#7rt!F}&JP1IxdB32OW zIhx-Cu0EY&@~H;%U?HgrM)xfnLOUkjgC+bQp0d2Sebrg{n#OYRh{~lz%rt5u@quv_ zdaCQ@=}`MiiOnTVuC|0WXG>~-_}yBKIiwIQQ;uf9>Z)oQd50bNnpmaqX=0Ci=zfuq z$r_Iak{@|Lm7OSUrqnnrBEggjUiq#)$EACQ>Bv z1e&fIm0BPN>fG6BCywwt{QN$N>$T?K+u6XyVd<(SDAbO7;=~-h_MmUCJ`k`Vq9~%Lr8W2Umzpv7$Q{yBS)Bdhxj!+ z7(E^tIldN$6o+5` z#YZU1B6SHbXWP|~!9TPep2shB`=wa^QzW`&6dDk0fGd<~`%)ev>M0OgM9W&pive8- z8Ltb;z7X4kh!_S73kQUY6NSxI5k=t!A+VyFF=|4HfJ9NiqGdeZM6Hd&15e)@KlFK5V=))Hx3eAY=-Uw}li5Hb-$kQKX_M z2$DKbuA)*(B`TFUy8_8b8D=lXan7eL?~!xXyTcYz6q1x(i=0=A6}B>x6cz|ahL0}_ zU;_df!h@(Bpdm*ip@u6KBKsrfqE#SK*;vKcq-ZCCn*zyEMPP3M5QR7al7IuAO0{2* zsZvXHn1LK((jrK^v}1)+P*Y@MNSUIE!DB4|46{V|Bzh_=_7-TkD2+(U<}r;dkPM(q zDd`a;n%wtVq)o>}G8(Mj*oF%I8DrLpewaPp*DaL5Wa2D7MI9SX1e;W%8fVO8}cb8k^HZ z^`v#+9p;a3b4O;!U4`v{xf5YyS6^)O5TMZG`)~WeN$4Nkr1vuheUs{5ff2`#5p}Ze zmylWaQzHXnHid|dHiSvAaSddJXg1_-waVo1!N1Dq^69;qT_9+EMl*vjo@Q|$jG`lY zJR*MHcujeak`{4%OH7KCLPe6K49!FZ1N#F5xwJt14N}7k{lToPtj0i2X!6jYemfRu za(FaRQF~v7Qpi}`3R*-+dLaW4&@*1#s2*Yvw?IYBdkb0vf|shz4B-k9(RsXXuaTg{jLgsG*u4@CK8jn~?*_ zGmiW~-x|uShU)9Ue$!j1oPLRZz;N<~@2w53RQe?$d6g3?!Nc`Qa!+ zcTo^7WUnidlteXIH3qKd)ri<|AS$fHF4cE5vuc2n24ZXltpw?(5D9gZCp-mo;9vli zjG3=8C6*+rCO|Pse?^Qk90s#g3~L_%X6v0z4#nulqXS4MAta(FqmPBkoQYRRq($LI zRVo0cs*NoXO<{&1EkVNoOV&tW)ZUG=7>1xTk;Cv61YjxQNHw@>e(QCi+C!n>YHIN;c!Oibz`D{m_35UMxZ_j z5egTU6_OV)4^yIC4^ss53x*UDH7GVZfov?&7?vHC91;~3krWXM77~#ZHX1=4Kqn^5 z!We-H2k=b1pM?X4s__A$jB(-TFi7d+iAldfoQcojh$>6Gp&|khfrt{(3H>UF(12D* zc1UxCepGUCvpJZ0Dri5n2hj&fR9y#Wzk4GL04ixhzxSpkT#G-?DG7VI#4Z2ki&Cy7;|vGn&h<#%kG0O+A4 zkqu&SRMb;9Gs&-z#3Xlz`{9zBWIV(ZRjEQq3q`5Ti&8`TVg0m5ahPmy<6HIBH3*&I0h>z z0cjfTIZ=!x0l*EizJ)4bysmPTEmIJAQP(S>ih9I1rn;M6Ir!fs@7Nd@xoz105HVTHgbl`>Q%Qg$e|$#FVHYBV-=cI3p7HfG7= z$y$PsW|TIafSY@9Ex@d$gUGRblaO-u?B3&^4SNr#+fNqxZSE_$P+^XU)>4|X2r)D8ca^evq=nK&Ap#IP8r4A!wIdUnQvgG&<*0YQnO*|_et z16{quuDTQmO%;VN|D>WG)$O9n7i#7!rwNPsijQs>Zz>J<%g+x=@%CJ;n?fW8)ccx_ ziM=BpbHdEsWF<~nDAlbKOU~s8kPbMMN}R`eDy39Q&7zg7Hb*q3hE^9>l3-OGfy7oX zj3weNGzKq4NeWq{L(UpRZ63*g_`2eELC@v>w&fQ2FKJ}i@(xTHc)9$$;OgqmC!1Wj zBF0MD4mE}iweiD|U>BQKAJsl7zXz5LFh?^7F&{x1N(w>)A_5x7m+_;4OKR4d*2pdt zEYqM@5tc-|AhhxCaP*C|V~>bZ^gN~TG`ST03#t_ZBPM`isH!CLq2VHSWn;+wFzuKQb)=*r0G%E8lt?kUGqoV<=4*n_9V?<&oTGp7w?-C*hZdh!fLOMX`$VsnG zxQoawjBb(m%68JoHaT6UvZX zkacXNjn*8quEZEeyRVOR)9zDk9#958@F!CJJXDyz zDLcWhHS>(^&&NHI7k=oW)7Rp~1FLf8jbh`3;Hq$EO;T+*gRn78Ko_Yy+#19o`q(7E z9bhkN4ycFCn1jGgij)c8?u1*;`93)3vy4~H31%%+^=cJPV@iQ_jxOAZ5feLJF-R{% z6jKv^ZL3A0@+X0Nw3N53QLb`kd`8HWSEUL+FM3Z&rh;RJ%dku5Erk9P}g7&a>P(R+72GaE~nPEcP4~_}a zOb|81>Ax0X7S}{_`Q~n@Xg~6WRlEgfRYzZDEXgpO6e>9tvI{&0W-)patyf!972R+h zvE{L3r>TdXP0U%cz(C25I3OXCGuk*|5}v3WY0wYqL^?=yGzCOf?r<~7-bI%vJm}XU z-Q0Za9q@!#VDO9!y9v5+iCb4DcZfCiyi z6;-QS#r{K?sW1@@(HT@p|86>`o&LzZT9)QOMqT8Hp2g_-q{sRC(zdPibt^0^#4D6l z3YFQuF9K!XERMPjn5H)Hw!2Wzg@Sn*;)+D@}^N9xayyo9Sq7_;b)kifJD zu9EWs<}eyjSScwrAYQlrm>PbN=ibE+Fcfi;hC};>br! zWYE1goD!(l1O~k%(g(7llVT3ZkS2+E1IX>B-FYvaDkZF*pHmi#QzTSb#!_Z@`rz{Z zr&)S5yzLIbyDa%^{y&pvm__R;MpN-hf&IWxKN0d|vPczxzK*}XQL9vl7zJJYYuS^< zSN+e6WnExevdK7ks#@cOmEKNJW*ANwYMHg4%3F*rfV4T-AWBBV`@wq^Fc_5S z$}qTu6nvV+uyHKpYt?RJEk9jK6xnI=pEL7ncB>EgI;V^(AW$x!+e-zGUv4Q3hr)=d-pg9{Z> zzTB;WCiUvM%|WdhI0bKP!qudYRH;M8WpBa{;sl&_6X_}rHvw{AtNwUb>ZT&iq@0rn zs(uygqAsHYk;JIHQJ+FjV-|x#b-!Nq1qRyuudr#NUW;e_KTj(F*_y`cww#^745YE{ z(#HU*I{(A5ynm$!Lp(bf?U(40O!&yYPN+U0DG(f70{|j1{0Q#c2}eCjj;fHCLOuqY za|lf%#wePQ86lAj9pprbUH9 z>tw=m!J0c-zEDBKDAw7C86mXsT||8VYcd`l6b`)&`mcOvMI~i7R!%}8pK5j*%=uO& z0I<~Ig`J2t%59zNC@22GojnD$Y$bG`b-G=;#zUMSMIua?;7G;1#kR{$CLWDQb_!I> zmW3L*SxE<|!^6@pwp+-VC-ECLv%8=P(BhQZ9zjZnF}Py(^O3R#Z?XQ?6cF#<6gDdD z&+ObTYME6PXkIeNo~7d?m~zT6*7cjM1`c*(X5tKERzi@jK;}!nlAQqJCC8O3H)IO; zGK+!+?fCAM+;qrlaFHCA+LVe?X8nG;mw>BOvaD}*x2r)}Ja*HMyOVYP4!IUPKLzo( z;_naH2Z(lv1DWXGHJ)UoC?V7!lCdouWbm-L*5oPDV&wcL2<_#x)1B3ejp-!I&B}t` z8%8E&L(#kg8^VIsHCFy*)az^=sg zPx-fcdwLl0q?}MYl8r=qig7AFRn!N&&4I&ScagYH&w_RKi#ED=%Eq6oN_|V>e$X9i z?-!+nUyjQ-W2!`Lv`nNOSpy9nXc|CQMnR`-m9B@Ulr~*GX|96d!|+o9rs4-t@SV*3 zAHgHa(ra~B9Y%a!KTKQQdVCgK4AbEaM_o2*PEpzpiQ<6Q*ToMk#Bhe~b#)X@0_vt? z{GK0Y#pPBsBtrar>v@*rb3qVP@AR;;;Tq5y-dkau+l#-{Z1jOC&iBh=vEW*jty2qn zyfh@mw<&chav8#UVT9Xt`#|+@$t>KACmxpipKIev%dg(80Yo_c>PRR%=ldO|Y<8TL z=8}>$osp4+(O3{>u{vb-{pNNa6*mF5S*Jrhbtq3NFB_bz3gg!H;%#g>b2b$J3~7;h zlZF!V6qWiuUAcQx*-&H}=M(?@nulj!?cEPg|0Hiy9DBZc>aOiRX$Fbh>w z2b9qcQ3);js~QI0-_UAT0n0X$FBW#~4cr{oevVxDCIT^)X)twx99mq2TIastI@)QL zGt{sQgirH)Gx~*H)=y+C%q=~&lD|j}Ycr*=S@sUPo1QCi16MrHR&eKWNq_RG9X3z? zlP|S_9)Ypa4WZ%tNqL>`-SqsewA8q3rnsL8jxhqi>Wz(wx`B1ajCK~HexwH++(rZw|S8{(G+D@jXGFI9Vmr|wc?l04nACh5>|pO@-7$od?h zvGwcoJ{9`CV_>ogl|>53tlQrX#bXP=}^LKjNMeK}$GsNbGg2m5Z@*75d^_P9WS zrp`)`e%VB+Q6z?TXo+gB?GAEr5gZR8H>VF8X(4PKv^O8J{4eHg=G}ji{3E8=7*HmP zjqg3<%yK+oq()8cB$w~%!1ob786kYsxDiwN&KhQ$^`*8tcN(vSt$rSptW^%G>i;vh zr&C95aEB zgZ&Cui7SzY1IGVj1vADNMrgo_pfzmB&CRhkcI~+prWcF|kVdTD_0HT)9%h}JL0l*f zMAQ$g!!p-Npo={Etp$>SAYA9fy({X{)e8)3EqmL>gt;^7rmp&UqIg1_9 zq#|{Q6csa$33|G&V$1h2%qeQB1`_>l_Kndd(O3_*FbA~nIIH^{8of@74D!CIa$8jM zEmW4N@C=npW88i`7s(U)vAh!Nq7@e~4EP+CF>*4t!3;wKamxPBS2v36vY)3-(nhqn z3WkKbN3hYqr=)V$0u@f);y#35=FZm6SmKpugt94Rh08-8TR(g05+2q}RNEJDGGf*r z7feh4W=kkKRfo#S+pL!sb=Zc(JSJG%@_cqNKvI;ynA-on77eT_9BJ*891D3=BdvPk z>F{oH#v9ke=hXK4IoY96!k_`}bJFdC$&JHd?s;#vK7&;tbd*lnk{34&uge$*mW-%^ z6b#XVTF`_X)K+s^c!&DVtb}j#Q*K`{ep}HP2~ArTGDsn%eQuQ18;J0wMH&zbjA0X* zhQ+h(v^(snm(rqOz022l_ofyBdgg2RN3i5KW1SJR1`;@J-y^WdSpzNQ2$)C+y7K#N z`@WP+T0hPNr4{;QvRDP&3XYsuan#^wh9PMR58?{GU)qH7i*{O zIkVCqFHpYzN*>Ed&Fx?j`q}J@btsn)?)L#B{%8fj4ATLZG@H0zpX`2 zZ-E(%1Mr{&mHdGW3hp_=`f-?pA#N=|@uz;(TAr;D8pDXQ9)|ZkWJdaS(a5o(AT_Be z)b$8<9VMC)9+uuD=yL3Qw&jQKUUnf|7q^#-6b3<80S-n2$)i_yd*;$@%ZN2D)UV1= z-V0$53eT1IKKmOjCBrDj|Gi6$)~RhCNv5)-%0pZ#gHee|<;IGas1;GhToI38pcei0 z3W}Ymg>VR$x2|WC>I``~v_(buU-EId~hmh4a}plGKi5n!he~FvI~ROhBvK z%UYb1!A-NhzHh%^qwdn{D;W&D!OK!F4!LU5Fm(a60t5kz_WV6;)22D%A4}TwzXH)X z`iLt5rmk$7acQ$>G1l-j(?#87?0kWW3FYzpnfP-ct!ct#Z3!!=G`WU|7i(sgnUZu8%1ScEo#KL_)2A9z!q*tej z!{_yS%_L;Resv1kJbgv^Q@YRofxyx4XkdO`nK(|`h$osxpD(X26IC4#PwlHOp7jz{ zp23Z2nvz}Dj^4oc(v*YAc*wFtI403X6^fC*9TT(?g6lU8|DXDg`qglk6Afbefc1()Nd&jy?51thtr?tY#dknq5QZ)8*Ir5!fddoKG#l^jH&|V z2m_2BqFKfjh&SY@HVFsf^va)?4%mjFiy6pv+%c3xeCiTR63vX!WXUD%0wcxBDx zz58sUF(0X7(5e=^_e>^7?X8*9mV?sl%SPtli6GYIz~hWDBk}Mjm`Om#a5{IYAl_hP z7r(O2dWW>pE5@?zr#b4A#;e~BwpxnO1NVcats9emDpy^tYpg6Mk``DKdQEvi5j2V- z*t?XUKU_KGek*0Qgepz%3koXQTdLDQkX~HO%&*;c&Bn*G%vy3>EJg8z+%ZbUbmB1C z8Bc%&nPM&`-gyHYby?JX{8gnFeW&l-?BdeE^2>;wN=b%HvAXv5Fs4PpT`7R)6j%;O zp{7GQF1?QmEb%G39R2AE{6D{$x(ckbm44#+rjM4pn!&Aj&UDz?K5nF`Q_RFPV@u^p z`d&ie2kaHH%!p%eZXaFUydn6IYTjyNU;(!o@dSqArmh#H-dHO|2z3eAH zb%}$ll+f#(T)MaED3_gqTN%JyRh!L}Qvr5q&fTjK;?OYx)Drz?v~%;|nPi0U(Otbv zGXl6+{x5ztcJw?PNM_eFdW@=P)jyX+_4GW=xpJm3g1IMjO_|T6(;cmO0SPgutks6W zrEjgJQjO8XT!nxX%tc`@H}{iM&H~rS{^%onjC^SB`=yYncmIC^Fe!_-E5kGgBtlU% zJZjS=&4t+%arOJYEO8AYjnO$PkFj8tjilt-nN&xvCht)3y}Hg{gM43aD}#_cgLt6B z$D2Zg3Y}F59)w$+8(n$=v6YWf519gc!zBSag_N){y%vrOz?!p})x6r=LsM2l30Z9E z1N6ss8iRIlN&_)TJ|zaDRhDz}Gsm~vtg>=^^Us{VufDKF2Y<8NQsDqk*O!5x*b!ms z*)qiw9(cwj;vEh$-bm>SQ>a{73P{HF)iKQtxSX!pw(7-NYZ2ISDd2WXwQ}(zeSN#zutDx-#KcRngC!BmQc#6QF9@gK6iKMCB*0O;(!7=d% zuNO8x$5j_rG+jL0Ib?s-o@~F(G}K}bap_KZ0~P_p9k2?X!jS-3Vnt+WK|JLqT(`cg zGMpb77o!-zE%Pn+w9A;izIfyNj$RI}d1lP$I?FAXr)&HLk7ek#|kNAu_b*2XMECA|;zvWt^fLrG*qGRk-dDOWk z!A)>ll$-EV)mZEeM49WEDmXs66FCKS_rC@rmsJDw3L1uo1;O}kmIBTKM(zy0*I5KT zRakp%m_b#bADWQ0?$*Ld>r?8J=ATbr_X6`Dhr7RL_Qz?Sq$5_)Gw`wm8#4gY#x=*=qXIhKR^Xzgi1u zM6G=(u13N_h)A37_KyQ^hmySLy~oxYm%;M51aX6`bJzoQh1VDYZM~Kn&J1zM^_YGIxF*W3MB>Je5Kc#@Hlh8YWSMbu?nIlSg05vMB2W-1>XK%G~&#>CIE;oHhx z(nLkb&|I~!B$qkK>KtNK3)R+lxpumI;j{~IOUSA~V?Rp!aTe8b>WiNh`)^wK-;R;z zkCPcAAwnWQYtEd9R7R^NCPA~3kO9UXy@T6iuQ7I_n<-qb8df_l+R3K$bi`3@1>sDD zwxh#PuW*^&B_ojt;7tDoFpLwJCMFf7c1b{?44= z-m~XDH)nG(gqK4RR9o@Gr$)XnOK$MFRKWIYN_R(lDtwQXtkgu}p$|EMslpnr-fFu9 zmoqW@xLK+r{ceVhmXVa&r^V^!M)*rgLTUneTsFqq08O0g9!R!E#9YYcR4K}^nzglO zTfILr1zui`tVa&9NkEuP;wVyj6W#9fk6NiSM6Tr=-r<&7qy{*tttN2900W=D`gy(< z22Nj!i`OV8Vv1nYwSDZEJ*!5i<)l$CHdYng;LR1SbcK!^f5ZqiaTdRAiaJpBGd^I0 zt+?VtRd@oc%GPfs@Pq_}a_ip0^%NLezQnM-EK9{ zVG+{faN~v{BdOASO_k>CiqC?A*ZkA!Q0$ix8#c+GcQ%6WU|IGi_%Jpp5xQzlsBnKk zmkmV5xgR}OVcTOx^iak6PiJJ-MleH=CP^CiFB_PgTE3NE8i7`~Um8I^4FeY;#ExsQ z0@U|smqpe2lGRJ*EDllz4*2Q>VHG~71`>ZA%rGxbxvEC<$3}pbpX^l3#@jV0VB8XS z+~FaDjOp#=ej&k}Lyjdot7MRQz9&IsIh{c=j?mM5RSNIt^HX^-jwLgc$Z8RRn%$^I z)et3+pOeqs7IAvMaq>QPed4dKk7GHP)s>s81=SCA&nI=9f4_Ut3{cn&8rfoh#$@Bw zAarT&byN;8o>Z-U@)A!&cH6NJ@|)RgoG$A_WbPBPLRSBdxEln4L%9*3-8~|tDTu!b zDk*8|a<$N-NP1L>zT30`vpkO9s`@^R{5nFPguUwfzNU*kHz)U^2dddUG;@D1G3_qc zcC7hTR)4SQfaG=y)Kz+A#@Q`wA$Xg|r@3(BhnlM($!x?aX-A`sTmpJgO)fz(S4pX9 zAz1QbGB7W4Gv@5LVIH}j4^7I<=TT>*1wV-4p*3R^4n7T77sj*bwbgKGp^i^JrwDjF zEt;KVaskR}#JjF|-gN9Zlo7_pe0pzK1cjpxj8;jAdhODwTsFvpJR2{V!1(r3#8cQogUrn+R=MPLZ)!6bt^kCl~TAux+yjml)vYq0FM0+*&0 z$!bu{a3}aaEg9K7D4U?8^f#5nezw=?;_COcjrs zYXPU}ckr&19Ny~|!;BS-X;chQT@c&TbnzqN9}7#zpmx(^>M=FDH|0qWW|#U?R<63FTWT&4 zk;~rRSLin5;WFC`$l_MD?rdDgl{w!n>0g+btPA{3mPqzP$Pb+uj8jQIGEqN)NDk5iSQ4F zUbE4DN6N6Xr^8N z*sweuSHfOg@?R#9^_gK#zZXqp7_y=(qO)rC8J}@knXb9;37LGCZo-|!>ZkLS>#ELb z@D!s~5}H>y7Ji8cIC_`X~sxv|!K)Op_4Q8%@gYmO#j8J}Vk zgqA*uXNgv@%Q}eJ)>G5Rz*9?QWqU! zxVZtt%?oEmyatOOL7+K{i+0S*rLK<>0KwSCrKP_#*);;u!ByGOnD@QIPt(yw`_0D)zssL z{he&R$t~5o#}$Gl64EKdi1nRDTMYJ6Z#P_#Ez$hvb;hNv4o|i%os>C*^{Q#<%93Hb zn2eF6a(le^UpZ;`+Dz(k7eMvfx*E>yahaB_w@IJXP|)YViBw%RYCu87>zXpls3+RO($WQs}P# zeOlTL)m7Fqt^JUj^x4hsG&t%`9uaX>jchQ*)9H1me3mLdOO;p#ajy?p>y?}#js5Eg zl{LDh*m1XT^?r*wXqxAVZCWcO?6?i^aG5cZoq@{W7R`_+9ns^mUo>pA6P%bBhiJj* zfifmWvu5QXsDtf7t$^3~$m>el_f8}?)r%Z4EFhbVrmz{uWU?C3>e#5UWSjgo=rV}g zo5ou4)6&2mQJx^>_PLV6Sfl8wqRr>t`zt}%=bv1a#irRt2wwr7c! zHP@n~+H3eM?Aeevm-bx24h&FR2%-QplqTtfqyv44B~-)1du0#;!S^Gk%do0|9f!Qc ztq+xoo&?80WBD=0lcrMJ^h$RPqoR6tO-u`TObl57!QQj5-&+UoJmeMzO+n;;QpFz| zySn-O`{c>}J}`fF=8<2zIEmMi++-uKD*x^lb7kuIIKBmFnljW|oJp%z(QMLT$8}QT z5W(qpg;3PrS?C@CJeY+{G$h?~wvZ+Rc-qLjeG>PgXGCx#vD5R9E-$6daC34x>5M%Z zaq?$PXUwp1s-M0u|HKY!v2!z>jP^5ZnMjn}h@K;ZRrq_^!~^||lKipQWFLJUmGa$W z(QL>vzXJ1V_TPFyr_T@Wx7PW!7Xqb}Gp&7g+r8Zd#IUh9T#FfHhO7%jF;E#}S=BXq zW$BPEq6D^j>l+JVT8WIdd{XZd^?us>Bm-GT>hn3+$^jzNmP9S*M!|}L$`^-w0{G*v zl)>i(Q_&|kv;dmDaL9R7z-)&;CK~qEZ%keArv*d%5>n-AyPafkC6`oZB;Bj`o_fl_ z53ZprTO-Cgrh9lL=3ruJJjk=%Z*7O)J`%qW5qxHB^#sCLrV!}+%~a~3rM^k+1Wsl6 z5{)i0r0~8TQ!4eb&nyP1({QqvKdM;(7Tk|zbkEuAtSZ-G(~K9OStY0cuEkgLV)n9kv^XgP8`n|1Q2R!^?EAwC}U+)6$hj=zY$b{c|s6 ze*C>$cXM%KGs$Z_;3%3RPrE*TF>?CE`KZ3WRRvCdt+X?3u=}m`>~*8U)(#@m@?%QR zJ+I>ZIlUDHI+!8E!C<2^`6l4{Q~droWG!YExy=Q7oukqs9}9~+X0eyZfL~&xG{GRx z(LZ!OolE`)J}#LZZ1?xsB*(zLBAq7RbflWCURSU7fJ@?D{{ZJu8rT1_iXrpsr$;ZP z&EI#NAK;(t|BZ!qM^HYT}ook=lhIySHBq}5xq+1Z#3=?W>A zprxnb2UcrAbp8v-sOH~*|J34CV&){cA;W-1gC1h~Lz#ebL#%Lpju~;l04IX%?k#F; z1>M0=&A#4md+To(7E)uYARtqhH|@m$P?zPY^Ht=oW4nq|%qu%k^Fs?r$IDpFBi&vj zx{Ho{kmdHtmLu7%CWURE~4(AiKDaIrw)(7!P6SqRBNMPt;P(CXOUJ5KU;5PmQ|^KEWqL| z*NKhr!gXgq*SN&D4eG>gk#aBBr`gF}MfUT;{%o`ihI zsAyTwFw+d9*!av0t6yUoLDAj@e+;pE;Bu8|Y29)=qT1{Cd)wNXK-DXWzf9ah^@_(sUwghIdXIBU1f zM2mtg$FTZQa5<|k5ta(c>HGDT|6bYVzb~PX6?p2! zh#M;~e19pox&_A_Z+#XG(EN~>&&$%?_pNu$voXWk@+2;ntFk^>X}>6Vyc~Ove*X&12qUJnt{DD>TPyuzQoMGOI{39jhcOlO9tV+t+@O;H5+$-F}^5QIr^_2+#mT>l@?i%GN8++*6*w{GsM1c z2=6FH-hS0Hbb$DB8-H)?@~#Z;MPxM$t2G2YP=;+3Rw1xyDc^suWn5g)q)aP8ASKCW=bAbq#VL2R z>BLgkzD0)E$GHJ@9h)$iNI`OraDdrG9$J@a*nkq)|4@pv%ey)!#FI&@bQKw&wEnelJ!(jl9^blK@rhX)i!lQ{+q|qx0S1| z{0=tX$Il^~wCUz7Jx$47k8Y%4vuSgor-BcAPK1Y?S>k-(eOKqFe^XTMpC=eL3WU}s zv`p2d%$GH4OZ<={Sc~J?E6%OF_8#%x-|x(AZsV$gIH8qJrxi{B8?jaHs@(M zQVue%iHQ7ew<(nux}A?)0j~U$$)ucbQ#E_bX-tTTzY)SI({9KN%4nvmy!406C%dmS z2Ym$k|2hCN@9n=4LmAKu_tGh@(`i+=h?-mC=lA@3J2Z&_{9Db|`!=H>73|;46PHpT zByVLTq_{8Q*W1~c#}MZD=d?pip`_4diUd=aqu=7nwzEA|gBQa>h_2DShOR&z8$Uyr zwQ|u-mkNwsbf*>`<;GftmtHL7zuabkF;pKxx_o%}N8tB+LBJJbmO>Rko%r>Pcf9ZK z+u7dj;oIZMQ>%NFI#9h|W8pN6R?C&Hd6lnTvsuV#@;}Y+^Z|r_2dhYzf1+3E&952x zvkH+JpIs`=UI{ia@U*_U`=EDWUTOC4WrO|-gij0p$HkM-+jiAB9@KGLgV^Cs<{Z7lD)qiQ3kEbd5ELzm7A9g?xG@YF z%w`A!mk%*cghai*9=Rj3DI-%|VT(&tqcYwuJopC0#yQMEk#D!HEyR>rF>B^Lu&!D! zjrwm_(71-M#>~SCwgD}c$~mqYxNR@Ua4H;7q$aTqAO6CjL`pX|v++#^9Inrt-?;6M z8=$go-s-;csxH@z_*Zwno)$ejk9H@XnqKExspn)Y9%PvmvI+c~D_a`TrI&drGL%MJ z(}CQMjI$hKIpb4}8qFGRRq}N_!W<`-n*DR3xD`<}9w^99!tdwfFT0e5&)##;W9EQH zO1CCKt2-H%r zw9^w|DEG&*(P(Vkh*!4~N}msp;{-O`H*?pv*{+_53N^$lKV+#>&NMYY27aa+%o=Fv zoi2-%r0ZH9y?w7rN|I}D@H7A;Iod-@ThMX_gk9%XNX}Y(t3YpF#T=u^rAGQ?6F8+t zf>FZ0()m!pg^LISt1hd2eVw3uEtK2A=)nX~4^{w?=8eu=B|I4ChFghaIL63_*+v^> zWB2GdSgP31n`DFBLUyXrs9S(<8xzL-pUhQ8(w#q(v8WXR$@11#^Y=Uvv;L1U89R?> z8A=D^j0{zQ8@_=|>5FT@R4&CxDII^`dix$Hd6F5wRuYhrg@m%>+FUwEUe3MRHEMV& zi{#7_^n|aXzQR+%QA+&ziYc-P@Z5AkArI?x=iq!5-g< zj+208#R*{Q^BTnBx!Oh7AeGlHHh8l?5~_7P@Dx9+KYmD|+qvZg>TY6n0xrQ&12EQ#qtN-rq2pwbozyU;f6;lcS>_IzB%B z!K3kL$5G2VDXA9IEyCW0A70f+zQSB;&|jLHH7fV&rT-U=*w4K-x18*3zpj%jECrgH zOm$=XX#`b2-zbQ1Wow5!YGJzlj; zLLw{c%nGlW^FpH)jHWT>b~V7X&M{b%QJ|&jxFbB0RbAMErKZdCk_!Sz2@ezqA>m*U z%yN77#$k3GCoaMHrdDmr-8+KKJZ?-z#_{x9Gv=Q-9vxrGU0!iht^9$TlLFX&;#HYU zy%fIgjf?74nC<>7o%WXJ&860Jo~w&-veY_z(F@GHuFcj~La8tm3{8j~+so}qI&(+U z6!ob}Z9o%OfM%BGI{w@jPF}zFF#mkwdLs=2g(>VNRXQvfc#hD^b_TPC4!puy=HdV| zM}S4eFYD-m=4`I&*Rg6ZG6$Q==~{3P8t*U&3ZMc5HQW7c=h*ijxi)B-*@(4QE zjJfc2Z^LB#`nmu0e|YA>!+U@E_~iKe4o62@4lIpgyrd~D9x+m9F;dfA+L%f8KIwdp z)G`F^H2!Vltg9${hZ@>u_1ThGQ&+on&-#bh9?l~hL44LluNgukf zU19r(+9tDU|M@NmFl!arT>ucy(_dBr44Z%K>L{Gzd@-y~6coZ}W-s^k^1H6u+gC65 zF5P>WkMU@YlYj2Td5=xF^bl|3)e#}EJSJ*iap;%n*Z=;VOJ^bSR(c#?(vj%VK zVlzo2WQqaIjz-DRXo5Sb_V#o1GKj5I6xSOwTiXXJ?-^?q?VYcR5on)}g=*90`SslO zu=yeY)4ahJVk)hOCLjVN;q5)#{Ob2^Js$>UP!WK89Rje$A`la7G?|OBn8A0y_@UFo zgBM4qqbOBZahYr6m3aQCK(?Lem1uut}@)CGEM}Y_LgrafONasad})U>W?W2 zAIn3FmUQ$uKc{+wSU%?+TwcR(c)U zObIl$0W`~P>VHn4^Vl$%H?q@Dp2g!2j%Sl7pLfPo=4UlZNy(NRPP1H}=*)>$%lnrc z|Ev8$wGdz#RL%n!bfmxWmH-Jg2BWBZ1zQ?y54ONbHhtqWUpPFv`^K~p&o|T7RVLF6 zn_~R`b$0R%~41&|;t(mc!~B+{fsiiafx zf>g*325IXcXesER9ik&_NmR&=u)}6pVNw(iixf%0#0?O;i(TyQ?Cj3YeRX$r9eIA= zd;TLct1`1Pv$DFYXBt#*)OJ@*-TCG3`@P?L@Am*dii~^thI?(`(%Fc*w^+3qq99zB z0ICsoD|(p90R|NSlh-}sxR^Ld^8YsSI-kc^s1ea>FmX&vEa!c(FJl(lDU#F6QUf=HE)W%VoRv;a(*so z#7OFx(1L%Tva2Koj#&Kebi433hdWoEefie-=C+Udly#BC6zgPy47f}$*RPMquU(j2 z9tEv8j9MSU?h+Km$E!qhDQ1}Rkh2J2umr%Awtba`(Utj`%LZO7N0)8t~Pq=NLz&`75q*-IJ>O>h$@mk)Bs?l zoY~AqK2&Fh8hHTI;;^m2f+|BUTFhj!wyW`N5)TUm0W2U=YU9`uId{>$5orlC$EjGA zec)OR4m6Yb?tl8p!^bvy-#OgczRwLk#|Xz}+>+N}vL)-1+i@`0;yl-&R>&63S`JE> zO!j(l-m{dqG|U)Qv9%#n!%}1>kkWCr6~mYckI($g$r#$Ch)+SG*X_gh*p03aC&mxU z{9?)k-=J^_3zsS5Ie&3$_@!sBytF+u&qwGEpt?ytNU>H2h4H+51(Bl z*!K>5Vfdq-J9!|~p(RO4JY{%Eo?Yg>aqB>(c)OH=O;d0wfJqTVq!7o=flW3Ogn3|D zDEt<{289Y_PQ=AFY;3G=h<|-Bxc2<3+o9`g%vbo9Wt57S0C@-fY*?i?cf!fm2yghh z^}0c4!my>PsW9)`y9bfC$;pcvCRM{LWeNRszF{)+SZR=z%4V3RyqZ8dQa#J-zwfO_ z9yxrdwO$f7m4VEG$S@t)aOpq$pZ{TJd$9G^o#F5YH%EiJJdTtk&UeMBpwlwAxvE?$ z4}q#equP+DBB&v%6?1EEE1Y1>j($x|Rhly{=p7;g8x}U4z8r1!g3-ClH?F*JZjjhH zWV1=d>Rvw+B4q{NtS+N7G+h8l5Ncr|@6735uivAGZA6ENwGx&Zwn7a7Mix(#to$|! zjk=<1L1Py}a3jf{D$`q>qz9FPb@=Gv{-qny)$5zVPKo$i?9M(A6DJQUlOf-@Zvm;l z?hePNeH|*3&R$Ne9TPcoaXK;+Qpr50of{ILWi3V8EqPTr7w+VB;{uy0-X>WS?<&Sp zGpaTpDdobfyug}NE;G=wZS?wGo?N)GdEhG@)jH`9bE3%6W_LdhZ_%ca9H@rwlQsy>^+}7fL5m&*!d7 z_pBM9RD(^Cx#T7Q)aWXCx6E?ZQU@$^fU=81JT6OxGsAXlbUPh}>rH~~9iN%YSd2z> zpHfg1cuS~x4y=YlH~7pKuAdu>{EyN%&DX5IOf|7ij1bL0{FITG6xQ1e*SxZ-n#C&Pwn{r zH~H@5aKu_k)&oZJS_)-o=$t4cHNCl+8k2djDTGCZ&}R{_pa?7|%OIf!RLYY`<(FjI zfTW0#f=pb`Pe#ypI_S5%(bntNwr;(4c~k(GIse`g7891Rn5sF=)8~8rwO59Nk$cuR zt#hn;u2{}&iekq17sZTVDM&2Z_^UT*X{fy{S6sJ8z-Y|I(giQcoF<0Fu6^bh-Sxmd z>n95WaJ#@{%EG4G9y%R3kQsgJp?h{lzl7^4)}AC>fVx8SH!kvp@5{dL&=l_S`J{OHiINJ|4z9lkR@U# zX^Je1GEGhRPZkE004n~TY0IC;=OhAx|(H%%s!r(DlH z;&Vu|MB}_ERlbvU!2v8xHLTomiuy|iY^qoc=0c%jF=%}V1X%7u?arcCS&3OY^Q*wi@@`Ey^sxOw54es&c0z8=!rNGvBYXP;S4 zLdn#0Jb%pU0j4q)C8!uplD}_N>)P_+(IUX0n#@Gab7xbgQyR}u5~+<=bojxO>fU2V zIvY6Pjgto|h5gaL|5NQ7-st^1JA-c@dE>i04lT-6#U%ePVaBwimQ~j~RGk2&(wEPV zU8#PiV&QKtVUY_0o8?F5%*+Xiy=Ht5n-orL9FO@4!*h|qPCQVmY zRrqErO^b7xbMb$q4KbYX-XE2saoIAF>eMRoEM~q6Fl!}IyiE#)f;In%H@LXD zIXHKD7!0Q-;bkLE{E{$flDRFd@XZRpRaK=_1~#u<-VTl&bG*CnUVEt5p+}+J#LcQ; z(5TN>xrfu^%fSKBn&7_**ZH>d3TuoFnad)Y;CD`LytOl5PfttTH|>p5#!Jk_Ag3gR!fCi5LX@O?_Rwg^Rir36rN|60~6P*y;OIX{;C2_+yQw3UON)iG8e zel+$Xo(*d&`o)y__ZBZvCPb>5zg+eu&1pYp-xzM6zaD&H9JF2(YaK#XA>+qDNt5fW z?Y`oe$^y+p7SER5dw8^qP_AxhoX~>%#TF12YjwD1j=tx~!*5;d*=s0IWoLn=%4=rd z*vuUVne}ges6&R|AAKz7+uF zpd$14E2gjKR$g|@2@5PDtaW-~xq9MW*&GGKNtkINSY)kPCiE^6drQ8+x!W0ldHvN} z<1c*a`q#I2=!+qGw?wr#83~c&MwLLi5MXBK$;^q5%IA~sS=`+tz%0^hQlMeV%wkEz zBaUw;D2NzxRN!p%!(%6pI!7$4k>PlqsnuUTP3Gh?Z$04-Cm)>*c0Ru4jn=djn*V9n z$?0WpTKHU4^Ak`w@@!b`I@!E>kCi(me*rMz7urs z@k3T|;$$70v2YtKI`1gROxEQ{=mzf!eE)4D4qBW8)+I&0rlC-Yp4)8hUa`!-e3{I< z>|tJi*@bvr+1{6W_!>dWa@|BV}5U zZ7Va3TGu@3zG0{r3ON~pD_xl}$Os6+RFim>dQr7j+-)**X`jU1WmZDAb)@VcS)g=4 z>#bnp!85J9Paf+XMtM(DS%>ytYE6c=gUQow=zd_ZGw5hG6uaZr7q#qd24^{RvF#rOz0%@aqE!}_MF6W-Rj<=4L=rV2GA&bsC1~Q-g@Bgvmj@#&%S=;+BN?xf$5xQ)eT_Tv$@#`gPB&(N)^O6`~GFoJC!*dec#y2 zasbod{(=}}K(G*6hr7{{Gso4*PTTHb-fyN=!DRN;XXZ|U44t($pL9p=J4eHDFEV<* zlcUT}bET|iaX2KqSz$$Es(lENvMmH60!s+pb_XrXj>4_+Xy@AIBnX0{NqF6ulPY6y zUBY6ToU&DHW*V{uei)p)GIo?kD!91AXW-w5pmbh6J) zOTVG{q?6RVH){UmRfg1aoO;g6!JyhRCR-O%*I>6~T$f`rlzl(8rHo|}r@C*m)`8{# z(>U_P?$+DBu$S^foIgM6UPC}EVu?)aW3oUKWJ0D0v*NrgL*2z0c<`7E0l?6Aztata zw~yR$D=nVRSM|y+VPR=n&~PE{PPnaAgvvZ*7G5wL)|OoFSS|FewvkCV*?RrT&hX}z zkNH%k&H%_F=er__l~M9PAU*#nCyV>45rxqNl#UAX3+9eMO6jrI*tXJ*wbvEAhS>?t&x zm%ZY3(p-CyYEinlsbqmhmeqG=&eqvMWQw#pwk}7Wc%b{x-KTrUDs-8m0KBiJR<|2u z2mn6#slWOClhNSuu{W{}F>=oDxpMs`2yi>}n)0`?$kA>uAem257dEiW_vFArTeXZH z`J-Hjrlff?!)PSdW|T72YjgkZqjdV@VfzTmUGq|1 z#zB3}%u3kI9bqz_>;IG&1yA@<$!}=k1k3DOMy6pnecP;JD~QC&gE*jmD_VQvf$sfhPIiwfMP)|g zbpr58+05+}e(Br(o1bW_uJeJ5m#*A94m?XkDE>_G_}ThVpsNyaS1O#>E*M(XGLuYo zdAi37U_qhNYD-I$AC7!qLTyl8d{@;BSqzs zrhBISX4_sn4V`4)DFZaTi_j=DinboGmtZd|(sq`63{?x-T-0g>L=mm^%-UNX=sohn zh4$;$H~p?KK&{bwC}Qh|3H z`s^CD3bC2QfkfMK&~JB4cylluymo0PoVXDdw-7ADVtB=0ij;}KS8n-}Etjr%rh7q4 zcL?QV+L&bTUc0xg?q$V>H+~EZ5aJtTaKxViwcX;#Wb~s{|2+bQO z%S^2fHj@c^)`M27^)p-B+v{Nzrt-_ooC-x_s+xSBtnSimwowypWqD#$^_278GsQ5B z;E;{AZjWgYjQy+I6BCC@yKNz;G6&xeNo%f#Ck(ZI_UkvcE?)Is3PSsJp0kOK%MH9IUC;gAQQ-CrGn6E*>r~k2rly-TlY#dqnyD9WS1CZ(fzcB0 zB~52rAgnoUY;^j@yRkFczHno#<36RT7J|A^DMYmwtTaFEmO78;I>U{T=*D)mwd3MB zKeAqB%h96L%v*+NcB#`*RuvlUwQ9Fu%dpIVx6;>u!cP@q*a5_LK;LM zA+(f*^^fol#(|-!N8hB&x+ws`5w(N%_>t zWf?+4X1OdN$&#snl&Q|g&t)<~TooPPC2Q^_vqb{|2}9|zb=MI(ao36NQB+TxEEeY} ze1p`<(DkPd-|vmaPwou1d!7k%NovVj%~5vrPJV(Sc4Ywd4a9D$EGIMOR7mVK9c5#! z)8m$bzjN;VV0h)4R{{`K)|yqF)*5;5-n|OF%d!~(z+tHM^XL5=H%IFENZJ=gbwen7 z_MS+lJNT3hXIOEycaY3i4(H;liW;lT`pX=s`IDchM1raJF)Fru%hKQUEIgVulV$)W z@#BFJ*z8*m-(}zb@ZFu$H6hc!wHoX@li40`e{(RNyk|TdIa*Av;gFKgF!u!)jfNVH z9{t8;H&P`gWcop0!LI&eB|J-mE#d;9#AkqN`1N%*1`f}jv4RcSG@PhVg0Q|1Q2 zz54Qn;pS#=&I>!|nEGQ-J9iS#TQSJ2Ab##k#Nr(-F5UnDAOJ~3K~!qmsy8Zi2dL!E z$=s-A9YFG(Mv07wfqql~Ra)QAd z*9W5;+di7L5R_SKR;8=&6q||Pe;7tDzdE?Qxq~kUx_ybMtw9#eI<=5zF6mA#<$B0& zCIyJ>4LzH#RoTU&o}ay5P?yuH&D4Ng#SOJKd)AxI*blt(EgScvy44^%KYL}Z2K&ln zE}h|bO$OtqMw4+bgia1&24LpIFFKeAvP3F;w~I7Of^%k_)ALHu?e)-t?RytCw?-Fk zO-y96LTz0OL0QT=8zwce*W6DwlLN}ne&w~zt2h0xhupcyYRwa?JzF2sP#{@5*%K>w zQ{7ss$xf9mN22`ireSnNex_0vsy!FdA&1!=xk5me+3ajs1hN1nfpuy_PCouX`yrIO z<`qLG8!Kux*e{SF02ug_4+UZHv>yg7gXKlK%7w7ov$;{-3ls)sioilt@fcKWnp6!GRII3z(&xyVU1Z)@<#VOW zc*gRG7#2MHuETu#{qH#brUlxJQz8KGn$7G>#qZny#z(EEe(1wb+_-u3ySFF9CtU6K z3~{pesQCAaN_i=}!z?T;sNYs^H;<~Xa+2KE*K2pNp*o&i-Ps(RyF3WSUWoFVnCx8Z z;+T`{$k_n%tpvAIU9Z}T6#zQ>#+G;LWY<4=ynA2Q#=|6j3(%Qv8Z}Md0>x1%%`-r| zfyI^dDM=OH=7C9a-ZNA_2f3gU8gr%I& z%IX0|_61>W%I@>=ZF8_j*l;}wHAnSX5=nS`%hi_o3od_ z7u7Adv>LzooR1P3nV*+FH3?uza)ze_Q3M=fy&WBT=Do+?-Lh4u04}?kI7zn~WXL|b z(Pzjr{=|QJqJwq_!}CIVnQDsL(mt^JRKe|f%}mR_Bx7d}twV232BY)WceEGk3Ko-s zND3@|CUnZOn5MIo zl)aWL)~FX@>J$cK-bY#tS`;`Z*UeoU>-IXu7M*n!zU8-5Gmn;cNk1W?f{T1u=boe&&SohZROz5`XL0H!{O%Zmq&WmX7_E1WG-=yiJ1GfqIR4#luppv45(-7KYpz+%e6CiChWTa(}YlXK5+ zkL8POtxW_@#u08Yz%0MZ$gb*FmS!)NKtYY3qkdG1BuABUJXJWgZjIT@QxCTvKYGaC zKzTZQ(Tt|XY-W`pLz?+yq|N)IFnZLJ$Py7INib#w*(54chWGe@@?j;vJeX6M^><8m;XaY$X7^d7#abNcY1_Bxht zoNU~sy)uybu}^)nHFPKUjNI|Pqv4P=bLvQynmVio$*{uGJ*tti==SL~86W5v%mh%R z(C>7y=5+Pw;*G)J()9@&X4Get!h$B#l*P#Ye!`^)z?=YlV{_tv<)!F_o5R+hY3gr_ zau_PRDbP0@xXiJaT)hhl@pGmIXqm-Haa~R#gG#D>6+EwG^ zsz8P&UD^nB^ky&c?;Ay~VPO^#aFPNb%*@pf&GyXB&Ou62a+VQm4HYax(33^2tbGzC=89R*)} z{>n?Y2K*U~{tm3RfJA2AM9Urj-56HwoxR9nbSeXdJw)JT%J8&HTpL*IIj0Y+29AKj)z^(n*>6lDFzq= z0>=dnsp(gmqWzB%P!_~#$>!F!Z1l<2GV;cgE4N1Bcsl096ttK!7PB97tq%g5nF8w{ zf9As33)kE~45ar4>@|T{Qst%6yz+qNMOc*h!>kNk_UUnRo!pq7Z>hnRBxC1U02T-v z5yg=@+^56$p6(vcfJ<46!J>5b{xBKUZ!2-b2RsuTc6AU^LeUv8*=#*E)}p`B0j1F( z?ZRiFcrmb`-|fK>@+TLs4~CbnPfQqbS?Ew;F+oF+IjAhADVx!kuMWKH+tC}YX?;CJ zcN3~TTV*9>O)ERuW%&=VCn0&+$H@|?odS#qm?5kU9FAH?da}OObGijBrpjlgad-Bf zK<1&3y<2T5x94sRognZH3kL)WAry&_5s;>-^xwdnVUK_!b8ajLKtZ0fm6*SGT-{4( zlZ|exWt3q*8oIs-B8~ElQdO8#=G}Xc>tdE=GYr6d?yJ|{c>VJ5_kC@B4Njk+RL;ms z(mBzzf|Gq!>}6H$4rT0RDcxIy#x@5t5x~Eks`^0#bNJmxPt#E$JoP948fPT9R zD}*+85mzvnGHcDc7J^mJwZ7f7FjpUR{=)X;`lfeLtM(0PuR$zl)(SAE z7SM7h?Y@Ub#k!aMVK3#nl%%Ig948w#^Qv$~jKr}Z+{ng^N1pd?f@0JIj{)2g%0R&Oj$FF9c|ACY8t z;Ibc~k?a+i_RL1i~DNWV?NdlN=*wY>>giU}35XadH-vGE0Q#iQh5?c~W7K zDa);@rjsFaccZDQFXeC!M?6s{1gJwx;v5 zr@p^3x53IDj`LpF%WVsdavSw*`KJ~uZ$;OesSwd+e7(N zan>2i$*`E>ZX`?UF8P;jv?Q{$8;Rl> zR#(cV1k+0QS7~y5SH1<)oYa?H?1{ApETz!5+gL|SW7BtoZ8s2>xf7}+R4V(uh{061 z_a3}U+1Hn=1dcT8n_I!qi|i{#I@@Bk43w1z`W&f|=8Gcrl@TnFsmw2MX}Y@=z-cM% zrJw<1Ytdx>u9CFIO@T%mur}aGgCi}hBM38-ZIP`M6@euSFskOb?LCFPy?K*{gB|fq zWFVxKkfs=50uuNT38p|JFv*3J%Yv?TnE}m`uuWFGCNJik6>d!ToDuX_1?hTUTO?B_F0K>VdDkz@zu?6-cpeYzV|42!TWq2`Pe7M3z#@wk_q@wq@Iv(`h@>a%|OUx2%4zV*tRh zEorrE>9kslnSX{m+!_oR1oS&`8GpCaCNBtN;(OBXbgA2F&-R2Gu}lPToE8Cq){)ee z;LyO7LKj;L0FOgsFNf$%fmkA@L$TpL0e-dA`GPd}G1K@7k~ zz>y#hl?+UzVYH6*naBuptQ}HAwo)59?FwXk*6@5!pqRz7HG?9MgfIw6QS4+wHdBYPG^vs~xpkEp1sA zTei)%WwTN-7LjEu+WAVvtmhZ95Q1 zq;;4CkF|$|4JTU?kv7_lT`!EHh{7PSgD_B|ouSoQ@2pMGa{_zFWPG8>Cm@>5BBH`D zxF(^rRLJ915tn3H3yO|Z4Fz3kv{L6;66ON(X}TkUa>EeKK*S;uLn0QASU40h5sQfo znaHrw3}YBQO|nx&<6SBp3ueKlE^HiynA47Z_{7meYvG~J#0_A;cDqf8 zv^HTFfGAQ*MMPFa$_kaTLS@;3vaFDl9V*L?L@6C8ONUAsMV5)TA;ob3MMAqY4igXz ziz|RwMBNzNMTwBsh69VpvMlK~Xb} zyt<>`=HiyUu5GlUK1h6k(oZeZML`J^O2Z{a4K^>CV-;CCv}l}9KFpc1qNb~ha+9Zu zdQ5D&2^b@ySww5*AY$Jl?WlMiShqGd|{Az&~G>|0l4?d5B|cAwVKr6Cjr00|Ui z`AlO5hG>=RPUE@j20b59EA~wq0gZo814He2z(tzfr-M< z=qNHqYi4F6GDVqP7jo_jWZHHM2#tUtL}cQWwS*7}L?k3qUdm_)6oMoIXc{sBP>IHn zYp5rpZ_FfX&5D!R(T_1eVsXIY4kYNoa}`YBl1K=Ukg%u%>6FE3dyS zi>C_P!_v1tf1c&W{z>`!psIhTga`{1m@MkRf(-?eEH&)9e1EBfOx09KFdMN;Q+7a& zp1aEXhH_At-N>?3D6NbU0UI!D5fh2%fLZ&7BU^K*G>4)>LaZMJpqQj4-hX(%Ss8 zY^Cfg$XxuD-x24-Zx&4=U>JyKB8mhE0rCLx0gBm7{CAj$zZ$c`p49`2$el|oEff=z zr7i>#2TJ!L{yIXx3lkA!j+V+2Qj*ZTZjc>oirVVez4JoZ&Eu%@xK%wDm58lLGvq9< zpa5y*3J4N5Rzj?3L7dcNok=DWf%4n4q&){RwB+|z5lbaE&wY);=|vz$L?VW zgODdlY8y%-2pJM#C}J=aR3@N2xRs}Sj?1PKG!qu1xC5ovfoKh^Td^!LYwarC6iG^V z@tNZZ&17XFL2*Vj(fnB?m1n->UIP_-YSqW563`H$xqp)>2ujV#ocSD5L29PaWXu|3 z=8*KsRZ@%vs;}(ANnT2TiVAsc5zI2c#jH~v2+NMpG~dI7GC!iZCyKv^*le3gV1&gm z!?0nK0*Q$rtVLL-ze!+3r04*!t4{u1gG{f}h3^EcBg3%CAYubcg~SM;;KPU~3O z%+E1|W(S+f?o0DWD36R%L7QYY+%MMEoUo3} z3}}pw@5~yIGGFMjSzWR(AY(f=I$~r@p}-g;LYg2U6ao-@0bB@NKs3bxURkszjm_|(;6cO%$W64FGB!h?H~~;( z|GUlO#6^0vdpTy6jHpn7r^JG7I4ehL9@q>m1-V-%sbu0AvZH>~gk}jn$}L zCTgCI&T&0qX^`Wk>bEYEOQ=$2lbsfo%c8=WbA_}0$B@$Nz z37Zigj6mXw;5Nm@c~)98lR2)H=PRuS50+L{s3Hp>C7Ru=)GJdcMFe6Smgzx-Yv8B{ zW1Qq39J^simi9}d&Mle?F{*ds6mS+1^}6r7k@J3O7H2*)qZDEE#ZOf}o7Osa`TkG- zZ}{`CzERENGR-^j$(La-Nw`Eg)>!i`P}4Oe33f?21*hy$sz0*XwL_F$JyJvOEu<9> z6^eKaFE9*_yOkg@lZkt-bp+ONsFVo61kn;_l!~*unrJht2N?iRE{n77ux1t!HXthy zf)8e&6io=2FpLW(mq_`5Bq&KHshd%WGvI9d7O6z;rNf|I*11aQ5-9w8G0Mqox?30>;)NXw^r5I^c$jfsH zl(;1;2@|UsPQviP%+tYlvnHH^W<@6H+^1P8cRKqw`yM#M?qv51hng#0g_hWOLMY0o zcc-j&YGy`K58jv+oaOE`6MO}d2)?lvqlF_44t1=>=m>GB6agITF~Sib*-&ZGV8Deb z?Y-D<3IN=E_AGZ`i>1Mcj3%ukFo%$&@>j$K%Ouuk!~;tJmN4<0F#_SFflU_M+%4(W zxfg(`d=4pP(^7*5N(h#2fx5wpPcp}H1|4Fk-Oq23obdZ;l!sP^TDU{1Hoxrki0Yl zij&Mz7Qh(It816>2TnelWGj*J0F6H6e9JP~n0GzKt%U_!#4 z!14iv0*L@};xT|=6xzlsbs1T}@mCQ|$ua;ZSqI~s7%9oN8mFzhpr`}K?%}CN@5VbG zJB2qta18gIK7`Z9*09!Vqt|g@7ziSRi5KDemW!*mMmT$66ED4X6Q6(nA~pwZVK=3k zx5*i;fl3*}BJD=X($wX&s?pxCXzo@PRB}v47!Z@~+nj+I6;jYCun-q$=5E%}3at|* zyHU}!vu4&~lO``rbyO!sz$~<-rjE6oDlyD3vtH{&=#9nSDZsFf84RacrKm!aDFRHH zHnaM02>`;uSe(Oc)U>3am#wLFIPhPJ!&Y)KCg0f< zX!79FI7_yhYTw#>H-El33qpBKZoXe2Q?$slB!j4AoO&86X@+PcNxB-6rmZ6l*5NEv z;t0Z_%s{5h#@G<2_}&dfhOSqfG3~{7!y$#gVdM=696tqIuL3D z37Y|!ge)PcWixdWZF8_$eo{`|zhy6Kkyd(`v3Z;_$UAJkD#?dx}(ime>4RfF0z{2M;nbXFviTY7?GI8aFnNJ zq>|LMKw#yodMRNyT+iZ~0gdcs+gbu(k`hYF0F9JO9W%uztxi%&GKmrv6K9kXb4?>0 zX_zph$LLx5S~wEn2qIw#iz$xQDTYc_;;*cf$pFChFTNy4KkzuW?G}3`)F2g+=722A z6T(DTCLkFBm=MtfpdN$*5L$8FOk4|2LJbLtRO=D6I^m|7X;wm96CnAK_k0weeC9{c za-1oMWW$oOOB@byBe2Qd)^h(KVaNagAOJ~3K~xle;m5xnAAHxt`2J7)a||azyg;eK z#WD*vl(MiQtKnT%T`wW7i@~4&#p@Zcjji*|^rDmN@$cbioUr*>#ts0ZKwQ5>AhKdW zQQ1}rYo?4-c|%z9S}fUja4FlkazKM(np|>L6f%|bldcL8;W$)ETzn&wFqlY87^kg8 zhhP&XnWYf(EGAlzU1}66EdlL~H+tImz+}{K8V^Na)4>$$!rE7QGJqm#m(0u4WCD{j6|Rm@QWY&34HH6zAYDeWPdlg z^gibb)f=}{2(uD89gWW6}NyCKyAak(h7@ z;Sqpwa+zd)y8t}o$M00Jn^GoYtxyXE0P5X+LbMo*3P4#CD0*xSyl1mu>4ubgaz=t0M2*Utj z;K$*Tm|4z#u3~n^+Gq+u8TM8QGP37AcU1sWjABdE)KaYaEvH`S+s0BrB2-$fZoFkz%|`T77CuWjMx_86WY!m( zmps-{rb9z=Q?v7IFnu5kO*2Zd4#Tkq6Nw2zXy1qN0~p^2haODmfujI09z?qk@iO4z zWxyt7E_K?>{#X1K1QG#2ExTnb-_@)TiAV@0ACL(FV-StOGEVAe`VjQN(n&%k8<6bR`V(9DqyJsFn-{jAHw&&^Fz}(e-TsBhVi*)-@qS#?iIXn_6jDG z3Bo7>v%pdU$5Oce?qm3-rys<}zU>{j|L)^(Y#U0c9I%vKS4!bO|Gp34w|?)lc=6n| z_+%3cP%19|BP$_|>H1KabnpBpUA~WO**IgywgfUa94)Ohl(bG}`W96@-$SWswq**S z`|M7%Z{U(!hiQmw#gl}jSmA-h!Xfz`tK&j!7!n!9kv1G^;wa*{$~TNt*E&p6)&ax> z!X_xmC`A=oj9`g&f>kq_+@5H6+pxMVir6TC6cJev*c3CC76=XqZ2;}~I zw!h?MV4CV1s|t@6co@+F2J_JIGx*i-`B~Vi*;je)(kA}#zxWgU)*pTa&%b;Tn_B~n zCoVkChv$26T^Hl=1edPfz?Ysqi{Jjk&trQq!sCzJgLccA1FKE${XPT7lJ2$g)~ zXM1Itj5H0E_6uYX+}uI$*am4OmM9`via?|YVnLCeWRzNc##djufbnPojw`v7^lXx% z&4`}D8bJ`?t1q0xr@!z5KKR}zvDWX-flFB!b@JFD{O%ur9)q26?sH8&N2r+U&xpV! zRl?;Uvx@Zg3}h$=D4YkKDeIYqMMN|edt<>@W&XBmKxTR0BDsy=Qb?6%Sj@EDGDrP{ z4JYmlaTdu0TC^XE_Chg1z&h|@e4ixrVvx}u#JIvb3od@cP|0A)#+_AyOb!gz?m7;m zM6qH@T19OTSwz%|gzPK2^@Ufj;h+5GzsI=?*TFiB`_WQh5k0-c*_Euo8Sm(uTLXOh^IyY9zV)5xb=#G~ zaQb(r?cmkdFX5{%zLvMc%=#v!K$8U(DrTH&fMI39N0!YLnzk?-Ba;EBNj^$avSb&^vX6v@s;MihE%R7Km&jvH`@PLKy*= z(kv6%F;`s7X7*)stp%8waPz6}`57GUtuI`t6EDO+`d|JCFTZvp&Ip5@G2Z{4Ct+o3Xv%&Q5pLev#(((SbI?X7Cu*5cI#t#4Cu3>Yv=4=OMO#YA zn61ft28lpP%6i6NW*}2!G?bs-SkuQ2>ulNsx^KWfEGCWmO9cAIUo z4aKvvBd`RSuIwRLMi2}k7(pV?x2^1Tl} ziTjV9p3Cr*Wqtn7-~S3;e)STJPFqAmz=UxPRMKS+(X&t~-&&pfV88tbpTW8FS8|oH z>EGGk#u(gp_X+g7HjsAmr{P%2qLR#wNI?sk>K?M2HMQi~mNlhH3k4G*t7aeqWhb>T zncpe_m?XkRwkC*BVs+VUER__FW7$2*|82LVPm&s;`RZxss-)!wSK-%B*TBhY*E*{4s7MEoHOvbzHg$ z@nDP#kug|CfDFOd0m~2~BM4jwdB?~Os%kd-Y z=y#l1SXKZUaNTQjVOsreFKBQ*y_%FrQAW(21Cp2Vrf5Lj#ThCQe^RAvlU8t?(720gfwu^8i!T zuVhf(K2T@xux}~s(scIbbLVjK-H&l7WDHS=h%K^J0K*;>O#m6e;vR(h5cDAEg3*RT z3qlSAc7|AF!={)(F0^l~nL{kH>m9glJ9yuNPu9lbX%^^DKmRf|w+6|{op#elv+yVv zB4o6XtXNsdjC}cP=cX+PY3e$y7S5*8`@Igj9V-dRW-_)Uk*J6Uu>w?Vm=$*>r{RT4 zcTMba!Y$gZILqY)8WS%p)CouqTxMcX+6E!HY&AqB_Ok;zx2}|!{7SB4^*}~q@U>*e(m@0uYTvt zbH||HZQ;AW{R#ZlZ+-+%KXMw!4)_;rbNHvPv_0*&o-B@N>WZMNGV?047q%=FNlK{ik|(=9^C8U5_0_uWik(tLe#W zE9!S0I(2MKJ^9F8&Ubw9seTwebL@q$zdHDx-}|FCUV8cEVH`5eOsV2&1i7B1;`OrH z80?nC+zyZt0OT0rP{C-;5r}MY$S1=tphh6>2&f0*E?9K|bOE%XkYt*~n$GB;=@whv zrJZHqRBi6PlyZ|&<>c9(yz8L_^fvyva$|ri*EbW^l1)`-1>Vepqb#_nOd3|@Qp=hJ z|L8aVHCnb+NCD?PVZ$iG<*PT7vnlD&W|O#UD9|)iQeZaFT2}&0`n%h<^5QIjANa`A z_~oB|21gEcb0@bkjP0EXc1CU{4V?z+RN8S}c^$Kk>&$2ZoV&D*^H&CV;^7me4W!xI z-u~ueAf!f&1=dn*7NvQhdGx+RXgO*jz=#N*JGYIA8s=U;AhO;$MB~`t_>@!UnThN@W0JP;E@bdjSD^ zKfxuvGI-&FwC_J|=t$d0#1V)Bv6N3F69GB`bV2AsNe_%30UZD>C^%rUp{9N_lxel4 zyiPK|BT)@mZC+TFts;#d_1LNVYvc0tggkrx2K>O!WRP?rOp;7kq%t~#%IFSB6JVio z?6?2uxqQ)@=y)Baz>%yGqfO=n5(seuE>VD`f+t`?yHSKrs(Bc_4j-uXS~GDU)jOg3tM>nq2ra-80mXj>pHmS zL=P9PkINFG$b0hSvuvG~!h@s3U&H9!0O^*Jz}J$Kd}NhRMEOL>;!LHwsRU@6w!W?5QhMYp+lKLt zF%C2oLMZaYuoHXAs1AU9xD;Pn0BlH_KA5%~fC!YSV~t~}%nq?D1FOpaKcI4qn=@-ea<+~IF*_%OW(CQN zH?9bzgvk_vCS@|~JqJ4@4}bsXK7t?o=+jehDQ09u1cRLkd@sni1SB9+2QFp5%f_R) zeuVQ^2G|+0&r{jXRIsMaHlp%^J#tVksX`6A*Wx)D9W$04ffb2%Q9EVgY#8WRs|t z8To{gYm)4^)C5nO&9R>yz?qxJ>Gh+HY9zLI#$X-g8~w6*j9fuk0x-%+z{W1HnZkgw z42vN$i8UpGM9=gF$^JowlPWL5ngvWIy?$i9h5Jvhp17 zTL!bGz+}pP=Kv;K`HQSi4CCyDO}u`2fT!McqBPr={rlaIpTfWS^x4cwFEh=HGTu8` zcRc~l9PQxbkxru%|0^%wfa`g4rvXvH+Xo8od-CMI0nAkYvMlu@Km5brF&U4yKmF-X zzm!i~)@m*3eN0XL0S*F_nXwrICT)z^iV&FyihPJT5RA!io0RH6Ne6-s7#)D(kV#+z zVx{>_iS-$dBYRNUyryM_Y#04wvdn-aFA(;e7FxEGJBU?)HJ*6W3SP-|5@(05t4tYu zoUSFyiHo0A>Wz}A0m&kWaFPaB)5_iSJS0xLT{sg4s7!@#J_92aAXEH&?|$lDJooY? z{Ok{Z0LGZP1)V*qnHj_31SSe+UvOpuV%b!Js=rZekj$K@7q1QQ>V-`_`S9`5I;HI2 zk3Db{EyW16nWcv*5yMjxtm(Oz*6RRozW2~nCt1|e@!97tWvoJxf1T+*Y2m@U*6^d> z@uqzRnDn}3S=NvJ*pGeBtFONLPp@9R>LTxGW?^QOtjbe!VC-@Rw7L!8GX0sHy($)i zF$oPK))bi#+W0Wyf_Vg%9T?dG%K$6`2oJ$B28#)vBqZ$X_O|moSWUd`GdaTxCk(t%S|k3BcGO&XnQAp;U5R z*&wSms~wp>CccnzW{gPXdwXVuYiS*ZOzUg3*139{?DfNIZTzhtcpuif&UElv@qX#= z@x;e)G|m(o{{QX0Ypf;Lbtd+$z3ZHF&wcfa-OX+`o9qWEi!D;LXh|H?93k=}HZ%i| zH4_AwO#H)00_TT~2vG=apRj1CYyG1prTR`=B-L6yToT{(Z`qogxW2;{aF!AryNEA*US@O-0S!K0l-5M~!jCMoe(SwU))3C5?b_RIs zgKIV04*f}P`*Tg;zx&P4<|*E^0K?4K*zEGv>uctt8>?o!)8%P_soicb{_gMo?$Uz`Ik>-No3~njA^$NA3gkldj1!mS$yoovBgPI&dHM}pZuj?`lVwp zzWCz%fUn@XwNU|@c&&QN&@BAS$42~y+w{h5Zalglrjs!=87Rs~QC~qshh%?V*D-skG}V0?BA9i7cKjOs@6$VuJ+_E z#bj?z0EaA5mG&bv&bjTAcLOPGz(~ARYhG!J8~vhoeLw5N!Z~n^OP8klz5?mH*}?ky zhKm}iLzp!nGY)7V){RF*gsp@~P!z6SU&WbAxA4?s2gU*n0DS3lNAQ1s^W{94mmI`7 zcbs(g+3xf>dT<_lmYP#U8G`S>dC9e;fXfY^6yAq%VBZpc`HM%P6-`Wim>C;eJ^9yv z{@uZc=PqY9?Hbs=5z{wf`x)#YJAdZK_Waoow*K+g{`0+G`rqjaz-chMHMwg@u zieW!hj##N6bA#fDyWUV<5DENvUaCe}CLsnG*OZ4ml9>cB;km6&53jv_9zT5Z3@&}N zg3aw7j4i&GUO&U->uX-4n#vK}2#^`M=C(kU&*48ye;~MUbq#B`yF>jt)!*yrp*>id z)7a|tOT9@Vl3&6CIjt4pG&qgY;OPQ|Tk zZujL6{>``gH*eguVh0S{XE8kv_hBY5>G^0?kb&^+{s%tfx>nS+hWIhj!@QuRALf9VGPpT9Yc)33aXTPqt#GZRHCs;meV zMKOW=6xLINjQc8mw{)rW>@?1T|LECEH*x;TD)u~aq!wV}-|e%<_v7U^&UxU|-qyB& zZYY;-&dUrw&6Yng}q)Sp2WwIGx?Rag)XN z89BHN7>(O!hsg$B$`?X*D!k_->pRQtfFtRR^ zNum?O%$hDKeEdss)?MDPGB8#K#vru@A}JU>F}w}Sn~ntL4X~_vGWfO|q?E3k=tfE+ z1_B0)3^S`Cn3z^6zOW8003zC?jILMJhxm~O$WU=mRT}ZAGDWN^05ifziKzU40)ZTc z2O}c5Ob~~j94bXJqt=)RK6mjt{`YVEC;a7qIE^b;uVXOiK{(AvWAgjKX(Jz{C^sb5 z61*cg8L;)+NlPSZOaNcIwT`owSE9a}(V9EYoH`l}ji!b4M!rqQr|n&8;;1Km$DO#= zGG2cDoF}Ctk~heC_$uS^BfIh7zQw7kL+_ot&OdtVjBx;aJM9ANFb^dGzI1__ty~}LUKW!J}`zto#Ah3*brUvz9fJ+nO;Mr zR@bNc8x_FvxyKLV$;S>4r%AOsC{+>e%B}w#o$dhN{oz^M-t3jTW@BK2%1`EM#8Q1c zNHcuvJ3qwVz4#;ad)?tCyCDEnE~+8|Ni-$xoAJht0hH4v-xXg1X$BPMuC(bO!-bDl zv9jL51A7+6ih4csxnq9B0xl!qFoWqh9$^Jigky)7ur%M8NcwJUb@AT0k36VU=F&(5 zN}v?s)X76g5_EV&fHU?0!vN>AFKcV7{q^>-SMn`M zLQpixt)jHf0~v9tLRKAQ9NXhkNkN=FtM=~|oHH3`FWtiVtExqhIM_*ldPGB7uv;MhZZr|NI%_EUN5 z-7{H;UR-)K5bp+A0E`5qa5s}=jIkRV8@>Je_b-gwev%}~XFvPd2j6<@trWuplYx`5 z{&C{(>pQ75{WQ|0;j??a$FOWLFb0Dxg_QvecVT2(SZ>3Fl!@11WgX17A-n~aZHV-o z$dzP1R^>5g_QVXXh-G|rCh!O#XlX#(xv4mW(Gd;uVMvM_^1^$L*w(n2oN;M}#AI`& z+cX~VivQ2JwLchOV`H;8>DiVvaYTy7!+d<9rkPYgV;k^>AD69CszO^~oZ`mnrcaq< zB*28_bB{k<>@UYnlWzYP+8U1>S{@m_#Jwvozj1EpJ8(m_MW_BkyNSaGcaPmxSbluw ziZy9B@GmT!GB{)5Ou#v~*l1ua10)lXwA<~b(=_cp^2j6mqw3OJlsYvF9&{*Ws-{l& zU!M%>=ja8!Ohl0(tq5e5r$;m_9LZp#)QLh@nrBXh6m)4I1o`EYFxpn7x?A}WZsata zr&tOJx1i1Z-Si_?`b98N5^`Km&NOKoSC#I@%v;q}mxg;b!n{*x^S2d&EuSKREAq@` zUnCHfBAHPUP4PMpM+cxtic$a)7{j=HZ5_APw{c+a;>hMX5y2Nf{}{gg;_K1p2xPei z#A5&MHjW%vp2)|nY;^G9g=@p=fd4Uz#!Kl7Q-w0G^=)tKfzcJJQ3>@gseu3J8W3AY0eGO7PNgYuZcR0MGHQ;%Z8 z4h{@MD-t40iZWN@lpdPU;)Wy}&XLl$!wMQ8(GVoiQ2v&Fh8>cS;hW63nKvr0G|4}N1+v9SsW;as7T!X zlMnAjyOm7*O<#KTOwo85BA0x=L*-w~o?Y|MT1`dz9@@WK{mS!CH%!{s5W`>=f_oD` zJYp3gBO;>|Wkh6%$bA0upWk=r(4pPayvO3=;(`Yl_P1FS#SHxY05GAPZ6aRA-mj5N zJqf(tbEMM4yDc)SpeRGe?#L7*&`Jx5CZ{puy4EafC{=VQD(~p2B9Nt_P+>xOJ068{ z2b~gy#5SSQMITMx?LzgGbHxpER^Y0OZt|3!P1$8JsL_R#uqH*T-3KWt<`>)((J+8U zV-utj2&qCYQzauoX5@1vprK0TuV{3G;@CN=Gls06j#0zSHfOen9Gm*Nu10xPd(mv z=BdXUcRH^$&2x=LBY;Q4gGaMwjYkhu)HgHiF*72f`DsQn^=Z@P4VD9oh6F%E5!^6k z$N>|9(j=T9@o5xTc^g6US&f3%I2w~WO-P>#E`b0jX&|xlplktFHK&dw>biqz1i;J| z1x+8_#FZJLqMAjda!E@U%J5VJc|{~6qocE$lDc!QOrmDPq&8g|cUzWvkn-$s z;L^3*xV5&8gZsw!xP1PJV>ol+qd-OH-cL*OO&mSEXDq+~z|GYyoWFe2aWUXZg|F}j z)1;);XxvkfxZCHn)=2~$Nt8M@Dtt^l+f<#*zHcL$ae%|Pxea+>foQ2^Ffa-Y)%WAE zn*fw(N{9jhMcM<6>!uG@LdYYU#J9gn)D?_Tmupm64aF_!bP19zz*Z)($1SZ^ zbEYrh?K3y2`B>~8pSQ3Hc z!%zf51DfYS=>pg^&^J8wk3HXR`V^)%{1}R6-gy5S-afbLhazJYH7TSHti{6zm+&wC z(bIVL^N&o|sgt+l$Hr*dNqtce=;omT$@=Zdc#g@>=ukWwkx!Dx%73$hjFf({A-fYQ z@5ky!ALp*F;TKLll=C2UC-})n4r9LELbsnrK*4zI(F15U^w{6oSjG?DIy=H;BBV(q z!9-6@F{|`(JXd*MML<&pmFjf%9ZhB550OlLt$nS_*fnQlz5ypYElP-pbTHasEr6n8 z+Qbjx_^ztBtf9i$O0Ksi08OkY7Y94J+NOfy7LsfMoGyTE3xh#@KS|xPxX_+yKHjpx zX1+lzA0rSaT^aOf*x<~?8@P6J10qMqrcb3vCLdBHCp1V5Qk*x6#gWXoh(?$zpc#|b zRZnUiNlheCx>OG`lK^Kr7XTN{u(*`z=Grz6RU(r3zEXtGoIHZp-aeP7Ozoz|(L;Mi z3V4U*qZ{kEbae%}HQ10Sd~qI=Ql)v7`y^$e3ecz;aM5GR*HeMb{gN)#0S<7x&zMUr zSOCie!|;~304oK75>bkT6|`qF#Sfj3DyKz6O(+Q#AG#E-I3w5SpQ3E7xdoLjz}h)5 z67*BXAY;rm^+Z19p@aL}Zt%od1GU~np){MX)kd$$e2%l`$sjyHZZS^m#Ke(!?Joyp z)1^z56sa^-ULN+$J(F@-QC-rr84D;w#P6)cI^n{#+caeFzj9&;cX_q}_Exc~KP=O3xCe4)Tsp63@trqM{j%NFd_J5yVR}Drq1w zZ6KQiSm(QVW3_{$4=zpoP$wTf1g#WI-N&tR8zuWosg%;=8K|O9Woiy3%+dr67P1Zi zSUmSjGi^_X(v+fum@0#pP%4tGNFrf$H4$8fPK=p!*$8W!1Dw0MfiFFI1c@H)GVsik zC-HCp@Bf&8&kr5kg9Ce)#}dBASiJJ)S>O9v5ezT-pF{{kL?Qx7Gegs!{Jma}Uwi$H z?VC4mW)$412$qN}5m}{_QA!yi%Cy#*QYzJ28>N&1z(mC4{bNK#F|%T3Eh1V(l!&Mg zKm2f|ra}~_QPnO^OcA*ZZR>uDWa_I;w+F=~LWIO>BJ%3KB7_7QLWyt8B9~dgH&G}7 z*i$$VkO&kBSe%L{pxvg#nHT!Xw)Ew0@${}qVsR=qm}MdAoK9y2e4~-0XJ9r zm5&+Y$24YO6<%Vd%eoY*bdiRQz{?usGM%$t4Qm9rW2v7=x29z6l0T-gB*E@A$92`8TUCyzs*2=Iz@iB7HId84(TO`dE4ZdPLOq_f!8` zm^%s^*8ma`iH9DwwU$s84hP1K^Sv!~BO}`p6?_0f!+)kG%q)Rf>-KU&g0kQrf|a zmr&##Me!v0ke5^;T`@^7cPelhb3R1+1$LHuC1;PqLNkcM5>yvS(M!e81<96 z@qlA^USqUNBx6b@Y|^6cLvX1(?c9goPAvxBVZ%5!$rqvD}KDazG zLVEo8VV64Xcd663Xyg3lo49dnO?-DhIdV%1a!q1SBW4I$ftc;>ExvwhEj#hZq2{EB z?bN9!7Erb#sXOr*W&fm6SE}$g65} z8Z3xpZCFl9J@jG5=kMRXKGg(vtJ%Om|0lnUh55M(pAz#cGCCcuoTRSNt>EFNRhBEy zFO|vUYHTt-Dv}Y`fr^Ijkfv{4T0cIDnVd4A{`)Gux5CBi+c1PXF-z5M&U<1B^&CWF;*5l(e-FW58Lqy}doSaOqlq8cycnhaaBbw{NdP zy^UmfBA4>TLdcpb*Bh_NeT_!cr=h2b?Zye^h+!^k!)cZh8tmQ%185wVIBtFw8g zY(cD@6Dc))BO@0DEpU* zQWY`qj6Sx?R=TKoJ`cY(Nke9uzMYAH1HxuE#rcnJW00EK&lHyDzx+8oed@%>&mK~x zAH97>AeOu$9UxXB4<0AO0A`4>U~9lxCY+|d&gS65vlq76jk1pgGNly#=5PMy{)ogK z1vYj}+LJ|~5^e*qgtZ4C5XWH+U=v3-wuZYwO$v2i%`VN7HVwBeZ>JXR2Enj+xqW!L zz}1ad1fs0#lM)uqOi&Ch3{fm1Oqy84cclrK6qCY}{rz(L`H*dFv;daLJB)pZ~MM;zhwY9g9R;PQ!$WMnjv0ic&zbTf-?nj*6) zGMgc_9m#A5hPRN}+c0(wnO%e770K)^WV|AlS72mK3~#{jmN0i(eA_A;t=uOgPIRX$npUV$=SO8`rkpeCyp?<34{_8jXhfz2E!2#}^hB zFaluGDC&sQo?aBGbOCga966$X|M!3YAD%dIq5+@-U<<&uUps#7`n4ZzZ&cbeH4&WP z{$EB#G+v_~jBW<7_pdMvh;(2DNR)G#Oq4T0(#nFBQxkI$je&vz*b*tLOrx!{Cd;7N zl8hRF6#!aDMOwm=%K*QBX+vIk?FxP63r8llpaa0}U5ogyzWysX@#sVNKmOg{VP&Hi z>9Pb>H5FQqfzm`LK?r!}=MLe&{U=Z2(Ei1#uKE&74$!Dvil;iU%PCX!#YrCIgsR%c zoem357uA&aXRDXt{MFld_DPcumd^5?B7!u{@Y>rS0&Jp-j>PTK7EW;20OA$Oc>p#8 z5jy~9{qA-)c;n5t%oo4#)V>EE*ta-ow&>8ILyLd#2Y>MNpZv+6yms~K)!vBcCFWQ1 z=!1ylOJDlZfvowak247fAmNH*N93}T1lzKMKe?TVt*1qW?aRo z0GhrrXljB|K%zu6cOY6w{At08DS?PKOrjV}1}sK289*6D%4lv_^jj>Mu&}WpYWlO? z4fy2cLCMdmfAftu$LSxu;2G>Ph2!11{CKj5LSg zI+`!t*v7S$Z5%ti`;MlX-#c?j*4JY*-5M_j6ATVIDq?$&VR>o=5uz>+g zTNE*%yl{``+>Kod#r9rm=zspRm*h|W$N!8HJ-yJ>o?VOh`fvOL{MN5Oi{2o^)$8k6 z-|WFypwUdQG(U&EyV}^ht3Bj2I4Rl)%lhqY{HGUR$I9B~7_2T{nyMLZq?XJmY#Dtl z-UFF}2^n?~K@lljUFqWNmD_mK^D?u(@9CG{1UM_0az_N_jYlFdKljs=q{Ofsfa{)q;eQIQQt z+>(oE1VB@ZbC%@7*@VeJ9PAK_g%$&lA<~(G&M0db&a`DgMr5oA8BoI#nI?!DfOb)h zD+dKLIb8T?6My)>oyNcXonNHNg=zA+NQC*hCQd$b;Ep(xQOoN37XIJwyo&F={5JZ7 zv?i*cJKpy6KhfREl+I*5Lu0ro-yz-U8(g@yiT=P~t~FcA)E}gH{jDDdk0bFT@gfi= zN5~k67%9@EKE(D#xCgdGPjfRB{ix}&K zy^R68UKnteg0lg{41}{DIO{=72W+|!+XdS$gge$`+dufh%V%DA;f0rP-@d(eH^4jV z-?mzAv(``biPNb)W-m4S{oB9&+t-`Trg`qU=YDbb?%fCO6_8B$TRC;=)ISAqdcu`LY97x# zTJUK|mtw9)N~se7bW)(D8Au%1urQ1WnqV*tDKSLKz#?NdDQJ*_Yzj0}5Yj;43AFP= zRoV(EL!g#ZnGm>f1UJe3;|r_mfB08_CI9_@`7HgysfRHseY%shq|T<~+?5r){Q5ck z;LS6*bon~iW+=Bc#28a!cRR(t4D&H`2R|L%@ySyUV#6i+&<#K(;B(J)239WK*h06T z(fnLvs(t7WQoR1=yGA6dG~0>w{;TIxfq@_qaV2eSp%MeYFmozMGbm(GHYMQ{WKxpGfV3Kj)u|{+$tD?;Y6}#DoOLdM z1j1h6hh%-Tr~cKSeVd+r>InT8zy1Y!D#MWcKsl13Vy=kBWX)sunWhJmdgFt;AbzKgmZ-34@&I+|`j%Y1xkZm1-8eNPMn%pzhv$?H7a;UgGGAL1hya2F!3_rw8B=wFHD7rtcefJ`&3BV#E((Cmuo;h>oTi^J`H@TJh5oU(5pn-+rjC7KMObXQ)h-3puBNdelz?_P*DMV$Y z^c+Ob38)32K|ta>yIDXamZ46+cAj2;_X0ih#KZKJFF#HvjvmCWrG+7_*I6Q)EVH<| zzKx3?t>J_7H*ogSEu6i09i3j!_u81k-BGwE^6)cIP|>Ku^wCUNZbHf@{HU=4x-*iw zELcSt>MZsHkd#MRRr%&h7)K0ZksGTWoVl_tCm-HJllDbK@ckdWW?X|^Xton}X%dGt zDFtNUolJdtBwZi9bO3RYOws5TH@Oi27-RHzzx&;H-+S-9tIs|6+@<5kkDoYv`0(-F zyLazTk|enUfDvZqe!qWnb93|jyYIgH()Ygiy|*u3ytw6GpR16*u>^!gy(->RN_aC} zi#|aMjkzC>zAH4f(=Bc4CaFeKq16D|bD(w`syPqUScFOzN$F*B_jf@xmj!wmDp?{* zmY|YFD766SHYw%pJyjEs283NyBSs4wC2RM> zY-6s~LL<>oO2IP27z<-9($r$B)5GR=ADf*%R@Sz0ePt6j*S2u=`Z{i{Z^7C~l2eAQ zR?D)G9$1vOC(%tnIjix!!y|dWd+AbTIk#?5lx&cxx zw{6`5sV1PC?zLQclRyM~^$Uj(I-Xr6*m#=5I3+*-7-I42n;&3pG^(Gvr!6l#tU~b>OeY>A}>ZxN7J@nAw0|yQq z+`W7E?#0E$rB@3966xj=C|QO|mH@pBoh*ZrB~p43q!&PX9-uj*05;MTK?1P}#A*?%!5P6t z*Cb*nQNUumNxPQXSYB+?;zAp9b4?^V@o5lCYAmIh#ddFiti2LpM6WxJKIQb(x6h!Y4 zz)^xkD5nsc0X%@%ffGP4y=N#_2ip}7U=C=+fm$Qz3w!xLl?x`50}m0-L`*8eeTEqT zw$EbwB4z;aKwt;re5W&US&j^ z8{0n8XcN)=u3fv9_V3@nYwzB@%gf8l^YiobbIoQ`k+b?uvn(5QyWQ^A*4EbA+S4@PDR`X3-Co9G@J5-||A1TkP6LS+L;Cc>74ZG4uKusDU;q7yI{sG_00 zt?|kwDeM3wIxgI~LPZ24HEB_N5*FZ6L@)th8ufN1RnMpRz5Qc~Dpk3LuSyCdxBNDE zEd?E%x{n)KvPdZ0@X&h}fT;jdg8VZn{~0tuT0G}e?6g?dzu-W{f-?ioEF`ty)Phq3 z9vHFtV++Z`kfYax@m{~e0bCpp1L;A~^Po}(F7evM@RV~^M!{ludYYr#apmMHJy5kZ z83iDMdaara^^%`6m9jsLATur46y%jy7Zw9Tq~PLrBjo!ayxEWuvHn0417SmAT@26G zKW0y0uy;z!&zNGyMf`=iP>@0~mK|$5P_AiSj&L#jJ4+njP=(}mZjFVb<0ODlB@m!U z?v;cq^M^kA@h5qHqKEtWdn%ABq9G}LEWh)4iiaZLl-w#&Kt1P$2n81mZ{)h&3Qs5o-vX!GjLLW?;`63R?>I5lWtsIu#X~5k$cx!Fxba zq^e0X?0zBOO(pLmrAxN3j)O@69rG|r@p|kkP}}1egJPUU1rj#)SxO?4H>c<)rQ<#B zdEw|2S_xLcIna>gljwO$MoRoX3*1PVkOLS25tA^ByI8mj1sfyQ7)WNoX$CvU#HJZ+ zKLrmAI8EJiS>`%-O$ITUYdGT2WEY~BfvY0r5lpuND%G`9!*5iHRD;oSnpI(MsR5%p z&IPCweJe*zqa-A%vrFbqBbnq=4l>g>?S49~Rl^0p3uf zm2zFSMz^5=Bq<9v#jXLGKpIjy`GX&lf{-rWhN`}J0wMNbB+f=fspzYVfh`!hk)I>= z=qWX2=)jxA7uS*#B|((aa&{d^Hqx0OZyH4cfe?w)a{+`{SU~PXa%78jX|A#0%nD}~ zHgzeJ?OU+}E1U{!$_3FI_!wrNb%ipUmqd^N7TqXP38_+?E``@)dCQnQjW75yzrrw}?C_7_ALQFCnaox8c7aMdcox5-=orbW{fL z^eu=001l%`L_t)!9At{rhor1*N)VFxeYJPHR1)bE7i@R%HFAV51H>eTL1f{TqyRQx zYlV&RTDwN9@!ZQG69+67oU(Anj{LR0gk6$!h$0S&D={(1Y(*(kCyHSDsA#=Z(hgu) zT9Z*PvzdB;X+%JiVAzBWHK|p+%{U#3wP?~2sS;zfh}_R~Br^$Uq(Z8dB_!;Cp_&W@ zEkaC|7?2FCGNHskl8iVRfOKE99)Ob`QPKyio+#A?bdN}Nq11wa7C@>EP#Z*T0a_5W z0BR7>5N`qK4HxpbB|%OCP$Y4QhNvW>o7?bG&6t3<2#=f`3xl;JPNlr%Q~;Th=WMy- zDr{B=BC1**mjY0t_fdLSnU8=Hy5!ZdqPSEL&*Z)i%B5AsRijHv=#KY-Q=}8;Q{v<= zMU04Hh)uyxsScbPh&95gfz1p!bpXVf=WQ&z-W+BRGI38peD#ktayvEAOk4)8YUYL$ z9hJzsI*iB|mfcLFNG3OG^J|=o#tYYwyB5RRzg02uIxdE1J^6lCK&B2{Ms+Th(= z1_LRJYBH2gK-vmL9P}2)!B_xyxdB;B@<$O>SxwJ|JFIXx{-5y*NQ4TI37q!G-lLL$=gT1$1)VD%K zFc(r7l~;tJbbdOJR4Y$IKG*_p@>%Kvma1i@gfeq<-}lai)GwIY5JZF`0zEg4VgW1( zSx>SX0UNNZ28kHsxD}H*GS`v15R>`))=f~GP)+1qC&pC`{mChHdMi~S?rPIruO@;q z6_AOKO@-mf=a@H%0mkbb<*OQ#HgQe4y9!)&VpZ7~E=G1hW_)ADD4u3i`otb^7z_i| zutLU?YFM$>fUFU*87Rp}Oa@B&AnJ-udQhrMR&}9tS4b^@)I5=z2WTFo+8}BHY7Rmz z5VZuxqh<(@*H4svWXgp~F9U>d$qY}!~B^Skz-vqgaIbEbL<%^zFu-AbO!79-Y%3>w^_U|J zTh3N1K#fWSqiZ4=)I{w(hDlKs5y{oll#9dfLabE33)niIgo6`+We+sgb0-n7xLy|5%Vb;?kWCisNF0zD*G%Vn zUwjlJ9$*j#m$-(6H8rK)!3Z9s&aH3pNUCVHuxn#P2bX%yJh5zy5L zYbN6NXB}i_0h{4r%W5Yj=_W`w95Cnvq+1A}LDT~2d4h6)qEs8u^B~=ZQf-22`Shvn zhJUCzn-f4 zaAv6ZLP^oREO|#=L~oIjz@@lcOMD$XZ%FjSst91c^1lZfvA(rGOg&o%HZUALXTh%b z1z;;;O%a`N=9?zd5XBUrVx5n=>t{+mL7e8J>%*nny6)E$Wo7@gCM}8y-ntYCm1<3_ zU0pris>hic0WMWOhHAi|&P%(lqE%JJlMw*312RA1s7BQu1f-h~f7MaC0ZM#?qvm|H z<9V2*4Wbs2YJ0%((GE3NW*WT~OI;^lYuJ45%@8Z&))c;MIPh19IDZnL6PJ2KJeJ`byh$|prFy2@# zi-57Qy1iAQj zE&x@m0x^Y$H1cT1f4RDg+t^LW{g5gWZk@xe-2Uwg=$Yo9WPP$ zT9t39MnF=NYD}XiI_>dRO|eE@C`ZX?a?LHqa4<6i%nr!R9@PLteeq+jG*K?Covs3@ z21qARx&=tf3$3)^%GfQJV(B@MY7)o^q)-4QFVI4&LF8uwl=eCbItdYuOQ%!-9KY%? zDVYNfmByv>837bhd6GA*M7dFM#jQp&#n?ow((Q&tC796X6(TE<(i{qddVyH$=7yL7 z>z-%J;!+;=b3|U9E6fzxf|~)d{1zPkHh@cp`WYQFB61n!F>Nv2p*xOy;V~zv%#gBA zS|=4eCTaJMB6#lzV0J*}-b6JRadoMZcG^`2lzXgn!%q|j!4+q_;!4`ZV^9l9HwYAq zvovx-IEc6?N{FHc$;ObO zW=tPToPNj%E&~|vyg2FNR-J&Q5&vg|lV9x|(=^ZFP61{IWbS&*4x2nFJu$50R%y)O68`YWTlvlt!z4U%yYKg3dx9iFG-ep|F1eeDapz(r7~& zTq1dH4lxUrq8UhJfad*)M40k{Q3T;95w=0KDvoY^V;!5w6~KgPcpsfaj*Y>l29c!R zQ0sgZMCv$~>SG=OF5}42QA3NfoUoIQxp9C(6MDojCXK?q1eYCfB?mMO4=Vn?QsFrdTtV1Hkpq={g#3F^f2Bc_^bAaL>!{nm_zM;mgQcY#* zA{R3zN}0xosE%W?7(F$8Hz({g075gI)6=9pGYvoPfXq)fg`x=+f~3OVL{W}vz;(z) zK#?>MK*9k?GY1pb(i;e1O;8O#H&8?}Ub%`$Ie^P2CByw#)-E`{d7$w`uv9xqrRG8% zCIWH=s=Nj+1+e7Zv{FPW?s*B|l8c4~@nXc{#U_7lbU(`|AgSY7?3i+{jmXft67VQ~ z0drVEMj_2t}zVxff_sIw2rLG7a=QUOD$0Zu0pBXR1KKlCY*6cLXj zYrLkWFz2nr0c<2pQw!KB)*uWoRh!xB_>sF=$JwzmCJRIT#JG%~@Hs3$t&?PDxwk+w zE7*(zojSmo5CPS7Bv*zlhdV_}xA{o7NC{-fOHPQ$G#o(O!8cCSx~>tdy4H23)ki!d9k?TCf8yJ0SB(1RIPwX;sbrNr0dy0MWEjiy8rV1 z0&p-T=wL=Lp$YFfZa*gt<4qIY-05@Eg31oC?10S9Z*qr#GwMD~cx{%+-#cBVF$bF@ zk~9ri%?d0#;IacUJHOA2zuPqF&9opw_wbmRG|w}wL*cASZ9BlS12Q|yUH(?H4$aYB zZ1-Ny%1jFkvl6j#hp+7{J0P>O+#}GrQy}@cr3K_Jx48oOe9XTi-3P~td<_40 z2UvDMW@ot%f7|=zSdgFa-|s9tAhWaV{N6i&vUAYwEIY@-4v_3DJIl_pv+OK8%g(a1 m>?}LW&a$)YEIZ5HEdM|HV|r!~K+7Hg0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vdg4&SX3Q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000P%Nkl43q75>hfH}-hEP2$9{oz%`^+^mq6v`L$UMwO@<3ZiNRY70MDT7)VAYFU1Q zDx|PUAc|Nj0cmMPCE!O}C`hQZK$|L|B+cg7N#iLvJc9 zchn`r#`-Xka7l9Psi=bUA%cOetLqN0xv%ckZ~U@4^lr8jR{~(er*Hcbi+r6$?ygwB zy^SlY*C5|siCxB8+v>er#4Mdq=_Ar@A?fypI^9&))Hu-phRMDs01qGe!%c;#^dp6C z5ax!+ddij^wuD*OYJ@m8FxG+DLqwp8fFR95g5KAZqV~TYvi|^3`JVxF-?{b2*4Z0G zl)QH^#%dully)Wba31Bz!8!};JUk0TLSjBYiYJ(F;j`LImp6B5n}7$y#up=MM)J<6%Z)7G!rzxc*MQ{pm@~)ns@Yl z+gQ7knTfrJvliA^L~(?fszI|Wp-YO048uAPW`T%8RUx7vAgBw`Je*IS&Q4#Rg?9vS z<99xHW4<)=p!2>>MAUgl&U#p5VB#40ic@c5TA#?nTcgekn3+W8oGVmSK}1NkwFJRS zC)`T_X0M!q4|F_aoZHR9B;FHyhP4*XIv8U#j$@jwTJGeME=46Uj=?M>A`k^sl~kbt zX%L2Jo-EZ3PE5H|0OVZ(toqu=-#=R|Kjggc6cH6>V$bl-!CD7v3_0g8JzC0VCUV)8 zi*2)tPk4rkD5)w`391SOC?@TL2_43t;K}yH1ovVZuuoFv7qiq}rTYQvi=eX@6})k~aZJhX61=Gb2b)jsluQfR49U zN(2!`qR`DYy{x09`-bPkO`@)B}N!zD4-o6s;liM7RI$5 ztMJ25eg#P%(1*8nWB1N=_|uE8AvS<#g(x7xm>3(z*w`pyNg+ri;TbSap+sO-@-~Jq zPZoS(@D-S;=K+kqnTkgWF1RLB(L}HoLC^~j0jg>Z?Y-*(96m5kKi~H|y!zSzZrHE_ zXU@EizBS9Sv2O($Qz1IqQb@p}A(g}j*LGp({4ADa>al&}5{&06+SAcUAKBW87G%e= zqbL6CZTt#=;w5=N#%4~T>Yjk*;kh6tf{3nM+<{}qPoNSD&K8^T;W3`n0pFoc_~ z@1+&Xn(*?$mJ2iu`@d(S7%EKIjGF*PJ1CJ4g>dkLIYCaVF@7L?6d zEsUN4O6LF^0dN?A1F!Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vU$N3GLYc000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000lQNklpib^gwMue+zGXVqxLNQ@Q`0wlyDAYv&20?cBtiIEFpSK>Gr8&jklJ1M(d z!DXCOQiCIwRUINx%6YHLK{+EHk0;!9ebWmd1Q?ePAP#XtB7KysNyRc_mp}ww3BBip=l^3cT7WBjS1M)ltr95~_L3s+E zQt%YP^Hd|4+sLOS9${_DldF7>-dw*TeCC-&x$linR0;s}iNxZaXz-60_n+A_(f4D9 ztP_?_Yi-6FqY9y+NQ2h-lM;l6wARqtKpO*NEUYmi0%8$}fQaCcaHH>0S0=^hW-_Vq zR}V$~073wKyz!_L1+e|lYY&#Hm8EeMXSLSK8Y^rWDG2^2-;7byKyX};xot*7A`B5p zJ`(_>M3M4RirUw7!B) zl}8+D#BovuV=Sz-unY(bm<1w$h>##b)6ys>6-;yC&7t5RfFc0ro2!a4n7$J^h=vc#Ai{}bClnv$v=~nVHi>pqp5-bo9L>QmANPikos{k|~ zZ*0e1fz`KMxoB{5>>qB z;6MQo2t-J-KIf3i7WefuRKLh?R@cj#khJFiEBd3V4DPHt%1=7T5Hz}$r=wB7iFeFHg-+S zu$GSm&rXWODG~?*76qZ@iyKaU?zM0WfJs+{_YYubF?CHAXYRGa4Z=(!4CW*twid=3 zSZ$%Tc0giituYl?oY5GeQ_qSqOqLnUu8AFpq@s!Fx*tgdXw8}hCC*Ls4n+r?BJulH zp}^>`RKj3^j$(@92w@N+3L}I;fG`LUR1-A{!vIkjB93CjQ7p=WH}CNJ4Eag$F8j>v z6zK>E5lR$_0bzm&uyHltkn+`O0CMjZ=et(m&PV>HW!u3$PZ>6l_q@N zj%7TL37`;EZ`H;u63dii+Co_B+HW0QOhOqLqoHF11w#J$H}-Qfhz>`Q+21qS@-L3( z!om)O6CoitjgL%kr%VE|_~WZmp8~KPK=!x+h=?i%rN3rLXeVxR)`PEua8jxhDK$EV znhs`XdWNR}3;{R@VEXSL+V^CMI(G{!B}|kf%2THfxgKx>j)<5^mbB_sXPuJ%Jpc>e zsS581VELD>|7JO=Hj+SUd}n57#FA>%cyEnOW`Q-r)`~qmJ;c`L0UQD_2p|9u@92@Q zS;~NkDe*qe8`XF(bxVSb+Z&%h9X0hj%}o22~oZzpzE;`EF44A+t`wYvbQsgXz$CKH$$ z=Pa`uGMUubt_t3}0@!`{z}1Fr2QdWB{=%(fh#jd&Qk6uBKmzqvp)ZP}X#j^^_QTqB z`$x*Ng*f})$(A5tQ4NG}@|_(xhU<&OW=L9T`t+5#-v@B=(Y^3C0I}%1t+40hVBQx5 zpjy`E%>_Z5%IfhgdwT(l0_btspR3*Wo*(%?(5h()?lJ(?YCK$3;FS21 zu7#QN04$hWg?Rwh{Q1q-m4ouxij;_(m?Y$auK9VHM=22oiHPnQAF#&E0(jF=C_KtZ zN;K1(AFV9+t^}|YKtrt;<^dR<9=p#Z`bJbU zCUX|KRsTvrNScYG17m}8l?T8(9hK0xf7tgQq2vzNO>U@s19IsW}*pDc}PvBB~fMf zeNF>7NCFn7wselCfBnXO$NdA&0>7Jw*RKq=JZ{O)158H{98n)S`aMasFo-4YUSQ8~ z&D;op>VrY+c#?<)SgAEiu`fiFfFRckZ$Hl?5OUKEdEK-uom-gmn>v;+$}K!)otMg3 zKwuNmhw?-n(M{mFF|C)K{K~c^s^>;=B#`>Oq(0E*3|3(g%oI&LI8_OJk6MkDOu~~| zH-GfZ4oP`mLE8IMQq)F75G4D&qYoi#GEH#Y|3ee!mX(@(0q3xN_1B@9Cz*l5G${FDhxBhHVICJI#5lA$A(Hw_`5?6+XV1s_wXCVNYC!=aM9z|?^NrvANVVm$W zF@`k`GYdX{=}ox&wDa)5fBp)KFZ=>dz2r9R*>@1PT)PHWU(g9e1!x^1)&?SgvB{?X zv1fMS;s5$IiiJFE96@VyM2;bdt-vrR;j=&+1*McwT#QZO&=^-IdI1@570>`=p0Ds{ zV&;x)37%R=o?0!6vPdL2xhN6DYW(A-FQIQJkFR~}0eC7z7z+-*HG%$tVI0`M4?| zNIW$@5`6U9jjQgsJ*Xk`7@LF!QeCrN|94vJDl1PGG{KiLBq4G80u z6-#mFA6*Ayle3boyL$1n7kW^w1c;(4{@@GWM7~gjuNn|kN(jRSsAwEdZXUz!H=mD7 z*Dl1?9lLPm()G~V;N@3e$C75?;0+}o|q|OvV3W|}LT`87hB4^k^3W@|>3(`3C@4B|L~m=Ix=@%;8fxb*y0$UOWrEa}K%GGCOwL%p=&iVGyxhAvvS z%3t^3ce|8QogzZ1RH_BQN;mN*jtu}{9G;pMv*4#>SxJlBhHPq$vYCv@FQ@6*vaDXU zlwdUaM`rNV`<}(s7j)t4w_gbz6d>gx=r}|a#ehWN4wdKVvGtWM|d8nzW=}q7FCo7do))~3R8heg?E@ar? z@YJXb&pv^v^1q=NZue%oieR6g-quHpI$H53pZz#m8+~-N<50 zP#~2CsWhxfPB0P=N9Z4`VtBlW+itxYVHDG^Ufj;gGu2(MZhNa-soHbSS(_^si_>Fc zW1~?N<+awm&aTwW;(I+}G8md2lR*Cz9d;7zeNy?w%l`fG*SZ$9da2t#bsau-O%Z^? zg4QfvKRAddf4Kty!Se_yzh(v#5%4`h+E=x?B2&ef`p1e`f7W6={oGbYFi~ZWhBz+2 z{MchZ*|llYrd#j5_ueavG3!&QRO86V$dh;9efKl22lRfXr|nzwGrCiJAuC5K`7sXQmr`kw9}FGH1_P>4XFwouIefEY88?Nzv-|y}1-M4k?);%u! zy8#RXFembuRRNSmrfm^5EIgaiZC8l$FA>H{5Vex>edVPT`HeuP4di9Px=dtBpj4Ak zW&uQ4IG7SdGnSMWK{#)#V-r#uEI=0nfCm6<0q~mJ(X|6u?q#kp4g<^dnEwn6Q$76Ae6g!4)EIHrA~s^umoOaF?pFz z<)zv|eh!cfgh|9QSVv;QirBCW8_j^t6d+TM&(rSwv+5=+A7xF|9J@OAv;WhRdbdr3 z@3ND1@|JTe3m`LR1I{jkfeWPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vLsMBaVy!000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000=_Nklpkb>4UGd#_)2&-84-U+Hhw2P7$N)RPe6a{esgaHW5V1NN;!R*uf+wOAm z{7LiMR6RRe*rk_C|8($7 zf2q|NFs*1HZifRw5LUu4DurR_M{(@NiPTaiDv4znOVd)?)MKfuu`<;t;d(3PVC<4i z{_`_Z{U7gu&n!OY2K8pIO4Ptr}ACid1G!Nh(YPXy3^vo~kYj0ho8e3C_D={8R0dm5HU9hmAIm zF!P5DoBIs&0j>3pro`X?B|Rff&1YpirL?P*c9b@PwHDfF!ORY`ahTzP*<&_Eg6S1R zLqcG?<6y)gT<;3(t(4IJgNfqVD2z1#w(IBXfWx2o&~Jw_d{i^vWsDhN!vn@}$r$al zr4}a9bgLoSvQdjaCrc zn#8d$6DgEZq?BT#4U9GfFzQm^m39x7v0~i8OxLRA@kpm_drXOmyTZfY*MjXe8 znJ%pqSZk~#gdetgu&M~mY?pOL$ND^>)3?~VDtnJ9V~4?Bea(m7>%Jer zFo2$`wdJaz^Vl~(w{Njg{bZQLdqC;MvSBh>!x&3!NT(q!c{rox4!h5-K(wopEko_gg_}Yt?|qZZBd}4 zb%IimQbDT((`^Tbi&a!~45hSjM$rD(%BVbtnYm+t)|LQuYPd}Ur6g*xhNm^Ib83LnP`L(39bpXT&`%A| z&~LdT%{O8Y6Abyj=xar^Ffl790n`CVOC>)Y2R!)1A8o0(oBy^EHm@b3Ot|FHH`?Uv zueE~Ca$PAXsbG}CR6w|`xQeogp_NUWEdO%{@MYB?bw{QlK!zA)AHLL%dVQMD#fe#d zyIkbl%V_pSx#SEi)cE4mqMEW?kX$JjygdXQ+T2@fHU6R=w)PVd zgPAP*!(=Eh9S$(sSPsaDFkM!>~ zJ!tH=WuG#J&eFiJ0cRv=OiqLu7ucU!YDIlbt{?yU>*IGH=pA+uI$HC(=yz%2ZUO{# zIRUvYD7wZ=j3-Y|$qA`=7geaKjdYb$iL)M;dugiJb!kZ}SjJJHXP zA|?64#p=FV|FMaEHa)t!MK<6mPk&v-Ja`x|re?~z76B}c2^B%fu(|~)ORfokZ zX_BrO0q!k3AFqdvgG9nMDV*mebDH}=hY(Xiq&viD4766PwV|G-uFZdMbW$g3d45%% ze&F_jgF=S|llKJOHNOi8nKM!~+;Iwlm8LI%opM-)dLcsl>eeAAU zv;OPM$mMDVbz`iUQ7YH}*;0vwOp;U%O9>?v`NBnVW`16WNfW^Q+){Y#^sM+ALs-YH zCqTB5H@Wd3O0BYK!M4RV4BR%tcMtTqdjV{`5)@n!0?hsm|E?M~4}b*QhCY9En3*qM znXpNpSsP8gAvNb;IC)OCqa^_2%s4ePSU$Udd*NZ2$Y*A&Ejk@zR{NQaecdT?DGIXB z5*Iz~E8z#HCX)#ORRGajq2MPX;GR!^;?~u6C&G@DlVjDD5O~-=p8xUn%bA4hraPJ79Ws{tuBqvUITHWTpO&B#yJV*m4m>7 zdkb>#BkwCeXob<6qTo#(aQ|n1_dv7VdVm=&6J=ku&UkcQo3+nC-XW4l9%wOG4d+%@ z0j${EpYJMD49Mii7u{pc$om$P=;S{k7g}k_qdepp0p^Y% z(o8cF-_e(7KYUGo9h(!sWOCSvOGlEDXVDcu2JlO3BmSLA>X|J6U= zS`8Y%qS=&f$6+-WBdx|JD@J)Tc1Bp-jS6zffm@f2U~+yDz^aY@f|aW4(l}1W7s}rY zr1Sk0@=TpFC;$?j+&8vjbUDK0|44wD;0YA&y%F~Tw6kk?N6eI8h(-u#!c?v z4hfo!5KT7JBz;3kZoU83-aEU7r_NhC;QgQeoh|id{Q+%sNu>Ek>n4-=NP^ex zO>tK+nGHEaaGSDGJ9+Vvoz~1)C%jps!T`&e`q1-RfM#^P5kz6L z>*t%(i!%T&05}EUB7o*wOl|1siRQuw?&#Z7q~twhjKisglo^UF+H1bpUL9FzkN}vN z1e5QgEUC0QITxSr8km^N5b(Y~f3&}qgm+7=hStrZ(oGxUt{oi8F9aau&Pv}SfYBqJ zpgneJ&O&|)z$I(^TQw*Qgvpt?zNaL+=WT?k13Auu-=zqxAR;>4&pwRVkWn*Y0qyxAM4{*}ldB&9GgR zTDOT2A>}aJ_jdF+b!UEeP0Y(s`oTW1f$5#6PyMjBPm9{la zP*!oMg9>!b3z@Sf39K}0t&CSGnr+qrWt;w#tE0^yf1g-x)dFUoB|&Y&=oi9}C4l^k z-gMN+9ku3yP+1D+YKd$Y94r-FT-w}&`ailE>eC;GKpDU_VC({85Wq1IWpT0L3LsF{Nmj7 zi|uCXy8vFXh>X|hV<%88Q*b7^fN2t9FEhKyJwR)0O~of+4LK1&Mu3+_XgL%<$oC1T zq<^8;5r1|Lz!r5|Z9JDC1f`Q?ttvCpcv{kTof)7c7SLEf+`>qIlFgxpECI6;Yc}Qv%4EZxDi7G1@!k8QS=>1 zt&k|47Lfcbz}m9`28`{SD){UtAI4w)@k8)E#_=;#ND>KQ(b`>n)*dOys*{0$fC-HLzw-jCw$gV$qtr~(ZK<5R2n%C}D9i_g4@x#cz-*8@SU?P0CfGE9gQiDt8f zuvLeN>R<_=Py*nAm~ymJXLFBF-xoW!?ZJb~%CB^=zh z1rOhU5X2HkkDY;(8X%GC2Fg~NPC*podoPdU3t#&lj=ub31g%4kz&!RP#gYi zKu29;bC`r+B$Eyk6D+Ri=7mX)R>uHy)~eBlrCYvC3HB@`Mr|ocIHF8~c9Eb>EZ7qe zM7hkMycIQC;nr)e$0vW`H&H2-@mGKI93KChXK>^@FX8zgyoN+3xc|;W7_9hs`L&an znq7o44pf-#7zxKg9L7*ugM>h<-a>n&hByu(1VJhXTD#D2;JP9QP9il_te_3U5vdon zW+YOhr{to?RVJv-Hcf@lYkv&#^> zX|O1t*bot*5j(R)6zxn*L_*Z}U%ZMV0&wcUx_{4AAi^C%u@XZ%a;^`wN@z_Uh!_F-OICrUm z|MJWk2y)>24u0`H+i>rpVZ45!hG%~`gT-ou-P`)`(4AX(>xLrv4vSW6fA5K71EsHh z<%{zGmaHNTyHA$A;grNVv!ryWF2u(2UuXoa2a>pxEaO(n?Ch0?!ILYj=XdRoHTG?S3mB% zWhchZ&jOrIl@4FK0SERB;K`?d1cry6N+0gKX&AR(zX6leOITT6#5J1-@O!_qm-lX~ z5STH)RMoq#-BH}VZScAsTZe9a{PD+Mu&_7XO7smKpa8~XwS|2{qa?%;1~vokt?Y_k zWhe4u`C=f@xwBZ?wO8RL&W^*IEsCfF%p`?l>!;>d2T1rVx^vGFEm7i$>VF@)Q$-;86U zXR&M32r4}Vync2DV`JyIzaO-7QxE)ti)X(5BRPNZWT1nk@byz+J&xnug+gIqWMt&# z(b3T{>wr8B-ukTYOe2OPrVM(&O^kl9S0LZp%L2vp*qR|kLrl^qZH>3IjVM-Fskb4B zv14;TDrFx@4C^w>(+f62^e%;*G^X92q88C*lrbI)|CCk z!_th4wE&E>YSOL!$pD++}c7>+l5q$hllzIR)0VHg9&`|g$vlRwTwT1 z?EN@&-FB$34ulI(aT_v`9bqI2K%oy*7=SheB_)j3X}xzHeE;|ie(k}Vuz7d@*K8ZY zfsrjdzuchFv5S?c}|?w$j*S4Nk#8doCQ|$+FMs1G&D90Gaz74@Y{Z6vUP!4Rl>%79Xa%E9 z-cbMo1P5SY&k1Rmu6=Ofx_JJT85|nfi2H6oKuMDD#Q7;S7v{C_ouEFuG&^~IqIcK! z;hlHiefQwP!otAx^z?G2QW@T}XU`tjb?FOV_`?6P8#1fi)95R`Uw~ntu+XX@Rwp@0 zLQ(Ro&~(3`;PC8xwD~`N`IXY6kK7~<9~_|_+lH}R4cIGqG(1oS!1&s8Kf>|XCjsHW zaRdsUST{&adkNPe6g&s65Lvsxj&SI;@f8G-LVu+PODi>c`IXlsbUomR7m+m2{oT`F zy>!j?&G+uxx9`BmKK8K#?RI;+>$t8=LJqNyb-mN{kUHiC8u% zDlH*#mSJQlgmLGWTmGvjCktmME>ak@p_Qch#Z|oc+F5+*nV0y;3$M{?wFY=a2(J%w z%K=WDp2W#B=K%6Rem}@7BTf{~U7W|U(Q%%gUm+t(M1@{X3~{Ym)8{8A^|9BE$sfM- zgMd|g87i0n`mOuY2mbI*NaY;3G9r3|eD@^b@M zbIjag)+@p99}@o1UigDIlUKQ&g?FPX%npxaFR^kBKw1MzX<}nQjtlbo;Fbp=gbPk; zkUjAmtbhAyh$;bdgI822;hEoDym}SdwTr(^KMW7h08%8!( zO}Jb|yxN2cBCxL8N%JUx37g*ahFhwTTP%@VF2M0U2v4M&{Ss_+I_M&y!K`4UV%bhOX+)6CkY&4S zRBHvYy$BU9fz_(*=2q+;!`!-q5T0fHUVB>1vC$3ywCuCWj~Ts7_e?pKPzwMmAa4VN zzZq_EE8OB%a*CVCDQX*&y9t(~^yf!8!z+&>GmZtI-v~&_-2X!97FtR=@vg+&GyzB6Eh<T}{lpa>v+D%K_^-qT3Px# From b7f8a821d2e30312cbbda82fdc1495c587b147db Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Mon, 29 Sep 2014 18:04:07 -0400 Subject: [PATCH 69/79] Update README --- README | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README b/README index 68af0a73..6eb2374a 100644 --- a/README +++ b/README @@ -1,5 +1,7 @@ -Grive 0.3.0 -25 July 2012 +Grive 0.3.1 +29 September 2014 + +Command line Google Drive Sync http://www.lbreda.com/grive/ From ba8766416ed4d4fc957d0a62c168763c4bc5bac8 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 29 Sep 2014 19:52:29 -0400 Subject: [PATCH 70/79] Change to version 3.1 --- CMakeLists.txt | 2 +- README | 6 ++++-- build.sh | 0 3 files changed, 5 insertions(+), 3 deletions(-) mode change 100644 => 100755 build.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 45c80093..73b1b0ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) # Grive version. remember to update it for every new release! -set( GRIVE_VERSION "0.3.0-pre" ) +set( GRIVE_VERSION "0.3.1-pre" ) # common compile options add_definitions( -DVERSION="${GRIVE_VERSION}" ) diff --git a/README b/README index 68af0a73..6eb2374a 100644 --- a/README +++ b/README @@ -1,5 +1,7 @@ -Grive 0.3.0 -25 July 2012 +Grive 0.3.1 +29 September 2014 + +Command line Google Drive Sync http://www.lbreda.com/grive/ diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 From a946969ac7c1c50e1b9c710160569597d776705b Mon Sep 17 00:00:00 2001 From: linwiz Date: Wed, 1 Oct 2014 09:37:53 -0400 Subject: [PATCH 71/79] Added .travis.yml --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9eb7f2da --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: cpp +compiler: + - gcc + - clang +script: cmake . && make From 5056c81b7b1f29e84622ed3ec0c89639a63fc637 Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Mon, 13 Oct 2014 13:23:21 -0400 Subject: [PATCH 72/79] Update .gitignore --- .gitignore | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index d0c63324..a7a94cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,14 +4,17 @@ grive.kdev4 .project .cproject build/ -/CMakeCache.txt -CMakeFiles -moc_*.cxx* -bgrive/ui_MainWindow.h +CMakeCache.txt +CMakeFiles/ Makefile -*.a -bgrive/bgrive +cmake_install.cmake +grive/CMakeFiles/ +grive/Makefile +grive/cmake_install.cmake grive/grive +libgrive/CMakeFiles/ +libgrive/Makefile libgrive/btest -*.cmake +libgrive/cmake_install.cmake +libgrive/libgrive.a install_manifest.txt From 2e4cf0fe725dad6e3aa0c42e5d68ff5453e87a28 Mon Sep 17 00:00:00 2001 From: linwiz Date: Mon, 13 Oct 2014 13:28:45 -0400 Subject: [PATCH 73/79] Removed old files from master branch --- old/bgrive/CMakeLists.txt | 45 -------- old/bgrive/src/DriveModel.cc | 116 --------------------- old/bgrive/src/DriveModel.hh | 61 ----------- old/bgrive/src/MainWnd.cc | 58 ----------- old/bgrive/src/MainWnd.hh | 56 ---------- old/bgrive/src/main.cc | 62 ----------- old/bgrive/ui/MainWindow.ui | 132 ------------------------ old/icon/128x128/128x128.png | Bin 18608 -> 0 bytes old/icon/16x16/16x16.png | Bin 966 -> 0 bytes old/icon/22x22/22x22.png | Bin 1369 -> 0 bytes old/icon/256x256/256x256.png | Bin 53136 -> 0 bytes old/icon/32x32/32x32.png | Bin 2355 -> 0 bytes old/icon/48x48/48x48.png | Bin 4186 -> 0 bytes old/icon/64x64/64x64.png | Bin 6534 -> 0 bytes old/qgrive/CMakeLists.txt | 29 ------ old/qgrive/include/QGriveApplication.hh | 64 ------------ old/qgrive/include/QGriveMainWindow.hh | 57 ---------- old/qgrive/src/QGriveApplication.cc | 100 ------------------ old/qgrive/src/QGriveMainWindow.cc | 77 -------------- old/qgrive/src/main.cc | 43 -------- old/qgrive/ui/mainwindow.ui | 75 -------------- 21 files changed, 975 deletions(-) delete mode 100644 old/bgrive/CMakeLists.txt delete mode 100644 old/bgrive/src/DriveModel.cc delete mode 100644 old/bgrive/src/DriveModel.hh delete mode 100644 old/bgrive/src/MainWnd.cc delete mode 100644 old/bgrive/src/MainWnd.hh delete mode 100644 old/bgrive/src/main.cc delete mode 100644 old/bgrive/ui/MainWindow.ui delete mode 100644 old/icon/128x128/128x128.png delete mode 100644 old/icon/16x16/16x16.png delete mode 100644 old/icon/22x22/22x22.png delete mode 100644 old/icon/256x256/256x256.png delete mode 100644 old/icon/32x32/32x32.png delete mode 100644 old/icon/48x48/48x48.png delete mode 100644 old/icon/64x64/64x64.png delete mode 100644 old/qgrive/CMakeLists.txt delete mode 100644 old/qgrive/include/QGriveApplication.hh delete mode 100644 old/qgrive/include/QGriveMainWindow.hh delete mode 100644 old/qgrive/src/QGriveApplication.cc delete mode 100644 old/qgrive/src/QGriveMainWindow.cc delete mode 100644 old/qgrive/src/main.cc delete mode 100644 old/qgrive/ui/mainwindow.ui diff --git a/old/bgrive/CMakeLists.txt b/old/bgrive/CMakeLists.txt deleted file mode 100644 index 3e6ce031..00000000 --- a/old/bgrive/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -project( bgrive ) - -find_package(Qt4 REQUIRED) -find_package(Boost REQUIRED) -INCLUDE(${QT_USE_FILE}) - -include_directories( - ${bgrive_SOURCE_DIR}/../libgrive/src - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} -) - -file (GLOB BGRIVE_EXE_SRC - ${bgrive_SOURCE_DIR}/src/*.cc -) - -file (GLOB BGRIVE_UI - ${bgrive_SOURCE_DIR}/ui/*.ui -) - -QT4_WRAP_UI(BGRIVE_UI_SRCS - ${BGRIVE_UI} -) -QT4_WRAP_CPP(BGRIVE_MOC_SRCS - src/MainWnd.hh -) - -add_executable( bgrive_executable - ${BGRIVE_EXE_SRC} - ${BGRIVE_UI_SRCS} - ${BGRIVE_MOC_SRCS} -) - -target_link_libraries( bgrive_executable - ${Boost_LIBRARIES} - ${QT_QTMAIN_LIBRARY} - ${QT_LIBRARIES} - grive -) - -set_target_properties( bgrive_executable - PROPERTIES OUTPUT_NAME bgrive -) - -install(TARGETS bgrive_executable RUNTIME DESTINATION bin) diff --git a/old/bgrive/src/DriveModel.cc b/old/bgrive/src/DriveModel.cc deleted file mode 100644 index d2ee81ae..00000000 --- a/old/bgrive/src/DriveModel.cc +++ /dev/null @@ -1,116 +0,0 @@ -/* - grive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2013 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 "DriveModel.hh" - -#include "drive2/Resource.hh" - -#include - -namespace gr { - -using namespace v2; - -DriveModel::DriveModel( http::Agent *agent ) -{ - m_drv.Refresh( agent ) ; -} - -Qt::ItemFlags DriveModel::flags( const QModelIndex& ) const -{ - return Qt::ItemIsEnabled | Qt::ItemIsSelectable ; -} - -QVariant DriveModel::data( const QModelIndex& index, int role ) const -{ - const Resource *res = Res(index) ; - if ( role == Qt::DisplayRole && res != 0 ) - { - switch ( index.column() ) - { - case 0: return QString::fromUtf8(res->Title().c_str()) ; - default: break ; - } - } - - return QVariant() ; -} - -QVariant DriveModel::headerData( int section, Qt::Orientation orientation, int role ) const -{ - return role == Qt::DisplayRole ? QString("header") : QVariant() ; -} - -int DriveModel::rowCount( const QModelIndex& parent ) const -{ - return Res(parent)->ChildCount() ; -} - -int DriveModel::columnCount( const QModelIndex& parent ) const -{ - return 1 ; -} - -bool DriveModel::hasChildren( const QModelIndex& parent ) const -{ - return Res(parent)->ChildCount() > 0 ; -} - -QModelIndex DriveModel::index( int row, int column, const QModelIndex& parent_idx ) const -{ - const Resource *parent = Res(parent_idx) ; - - // check out-of-bound - if ( parent != 0 && static_cast(row) >= parent->ChildCount() ) - BOOST_THROW_EXCEPTION( - Exception() - << InvalidRow_( row ) - << ResourceName_( parent->Title() ) - ) ; - - - return createIndex( row, column, const_cast(m_drv.Child(parent, row)) ) ; -} - -const Resource* DriveModel::Res( const QModelIndex& idx ) const -{ - return idx.isValid() - ? reinterpret_cast(idx.internalPointer()) - : m_drv.Root() ; -} - -QModelIndex DriveModel::parent( const QModelIndex& idx ) const -{ - // if I am root, my parent is myself - const Resource *res = Res(idx) ; - if ( res == m_drv.Root() ) - return QModelIndex() ; - - // if my parent is root, return model index of root (i.e. QModelIndex()) - const Resource *parent = m_drv.Parent(res) ; - if ( parent == 0 || parent == m_drv.Root() || idx.column() != 0 ) - return QModelIndex() ; - - // check grand-parent to know the row() of my parent - const Resource *grand = m_drv.Parent(parent) ; - return createIndex( grand->Index(parent->ID()), 0, const_cast(parent) ) ; -} - -} // end of namespace diff --git a/old/bgrive/src/DriveModel.hh b/old/bgrive/src/DriveModel.hh deleted file mode 100644 index 9885aedb..00000000 --- a/old/bgrive/src/DriveModel.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - grive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2013 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 - -#include "drive2/Drive.hh" -#include "util/Exception.hh" - -namespace gr { - -namespace http -{ - class Agent ; -} - -class DriveModel : public QAbstractItemModel -{ -public : - typedef boost::error_info InvalidRow_ ; - typedef boost::error_info ResourceName_ ; - -public : - DriveModel( http::Agent *agent ) ; - - // QAbstractItemModel overrides - Qt::ItemFlags flags( const QModelIndex & index ) const ; - QVariant data( const QModelIndex& index, int role ) const ; - QVariant headerData( int section, Qt::Orientation orientation, int role ) const ; - int rowCount( const QModelIndex& parent ) const ; - int columnCount( const QModelIndex& parent ) const ; - bool hasChildren ( const QModelIndex& parent ) const ; - QModelIndex index( int row, int column, const QModelIndex& parent ) const ; - QModelIndex parent( const QModelIndex& idx ) const ; - - const v2::Resource* Res( const QModelIndex& idx ) const ; - -private : - v2::Drive m_drv ; -} ; - -} // end of namespace - diff --git a/old/bgrive/src/MainWnd.cc b/old/bgrive/src/MainWnd.cc deleted file mode 100644 index a440efab..00000000 --- a/old/bgrive/src/MainWnd.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - grive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2013 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 "MainWnd.hh" - -#include "drive2/Resource.hh" - -#include - -#include - -namespace gr { - -using namespace v2 ; - -MainWnd::MainWnd( http::Agent *agent ) : - m_drive( agent ) -{ - m_ui.setupUi(this) ; - m_ui.m_dir->setModel( &m_drive ) ; - - connect( - m_ui.m_dir, SIGNAL(activated(const QModelIndex&)), - this, SLOT(OnClick(const QModelIndex&)) - ) ; -} - -void MainWnd::OnClick( const QModelIndex& index ) -{ - const Resource *res = m_drive.Res(index) ; - if ( res != 0 ) - ShowResource( res ) ; -} - -void MainWnd::ShowResource( const v2::Resource *res ) -{ - m_ui.m_title->setText( QString::fromUtf8(res->Title().c_str()) ) ; - m_ui.m_mime_type->setText( QString::fromUtf8(res->Mime().c_str()) ) ; -} - -} // end of namespace diff --git a/old/bgrive/src/MainWnd.hh b/old/bgrive/src/MainWnd.hh deleted file mode 100644 index fe9401b6..00000000 --- a/old/bgrive/src/MainWnd.hh +++ /dev/null @@ -1,56 +0,0 @@ -/* - grive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2013 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 -#include "ui_MainWindow.h" - -#include "DriveModel.hh" - -class QModelIndex ; - -namespace gr { - -namespace http -{ - class Agent ; -} - -class MainWnd : public QMainWindow -{ - Q_OBJECT - -public : - MainWnd( http::Agent *agent ) ; - -private : - void ShowResource( const v2::Resource *res ) ; - -public slots : - void OnClick( const QModelIndex& index ) ; - -private : - Ui::MainWindow m_ui ; - DriveModel m_drive ; -} ; - -} // end of namespace - diff --git a/old/bgrive/src/main.cc b/old/bgrive/src/main.cc deleted file mode 100644 index 3e24ebcb..00000000 --- a/old/bgrive/src/main.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - grive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2013 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 "MainWnd.hh" - -#include -#include - -#include "drive2/Drive.hh" - -#include "http/CurlAgent.hh" -#include "http/Header.hh" -#include "protocol/JsonResponse.hh" - -#include "protocol/Json.hh" -#include "protocol/OAuth2.hh" -#include "protocol/AuthAgent.hh" - -#include "util/File.hh" - -#include -#include - -const std::string client_id = "22314510474.apps.googleusercontent.com" ; -const std::string client_secret = "bl4ufi89h-9MkFlypcI7R785" ; - -using namespace gr ; -using namespace gr::v2 ; - -int main( int argc, char **argv ) -{ - File file( ".grive" ) ; - Json cfg = Json::Parse( &file ) ; - - std::string refresh_token = cfg["refresh_token"].Str() ; - OAuth2 token( refresh_token, client_id, client_secret ) ; - - AuthAgent agent( token, std::auto_ptr( new http::CurlAgent ) ) ; - - QApplication app( argc, argv ) ; - MainWnd wnd( &agent ) ; - wnd.show(); - - return app.exec() ; -} diff --git a/old/bgrive/ui/MainWindow.ui b/old/bgrive/ui/MainWindow.ui deleted file mode 100644 index 61c99206..00000000 --- a/old/bgrive/ui/MainWindow.ui +++ /dev/null @@ -1,132 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - Grive - - - - - - - Qt::Horizontal - - - - - 0 - 0 - - - - - - - - - Title: - - - - - - - - - - - - - - - - - Filename: - - - - - - - - - - Mime type: - - - - - - - - - - Last Updated: - - - - - - - - - - - - - - - - - - - 0 - 0 - 800 - 23 - - - - - &File - - - - - - - - - E&xit - - - - - - - m_action_exit - activated() - MainWindow - close() - - - -1 - -1 - - - 399 - 299 - - - - - diff --git a/old/icon/128x128/128x128.png b/old/icon/128x128/128x128.png deleted file mode 100644 index 5914ad64a5bb56e24c0a38037d82ae51671ec4c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18608 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 Hu0mjft9SHl diff --git a/old/icon/16x16/16x16.png b/old/icon/16x16/16x16.png deleted file mode 100644 index 2e6949b3a6a9d48a6b1442ee51b7740073e86bd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 966 zcmV;%13CPOP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1vo0H_CX>@2HM@dakSAh-}0009aNkljSutf&o*(w0XcDpG}1B)Sl(AVv@>0}>Jo1Dy~H zY#kUF*cdCZ1O%u^AR$2NP+HWGQnhsobsXH-@%6QRAHL7;`!j(kuQML~&Tl(}|4H}K z({!)VLdP0l^&N}Wv&$8uVKbW=}0engI=kdrX7gfve`3Sw=hjPn3~`Gc2#9l!MXg}sjFzMZP%x!x#+ z@OqdHci{RVl2kzwA8pyZ+pxrsuCJ1R2y)909d$hKgEWpamKU+-4rwN81A&hyNtv}K zBC2L3e|e*!tOo?uw^j|$^WO9W|5Oyl9E^Nw+rBD#7Ekj~go%dIOk+8o>-BwM{3!L{c5PaVsYSnCDFOj-j*j;3snerBQ#0RUq%zb{In z*R|3}lLSc|Bks8)ZrPXbbmFx{i?34!Uu!^XVo8ko3ccp~sx0=ryh46BdO<5a#agpg znsl5%^_|VA-u?nWY-R@^6Vj`aGz6stR+uiOPoAiW)0r@e2*4r)Kmar}*h4CV)(CMyG%G zUXLGJs%US}E;-J?ltM_Y6*wNI;r4g$O4PfcIkQVd%Pdf<6eoGvcvO7#?RDeuA=5m* zFl|=%8|8!LLZM}|FijKl)q|)VFoNcn135P|Sm?lSHw%izgPwxs(s=zSXV^0N|f?n7i9Q;69(zJEe_?B+XTd)ND4;AG&b; z2ZfldZ>e#luMGriwG$qEy=jJ8lUQwD}gfTg*#aNbfl&G-Z&IH@* ov2*{^1N+Tuqme)FIL_VQ0q|?bwe}FZ2LJ#707*qoM6N<$f(CE7!vFvP diff --git a/old/icon/22x22/22x22.png b/old/icon/22x22/22x22.png deleted file mode 100644 index d005088ac4b5872a8f31dba7feef0104153847c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1369 zcmV-f1*ZCmP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc2 z1v(0#yOKiy000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000EENkl3l<7D!xG(W|1!mBKWBkM-fR#ww!bC=Vj;pJkN7K_jBJ@A2!X2mIPg&uj|L3|Mdp^ zPeFH+6l>e!NsYz=v5BN7naSHd6Q*(Ch@t-z_!#$jF7$S7p3G#oz3Xjl%8m@rnux`H znQYD~6s(b=<(yCE`Rje}8)t4;@4gdw_KtN&9M*5yQZ9#Ctgd$wA;UC-LRev~b)Ad! z+JIL#NA3-DxA%%(0DN=3>vqsre*G*Qi^q27vpGo9!pTe!k~LTpmMoRQe3in&SAs0Rw&1Tumnc4HmaN?B4QFn(}t81j?&PI;rF7ldkEbVY1R3U;Pvn9 zojaTy|5z&xVG9V;f@KtOI!1WhI}FnjkWxV@4b2RIQCsC*+}dFu1z_9}EEZP0A#8h< zBPDEM!?FY{!{Dr8P*pK&Rifaw9YtDc=qXD$6wnbv`3A0x$&Tw@&+z!MH}`r9#p08O zVQ?;&M>dm1CY?eylOd!H^Q$igTBMewlxC$FiWyonISN?Q$a|O(zRvR84DJ}Xd`Q?L zva2@G&;1+5MQyz2}@em6t$yceFR z%$T|7Su-o8VB0oqAs|eP?O3)@98FvR(0Oq<@U&tAYldcqW6-s_q`5GslEXo zPbYS0&CHso{Zmj%K{}G?T4oT869969!?{aBQM;N}t9i;)r3iHq)zmb%Wc>`VqtyY{ zOsq9nYp`NyrQnlrjP|Ri0JHE6f{qK!`;*f8QpoySCtU=HqFx7hV3)ExIE zO`02NAh&xJ0n7|4^_Ae|N1AEN+Esp^-(UHAe>^H|jsg_jw{uzaL|b2QQq^$W2vOV& zAz=g&%X>LFdgUz4*q1jJglfu1$m`w-mn*=`{My!L`sw?AeDL8>Y}>F9iOCc;J-ig9 zeiww9LpbPxWov4v4T7|T1^1U@>&lQl(tGCfLO$Daqj~(}mESmHy$Y#pVy19O84r&P z;iVUMA(eL!tt>-RwTb@D)7ZG83h}W4G}W4TbZHsesct;AVU`-d+L3Lsj>b(y!}xdKQJ#0nIFgH{z0T=07lWk=vV^F8f#GEu}N8ZQ%l1k zR(&lkEdv0mZ@m>7iS#*-HS3Rao%Zt056-XHzHtE^KluydsRCTYJebf_9r5CP*EKZG zpM&#fT8+MrpTC*YP=9sNqD4yzg~I8co}Sh_eGsBRw2=|n1#)ddSw)>YSW~K`>Gt{q zjw~cix15|%>Cp~2vX{_W>^0aU`}X&{e(HrN$nEftiN0x$$%5Wpk= bd28WcbNA9Q<1SB+00000NkvXXu0mjfRU2=; diff --git a/old/icon/256x256/256x256.png b/old/icon/256x256/256x256.png deleted file mode 100644 index c6a6b5fd271a52316ffc2c70fecac5f2579a2c93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53136 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 diff --git a/old/qgrive/CMakeLists.txt b/old/qgrive/CMakeLists.txt deleted file mode 100644 index 56f882ac..00000000 --- a/old/qgrive/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -## QGrive, Qt interface for libgrive -project ( qgrive ) - -## Declare sources and headers -file( GLOB QGRIVE_SOURCES - src/*.cc -) - -file( GLOB QGRIVE_HEADERS - include/*.hh -) - -include( ${QT_USE_FILE} ) -include_directories( - ${libgrive_SOURCE_DIR}/src - ${qgrive_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR} -) - -add_definitions( ${QT_DEFINITIONS} ) - -## Generate moc files -qt4_wrap_cpp ( QGRIVE_HEADERS_MOC ${QGRIVE_HEADERS} ) - -## Generate the .ui file -qt4_wrap_ui ( QGRIVE_HEADERS_UI ui/mainwindow.ui ) - -add_executable( qgrive ${QGRIVE_SOURCES} ${QGRIVE_HEADERS_MOC} ${QGRIVE_HEADERS_UI} ) -target_link_libraries( qgrive ${QT_LIBRARIES} grive ) \ No newline at end of file diff --git a/old/qgrive/include/QGriveApplication.hh b/old/qgrive/include/QGriveApplication.hh deleted file mode 100644 index 6872f41b..00000000 --- a/old/qgrive/include/QGriveApplication.hh +++ /dev/null @@ -1,64 +0,0 @@ -/* - qgrive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) - Copyright (C) 2012 Massimo Gengarelli (qgrive) - - 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 -#include - -#include - -#include -#include -#include - -class QGriveException : public std::runtime_error -{ -public: - explicit QGriveException( const std::string& exception_msg ) ; - virtual ~QGriveException( ) throw( ) ; - const char* what( ) const throw( ) ; - -private: - std::string _exception_msg; -}; - - -class QGriveApplication : public QApplication -{ -public: - explicit QGriveApplication( int argc, char *argv[] ) ; - virtual ~QGriveApplication( ) ; - - void setup_environment( ) throw ( QGriveException ) ; - int exec( ) ; - - // Logging facility - friend std::ostream& operator<<( std::ostream& os, - const QGriveApplication& application ) ; - -private: - bool _config_by_env; - bool _config_by_file; - std::string _config_file; - std::string _config_env; - QGriveMainWindow _main_window; - gr::Json _configuration; -}; diff --git a/old/qgrive/include/QGriveMainWindow.hh b/old/qgrive/include/QGriveMainWindow.hh deleted file mode 100644 index c3c04ef1..00000000 --- a/old/qgrive/include/QGriveMainWindow.hh +++ /dev/null @@ -1,57 +0,0 @@ -/* - qgrive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) - Copyright (C) 2012 Massimo Gengarelli (qgrive) - - 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 -#include - -#include -#include -#include - -// Forward declarations for Qt generated files -namespace Ui { - class QGriveMainWindow; -} - -class QGriveMainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit QGriveMainWindow( ); - virtual ~QGriveMainWindow( ); - - void activate_log( ) ; - -signals: - -public slots: - -private slots: - void refresh_tree( ) ; - void sync_directory( ) ; - -private: - Ui::QGriveMainWindow* ui ; - - bool _log_activated ; -}; diff --git a/old/qgrive/src/QGriveApplication.cc b/old/qgrive/src/QGriveApplication.cc deleted file mode 100644 index 99893897..00000000 --- a/old/qgrive/src/QGriveApplication.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* - qgrive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) - Copyright (C) 2012 Massimo Gengarelli (qgrive) - - 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 -#include - -#include -#include -#include -#include -#include -#include - -QGriveException::QGriveException( const std::string& exception_msg ) - : std::runtime_error( exception_msg ), - _exception_msg( exception_msg ) -{ - -} - - -QGriveException::~QGriveException( ) throw ( ) -{ - -} - -const char* QGriveException::what( ) const throw( ) -{ - return _exception_msg.c_str() ; -} - -std::ostream& operator<<( std::ostream& os, - const QGriveApplication& application ) -{ - if ( application._config_by_env ) - { - os << "Using env: " << application._config_env ; - } - - else - { - os << "Using file: " << application._config_file ; - } - - return os ; -} - - -QGriveApplication::QGriveApplication( int argc, char *argv[] ) - : QApplication( argc, argv ), - _config_by_env( false ), - _config_by_file( false ) -{ - -} - -QGriveApplication::~QGriveApplication() -{ - -} - -void QGriveApplication::setup_environment( ) throw ( QGriveException ) -{ - const char* env_cfg = getenv( "GR_CONFIG" ) ; - - if ( env_cfg ) - { - _config_env = getenv( "GR_CONFIG" ) ; - _config_by_env = true ; - } - else - { - _config_file = "./.grive" ; - _config_by_file = true ; - } -} - -int QGriveApplication::exec( ) -{ - _main_window.show( ) ; - _main_window.activate_log( ) ; - return QApplication::exec( ) ; -} diff --git a/old/qgrive/src/QGriveMainWindow.cc b/old/qgrive/src/QGriveMainWindow.cc deleted file mode 100644 index 654310d4..00000000 --- a/old/qgrive/src/QGriveMainWindow.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* - qgrive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) - Copyright (C) 2012 Massimo Gengarelli (qgrive) - - 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 -#include -#include -#include -#include -#include -#include "ui_mainwindow.h" - - -QGriveMainWindow::QGriveMainWindow( ) : - QMainWindow(0), - ui(new Ui::QGriveMainWindow), - _log_activated(false) -{ - ui->setupUi(this); - - QObject::connect( ui->refresh_btn, - SIGNAL(clicked()), - this, - SLOT(refresh_tree()) ) ; - - QObject::connect( ui->launch_sync_btn, - SIGNAL(clicked()), - this, - SLOT(sync_directory()) ) ; - - ui->statusbar->setEnabled( true ) ; - ui->statusbar->addWidget( new QLabel(" Welcome to QGrive!! ") ) ; -} - -QGriveMainWindow::~QGriveMainWindow( ) -{ - -} - -void QGriveMainWindow::activate_log( ) -{ - _log_activated = true ; - std::cout << "LOG ACTIVATED" << std::endl ; -} - -void QGriveMainWindow::refresh_tree( ) -{ - if (_log_activated) - { - std::cout << "refresh_tree()" << std::endl; - } -} - -void QGriveMainWindow::sync_directory( ) -{ - if (_log_activated) - { - std::cout << "sync_directory()" << std::endl; - } - -} diff --git a/old/qgrive/src/main.cc b/old/qgrive/src/main.cc deleted file mode 100644 index 0f00709c..00000000 --- a/old/qgrive/src/main.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* - qgrive: an GPL program to sync a local directory with Google Drive - Copyright (C) 2012 Wan Wai Ho (libgrive + original idea) - Copyright (C) 2012 Massimo Gengarelli (qgrive) - - 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 -#include -#include -#include -#include - -int main ( int argc, char *argv[] ) -{ - QGriveApplication app( argc, argv ) ; - app.setup_environment( ) ; - - std::ofstream log_file( "qgrive.log", std::ios_base::out|std::ios_base::app ) ; - log_file << " ==== starting log ====" << std::endl ; - - log_file << app << std::endl ; - - int ret_value = app.exec( ) ; - - log_file << " ==== closing log ====" << std::endl << std::endl ; - log_file.close( ) ; - - return ret_value; -} diff --git a/old/qgrive/ui/mainwindow.ui b/old/qgrive/ui/mainwindow.ui deleted file mode 100644 index f38b701c..00000000 --- a/old/qgrive/ui/mainwindow.ui +++ /dev/null @@ -1,75 +0,0 @@ - - - QGriveMainWindow - - - - 0 - 0 - 586 - 407 - - - - QGrive - - - - - - - - - - 1 - - - - - - - - QTextEdit::NoWrap - - - true - - - - - - - - - - - Refresh - - - - - - - Launch sync - - - - - - - - - - - 0 - 0 - 586 - 22 - - - - - - - - From 1a77f08d40b8b1cc7d1187a965a223d2418273ea Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Mon, 13 Oct 2014 13:34:14 -0400 Subject: [PATCH 74/79] Update README --- README | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README b/README index 6eb2374a..25cea89a 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ Grive 0.3.1 -29 September 2014 +13 October 2014 Command line Google Drive Sync @@ -53,6 +53,11 @@ Enjoy! Version History: +Grive v0.3.1: +Merge Many forks (bug fixes and features) into linwiz/grive. +Remove useless bgrive/qgrive. + + Grive v0.3: Bug fix & minor feature release Fixed bugs: #93: missing reference count increment in one of the Json constructors From f80852aeda01aba06f5ce0765bcf552383dbf473 Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Mon, 13 Oct 2014 13:35:08 -0400 Subject: [PATCH 75/79] Update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 25cea89a..c1b631f1 100644 --- a/README +++ b/README @@ -55,7 +55,7 @@ Version History: Grive v0.3.1: Merge Many forks (bug fixes and features) into linwiz/grive. -Remove useless bgrive/qgrive. +Remove useless code: bgrive and qgrive. Grive v0.3: Bug fix & minor feature release From e9285f9626f105f60fe19af7c65559ddae17da40 Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Mon, 13 Oct 2014 13:37:28 -0400 Subject: [PATCH 76/79] Delete .travis.yml --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9eb7f2da..00000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: cpp -compiler: - - gcc - - clang -script: cmake . && make From f8e0fc7f201ce1a45e9a3e42c61a114e42ff5a10 Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Sat, 8 Nov 2014 16:07:52 -0500 Subject: [PATCH 77/79] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73b1b0ce..45c80093 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) # Grive version. remember to update it for every new release! -set( GRIVE_VERSION "0.3.1-pre" ) +set( GRIVE_VERSION "0.3.0-pre" ) # common compile options add_definitions( -DVERSION="${GRIVE_VERSION}" ) From 1711df2ef76af221c492a68bc2630032aa6fefac Mon Sep 17 00:00:00 2001 From: Matthew Motz Date: Sat, 8 Nov 2014 16:08:16 -0500 Subject: [PATCH 78/79] Update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index c1b631f1..fd1f67f0 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Grive 0.3.1 +Grive 0.3.0 13 October 2014 Command line Google Drive Sync From b230a1c8c31009f29d1592a73c6bfafed95d7c5f Mon Sep 17 00:00:00 2001 From: Christoph Junghans Date: Wed, 19 Nov 2014 11:42:02 -0700 Subject: [PATCH 79/79] cmake: use pkg-config to find json-c --- cmake/Modules/FindJSONC.cmake | 8 ++++++-- libgrive/CMakeLists.txt | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindJSONC.cmake b/cmake/Modules/FindJSONC.cmake index 9c6d6c8a..15a09b78 100644 --- a/cmake/Modules/FindJSONC.cmake +++ b/cmake/Modules/FindJSONC.cmake @@ -6,8 +6,12 @@ # JSONC_INCLUDE_DIR - The JSON-C include directory. # JSONC_LIBRARY - The JSON-C library to link against. -FIND_PATH(JSONC_INCLUDE_DIR json/json.h json-c/json.h) -FIND_LIBRARY(JSONC_LIBRARY NAMES json json-c) +find_package(PkgConfig) + +pkg_check_modules(PC_JSONC json-c) + +FIND_PATH(JSONC_INCLUDE_DIR json/json.h json-c/json.h HINTS ${PC_JSONC_INCLUDE_DIRS} ) +FIND_LIBRARY(JSONC_LIBRARY NAMES json json-c HINTS ${PC_JSONC_LIBRARY_DIRS} ) IF (JSONC_INCLUDE_DIR AND JSONC_LIBRARY) SET(JSONC_FOUND TRUE) diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index efcd102c..d75e4e66 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -4,6 +4,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") find_package(LibGcrypt REQUIRED) find_package(JSONC REQUIRED) +include_directories(${JSONC_INCLUDE_DIR}) find_package(CURL REQUIRED) find_package(EXPAT REQUIRED) find_package(YAJL REQUIRED)