From c7c07b12a75ea6bd78cf12d6bd678e8ab2d9e2fb Mon Sep 17 00:00:00 2001 From: abraunegg Date: Mon, 28 Apr 2025 08:58:32 +1000 Subject: [PATCH] Enhancement: Update 'skip_file' documentation and option validation (#3251) * Update 'skip_file' documentation as to why the existing defaults exist * Add warning message about 'default' entries for 'skip_file' missing aligning to documentation --- .github/actions/spelling/allow.txt | 1 + docs/application-config-options.md | 34 +++++++++++++++------ src/config.d | 48 +++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index edebe4b6..86c0269b 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -35,6 +35,7 @@ autoprocess autoupdate avmkfdiitirnrenzljwc avx +bak baus bcdefghi beffdb diff --git a/docs/application-config-options.md b/docs/application-config-options.md index 0ea4236d..38f9ee14 100644 --- a/docs/application-config-options.md +++ b/docs/application-config-options.md @@ -576,7 +576,7 @@ _**CLI Option Use:**_ *None - this is a config file option only* > [!IMPORTANT] > The Microsoft OneDrive API for this capability is also very narrow: > | Account Type | Config Option is Supported | -> |--------------|------------------| +> |:-------------|:----------------:| > | Personal | ❌ | > | Business | ✔ | > | SharePoint | ✔ | @@ -758,15 +758,29 @@ _**Value Type:**_ String _**Default Value:**_ `~*|.~*|*.tmp|*.swp|*.partial` +By default, the following files will be skipped: + +| Skip File Pattern | Meaning | Why this should be skipped | +|:------------------|:---------------------------|:---------------------------| +| `~*` | Files that start with `~` | Temporary or backup files. Typically auto-created by various programs during editing sessions. These are not intended to be saved permanently. Example: Emacs, Vim, and others create such files. | +| `.~*` | Files that start with `.~` | Hidden lock or temp files, especially from LibreOffice and OpenOffice. (E.g., `.~lock.MyFile.docx#`) These are only used to prevent multiple users editing the same file simultaneously. | +| `*.tmp` | Files ending in `.tmp` | Generic temporary files created by applications like browsers, editors, installers. They represent intermediate data and are usually auto-deleted after a session. | +| `*.swp` | Files ending in `.swp` | Vim (and vi) swap files. Created to protect against crash recovery during text editing. Should not be synced because they are transient. | +| `*.partial` | Files ending in `.partial` | Partially downloaded files. Common in browsers (like Firefox `.partial` download files), background downloaders and this client. Incomplete by nature. Syncing them causes broken files online. | + +The following suggested skip file patterns are not included in the default configuration but could also be considered for skipping: + +| Skip File Pattern | Meaning | Why this should be skipped | +|:------------------|:---------------------------|:---------------------------| +| `*.bak` | Files ending in `.bak` | Backup files created by many text editors, IDEs, or applications. These are automatic backups made to preserve earlier versions of files before editing changes are saved. They are not intended for syncing — they are redundant copies of existing or previous files. | + +> [!IMPORTANT] +> If you define your own 'skip_file' configuration, the default settings listed above will be *overridden*. It is strongly recommended that you explicitly include the default 'skip_file' rules alongside your custom entries to ensure temporary and/or transient files are still correctly skipped. + _**Config Example:**_ Patterns are case insensitive. `*` and `?` [wildcards characters](https://technet.microsoft.com/en-us/library/bb490639.aspx) are supported. Use `|` to separate multiple patterns. -By default, the following files will be skipped: -* Files that start with ~ -* Files that start with .~ (like .~lock.* files generated by LibreOffice) -* Files that end in .tmp, .swp and .partial - Files can be skipped in the following fashion: * Specify a wildcard, eg: '*.txt' (skip all txt files) * Explicitly specify the filename and it's full path relative to your sync_dir, eg: '/path/to/file/filename.ext' @@ -781,17 +795,19 @@ skip_file = "~*|/Documents/OneNote*|/Documents/config.xlaunch|myfile.ext|/Docume The 'skip_file' option can be specified multiple times within your config file, for example: ```text -skip_file = "~*|.~*|*.tmp|*.swp" +# Defaults - always keep +skip_file = "~*|.~*|*.tmp|*.swp|*.partial" +# Custom 'skip_file' additions skip_file = "*.blah" skip_file = "never_sync.file" skip_file = "/Documents/keepass.kdbx" ``` This will be interpreted the same as: ```text -skip_file = "~*|.~*|*.tmp|*.swp|*.blah|never_sync.file|/Documents/keepass.kdbx" +skip_file = "~*|.~*|*.tmp|*.swp|*.partial|*.blah|never_sync.file|/Documents/keepass.kdbx" ``` -_**CLI Option Use:**_ `--skip-file '~*|.~*|*.tmp|*.swp|*.blah|never_sync.file|/Documents/keepass.kdbx'` +_**CLI Option Use:**_ `--skip-file '~*|.~*|*.tmp|*.swp|*.partial|*.blah|never_sync.file|/Documents/keepass.kdbx'` > [!NOTE] > This option is considered a 'Client Side Filtering Rule' and if configured, is utilised for all sync operations. If using the config file and CLI option is used, the CLI option will *replace* the config file entries. After changing or modifying this option, you will be required to perform a resync. diff --git a/src/config.d b/src/config.d index 0ceafb94..a867575e 100644 --- a/src/config.d +++ b/src/config.d @@ -3,12 +3,14 @@ module config; // What does this module require to function? import core.stdc.stdlib: EXIT_SUCCESS, EXIT_FAILURE, exit; +import std.array; import std.stdio; import std.process; import std.regex; import std.string; +import std.algorithm; import std.algorithm.searching; -import std.algorithm.sorting: sort; +import std.algorithm.sorting; import std.file; import std.conv; import std.path; @@ -968,9 +970,53 @@ class ApplicationConfig { return false; } } + + // If we read in 'skip_file' from the 'config' file, this will be 'true' + if (configFileSkipFileReadIn) { + // The user added entries, are the application defaults included or were these discarded / discounted? + // Check for temporary and/or transient files to skip (application defaults) + checkForSkipFileDefaults(); + } + // Return that we were able to read in the config file and parse the options without issue return true; } + + // Perform a check on 'skip_file' configuration post reading from 'config' file + void checkForSkipFileDefaults() { + // Split both the default and user values + auto defaultEntries = defaultSkipFile.split('|').map!(a => a.strip).array; + auto userEntries = configFileSkipFile.split('|').map!(a => a.strip).array; + + string[] missingDefaults; + + // Check if all defaults exist in user config + foreach (defaultEntry; defaultEntries) { + if (!userEntries.canFind(defaultEntry)) { + missingDefaults ~= defaultEntry; + } + } + + // Display warning message about missing default entries for temporary and/or transient files that should be skipped + if (!missingDefaults.empty) { + addLogEntry(); + addLogEntry("WARNING: Your 'skip_file' configuration is missing important default entries. Temporary and/or transient files that would normally be skipped may now be included in syncing.", ["info", "notify"]); + addLogEntry(); + if (verboseLogging) { + addLogEntry("By default, the following types of temporary and/or transient files are skipped:", ["verbose"]); + addLogEntry(" Files that start with '~' (Temporary or backup files that are not intended to be saved permanently)", ["verbose"]); + addLogEntry(" Files that start with '.~' (e.g., LibreOffice lock files)", ["verbose"]); + addLogEntry(" Files that end with '.tmp' (Generic temporary files created by applications like browsers, editors, installers)", ["verbose"]); + addLogEntry(" Files that end with '.swp' (Transient files created by editors such as vim and vi)", ["verbose"]); + addLogEntry(" Files that end with '.partial' (Partially downloaded files, incomplete by nature, should not be synced)", ["verbose"]); + addLogEntry(); + addLogEntry(" Missing the following important 'skip_file' entries: " ~ missingDefaults.join(", "), ["verbose"]); + addLogEntry(); + addLogEntry("Reference: https://github.com/abraunegg/onedrive/blob/master/docs/application-config-options.md#skip_file", ["verbose"]); + addLogEntry(); + } + } + } // Update the application configuration based on CLI passed in parameters void updateFromArgs(string[] cliArgs) {