Update skip_dotfiles handling of .folders when in monitor mode (#848)

* Prevent monitoring files inside .folders when using skip_dotfiles in monitor mode
* Handle '.folder' -> 'folder' move when skip_dotfiles is enabled
This commit is contained in:
abraunegg 2020-04-06 20:05:06 +10:00 committed by GitHub
parent 31629e697f
commit 7a18393ed0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 100 additions and 23 deletions

View file

@ -529,17 +529,27 @@ int main(string[] args)
}
selectiveSync.load(cfg.syncListFilePath);
// Configure skip_dir & skip_file from config entries
// skip_dir items
// Configure skip_dir, skip_file, skip-dir-strict-match & skip_dotfiles from config entries
// Handle skip_dir configuration in config file
log.vdebug("Configuring skip_dir ...");
log.vdebug("skip_dir: ", cfg.getValueString("skip_dir"));
selectiveSync.setDirMask(cfg.getValueString("skip_dir"));
// Was --skip-dir-strict-match configured?
log.vdebug("Configuring skip_dir_strict_match ...");
log.vdebug("skip_dir_strict_match: ", cfg.getValueBool("skip_dir_strict_match"));
if (cfg.getValueBool("skip_dir_strict_match")) {
selectiveSync.setSkipDirStrictMatch();
}
// skip_file items
// Was --skip-dot-files configured?
log.vdebug("Configuring skip_dotfiles ...");
log.vdebug("skip_dotfiles: ", cfg.getValueBool("skip_dotfiles"));
if (cfg.getValueBool("skip_dotfiles")) {
selectiveSync.setSkipDotfiles();
}
// Handle skip_file configuration in config file
log.vdebug("Configuring skip_file ...");
// Validate skip_file to ensure that this does not contain an invalid configuration
// Do not use a skip_file entry of .* as this will prevent correct searching of local changes to process.
@ -550,8 +560,7 @@ int main(string[] args)
return EXIT_FAILURE;
}
}
// valid entry
// All skip_file entries are valid
log.vdebug("skip_file: ", cfg.getValueString("skip_file"));
selectiveSync.setFileMask(cfg.getValueString("skip_file"));
@ -677,13 +686,18 @@ int main(string[] args)
log.log("OneDrive monitor interval (seconds): ", cfg.getValueLong("monitor_interval"));
Monitor m = new Monitor(selectiveSync);
m.onDirCreated = delegate(string path) {
log.vlog("[M] Directory created: ", path);
try {
sync.scanForDifferences(path);
} catch (CurlException e) {
log.vlog("Offline, cannot create remote dir!");
} catch(Exception e) {
log.logAndNotify("Cannot create remote directory: ", e.msg);
// Handle .folder creation if skip_dotfiles is enabled
if ((cfg.getValueBool("skip_dotfiles")) && (selectiveSync.isDotFile(path))) {
log.vlog("[M] Skipping watching path - .folder found & --skip-dot-files enabled: ", path);
} else {
log.vlog("[M] Directory created: ", path);
try {
sync.scanForDifferences(path);
} catch (CurlException e) {
log.vlog("Offline, cannot create remote dir!");
} catch(Exception e) {
log.logAndNotify("Cannot create remote directory: ", e.msg);
}
}
};
m.onFileChanged = delegate(string path) {
@ -704,7 +718,7 @@ int main(string[] args)
log.vlog("Offline, cannot delete item!");
} catch(SyncException e) {
if (e.msg == "The item to delete is not in the local database") {
log.vlog("Item cannot be deleted because not found in database");
log.vlog("Item cannot be deleted from OneDrive because not found in the local database");
} else {
log.logAndNotify("Cannot delete remote item: ", e.msg);
}
@ -715,7 +729,13 @@ int main(string[] args)
m.onMove = delegate(string from, string to) {
log.vlog("[M] Item moved: ", from, " -> ", to);
try {
sync.uploadMoveItem(from, to);
// Handle .folder -> folder if skip_dotfiles is enabled
if ((cfg.getValueBool("skip_dotfiles")) && (selectiveSync.isDotFile(from))) {
// .folder -> folder handling - has to be handled as a new folder
sync.scanForDifferences(to);
} else {
sync.uploadMoveItem(from, to);
}
} catch (CurlException e) {
log.vlog("Offline, cannot move item!");
} catch(Exception e) {

View file

@ -1,7 +1,7 @@
import core.sys.linux.sys.inotify;
import core.stdc.errno;
import core.sys.posix.poll, core.sys.posix.unistd;
import std.exception, std.file, std.path, std.regex, std.stdio, std.string;
import std.exception, std.file, std.path, std.regex, std.stdio, std.string, std.algorithm.mutation;
import config;
import selective;
import util;
@ -85,19 +85,28 @@ final class Monitor
return;
}
// skip filtered items
// skip monitoring any filtered items
if (dirname != ".") {
if (selectiveSync.isDirNameExcluded(strip(dirname,"./"))) {
// is the directory name a match to a skip_dir entry?
if (selectiveSync.isDirNameExcluded(dirname.strip('.').strip('/'))) {
// dont add a watch for this item
log.vdebug("Skipping monitoring due to skip_dir match: ", dirname);
return;
}
// is the filename a match to a skip_file entry?
if (selectiveSync.isFileNameExcluded(baseName(dirname))) {
// dont add a watch for this item
log.vdebug("Skipping monitoring due to skip_file match: ", dirname);
return;
}
// is the path exluded by sync_list?
if (selectiveSync.isPathExcludedViaSyncList(buildNormalizedPath(dirname))) {
// dont add a watch for this item
log.vdebug("Skipping monitoring due to sync_list match: ", dirname);
return;
}
}
// skip symlinks if configured
if (isSymlink(dirname)) {
// if config says so we skip all symlinked items
@ -115,6 +124,7 @@ final class Monitor
}
}
// passed all potential exclusions
add(dirname);
try {
auto pathList = dirEntries(dirname, SpanMode.shallow, false);
@ -148,8 +158,23 @@ final class Monitor
log.error("ERROR: inotify_add_watch failed: ", pathname);
return;
}
// Add path to inotify watch - required regardless if a '.folder' or 'folder'
wdToDirName[wd] = buildNormalizedPath(pathname) ~ "/";
log.vlog("Monitor directory: ", pathname);
// Do we log that we are monitoring this directory?
if (isDir(pathname)) {
// This is a directory
// is the path exluded if skip_dotfiles configured and path is a .folder?
if (selectiveSync.getSkipDotfiles()) {
if (selectiveSync.isDotFile(pathname)) {
// no misleading output that we are monitoring this directory
return;
}
}
// Log that this is directory is being monitored
log.vlog("Monitor directory: ", pathname);
}
}
// remove a watch descriptor
@ -181,6 +206,7 @@ final class Monitor
{
string path = wdToDirName[event.wd];
if (event.len > 0) path ~= fromStringz(event.name.ptr);
log.vdebug("inotify path event for: ", path);
return path;
}
@ -214,16 +240,17 @@ final class Monitor
// skip filtered items
path = getPath(event);
if (selectiveSync.isDirNameExcluded(strip(path,"./"))) {
if (selectiveSync.isDirNameExcluded(path.strip('.').strip('/'))) {
goto skip;
}
if (selectiveSync.isFileNameExcluded(strip(path,"./"))) {
if (selectiveSync.isFileNameExcluded(path.strip('.').strip('/'))) {
goto skip;
}
if (selectiveSync.isPathExcludedViaSyncList(path)) {
goto skip;
}
// handle events
if (event.mask & IN_MOVED_FROM) {
log.vdebug("event IN_MOVED_FROM: ", path);
cookieToPath[event.cookie] = path;

View file

@ -12,6 +12,7 @@ final class SelectiveSync
private Regex!char mask;
private Regex!char dirmask;
private bool skipDirStrictMatch = false;
private bool skipDotfiles = false;
void load(string filepath)
{
@ -41,6 +42,19 @@ final class SelectiveSync
this.dirmask = wild2regex(dirmask);
}
// Configure skipDotfiles if function is called
// By default, skipDotfiles = false;
void setSkipDotfiles()
{
skipDotfiles = true;
}
// return value of skipDotfiles
bool getSkipDotfiles()
{
return skipDotfiles;
}
// config file skip_dir parameter
bool isDirNameExcluded(string name)
{
@ -97,6 +111,22 @@ final class SelectiveSync
{
return .isPathExcluded(path, paths) || .isPathMatched(path, mask) || .isPathMatched(path, dirmask);
}
// is the path a dotfile?
bool isDotFile(string path)
{
// always allow the root
if (path == ".") return false;
path = buildNormalizedPath(path);
auto paths = pathSplitter(path);
foreach(base; paths) {
if (startsWith(base, ".")){
return true;
}
}
return false;
}
}
// test if the given path is not included in the allowed paths

View file

@ -1964,7 +1964,7 @@ final class SyncEngine
// scan the given directory for differences and new items
void scanForDifferences(string path)
{
// scan for changes
// scan for changes in the path provided
log.vlog("Uploading differences of ", path);
Item item;
if (itemdb.selectByPath(path, defaultDriveId, item)) {