mirror of
https://github.com/abraunegg/onedrive
synced 2026-03-14 14:35:46 +01:00
* Add option to remove source folders when using --upload-only --remove-source-files * Parental path will only be removed if path is empty - that is, no other folders or files present
This commit is contained in:
parent
42f7ad95e8
commit
2f339c5663
6 changed files with 89 additions and 2 deletions
1
.github/actions/spelling/allow.txt
vendored
1
.github/actions/spelling/allow.txt
vendored
|
|
@ -75,6 +75,7 @@ Cforce
|
|||
checkinterval
|
||||
chkconfig
|
||||
chpst
|
||||
chrooted
|
||||
classinfo
|
||||
clen
|
||||
cloexec
|
||||
|
|
|
|||
|
|
@ -734,6 +734,23 @@ _**CLI Option Use:**_ `--remove-source-files`
|
|||
> [!IMPORTANT]
|
||||
> This configuration option can *only* be used in conjunction with `--upload-only`
|
||||
|
||||
### remove_source_folders
|
||||
_**Description:**_ This configuration option controls whether the OneDrive Client for Linux removes the local directory structure post successful file transfer to Microsoft OneDrive.
|
||||
|
||||
_**Value Type:**_ Boolean
|
||||
|
||||
_**Default Value:**_ False
|
||||
|
||||
_**Config Example:**_ `remove_source_folders = "false"` or `remove_source_folders = "true"`
|
||||
|
||||
_**CLI Option Use:**_ `--remove-source-folders`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This configuration option can *only* be used in conjunction with `--upload-only --remove-source-files`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The directory structure will only be removed if it is empty.
|
||||
|
||||
### resync
|
||||
_**Description:**_ This configuration option controls whether the known local sync state with Microsoft OneDrive is removed at application startup. When this option is used, a full scan of your data online is performed to ensure that the local sync state is correctly built back up.
|
||||
|
||||
|
|
|
|||
|
|
@ -288,6 +288,10 @@ Remove a directory on OneDrive - no sync will be performed.
|
|||
\fB\-\-remove-source-files\fR
|
||||
Remove source file after successful transfer to OneDrive when using --upload-only.
|
||||
|
||||
.TP
|
||||
\fB\-\-remove-source-folders\fR
|
||||
Remove the local directory structure post successful file transfer to Microsoft OneDrive when using --upload-only --remove-source-files.
|
||||
|
||||
.TP
|
||||
\fB\-\-resync\fR
|
||||
Forget the last saved state, perform a full sync.
|
||||
|
|
|
|||
|
|
@ -361,8 +361,10 @@ class ApplicationConfig {
|
|||
boolValues["dry_run"] = false;
|
||||
// Do we sync all the files in the 'sync_dir' root?
|
||||
boolValues["sync_root_files"] = false;
|
||||
// Do we delete source after successful transfer?
|
||||
// Do we delete source file after successful transfer?
|
||||
boolValues["remove_source_files"] = false;
|
||||
// Do we delete source folders after successful transfer?
|
||||
boolValues["remove_source_folders"] = false;
|
||||
// Do we perform strict matching for skip_dir?
|
||||
boolValues["skip_dir_strict_match"] = false;
|
||||
// Do we perform a --resync?
|
||||
|
|
@ -1308,6 +1310,9 @@ class ApplicationConfig {
|
|||
"remove-source-files",
|
||||
"Remove source file after successful transfer to OneDrive when using --upload-only",
|
||||
&boolValues["remove_source_files"],
|
||||
"remove-source-folders",
|
||||
"Remove the local directory structure post successful file transfer to Microsoft OneDrive when using --upload-only --remove-source-files",
|
||||
&boolValues["remove_source_folders"],
|
||||
"single-directory",
|
||||
"Specify a single local directory within the OneDrive root to sync",
|
||||
&stringValues["single_directory"],
|
||||
|
|
|
|||
49
src/sync.d
49
src/sync.d
|
|
@ -6727,6 +6727,15 @@ class SyncEngine {
|
|||
if (debugLogging) {addLogEntry("Removing local file: " ~ localPathToRemove, ["debug"]);}
|
||||
safeRemove(localPathToRemove);
|
||||
addLogEntry("Removed local file: " ~ localPathToRemove);
|
||||
|
||||
// Do we try and attempt to remove the local source tree?
|
||||
if (appConfig.getValueBool("remove_source_folders")) {
|
||||
// Remove the source directory structure but only if it is empty
|
||||
addLogEntry("Attempting removal of local directory structure as --upload-only & --remove-source-files & --remove-source-folders configured");
|
||||
string parentPath = dirName(localPathToRemove);
|
||||
removeEmptyParents(localPathToRemove);
|
||||
addLogEntry("Removed parental path: " ~ parentPath);
|
||||
}
|
||||
} else {
|
||||
// --dry-run scenario
|
||||
addLogEntry("Not removing local file as --dry-run configured");
|
||||
|
|
@ -6736,7 +6745,47 @@ class SyncEngine {
|
|||
addLogEntry("Removing local file not possible as local file does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty parent directories of `filePath` upwards until:
|
||||
// - we hit a non-empty directory, or
|
||||
// - we reach the visible root (i.e. dirName(current) == ".").
|
||||
// Never tries to remove ".".
|
||||
void removeEmptyParents(string filePath) {
|
||||
// Work with a normalised *relative* path inside the chrooted configured 'sync_dir'
|
||||
// If someone passed an absolute path, normalise it anyway; your codebase
|
||||
// likely already ensures paths are relative within the sync root.
|
||||
string current = dirName(buildNormalizedPath(filePath));
|
||||
|
||||
while (current.length && current != ".") {
|
||||
// Safety: don’t descend into symlinks
|
||||
if (isSymlink(current)) {
|
||||
if (debugLogging) addLogEntry("Skipping removal; parent is a symlink: " ~ current, ["debug"]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Stop at first non-empty directory
|
||||
if (!isDirEmpty(current)) {
|
||||
if (debugLogging) addLogEntry("Stopping prune; directory not empty: " ~ current, ["debug"]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
if (debugLogging) addLogEntry("Removing empty directory: " ~ current, ["debug"]);
|
||||
// rmdir only succeeds for empty directories; errors are collected not thrown
|
||||
collectException(rmdir(current));
|
||||
} else {
|
||||
addLogEntry("Not removing empty directory as --dry-run configured: " ~ current);
|
||||
}
|
||||
|
||||
// Move up one level
|
||||
string next = dirName(current);
|
||||
if (next == current) { // Just in case (shouldn’t happen with relative paths)
|
||||
break;
|
||||
}
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the upload of a locally modified file to OneDrive
|
||||
JSONValue performModifiedFileUpload(Item dbItem, string localFilePath, long thisFileSizeLocal) {
|
||||
// Function Start Time
|
||||
|
|
|
|||
11
src/util.d
11
src/util.d
|
|
@ -1917,3 +1917,14 @@ void displayFunctionProcessingTime(string functionName, SysTime functionStartTim
|
|||
string processingTime = format("[%s] Application Function '%s' Processing Time = %.4f Seconds", strip(logKey), strip(functionName), functionDurationAsSeconds);
|
||||
addLogEntry(processingTime);
|
||||
}
|
||||
|
||||
// Return true if `dir` exists and has no entries.
|
||||
// Symlinks are treated as non-removable.
|
||||
bool isDirEmpty(string dir) {
|
||||
if (!exists(dir) || !isDir(dir) || isSymlink(dir)) return false;
|
||||
foreach (_; dirEntries(dir, SpanMode.shallow)) {
|
||||
// Found at least one entry
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue