Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kamm <mail@ckamm.de>2017-11-28 11:41:52 +0300
committerckamm <mail@ckamm.de>2017-12-07 16:38:21 +0300
commit1c3d5ab15860809f4e437b95dde2cb5926f84bae (patch)
treec4e0b3875c33000bb058ab1a71fe3a48a2c2667d
parent5d668eca4062a89525a8ff7544c533aa33f30bec (diff)
Excludes: Introduce dir-only regex matches
-rw-r--r--src/csync/csync_exclude.cpp62
-rw-r--r--src/csync/csync_exclude.h3
-rw-r--r--test/csync/csync_tests/check_csync_exclude.cpp31
3 files changed, 75 insertions, 21 deletions
diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp
index 37f898486..b3220d59e 100644
--- a/src/csync/csync_exclude.cpp
+++ b/src/csync/csync_exclude.cpp
@@ -463,7 +463,7 @@ void ExcludedFiles::clearManualExcludes()
bool ExcludedFiles::reloadExcludeFiles()
{
_allExcludes.clear();
- _regex = QRegularExpression();
+ _bnameRegexFileDir = QRegularExpression();
bool success = true;
foreach (const QString &file, _excludeFiles) {
@@ -538,7 +538,12 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const char *path, int fi
bname = path;
}
QString p = QString::fromUtf8(bname);
- auto m = _regex.match(p);
+ QRegularExpressionMatch m;
+ if (filetype == CSYNC_FTW_TYPE_DIR) {
+ m = _bnameRegexDir.match(p);
+ } else {
+ m = _bnameRegexFileDir.match(p);
+ }
if (m.hasMatch()) {
if (!m.captured(1).isEmpty()) {
match = CSYNC_FILE_EXCLUDE_LIST;
@@ -552,6 +557,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const char *path, int fi
CSYNC_EXCLUDE_TYPE ExcludedFiles::fullPatternMatch(const char *path, int filetype) const
{
+ // bname check must also apply to all path components
return _csync_excluded_common(_allExcludes, path, filetype, true);
}
@@ -573,39 +579,59 @@ void ExcludedFiles::prepare()
_nonRegexExcludes.clear();
// Start out with regexes that would match nothing
- QString exclude_only = "a^";
- QString exclude_and_remove = "a^";
+ QString patternFileDirKeep = "a^";
+ QString patternFileDirRemove = "a^";
+ QString patternDirKeep = "a^";
+ QString patternDirRemove = "a^";
+ auto regexAppend = [](QString &pattern, QString v) {
+ if (!pattern.isEmpty())
+ pattern.append("|");
+ pattern.append(v);
+ };
for (auto exclude : _allExcludes) {
- QString *builderToUse = &exclude_only;
if (exclude[0] == '\n')
continue; // empty line
if (exclude[0] == '\r')
continue; // empty line
+ bool matchDirOnly = exclude.endsWith('/');
+ if (matchDirOnly)
+ exclude = exclude.left(exclude.size() - 1);
+
+ bool removeExcluded = (exclude[0] == ']');
+ if (removeExcluded)
+ exclude = exclude.mid(1);
+
/* If an exclude entry contains some fnmatch-ish characters, we use the C-style codepath without QRegularEpression */
if (strchr(exclude, '/') || strchr(exclude, '[') || strchr(exclude, '{') || strchr(exclude, '\\')) {
_nonRegexExcludes.append(exclude);
continue;
}
- /* Those will attempt to use QRegularExpression */
- if (exclude[0] == ']') {
- exclude = exclude.mid(1);
- builderToUse = &exclude_and_remove;
- }
- if (builderToUse->size() > 0) {
- builderToUse->append("|");
- }
- builderToUse->append(convertToBnameRegexpSyntax(QString::fromUtf8(exclude)));
+ /* Use QRegularExpression, append to the right pattern */
+ auto &patternFileDir = removeExcluded ? patternFileDirRemove : patternFileDirKeep;
+ auto &patternDir = removeExcluded ? patternDirRemove : patternDirKeep;
+
+ auto regexExclude = convertToBnameRegexpSyntax(QString::fromUtf8(exclude));
+ // patterns always match against directories
+ regexAppend(patternDir, regexExclude);
+ // but some don't match against files
+ if (!matchDirOnly)
+ regexAppend(patternFileDir, regexExclude);
}
- QString pattern = "^(" + exclude_only + ")$|^(" + exclude_and_remove + ")$";
- _regex.setPattern(pattern);
+ _bnameRegexFileDir.setPattern(
+ "^(" + patternFileDirKeep + ")$|^(" + patternFileDirRemove + ")$");
+ _bnameRegexDir.setPattern(
+ "^(" + patternDirKeep + ")$|^(" + patternDirRemove + ")$");
+
QRegularExpression::PatternOptions patternOptions = QRegularExpression::OptimizeOnFirstUsageOption;
if (OCC::Utility::fsCasePreserving())
patternOptions |= QRegularExpression::CaseInsensitiveOption;
- _regex.setPatternOptions(patternOptions);
- _regex.optimize();
+ _bnameRegexFileDir.setPatternOptions(patternOptions);
+ _bnameRegexFileDir.optimize();
+ _bnameRegexDir.setPatternOptions(patternOptions);
+ _bnameRegexDir.optimize();
}
diff --git a/src/csync/csync_exclude.h b/src/csync/csync_exclude.h
index 7dc5808bd..08d0a63b1 100644
--- a/src/csync/csync_exclude.h
+++ b/src/csync/csync_exclude.h
@@ -165,7 +165,8 @@ private:
QList<QByteArray> _nonRegexExcludes;
/// see prepare()
- QRegularExpression _regex;
+ QRegularExpression _bnameRegexFileDir;
+ QRegularExpression _bnameRegexDir;
};
#endif /* _CSYNC_EXCLUDE_H */
diff --git a/test/csync/csync_tests/check_csync_exclude.cpp b/test/csync/csync_tests/check_csync_exclude.cpp
index 9329ca6de..c8e3a48ad 100644
--- a/test/csync/csync_tests/check_csync_exclude.cpp
+++ b/test/csync/csync_tests/check_csync_exclude.cpp
@@ -113,12 +113,12 @@ static void check_csync_exclude_add(void **)
excludedFiles->prepare();
assert_true(excludedFiles->_nonRegexExcludes.contains("/tmp/check_csync1/*"));
- assert_false(excludedFiles->_regex.pattern().contains("csync1"));
+ assert_false(excludedFiles->_bnameRegexFileDir.pattern().contains("csync1"));
excludedFiles->addManualExclude("foo");
excludedFiles->prepare();
assert_true(excludedFiles->_nonRegexExcludes.size() == 1);
- assert_true(excludedFiles->_regex.pattern().contains("foo"));
+ assert_true(excludedFiles->_bnameRegexFileDir.pattern().contains("foo"));
}
static void check_csync_excluded(void **)
@@ -356,6 +356,32 @@ static void check_csync_excluded_traversal(void **)
assert_int_equal(check_file_traversal("a * ?"), CSYNC_FILE_EXCLUDE_LIST);
}
+static void check_csync_dir_only(void **)
+{
+ excludedFiles->addManualExclude("filedir");
+ excludedFiles->addManualExclude("dir/");
+ excludedFiles->prepare();
+
+ assert_int_equal(check_file_traversal("other"), CSYNC_NOT_EXCLUDED);
+ assert_int_equal(check_file_traversal("filedir"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_file_traversal("dir"), CSYNC_NOT_EXCLUDED);
+ assert_int_equal(check_file_traversal("s/other"), CSYNC_NOT_EXCLUDED);
+ assert_int_equal(check_file_traversal("s/filedir"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_file_traversal("s/dir"), CSYNC_NOT_EXCLUDED);
+
+ assert_int_equal(check_dir_traversal("other"), CSYNC_NOT_EXCLUDED);
+ assert_int_equal(check_dir_traversal("filedir"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_dir_traversal("dir"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_dir_traversal("s/other"), CSYNC_NOT_EXCLUDED);
+ assert_int_equal(check_dir_traversal("s/filedir"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_dir_traversal("s/dir"), CSYNC_FILE_EXCLUDE_LIST);
+
+ assert_int_equal(check_dir_full("filedir/foo"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_file_full("filedir/foo"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_dir_full("dir/foo"), CSYNC_FILE_EXCLUDE_LIST);
+ assert_int_equal(check_file_full("dir/foo"), CSYNC_FILE_EXCLUDE_LIST);
+}
+
static void check_csync_pathes(void **)
{
excludedFiles->addManualExclude("/exclude");
@@ -495,6 +521,7 @@ int torture_run_tests(void)
cmocka_unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
+ cmocka_unit_test_setup_teardown(check_csync_dir_only, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),