mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-13 11:22:39 +02:00
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:
parent
31629e697f
commit
7a18393ed0
48
src/main.d
48
src/main.d
|
@ -529,17 +529,27 @@ int main(string[] args)
|
||||||
}
|
}
|
||||||
selectiveSync.load(cfg.syncListFilePath);
|
selectiveSync.load(cfg.syncListFilePath);
|
||||||
|
|
||||||
// Configure skip_dir & skip_file from config entries
|
// Configure skip_dir, skip_file, skip-dir-strict-match & skip_dotfiles from config entries
|
||||||
// skip_dir items
|
// Handle skip_dir configuration in config file
|
||||||
log.vdebug("Configuring skip_dir ...");
|
log.vdebug("Configuring skip_dir ...");
|
||||||
log.vdebug("skip_dir: ", cfg.getValueString("skip_dir"));
|
log.vdebug("skip_dir: ", cfg.getValueString("skip_dir"));
|
||||||
selectiveSync.setDirMask(cfg.getValueString("skip_dir"));
|
selectiveSync.setDirMask(cfg.getValueString("skip_dir"));
|
||||||
|
|
||||||
// Was --skip-dir-strict-match configured?
|
// 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")) {
|
if (cfg.getValueBool("skip_dir_strict_match")) {
|
||||||
selectiveSync.setSkipDirStrictMatch();
|
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 ...");
|
log.vdebug("Configuring skip_file ...");
|
||||||
// Validate skip_file to ensure that this does not contain an invalid configuration
|
// 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.
|
// 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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// All skip_file entries are valid
|
||||||
// valid entry
|
|
||||||
log.vdebug("skip_file: ", cfg.getValueString("skip_file"));
|
log.vdebug("skip_file: ", cfg.getValueString("skip_file"));
|
||||||
selectiveSync.setFileMask(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"));
|
log.log("OneDrive monitor interval (seconds): ", cfg.getValueLong("monitor_interval"));
|
||||||
Monitor m = new Monitor(selectiveSync);
|
Monitor m = new Monitor(selectiveSync);
|
||||||
m.onDirCreated = delegate(string path) {
|
m.onDirCreated = delegate(string path) {
|
||||||
log.vlog("[M] Directory created: ", path);
|
// Handle .folder creation if skip_dotfiles is enabled
|
||||||
try {
|
if ((cfg.getValueBool("skip_dotfiles")) && (selectiveSync.isDotFile(path))) {
|
||||||
sync.scanForDifferences(path);
|
log.vlog("[M] Skipping watching path - .folder found & --skip-dot-files enabled: ", path);
|
||||||
} catch (CurlException e) {
|
} else {
|
||||||
log.vlog("Offline, cannot create remote dir!");
|
log.vlog("[M] Directory created: ", path);
|
||||||
} catch(Exception e) {
|
try {
|
||||||
log.logAndNotify("Cannot create remote directory: ", e.msg);
|
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) {
|
m.onFileChanged = delegate(string path) {
|
||||||
|
@ -704,7 +718,7 @@ int main(string[] args)
|
||||||
log.vlog("Offline, cannot delete item!");
|
log.vlog("Offline, cannot delete item!");
|
||||||
} catch(SyncException e) {
|
} catch(SyncException e) {
|
||||||
if (e.msg == "The item to delete is not in the local database") {
|
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 {
|
} else {
|
||||||
log.logAndNotify("Cannot delete remote item: ", e.msg);
|
log.logAndNotify("Cannot delete remote item: ", e.msg);
|
||||||
}
|
}
|
||||||
|
@ -715,7 +729,13 @@ int main(string[] args)
|
||||||
m.onMove = delegate(string from, string to) {
|
m.onMove = delegate(string from, string to) {
|
||||||
log.vlog("[M] Item moved: ", from, " -> ", to);
|
log.vlog("[M] Item moved: ", from, " -> ", to);
|
||||||
try {
|
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) {
|
} catch (CurlException e) {
|
||||||
log.vlog("Offline, cannot move item!");
|
log.vlog("Offline, cannot move item!");
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import core.sys.linux.sys.inotify;
|
import core.sys.linux.sys.inotify;
|
||||||
import core.stdc.errno;
|
import core.stdc.errno;
|
||||||
import core.sys.posix.poll, core.sys.posix.unistd;
|
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 config;
|
||||||
import selective;
|
import selective;
|
||||||
import util;
|
import util;
|
||||||
|
@ -85,15 +85,24 @@ final class Monitor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip filtered items
|
// skip monitoring any filtered items
|
||||||
if (dirname != ".") {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
// is the filename a match to a skip_file entry?
|
||||||
if (selectiveSync.isFileNameExcluded(baseName(dirname))) {
|
if (selectiveSync.isFileNameExcluded(baseName(dirname))) {
|
||||||
|
// dont add a watch for this item
|
||||||
|
log.vdebug("Skipping monitoring due to skip_file match: ", dirname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// is the path exluded by sync_list?
|
||||||
if (selectiveSync.isPathExcludedViaSyncList(buildNormalizedPath(dirname))) {
|
if (selectiveSync.isPathExcludedViaSyncList(buildNormalizedPath(dirname))) {
|
||||||
|
// dont add a watch for this item
|
||||||
|
log.vdebug("Skipping monitoring due to sync_list match: ", dirname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +124,7 @@ final class Monitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// passed all potential exclusions
|
||||||
add(dirname);
|
add(dirname);
|
||||||
try {
|
try {
|
||||||
auto pathList = dirEntries(dirname, SpanMode.shallow, false);
|
auto pathList = dirEntries(dirname, SpanMode.shallow, false);
|
||||||
|
@ -148,8 +158,23 @@ final class Monitor
|
||||||
log.error("ERROR: inotify_add_watch failed: ", pathname);
|
log.error("ERROR: inotify_add_watch failed: ", pathname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add path to inotify watch - required regardless if a '.folder' or 'folder'
|
||||||
wdToDirName[wd] = buildNormalizedPath(pathname) ~ "/";
|
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
|
// remove a watch descriptor
|
||||||
|
@ -181,6 +206,7 @@ final class Monitor
|
||||||
{
|
{
|
||||||
string path = wdToDirName[event.wd];
|
string path = wdToDirName[event.wd];
|
||||||
if (event.len > 0) path ~= fromStringz(event.name.ptr);
|
if (event.len > 0) path ~= fromStringz(event.name.ptr);
|
||||||
|
log.vdebug("inotify path event for: ", path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,16 +240,17 @@ final class Monitor
|
||||||
|
|
||||||
// skip filtered items
|
// skip filtered items
|
||||||
path = getPath(event);
|
path = getPath(event);
|
||||||
if (selectiveSync.isDirNameExcluded(strip(path,"./"))) {
|
if (selectiveSync.isDirNameExcluded(path.strip('.').strip('/'))) {
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if (selectiveSync.isFileNameExcluded(strip(path,"./"))) {
|
if (selectiveSync.isFileNameExcluded(path.strip('.').strip('/'))) {
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if (selectiveSync.isPathExcludedViaSyncList(path)) {
|
if (selectiveSync.isPathExcludedViaSyncList(path)) {
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle events
|
||||||
if (event.mask & IN_MOVED_FROM) {
|
if (event.mask & IN_MOVED_FROM) {
|
||||||
log.vdebug("event IN_MOVED_FROM: ", path);
|
log.vdebug("event IN_MOVED_FROM: ", path);
|
||||||
cookieToPath[event.cookie] = path;
|
cookieToPath[event.cookie] = path;
|
||||||
|
|
|
@ -12,6 +12,7 @@ final class SelectiveSync
|
||||||
private Regex!char mask;
|
private Regex!char mask;
|
||||||
private Regex!char dirmask;
|
private Regex!char dirmask;
|
||||||
private bool skipDirStrictMatch = false;
|
private bool skipDirStrictMatch = false;
|
||||||
|
private bool skipDotfiles = false;
|
||||||
|
|
||||||
void load(string filepath)
|
void load(string filepath)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +42,19 @@ final class SelectiveSync
|
||||||
this.dirmask = wild2regex(dirmask);
|
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
|
// config file skip_dir parameter
|
||||||
bool isDirNameExcluded(string name)
|
bool isDirNameExcluded(string name)
|
||||||
{
|
{
|
||||||
|
@ -97,6 +111,22 @@ final class SelectiveSync
|
||||||
{
|
{
|
||||||
return .isPathExcluded(path, paths) || .isPathMatched(path, mask) || .isPathMatched(path, dirmask);
|
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
|
// test if the given path is not included in the allowed paths
|
||||||
|
|
|
@ -1964,7 +1964,7 @@ final class SyncEngine
|
||||||
// scan the given directory for differences and new items
|
// scan the given directory for differences and new items
|
||||||
void scanForDifferences(string path)
|
void scanForDifferences(string path)
|
||||||
{
|
{
|
||||||
// scan for changes
|
// scan for changes in the path provided
|
||||||
log.vlog("Uploading differences of ", path);
|
log.vlog("Uploading differences of ", path);
|
||||||
Item item;
|
Item item;
|
||||||
if (itemdb.selectByPath(path, defaultDriveId, item)) {
|
if (itemdb.selectByPath(path, defaultDriveId, item)) {
|
||||||
|
|
Loading…
Reference in a new issue