From 1364f36abaf0605b606bc0d26fdf5bc8d740ee70 Mon Sep 17 00:00:00 2001 From: abraunegg Date: Wed, 16 Sep 2020 17:03:00 +1000 Subject: [PATCH] Support wildcard within sync_list entries (#1063) * Support wildcard within sync_list entries * Update usage documentation --- docs/USAGE.md | 2 ++ src/selective.d | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/USAGE.md b/docs/USAGE.md index fcf11bb5..76ab01a5 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -425,6 +425,8 @@ Here is an example of `sync_list`: Backup # Include this single document Documents/latest_report.docx +# Include all PDF documents +Documents/*.pdf # Include all Work/Project directories Work/Project* notes.txt diff --git a/src/selective.d b/src/selective.d index 36b37889..362f11b3 100644 --- a/src/selective.d +++ b/src/selective.d @@ -4,6 +4,7 @@ import std.file; import std.path; import std.regex; import std.stdio; +import std.string; import util; import log; @@ -128,6 +129,8 @@ final class SelectiveSync // Match against sync_list only bool isPathExcludedViaSyncList(string path) { + // Debug output that we are performing a 'sync_list' inclusion / exclusion test + log.vdebug("sync_list evaluation for: ", path); return .isPathExcluded(path, paths); } @@ -194,23 +197,46 @@ final class SelectiveSync // if there are no allowed paths always return false private bool isPathExcluded(string path, string[] allowedPaths) { + string wildcard = "*"; // always allow the root if (path == ".") return false; // if there are no allowed paths always return false if (allowedPaths.empty) return false; - path = buildNormalizedPath(path); + foreach (allowed; allowedPaths) { auto comm = commonPrefix(path, allowed); + // What are we comparing against? + log.vdebug("Evaluation against 'sync_list' entry: ", allowed); + // is path is an exact match if (comm.length == path.length) { // the given path is contained in an allowed path + log.vdebug("Evaluation against 'sync_list' result - direct match"); return false; } + // is path is a subitem if (comm.length == allowed.length && path[comm.length] == '/') { // the given path is a subitem of an allowed path + log.vdebug("Evaluation against 'sync_list' result - parental path match"); return false; } + + // does the allowed path contain a wildcard? (*) + if (canFind(allowed, wildcard)) { + // allowed path contains a wildcard + // manually escape '/' + string escapedAllowed = replace(allowed, "/", "\\/"); + // manually escape '*' + escapedAllowed = replace(escapedAllowed, "*", ".*"); + auto allowedMask = regex(escapedAllowed); + if (matchAll(path, allowedMask)) { + // regex wildcard evaluation matches + log.vdebug("Evaluation against 'sync_list' result - wildcard pattern match"); + return false; + } + } } + log.vdebug("Evaluation against 'sync_list' result - NO MATCH"); return true; }