From 02f467a25bf5169d534f2dfcb0a454d6a87a2bc4 Mon Sep 17 00:00:00 2001 From: Dmitri Vereshchagin Date: Sun, 14 Aug 2016 14:58:48 +0300 Subject: [PATCH] Add glob patterns for --include option --- CMakeLists.txt | 1 + doc/innoextract.1 | 2 +- src/cli/extract.cpp | 63 +++++++++++++++++++++++++++++------------- src/setup/filename.hpp | 4 +++ 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9f35164..5f035cb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ find_package(Boost REQUIRED COMPONENTS date_time system program_options + regex ) check_link_library(Boost Boost_LIBRARIES) list(APPEND LIBRARIES ${Boost_LIBRARIES}) diff --git a/doc/innoextract.1 b/doc/innoextract.1 index a101b426..75ded0d6 100644 --- a/doc/innoextract.1 +++ b/doc/innoextract.1 @@ -149,7 +149,7 @@ Show a list of the supported options. \fB\-I\fP, \fB\-\-include\fP \fIEXPR\fP If this option is specified, innoextract will only process files whose path matches \fIEXPR\fP. The expression can be either a single path component (a file or directory name) or a series of successive path components joined by the OS path separator (\\ on Windows, / elsewhere). -The expression is always matched against one or more full path components. Filtering by parts of filenames is currently not supported. Matching is done case-insensitively. +The expression is always matched against one or more full path components. Matching is done case-insensitively. Each path component may contain wildcard characters. A '\fB*\fP' matches any part of path component, but it stops at path separator. A '\fB?\fP' matches any character except a path separator. \fIEXPR\fP may contain one leading path separator, in which case the rest of the expression is matched against the start of the path. Otherwise, the expression is matched against any part of the path. diff --git a/src/cli/extract.cpp b/src/cli/extract.cpp index 8fe500c0..7fc4d501 100644 --- a/src/cli/extract.cpp +++ b/src/cli/extract.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #if BOOST_VERSION >= 104800 @@ -168,19 +169,13 @@ typedef processed_item processed_directory; class path_filter { - typedef std::pair Filter; - std::vector includes; + std::vector includes; public: explicit path_filter(const extract_options & o) { BOOST_FOREACH(const std::string & include, o.include) { - if(!include.empty() && include[0] == setup::path_sep) { - includes.push_back(Filter(true, boost::to_lower_copy(include) + setup::path_sep)); - } else { - includes.push_back(Filter(false, setup::path_sep + boost::to_lower_copy(include) - + setup::path_sep)); - } + includes.push_back(translate_glob(include)); } } @@ -190,22 +185,52 @@ class path_filter { return true; } - BOOST_FOREACH(const Filter & i, includes) { - if(i.first) { - if(!i.second.compare(1, i.second.size() - 1, - path + setup::path_sep, 0, i.second.size() - 1)) { - return true; - } - } else { - if((setup::path_sep + path + setup::path_sep).find(i.second) != std::string::npos) { - return true; - } + BOOST_FOREACH(const boost::regex & e, includes) { + if(boost::regex_search(setup::path_sep + path + setup::path_sep, e)) { + return true; } } return false; } - + +private: + + static boost::regex translate_glob(const std::string & glob) { + + std::string e = !glob.empty() && glob[0] == setup::path_sep + ? "^" : setup::regex_path_sep; + + char prev = '\0'; + BOOST_FOREACH(char c, glob) { + e += translate_wildcards(c, prev); + prev = c; + } + + e += setup::regex_path_sep; + + return boost::regex(e, boost::regex::basic | boost::regex::icase); + } + + static std::string translate_wildcards(char c, char prev) { + + if(prev != '\\') { + if(c == '*') { + return setup::regex_not_path_sep + "*"; + } + + if(c == '?') { + return setup::regex_not_path_sep; + } + + if(std::string("^.[$\\").find(c) != std::string::npos) { + return std::string("\\") + c; + } + } + + return std::string() + c; + } + }; static void print_filter_info(const setup::item & item, bool temp) { diff --git a/src/setup/filename.hpp b/src/setup/filename.hpp index 978cfed2..c0bcc3ee 100644 --- a/src/setup/filename.hpp +++ b/src/setup/filename.hpp @@ -34,8 +34,12 @@ namespace setup { //! Separator to use for output paths. #if defined(_WIN32) static const char path_sep = '\\'; +static const std::string regex_path_sep = "\\\\"; +static const std::string regex_not_path_sep = "[^\\]"; #else static const char path_sep = '/'; +static const std::string regex_path_sep = "/"; +static const std::string regex_not_path_sep = "[^/]"; #endif /*!