diff --git a/grive/src/main.cc b/grive/src/main.cc index f151e4b..07fd613 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -120,6 +120,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." ) + ( "ignore", po::value(), "Ignore files relative paths of which match this Perl RegExp." ) ; po::variables_map vm; diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index cbbde55..f3aa775 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") find_package(LibGcrypt 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(Boost 1.40.0 COMPONENTS program_options filesystem unit_test_framework regex system REQUIRED) find_package(BFD) find_package(CppUnit) find_package(Iberty) diff --git a/libgrive/src/base/Resource.cc b/libgrive/src/base/Resource.cc index 058f08f..e206ebc 100644 --- a/libgrive/src/base/Resource.cc +++ b/libgrive/src/base/Resource.cc @@ -337,6 +337,15 @@ fs::path Resource::Path() const return m_parent != 0 ? (m_parent->Path() / m_name) : m_name ; } +// Path relative to the root directory +fs::path Resource::RelPath() const +{ + assert( m_parent != this ) ; + assert( m_parent == 0 || m_parent->IsFolder() ) ; + + return m_parent != 0 && !m_parent->IsRoot() ? (m_parent->Path() / m_name) : m_name ; +} + bool Resource::IsInRootTree() const { assert( m_parent == 0 || m_parent->IsFolder() ) ; diff --git a/libgrive/src/base/Resource.hh b/libgrive/src/base/Resource.hh index efb0d5f..06a61a4 100644 --- a/libgrive/src/base/Resource.hh +++ b/libgrive/src/base/Resource.hh @@ -100,6 +100,7 @@ public : Resource* FindChild( const std::string& title ) ; fs::path Path() const ; + fs::path RelPath() const ; bool IsInRootTree() const ; bool IsRoot() const ; bool HasID() const ; diff --git a/libgrive/src/base/State.cc b/libgrive/src/base/State.cc index 4aaaf22..fa1e037 100644 --- a/libgrive/src/base/State.cc +++ b/libgrive/src/base/State.cc @@ -36,11 +36,12 @@ namespace gr { State::State( const fs::path& filename, const Val& options ) : m_res ( options["path"].Str() ), m_dir ( options["dir"].Str() ), - m_cstamp ( -1 ) + m_cstamp ( -1 ), + m_ign ( !options["ignore"].Str().empty() ? options["ignore"].Str()+"|^\\.(grive|grive_state|trash)" : "^\\.(grive|grive_state|trash)" ) { Read( filename ) ; - // the "-f" option will make grive always thinks remote is newer + // the "-f" option will make grive always think remote is newer Val force ; if ( options.Get("force", force) && force.Bool() ) m_last_sync = DateTime() ; @@ -61,7 +62,7 @@ void State::FromLocal( const fs::path& p ) bool State::IsIgnore( const std::string& filename ) { - return filename == ".grive" || filename == ".grive_state" || filename == ".trash"; + return regex_match( filename.c_str(), m_ign ); } void State::FromLocal( const fs::path& p, Resource* folder ) @@ -77,8 +78,9 @@ void State::FromLocal( const fs::path& p, Resource* folder ) std::string fname = i->path().filename().string() ; fs::file_status st = fs::status(i->path()); - if ( IsIgnore(fname) ) - Log( "file %1% is ignored by grive", fname, log::verbose ) ; + std::string path = folder->IsRoot() ? fname : ( folder->RelPath() / fname ).string(); + if ( IsIgnore( path ) ) + Log( "file %1% is ignored by grive", path, log::verbose ) ; // check if it is ignored else if ( folder == m_res.Root() && m_dir != "" && fname != m_dir ) @@ -114,11 +116,7 @@ void State::FromRemote( const Entry& e ) std::string fn = e.Filename() ; std::string k = e.IsDir() ? "folder" : "file"; - if ( IsIgnore( e.Name() ) ) - Log( "%1% %2% is ignored by grive", k, e.Name(), log::verbose ) ; - - // check if it is ignored - else if ( e.ParentHref() == m_res.Root()->SelfHref() && m_dir != "" && e.Name() != m_dir ) + if ( e.ParentHref() == m_res.Root()->SelfHref() && m_dir != "" && e.Name() != m_dir ) Log( "%1% %2% is ignored", k, e.Name(), log::verbose ); // common checkings @@ -170,7 +168,6 @@ std::size_t State::TryResolveEntry() 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 @@ -185,13 +182,25 @@ bool State::Update( const Entry& e ) if ( Resource *res = m_res.FindByHref( e.SelfHref() ) ) { + std::string path = res->RelPath().string(); + if ( IsIgnore( path ) ) + { + Log( "%1% is ignored by grive", path, log::verbose ) ; + return true; + } m_res.Update( res, e, m_last_sync ) ; - return true ; } else if ( Resource *parent = m_res.FindByHref( e.ParentHref() ) ) { assert( parent->IsFolder() ) ; + std::string path = parent->IsRoot() ? e.Name() : ( parent->RelPath() / e.Name() ).string(); + if ( IsIgnore( path ) ) + { + Log( "%1% is ignored by grive", path, log::verbose ) ; + return true; + } + // see if the entry already exist in local std::string name = e.Name() ; Resource *child = parent->FindChild( name ) ; diff --git a/libgrive/src/base/State.hh b/libgrive/src/base/State.hh index c870cae..acbb699 100644 --- a/libgrive/src/base/State.hh +++ b/libgrive/src/base/State.hh @@ -25,6 +25,7 @@ #include "util/FileSystem.hh" #include +#include namespace gr { @@ -69,13 +70,14 @@ private : bool Update( const Entry& e ) ; std::size_t TryResolveEntry() ; - static bool IsIgnore( const std::string& filename ) ; + bool IsIgnore( const std::string& filename ) ; private : ResourceTree m_res ; DateTime m_last_sync ; int m_cstamp ; std::string m_dir ; + boost::regex m_ign ; std::vector m_unresolved ; } ; diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index ca7c86a..c1c53ea 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -47,6 +47,9 @@ Config::Config( const po::variables_map& vm ) m_cmd.Add( "dir", Val(vm.count("dir") > 0 ? vm["dir"].as() : "" ) ) ; + m_cmd.Add( "ignore", Val(vm.count("ignore") > 0 + ? vm["ignore"].as() + : "" ) ) ; m_path = GetPath( fs::path(m_cmd["path"].Str()) ) ; m_file = Read( ) ;