mirror of
https://github.com/abraunegg/onedrive
synced 2026-03-14 14:35:46 +01:00
Improve safeBackup function and documentation (#2966)
* Update safeBackup to use a new filename format for easier identification <filename>-<hostname>-safeBackup-<number>.file_extention * Update client-architecture.md to articulate backup file formatting and how to disable preserving local files to prevent local data loss
This commit is contained in:
parent
6024d30901
commit
8f9927f45b
2 changed files with 60 additions and 25 deletions
|
|
@ -97,9 +97,41 @@ This exclusion process can be illustrated by the following activity diagram. A '
|
|||
|
||||
When using the default operational modes (`--sync` or `--monitor`) the client application is conforming to how the Microsoft Windows OneDrive client operates in terms of resolving conflicts for files.
|
||||
|
||||
Additionally, when using `--resync` this conflict resolution can differ slightly, as, when using `--resync` you are *deleting* the known application state, thus, the application has zero reference as to what was previously in sync with the local file system.
|
||||
When using `--resync` this conflict resolution can differ slightly, as, when using `--resync` you are *deleting* the known application state, thus, the application has zero reference as to what was previously in sync with the local file system.
|
||||
|
||||
Due to this factor, when using `--resync` the online source is always going to be considered accurate and the source-of-truth, regardless of the local file state, file timestamp or file hash.
|
||||
Due to this factor, when using `--resync` the online source is always going to be considered accurate and the source-of-truth, regardless of the local file state, local file timestamp or local file hash. When a difference in local file hash is detected, the file will be renamed to prevent local data loss.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> In v2.5.3 and above, when a local file is renamed due to conflict handling, this will be in the following format pattern to allow easier identification:
|
||||
>
|
||||
> **filename-hostname-safeBackup-number.file_extension**
|
||||
>
|
||||
> For example:
|
||||
> ```
|
||||
> -rw-------. 1 alex alex 53402 Sep 21 08:25 file5.data
|
||||
> -rw-------. 1 alex alex 53423 Nov 13 18:18 file5-onedrive-client-dev-safeBackup-0001.data
|
||||
> -rw-------. 1 alex alex 53422 Nov 13 18:19 file5-onedrive-client-dev-safeBackup-0002.data
|
||||
> ```
|
||||
>
|
||||
> In client versions v2.5.2 and below, the renamed file have the following naming convention:
|
||||
>
|
||||
> **filename-hostname-number.file_extension**
|
||||
>
|
||||
> resulting in backup filenames of the following format:
|
||||
> ```
|
||||
> -rw-------. 1 alex alex 53402 Sep 21 08:25 file5.data
|
||||
> -rw-------. 1 alex alex 53432 Nov 14 05:22 file5-onedrive-client-dev-2.data
|
||||
> -rw-------. 1 alex alex 53435 Nov 14 05:24 file5-onedrive-client-dev-3.data
|
||||
> -rw-------. 1 alex alex 53419 Nov 14 05:22 file5-onedrive-client-dev.data
|
||||
> ```
|
||||
>
|
||||
|
||||
> [!CAUTION]
|
||||
> The creation of backup files when there is a conflict to avoid local data loss can be disabled.
|
||||
>
|
||||
> To do this, utilise the configuration option **bypass_data_preservation**
|
||||
>
|
||||
> If this is enabled, you will experience data loss on your local data as the local file will be over-written with data from OneDrive online. Use with care and caution.
|
||||
|
||||
### Default Operational Modes - Conflict Handling
|
||||
|
||||
|
|
|
|||
49
src/util.d
49
src/util.d
|
|
@ -56,30 +56,31 @@ shared static this() {
|
|||
|
||||
// Creates a safe backup of the given item, and only performs the function if not in a --dry-run scenario
|
||||
void safeBackup(const(char)[] path, bool dryRun, out string renamedPath) {
|
||||
auto ext = extension(path);
|
||||
auto newPath = path.chomp(ext) ~ "-" ~ deviceName;
|
||||
int n = 2;
|
||||
|
||||
auto ext = extension(path);
|
||||
auto newPath = path.chomp(ext) ~ "-" ~ deviceName ~ "-safeBackup-";
|
||||
int n = 1;
|
||||
|
||||
// Limit to 1000 iterations .. 1000 file backups
|
||||
while (exists(newPath ~ ext) && n < 1000) {
|
||||
newPath = newPath.chomp("-" ~ (n - 1).to!string) ~ "-" ~ n.to!string;
|
||||
n++;
|
||||
}
|
||||
|
||||
while (exists(newPath ~ format("%04d", n) ~ ext) && n < 1000) {
|
||||
n++;
|
||||
}
|
||||
|
||||
// Check if unique file name was found
|
||||
if (exists(newPath ~ ext)) {
|
||||
if (exists(newPath ~ format("%04d", n) ~ ext)) {
|
||||
// On the 1000th backup of this file, this should be triggered
|
||||
addLogEntry("Failed to backup " ~ to!string(path) ~ ": Unique file name could not be found after 1000 attempts", ["error"]);
|
||||
return; // Exit function as a unique file name could not be found
|
||||
}
|
||||
|
||||
// Configure the new name
|
||||
newPath ~= ext;
|
||||
|
||||
// Log that we are perform the backup by renaming the file
|
||||
if (verboseLogging) {addLogEntry("The local item is out-of-sync with OneDrive, renaming to preserve existing file and prevent local data loss: " ~ to!string(path) ~ " -> " ~ to!string(newPath) , ["verbose"]);}
|
||||
// Configure the new name with zero-padded counter
|
||||
newPath ~= format("%04d", n) ~ ext;
|
||||
|
||||
if (!dryRun) {
|
||||
// Log that we are performing the backup by renaming the file
|
||||
if (verboseLogging) {
|
||||
addLogEntry("The local item is out-of-sync with OneDrive, renaming to preserve existing file and prevent local data loss: " ~ to!string(path) ~ " -> " ~ to!string(newPath), ["verbose"]);
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
// Not a --dry-run scenario - do the file rename
|
||||
//
|
||||
// There are 2 options to rename a file
|
||||
|
|
@ -96,13 +97,15 @@ void safeBackup(const(char)[] path, bool dryRun, out string renamedPath) {
|
|||
try {
|
||||
rename(path, newPath);
|
||||
renamedPath = to!string(newPath);
|
||||
} catch (Exception e) {
|
||||
// Handle exceptions, e.g., log error
|
||||
addLogEntry("Renaming of local file failed for " ~ to!string(path) ~ ": " ~ e.msg, ["error"]);
|
||||
}
|
||||
} else {
|
||||
if (debugLogging) {addLogEntry("DRY-RUN: Skipping renaming local file to preserve existing file and prevent data loss: " ~ to!string(path) ~ " -> " ~ to!string(newPath), ["debug"]);}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Handle exceptions, e.g., log error
|
||||
addLogEntry("Renaming of local file failed for " ~ to!string(path) ~ ": " ~ e.msg, ["error"]);
|
||||
}
|
||||
} else {
|
||||
if (debugLogging) {
|
||||
addLogEntry("DRY-RUN: Skipping renaming local file to preserve existing file and prevent data loss: " ~ to!string(path) ~ " -> " ~ to!string(newPath), ["debug"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rename the given item, and only performs the function if not in a --dry-run scenario
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue