diff --git a/config b/config index ba915d43..30ca71f6 100644 --- a/config +++ b/config @@ -35,6 +35,7 @@ # skip_dir_strict_match = "false" # application_id = "" # resync = "false" +# resync_auth = "false" # bypass_data_preservation = "false" # azure_ad_endpoint = "" # azure_tenant_id = "common" @@ -42,10 +43,10 @@ # sync_dir_permissions = "700" # sync_file_permissions = "600" # rate_limit = "131072" +# operation_timeout = "3600" # webhook_enabled = "false" # webhook_public_url = "" # webhook_listening_host = "" # webhook_listening_port = "8888" # webhook_expiration_interval = "86400" # webhook_renewal_interval = "43200" -# operation_timeout = "3600" \ No newline at end of file diff --git a/contrib/docker/entrypoint.sh b/contrib/docker/entrypoint.sh index c9b1313c..cf353bcc 100755 --- a/contrib/docker/entrypoint.sh +++ b/contrib/docker/entrypoint.sh @@ -53,8 +53,8 @@ fi # Tell client to perform a resync based on environment variable if [ "${ONEDRIVE_RESYNC:=0}" == "1" ]; then echo "# We are performing a --resync" - echo "# Adding --resync" - ARGS=(--resync ${ARGS[@]}) + echo "# Adding --resync --resync-auth" + ARGS=(--resync --resync-auth ${ARGS[@]}) fi # Tell client to sync in download-only mode based on environment variable diff --git a/docs/USAGE.md b/docs/USAGE.md index 8cc8e998..c01669e3 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -27,7 +27,8 @@ + [monitor_interval](#monitor_interval) + [min_notify_changes](#min_notify_changes) + [operation_timeout](#operation_timeout) - + [Selective sync via 'sync_list' file](#selective-sync-via-sync_list-file) + * [Performing a --resync](#performing-a---resync) + * [Selective sync via 'sync_list' file](#selective-sync-via-sync_list-file) * [Configuring the client for 'single tenant application' use](#configuring-the-client-for-single-tenant-application-use) * [Configuring the client to use older 'skilion' application identifier](#configuring-the-client-to-use-older-skilion-application-identifier) * [How to 'skip' directories from syncing?](#how-to-skip-directories-from-syncing) @@ -362,6 +363,7 @@ See the [config](https://raw.githubusercontent.com/abraunegg/onedrive/master/con # skip_dir_strict_match = "false" # application_id = "" # resync = "false" +# resync_auth = "false" # bypass_data_preservation = "false" # azure_ad_endpoint = "" # azure_tenant_id = "common" @@ -378,7 +380,6 @@ See the [config](https://raw.githubusercontent.com/abraunegg/onedrive/master/con # webhook_renewal_interval = "43200" ``` - ### 'config' file configuration examples: The below are 'config' file examples to assist with configuration of the 'config' file: @@ -544,7 +545,33 @@ operation_timeout = "3600" ``` Operation Timeout is the maximum amount of time (seconds) a file operation is allowed to take. This includes DNS resolution, connecting, data transfer, etc. -#### Selective sync via 'sync_list' file +### Performing a --resync +If you modify any of the following configuration items, you will be required to perform a `--resync` to ensure your client is syncing your data with the updated configuration: +* sync_dir +* skip_dir +* skip_file +* drive_id +* Modifying sync_list +* Modifying business_shared_folders + +Additionally, you may choose to perform a `--resync` if you feel that this action needs to be taken to ensure your data is in sync. If you are using this switch simply because you dont know the sync status, you can query the actual sync status using `--display-sync-status`. + +When using `--resync`, the following warning and advice will be presented: +```text +The use of --resync will remove your local 'onedrive' client state, thus no record will exist regarding your current 'sync status' +This has the potential to overwrite local versions of files with potentially older versions downloaded from OneDrive which can lead to data loss +If in-doubt, backup your local data first before proceeding with --resync + +Are you sure you wish to proceed with --resync? [Y/N] +``` + +To proceed with using `--resync`, you must type 'y' or 'Y' to allow the application to continue. + +**Note:** It is highly recommended to only use `--resync` if the application advises you to use it. Do not just blindly set the application to start with `--resync` as the default option. + +**Note:** In some automated environments (and it is 100% assumed you *know* what you are doing because of automation), in order to avoid this 'proceed with acknowledgement' requirement, add `--resync-auth` to automatically acknowledge the prompt. + +### Selective sync via 'sync_list' file Selective sync allows you to sync only specific files and directories. To enable selective sync create a file named `sync_list` in `~/.config/onedrive`. Each line of the file represents a relative path from your `sync_dir`. All files and directories not matching any line of the file will be skipped during all operations. @@ -1083,6 +1110,8 @@ Options: Remove source file after successful transfer to OneDrive when using --upload-only --resync Forget the last saved state, perform a full sync + --resync-auth + Approve the use of performing a --resync action --single-directory ARG Specify a single local directory within the OneDrive root to sync. --skip-dir ARG diff --git a/src/config.d b/src/config.d index fd0b7419..1ee493b0 100644 --- a/src/config.d +++ b/src/config.d @@ -90,6 +90,8 @@ final class Config stringValues["application_id"] = ""; // allow for resync to be set via config file boolValues["resync"] = false; + // resync now needs to be acknowledged based on the 'risk' of using it + boolValues["resync_auth"] = false; // Ignore data safety checks and overwrite local data rather than preserve & rename // This is a config file option ONLY boolValues["bypass_data_preservation"] = false; @@ -213,8 +215,8 @@ final class Config } // configDirName has a trailing / - log.vlog("Using 'user' Config Dir: ", configDirName); - log.vlog("Using 'system' Config Dir: ", systemConfigDirName); + if (!configDirName.empty) log.vlog("Using 'user' Config Dir: ", configDirName); + if (!systemConfigDirName.empty) log.vlog("Using 'system' Config Dir: ", systemConfigDirName); // Update application set variables based on configDirName refreshTokenFilePath = buildNormalizedPath(configDirName ~ "/refresh_token"); @@ -409,6 +411,9 @@ final class Config "resync", "Forget the last saved state, perform a full sync", &boolValues["resync"], + "resync-auth", + "Approve the use of performing a --resync action", + &boolValues["resync_auth"], "remove-directory", "Remove a directory on OneDrive - no sync will be performed.", &stringValues["remove_directory"], diff --git a/src/main.d b/src/main.d index 2829c1e7..be688cfe 100644 --- a/src/main.d +++ b/src/main.d @@ -120,6 +120,7 @@ int main(string[] args) "verbose|v+", "Print more details, useful for debugging (repeat for extra debugging)", &log.verbose, "version", "Print the version and exit", &printVersion ); + // print help and exit if (opt.helpWanted) { args ~= "--help"; @@ -148,6 +149,10 @@ int main(string[] args) // Error message already printed return EXIT_FAILURE; } + + // How was this application started - what options were passed in + log.vdebug("passed in options: ", args); + log.vdebug("note --confdir and --verbose not listed in args"); // set memory display displayMemoryUsage = cfg.getValueBool("display_memory"); @@ -158,6 +163,47 @@ int main(string[] args) // update configuration from command line args cfg.update_from_args(args); + // --resync should be a 'last resort item' .. the user needs to 'accept' to proceed + if (cfg.getValueBool("resync")) { + // what is the risk acceptance? + bool resyncRiskAcceptance = false; + + if (!cfg.getValueBool("resync_auth")) { + // need to prompt user + char response; + // warning message + writeln("\nThe use of --resync will remove your local 'onedrive' client state, thus no record will exist regarding your current 'sync status'"); + writeln("This has the potential to overwrite local versions of files with potentially older versions downloaded from OneDrive which can lead to data loss"); + writeln("If in-doubt, backup your local data first before proceeding with --resync"); + write("\nAre you sure you wish to proceed with --resync? [Y/N] "); + + try { + // Attempt to read user response + readf(" %c\n", &response); + } catch (std.format.FormatException e) { + // Caught an error + return EXIT_FAILURE; + } + + // Evaluate user repsonse + if ((to!string(response) == "y") || (to!string(response) == "Y")) { + // User has accepted --resync risk to proceed + resyncRiskAcceptance = true; + // Are you sure you wish .. does not use writeln(); + write("\n"); + } + } else { + // resync_auth is true + resyncRiskAcceptance = true; + } + + // Action based on response + if (!resyncRiskAcceptance){ + // --resync risk not accepted + return EXIT_FAILURE; + } + } + // Initialise normalised file paths configFilePath = buildNormalizedPath(cfg.configDirName ~ "/config"); syncListFilePath = buildNormalizedPath(cfg.configDirName ~ "/sync_list");