mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-08 00:42:13 +02:00
WIP: Implement international language support
* Initial start on implementing international language support
This commit is contained in:
parent
16fdd928b6
commit
fe2f10138a
|
@ -78,7 +78,8 @@ SOURCES = \
|
|||
src/sync.d \
|
||||
src/upload.d \
|
||||
src/util.d \
|
||||
src/progress.d
|
||||
src/progress.d \
|
||||
src/translations.d
|
||||
|
||||
ifeq ($(NOTIFICATIONS),yes)
|
||||
SOURCES += src/notifications/notify.d src/notifications/dnotify.d
|
||||
|
|
117
contrib/translations/EN-US.json
Normal file
117
contrib/translations/EN-US.json
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"language": "EN-US",
|
||||
"list": [
|
||||
"No user or system config file found, using application defaults",
|
||||
"System configuration file successfully loaded",
|
||||
"System configuration file has errors - please check your configuration",
|
||||
"Configuration file successfully loaded",
|
||||
"Configuration file has errors - please check your configuration",
|
||||
"Using config option for Global Azure AD Endpoints",
|
||||
"Using config option for Azure AD for US Government Endpoints",
|
||||
"Using config option for Azure AD for US Government Endpoints (DOD)",
|
||||
"Using config option for Azure AD Germany",
|
||||
"Using config option for Azure AD China operated by 21Vianet",
|
||||
"Unknown Azure AD Endpoint - using Global Azure AD Endpoints",
|
||||
"Unknown key in config file: ",
|
||||
"Malformed config line: ",
|
||||
"config file has been updated, checking if --resync needed",
|
||||
"An application configuration change has been detected where a --resync is required",
|
||||
"DRY-RUN Configured. Output below shows what 'would' have occurred",
|
||||
"Using logfile dir: ",
|
||||
"Database schema changed, resync needed",
|
||||
"Deleting the saved status ...",
|
||||
"ERROR: Unable to reach Microsoft OneDrive API service, unable to initialize application",
|
||||
"ERROR: Unable to reach Microsoft OneDrive API service at this point in time, re-trying network tests",
|
||||
"Internet connectivity to Microsoft OneDrive service has been restored",
|
||||
"ERROR: The OneDrive Linux Client was unable to reconnect to the Microsoft OneDrive service after 10000 attempts lasting over 1.2 years!",
|
||||
"Initializing the OneDrive API ...",
|
||||
"Could not initialize the OneDrive API",
|
||||
"Application has been successfully authorized, however no additional command switches were provided",
|
||||
"Please use 'onedrive --help' for further assistance in regards to running this application",
|
||||
"Application has not been successfully authorized. Please check your URI response entry and try again",
|
||||
"ERROR: --synchronize or --monitor switches missing from your command line input. Please add one (not both) of these switches to your command line",
|
||||
"No OneDrive sync will be performed without one of these two arguments being present",
|
||||
"ERROR: --synchronize and --monitor cannot be used together",
|
||||
"Opening the item database ...",
|
||||
"ERROR: Invalid 'User|Group|Other' permissions set within config file. Please check your config file.",
|
||||
"All operations will be performed in: ",
|
||||
"ERROR: Unable to create local OneDrive syncDir - ",
|
||||
"ERROR: Invalid skip_file entry '.*' detected",
|
||||
"Initializing the Synchronization Engine ...",
|
||||
"Cannot connect to Microsoft OneDrive Service - Network Connection Issue",
|
||||
"WARNING: Application has been configured to bypass local data preservation in the event of file conflict",
|
||||
"WARNING: Local data loss MAY occur in this scenario",
|
||||
"ERROR: .nosync file found. Aborting synchronization process to safeguard data",
|
||||
"ERROR: Unsupported account type for listing OneDrive Business Shared Folders",
|
||||
"ERROR: Unsupported account type for syncing OneDrive Business Shared Folders",
|
||||
"WARNING: The requested path for --single-directory does not exist locally. Creating requested path within: ",
|
||||
"Initializing monitor ...",
|
||||
"OneDrive monitor interval (seconds): ",
|
||||
"[M] Skipping watching path - .folder found & --skip-dot-files enabled: ",
|
||||
"[M] Directory created: ",
|
||||
"Offline, cannot create remote directory!",
|
||||
"Cannot create remote directory: ",
|
||||
"[M] File changed: ",
|
||||
"Offline, cannot upload changed item!",
|
||||
"Cannot upload file changes/creation: ",
|
||||
"[M] Item deleted: ",
|
||||
"Offline, cannot delete item!",
|
||||
"Item cannot be deleted from OneDrive because it was not found in the local database",
|
||||
"Cannot delete remote item: ",
|
||||
"[M] Item moved: ",
|
||||
"Offline, cannot move item!",
|
||||
"Cannot move item: ",
|
||||
"ERROR: ",
|
||||
"ERROR: The following inotify error was generated: ",
|
||||
"Starting a sync with OneDrive",
|
||||
"Sync with OneDrive is complete",
|
||||
"Persistent connection errors, reinitializing connection",
|
||||
"Authorization token invalid, use --logout to authorize the client again",
|
||||
"Syncing changes from this selected path: ",
|
||||
"Syncing changes from selected local path only - NOT syncing data changes from OneDrive ...",
|
||||
"Syncing changes from selected local path first before downloading changes from OneDrive ...",
|
||||
"Syncing changes from selected OneDrive path ...",
|
||||
"Syncing changes from local path only - NOT syncing data changes from OneDrive ...",
|
||||
"Syncing changes from local path first before downloading changes from OneDrive ...",
|
||||
"Syncing changes from OneDrive ...",
|
||||
"Giving up on sync after three attempts: ",
|
||||
"Retry sync count: ",
|
||||
" Got termination signal, shutting down DB connection",
|
||||
"Syncing changes from OneDrive only - NOT syncing local data changes to OneDrive ...",
|
||||
"The file does not have any hash",
|
||||
"ERROR: Check your 'drive_id' entry in your configuration file as it may be incorrect",
|
||||
"ERROR: Check your configuration as your refresh_token may be empty or invalid. You may need to issue a --logout and re-authorize this client.",
|
||||
"ERROR: OneDrive account currently has zero space available. Please free up some space online.",
|
||||
"WARNING: OneDrive quota information is being restricted or providing a zero value. Please fix by speaking to your OneDrive / Office 365 Administrator.",
|
||||
"ERROR: OneDrive quota information is missing. Potentially your OneDrive account currently has zero space available. Please free up some space online.",
|
||||
"ERROR: OneDrive quota information is being restricted. Please fix by speaking to your OneDrive / Office 365 Administrator.",
|
||||
"Application version: ",
|
||||
"Account Type: ",
|
||||
"Default Drive ID: ",
|
||||
"Default Root ID: ",
|
||||
"Remaining Free Space: ",
|
||||
"Continuing the upload session ...",
|
||||
"Removing local file as --upload-only & --remove-source-files configured",
|
||||
"ERROR: File failed to upload. Increase logging verbosity to determine why.",
|
||||
"Skipping item - excluded by skip_dir config: ",
|
||||
"Syncing this OneDrive Personal Shared Folder: ",
|
||||
"Attempting to sync OneDrive Business Shared Folders",
|
||||
"Syncing this OneDrive Business Shared Folder: ",
|
||||
"OneDrive Business Shared Folder - Shared By: ",
|
||||
"WARNING: Skipping shared folder due to existing name conflict: ",
|
||||
"WARNING: Skipping changes of Path ID: ",
|
||||
"WARNING: To sync this shared folder, this shared folder needs to be renamed",
|
||||
"WARNING: Conflict Shared By: ",
|
||||
"WARNING: Not syncing this OneDrive Business Shared File: ",
|
||||
"OneDrive Business Shared File - Shared By: ",
|
||||
"WARNING: Not syncing this OneDrive Business Shared item: ",
|
||||
"ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object",
|
||||
"Getting path details from OneDrive ...",
|
||||
"ERROR: The requested single directory to sync was not found on OneDrive",
|
||||
"Fetching details for OneDrive Root",
|
||||
"OneDrive Root does not exist in the database. We need to add it.",
|
||||
"Added OneDrive Root to the local database",
|
||||
"OneDrive Root exists in the database",
|
||||
"ERROR: Unable to query OneDrive for account details",
|
||||
]
|
||||
}
|
67
src/config.d
67
src/config.d
|
@ -2,6 +2,7 @@ import core.stdc.stdlib: EXIT_SUCCESS, EXIT_FAILURE, exit;
|
|||
import std.file, std.string, std.regex, std.stdio, std.process, std.algorithm.searching, std.getopt, std.conv, std.path;
|
||||
import std.algorithm.sorting: sort;
|
||||
import selective;
|
||||
import translations;
|
||||
static import log;
|
||||
|
||||
final class Config
|
||||
|
@ -118,8 +119,10 @@ final class Config
|
|||
longValues["sync_file_permissions"] = defaultFilePermissionMode;
|
||||
// Configure download / upload rate limits
|
||||
longValues["rate_limit"] = 0;
|
||||
// What language will be used for application output messaging - default EN-AU
|
||||
stringValues["language_identifier"] = "EN-AU";
|
||||
|
||||
// DEVELOPER OPTIONS
|
||||
// DEVELOPER OPTIONS
|
||||
// display_memory = true | false
|
||||
// - It may be desirable to display the memory usage of the application to assist with diagnosing memory issues with the application
|
||||
// - This is especially beneficial when debugging or performing memory tests with Valgrind
|
||||
|
@ -200,9 +203,12 @@ final class Config
|
|||
configDirName.setAttributes(returnRequiredDirectoryPermisions());
|
||||
}
|
||||
|
||||
// configDirName has a trailing /
|
||||
log.vlog("Using 'user' Config Dir: ", configDirName);
|
||||
log.vlog("Using 'system' Config Dir: ", systemConfigDirName);
|
||||
// Initialise the default language output as early as possible
|
||||
translations.initialize();
|
||||
|
||||
// What has been determined as the 'user' and 'system' config directories?
|
||||
log.vdebug("Using this 'user' Config Dir: ", configDirName);
|
||||
log.vdebug("Using this 'system' Config Dir: ", systemConfigDirName);
|
||||
|
||||
// Update application set variables based on configDirName
|
||||
refreshTokenFilePath = buildNormalizedPath(configDirName ~ "/refresh_token");
|
||||
|
@ -235,18 +241,25 @@ final class Config
|
|||
// Is there a system configuration file?
|
||||
if (!exists(systemConfigFilePath)) {
|
||||
// 'system' configuration file does not exist
|
||||
log.vlog("No user or system config file found, using application defaults");
|
||||
// "No user or system config file found, using application defaults"
|
||||
log.vlog(provideLanguageTranslation(getValueString("language_identifier"),1));
|
||||
return true;
|
||||
} else {
|
||||
// 'system' configuration file exists
|
||||
// can we load the configuration file without error?
|
||||
if (load(systemConfigFilePath)) {
|
||||
// configuration file loaded without error
|
||||
log.log("System configuration file successfully loaded");
|
||||
// Load the User Language File if this was updated from the default
|
||||
if (getValueString("language_identifier") != "EN-AU") {
|
||||
translations.initializeUserConfiguredLanguageTranslations(getValueString("language_identifier"));
|
||||
}
|
||||
// "System configuration file successfully loaded"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),2));
|
||||
return true;
|
||||
} else {
|
||||
// there was a problem loading the configuration file
|
||||
log.log("System configuration file has errors - please check your configuration");
|
||||
// "System configuration file has errors - please check your configuration"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),3));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -255,11 +268,17 @@ final class Config
|
|||
// can we load the configuration file without error?
|
||||
if (load(userConfigFilePath)) {
|
||||
// configuration file loaded without error
|
||||
log.log("Configuration file successfully loaded");
|
||||
// Load the User Language File if this was updated from the default
|
||||
if (getValueString("language_identifier") != "EN-AU") {
|
||||
translations.initializeUserConfiguredLanguageTranslations(getValueString("language_identifier"));
|
||||
}
|
||||
// "Configuration file successfully loaded"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),4));
|
||||
return true;
|
||||
} else {
|
||||
// there was a problem loading the configuration file
|
||||
log.log("Configuration file has errors - please check your configuration");
|
||||
// "Configuration file has errors - please check your configuration",
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),5));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -454,12 +473,14 @@ final class Config
|
|||
}
|
||||
} catch (GetOptException e) {
|
||||
log.error(e.msg);
|
||||
log.error("Try 'onedrive -h' for more information");
|
||||
// "Please use 'onedrive --help' for further assistance in regards to running this application"
|
||||
log.error(provideLanguageTranslation(getValueString("language_identifier"),27));
|
||||
exit(EXIT_FAILURE);
|
||||
} catch (Exception e) {
|
||||
// error
|
||||
log.error(e.msg);
|
||||
log.error("Try 'onedrive -h' for more information");
|
||||
// "Please use 'onedrive --help' for further assistance in regards to running this application"
|
||||
log.error(provideLanguageTranslation(getValueString("language_identifier"),27));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -587,23 +608,29 @@ final class Config
|
|||
string azureConfigValue = c.front.dup;
|
||||
switch(azureConfigValue) {
|
||||
case "":
|
||||
log.log("Using config option for Global Azure AD Endpoints");
|
||||
// "Using config option for Global Azure AD Endpoints"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),6));
|
||||
break;
|
||||
case "USL4":
|
||||
log.log("Using config option for Azure AD for US Government Endpoints");
|
||||
// "Using config option for Azure AD for US Government Endpoints"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),7));
|
||||
break;
|
||||
case "USL5":
|
||||
log.log("Using config option for Azure AD for US Government Endpoints (DOD)");
|
||||
// "Using config option for Azure AD for US Government Endpoints (DOD)"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),8));
|
||||
break;
|
||||
case "DE":
|
||||
log.log("Using config option for Azure AD Germany");
|
||||
// "Using config option for Azure AD Germany"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),9));
|
||||
break;
|
||||
case "CN":
|
||||
log.log("Using config option for Azure AD China operated by 21Vianet");
|
||||
// "Using config option for Azure AD China operated by 21Vianet"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),10));
|
||||
break;
|
||||
// Default - all other entries
|
||||
default:
|
||||
log.log("Unknown Azure AD Endpoint - using Global Azure AD Endpoints");
|
||||
// "Unknown Azure AD Endpoint - using Global Azure AD Endpoints"
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),11));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -612,13 +639,15 @@ final class Config
|
|||
c.popFront();
|
||||
setValueLong(key, to!long(c.front.dup));
|
||||
} else {
|
||||
log.log("Unknown key in config file: ", key);
|
||||
// "Unknown key in config file: "
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),12), key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.log("Malformed config line: ", lineBuffer);
|
||||
// "Malformed config line: "
|
||||
log.log(provideLanguageTranslation(getValueString("language_identifier"),13), lineBuffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
255
src/main.d
255
src/main.d
|
@ -1,7 +1,7 @@
|
|||
import core.stdc.stdlib: EXIT_SUCCESS, EXIT_FAILURE, exit;
|
||||
import core.memory, core.time, core.thread;
|
||||
import std.getopt, std.file, std.path, std.process, std.stdio, std.conv, std.algorithm.searching, std.string, std.regex;
|
||||
import config, itemdb, monitor, onedrive, selective, sync, util;
|
||||
import config, itemdb, monitor, onedrive, selective, sync, util, translations;
|
||||
import std.net.curl: CurlException;
|
||||
import core.stdc.signal;
|
||||
import std.traits;
|
||||
|
@ -11,11 +11,13 @@ OneDriveApi oneDrive;
|
|||
ItemDatabase itemDb;
|
||||
|
||||
const int EXIT_UNAUTHORIZED = 3;
|
||||
|
||||
enum MONITOR_LOG_SILENT = 2;
|
||||
enum MONITOR_LOG_QUIET = 1;
|
||||
enum LOG_NORMAL = 0;
|
||||
|
||||
// Language Identifier
|
||||
shared string languageIdentifier = "";
|
||||
|
||||
int main(string[] args)
|
||||
{
|
||||
// Disable buffering on stdout
|
||||
|
@ -108,6 +110,8 @@ int main(string[] args)
|
|||
}
|
||||
|
||||
// read in application options as passed in
|
||||
// EN only error message
|
||||
string helpMessage = "Please use 'onedrive --help' for further assistance in regards to running this application";
|
||||
try {
|
||||
bool printVersion = false;
|
||||
auto opt = getopt(
|
||||
|
@ -131,23 +135,35 @@ int main(string[] args)
|
|||
} catch (GetOptException e) {
|
||||
// option errors
|
||||
log.error(e.msg);
|
||||
log.error("Try 'onedrive -h' for more information");
|
||||
// Language default for this message
|
||||
log.error(helpMessage);
|
||||
return EXIT_FAILURE;
|
||||
} catch (Exception e) {
|
||||
// generic error
|
||||
log.error(e.msg);
|
||||
log.error("Try 'onedrive -h' for more information");
|
||||
// Language default for this message
|
||||
log.error(helpMessage);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// load configuration file if available
|
||||
auto cfg = new config.Config(confdirOption);
|
||||
// initialise config options
|
||||
if (!cfg.initialize()) {
|
||||
// There was an error loading the configuration
|
||||
// Error message already printed
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// --verbose --verbose used .. override any language setting to force EN-AU
|
||||
if (cfg.getValueLong("verbose") >= 2) {
|
||||
log.vdebug("Force application language to EN-AU due to debug operation");
|
||||
cfg.setValueString("language_identifier", "EN-AU");
|
||||
}
|
||||
// Use the configured application language
|
||||
languageIdentifier = cfg.getValueString("language_identifier");
|
||||
log.vlog("Application Language set to: ", languageIdentifier);
|
||||
|
||||
// set memory display
|
||||
displayMemoryUsage = cfg.getValueBool("display_memory");
|
||||
|
||||
|
@ -235,7 +251,8 @@ int main(string[] args)
|
|||
// Was config file updated between last execution ang this execution?
|
||||
if (currentConfigHash != previousConfigHash) {
|
||||
// config file was updated, however we only want to trigger a --resync requirement if sync_dir, skip_dir, skip_file or drive_id was modified
|
||||
log.log("config file has been updated, checking if --resync needed");
|
||||
// "config file has been updated, checking if --resync needed"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,14));
|
||||
if (exists(configBackupFile)) {
|
||||
// check backup config what has changed for these configuration options if anything
|
||||
// # sync_dir = "~/OneDrive"
|
||||
|
@ -300,10 +317,10 @@ int main(string[] args)
|
|||
if (!cfg.getValueBool("dry_run")) {
|
||||
// we are not in a dry-run scenario
|
||||
// update config hash
|
||||
log.vdebug("updating config hash as it is out of date");
|
||||
log.vdebug("Updating config hash as it is out of date");
|
||||
std.file.write(configHashFile, computeQuickXorHash(configFilePath));
|
||||
// create backup copy of current config file
|
||||
log.vdebug("making backup of config file as it is out of date");
|
||||
log.vdebug("Making backup of config file as it is out of date");
|
||||
std.file.copy(configFilePath, configBackupFile);
|
||||
}
|
||||
}
|
||||
|
@ -360,7 +377,8 @@ int main(string[] args)
|
|||
// not testing configuration changes
|
||||
if (!cfg.getValueBool("resync")) {
|
||||
// --resync not issued, fail fast
|
||||
log.error("An application configuration change has been detected where a --resync is required");
|
||||
// "An application configuration change has been detected where a --resync is required"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,15));
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
// --resync issued, update hashes of config files if they exist
|
||||
|
@ -368,20 +386,20 @@ int main(string[] args)
|
|||
// not doing a dry run, update hash files if config & sync_list exist
|
||||
if (exists(configFilePath)) {
|
||||
// update hash
|
||||
log.vdebug("updating config hash as --resync issued");
|
||||
log.vdebug("Updating config hash as --resync issued");
|
||||
std.file.write(configHashFile, computeQuickXorHash(configFilePath));
|
||||
// create backup copy of current config file
|
||||
log.vdebug("making backup of config file as --resync issued");
|
||||
log.vdebug("Making backup of config file as --resync issued");
|
||||
std.file.copy(configFilePath, configBackupFile);
|
||||
}
|
||||
if (exists(syncListFilePath)) {
|
||||
// update sync_list hash
|
||||
log.vdebug("updating sync_list hash as --resync issued");
|
||||
log.vdebug("Updating sync_list hash as --resync issued");
|
||||
std.file.write(syncListHashFile, computeQuickXorHash(syncListFilePath));
|
||||
}
|
||||
if (exists(businessSharedFolderFilePath)) {
|
||||
// update business_shared_folders hash
|
||||
log.vdebug("updating business_shared_folders hash as --resync issued");
|
||||
log.vdebug("Updating business_shared_folders hash as --resync issued");
|
||||
std.file.write(businessSharedFoldersHashFile, computeQuickXorHash(businessSharedFolderFilePath));
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +409,8 @@ int main(string[] args)
|
|||
|
||||
// dry-run notification and database setup
|
||||
if (cfg.getValueBool("dry_run")) {
|
||||
log.log("DRY-RUN Configured. Output below shows what 'would' have occurred.");
|
||||
// "DRY-RUN Configured. Output below shows what 'would' have occurred"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,16));
|
||||
string dryRunShmFile = cfg.databaseFilePathDryRun ~ "-shm";
|
||||
string dryRunWalFile = cfg.databaseFilePathDryRun ~ "-wal";
|
||||
// If the dry run database exists, clean this up
|
||||
|
@ -482,7 +501,8 @@ int main(string[] args)
|
|||
// Configure logging only if enabled
|
||||
if (cfg.getValueBool("enable_logging")){
|
||||
// Initialise using the configured logging directory
|
||||
log.vlog("Using logfile dir: ", logDir);
|
||||
// "Using logfile dir: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,17), logDir);
|
||||
log.init(logDir);
|
||||
}
|
||||
|
||||
|
@ -494,14 +514,16 @@ int main(string[] args)
|
|||
if (!cfg.getValueBool("dry_run")) {
|
||||
safeRemove(databaseFilePath);
|
||||
}
|
||||
log.logAndNotify("Database schema changed, resync needed");
|
||||
// "Database schema changed, resync needed"
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,18));
|
||||
cfg.setValueBool("resync", true);
|
||||
}
|
||||
|
||||
// Handle --resync and --logout to remove local files
|
||||
if (cfg.getValueBool("resync") || cfg.getValueBool("logout")) {
|
||||
if (cfg.getValueBool("resync")) log.vdebug("--resync requested");
|
||||
log.vlog("Deleting the saved status ...");
|
||||
// "Deleting the saved status ..."
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,19));
|
||||
if (!cfg.getValueBool("dry_run")) {
|
||||
safeRemove(cfg.databaseFilePath);
|
||||
safeRemove(cfg.deltaLinkFilePath);
|
||||
|
@ -525,6 +547,7 @@ int main(string[] args)
|
|||
writeln("Config file found in config path = ", exists(configFilePath));
|
||||
|
||||
// Config Options
|
||||
writeln("Config option 'language_identifier' = ", languageIdentifier);
|
||||
writeln("Config option 'check_nosync' = ", cfg.getValueBool("check_nosync"));
|
||||
writeln("Config option 'sync_dir' = ", syncDir);
|
||||
writeln("Config option 'skip_dir' = ", cfg.getValueString("skip_dir"));
|
||||
|
@ -587,11 +610,13 @@ int main(string[] args)
|
|||
// Cant initialise the API as we are not online
|
||||
if (!cfg.getValueBool("monitor")) {
|
||||
// Running as --synchronize
|
||||
log.error("Unable to reach Microsoft OneDrive API service, unable to initialize application\n");
|
||||
// "Unable to reach Microsoft OneDrive API service, unable to initialise application"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,20),"\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
// Running as --monitor
|
||||
log.error("Unable to reach Microsoft OneDrive API service at this point in time, re-trying network tests\n");
|
||||
// "Unable to reach Microsoft OneDrive API service at this point in time, re-trying network tests"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,21),"\n");
|
||||
|
||||
// re-try network connection to OneDrive
|
||||
// https://github.com/abraunegg/onedrive/issues/1184
|
||||
|
@ -618,7 +643,8 @@ int main(string[] args)
|
|||
online = testNetwork();
|
||||
if (online) {
|
||||
// We are now online
|
||||
log.log("Internet connectivity to Microsoft OneDrive service has been restored");
|
||||
// "Internet connectivity to Microsoft OneDrive service has been restored"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,22));
|
||||
retrySuccess = true;
|
||||
} else {
|
||||
// We are still offline
|
||||
|
@ -633,7 +659,8 @@ int main(string[] args)
|
|||
}
|
||||
if (!online) {
|
||||
// Not online after 1.2 years of trying
|
||||
log.error("ERROR: Was unable to reconnect to the Microsoft OneDrive service after 10000 attempts lasting over 1.2 years!");
|
||||
// "ERROR: The OneDrive Linux Client was unable to reconnect to the Microsoft OneDrive service after 10000 attempts lasting over 1.2 years!"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,23));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -642,14 +669,16 @@ int main(string[] args)
|
|||
// Initialize OneDrive, check for authorization
|
||||
if (online) {
|
||||
// we can only initialise if we are online
|
||||
log.vlog("Initializing the OneDrive API ...");
|
||||
// "Initialising the OneDrive API ..."
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,24));
|
||||
oneDrive = new OneDriveApi(cfg);
|
||||
onedriveInitialised = oneDrive.init();
|
||||
oneDrive.printAccessToken = cfg.getValueBool("print_token");
|
||||
}
|
||||
|
||||
if (!onedriveInitialised) {
|
||||
log.error("Could not initialize the OneDrive API");
|
||||
// "Could not initialise the OneDrive API"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,25));
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_UNAUTHORIZED;
|
||||
}
|
||||
|
@ -672,19 +701,26 @@ int main(string[] args)
|
|||
// Application was just authorised
|
||||
if (exists(cfg.refreshTokenFilePath)) {
|
||||
// OneDrive refresh token exists
|
||||
log.log("\nApplication has been successfully authorised, however no additional command switches were provided.\n");
|
||||
log.log("Please use --help for further assistance in regards to running this application.\n");
|
||||
// "Application has been successfully authorised, however no additional command switches were provided"
|
||||
log.log("\n", provideLanguageTranslation(languageIdentifier,26),"\n");
|
||||
// "Please use 'onedrive --help' for further assistance in regards to running this application"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,27),"\n");
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// we just authorised, but refresh_token does not exist .. probably an auth error
|
||||
log.log("\nApplication has not been successfully authorised. Please check your URI response entry and try again.\n");
|
||||
// "Application has not been successfully authorised. Please check your URI response entry and try again"
|
||||
log.log("\n", provideLanguageTranslation(languageIdentifier,28),"\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
// Application was not just authorised
|
||||
log.log("\n--synchronize or --monitor switches missing from your command line input. Please add one (not both) of these switches to your command line or use --help for further assistance.\n");
|
||||
log.log("No OneDrive sync will be performed without one of these two arguments being present.\n");
|
||||
// Application was not just authorised, attempted to be run without --synchronize or --monitor being present
|
||||
// "ERROR: --synchronize or --monitor switches missing from your command line input. Please add one (not both) of these switches to your command line"
|
||||
log.error("\n", provideLanguageTranslation(languageIdentifier,29),"\n");
|
||||
// "No OneDrive sync will be performed without one of these two arguments being present"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,30),"\n");
|
||||
// "Please use 'onedrive --help' for further assistance in regards to running this application"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,27),"\n");
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -692,14 +728,17 @@ int main(string[] args)
|
|||
|
||||
// if --synchronize && --monitor passed in, exit & display help as these conflict with each other
|
||||
if (cfg.getValueBool("synchronize") && cfg.getValueBool("monitor")) {
|
||||
writeln("\nERROR: --synchronize and --monitor cannot be used together\n");
|
||||
writeln("Refer to --help to determine which command option you should use.\n");
|
||||
// "ERROR: --synchronize and --monitor cannot be used together"
|
||||
log.error("\n", provideLanguageTranslation(languageIdentifier,31),"\n");
|
||||
// "Please use 'onedrive --help' for further assistance in regards to running this application"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,27),"\n");
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Initialize the item database
|
||||
log.vlog("Opening the item database ...");
|
||||
// "Opening the item database ..."
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,32));
|
||||
if (!cfg.getValueBool("dry_run")) {
|
||||
// Load the items.sqlite3 file as the database
|
||||
log.vdebug("Using database file: ", asNormalizedPath(cfg.databaseFilePath));
|
||||
|
@ -717,7 +756,8 @@ int main(string[] args)
|
|||
// - Any new file created under ~/OneDrive or 'sync_dir'
|
||||
// valid permissions are 000 -> 777 - anything else is invalid
|
||||
if ((cfg.getValueLong("sync_dir_permissions") < 0) || (cfg.getValueLong("sync_file_permissions") < 0) || (cfg.getValueLong("sync_dir_permissions") > 777) || (cfg.getValueLong("sync_file_permissions") > 777)) {
|
||||
log.error("ERROR: Invalid 'User|Group|Other' permissions set within config file. Please check.");
|
||||
// "ERROR: Invalid 'User|Group|Other' permissions set within config file. Please check your config file."
|
||||
log.error(provideLanguageTranslation(languageIdentifier,33));
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
// debug log output what permissions are being set to
|
||||
|
@ -728,7 +768,8 @@ int main(string[] args)
|
|||
}
|
||||
|
||||
// configure the sync direcory based on syncDir config option
|
||||
log.vlog("All operations will be performed in: ", syncDir);
|
||||
// "All operations will be performed in: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,34), syncDir);
|
||||
if (!exists(syncDir)) {
|
||||
log.vdebug("syncDir: Configured syncDir is missing. Creating: ", syncDir);
|
||||
try {
|
||||
|
@ -739,7 +780,8 @@ int main(string[] args)
|
|||
syncDir.setAttributes(cfg.returnRequiredDirectoryPermisions());
|
||||
} catch (std.file.FileException e) {
|
||||
// Creating the sync directory failed
|
||||
log.error("ERROR: Unable to create local OneDrive syncDir - ", e.msg);
|
||||
// "ERROR: Unable to create local OneDrive syncDir - "
|
||||
log.error(provideLanguageTranslation(languageIdentifier,35), e.msg);
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -810,7 +852,8 @@ int main(string[] args)
|
|||
foreach(entry; cfg.getValueString("skip_file").split("|")){
|
||||
if (entry == ".*") {
|
||||
// invalid entry element detected
|
||||
log.logAndNotify("ERROR: Invalid skip_file entry '.*' detected");
|
||||
// "ERROR: Invalid skip_file entry '.*' detected"
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,36));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -827,12 +870,14 @@ int main(string[] args)
|
|||
} else {
|
||||
if ((cfg.getValueString("get_file_link") == "") && (cfg.getValueString("create_share_link") == "")) {
|
||||
// Print out that we are initializing the engine only if we are not grabbing the file link or creating a shareable link
|
||||
log.logAndNotify("Initializing the Synchronization Engine ...");
|
||||
// "Initialising the Synchronisation Engine ..."
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,37));
|
||||
}
|
||||
}
|
||||
} catch (CurlException e) {
|
||||
if (!cfg.getValueBool("monitor")) {
|
||||
log.log("\nNo Internet connection.");
|
||||
// "Cannot connect to Microsoft OneDrive Service - Network Connection Issue"
|
||||
log.log("\n", provideLanguageTranslation(languageIdentifier,38));
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -867,8 +912,10 @@ int main(string[] args)
|
|||
|
||||
// Has the user enabled to bypass data preservation of renaming local files when there is a conflict?
|
||||
if (cfg.getValueBool("bypass_data_preservation")) {
|
||||
log.log("WARNING: Application has been configured to bypass local data preservation in the event of file conflict.");
|
||||
log.log("WARNING: Local data loss MAY occur in this scenario.");
|
||||
// "WARNING: Application has been configured to bypass local data preservation in the event of file conflict"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,39));
|
||||
// "WARNING: Local data loss MAY occur in this scenario"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,40));
|
||||
sync.setBypassDataPreservation();
|
||||
}
|
||||
|
||||
|
@ -885,7 +932,8 @@ int main(string[] args)
|
|||
if (cfg.getValueBool("check_nomount")) {
|
||||
// we were asked to check the mounts
|
||||
if (exists(syncDir ~ "/.nosync")) {
|
||||
log.logAndNotify("ERROR: .nosync file found. Aborting synchronization process to safeguard data.");
|
||||
// "ERROR: .nosync file found. Aborting synchronisation process to safeguard data"
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,41));
|
||||
// Use exit scopes to shutdown API
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -944,7 +992,8 @@ int main(string[] args)
|
|||
// List OneDrive Business Shared Folders
|
||||
sync.listOneDriveBusinessSharedFolders();
|
||||
} else {
|
||||
log.error("ERROR: Unsupported account type for listing OneDrive Business Shared Folders");
|
||||
// "ERROR: Unsupported account type for listing OneDrive Business Shared Folders"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,42));
|
||||
}
|
||||
// Exit application
|
||||
// Use exit scopes to shutdown API
|
||||
|
@ -958,7 +1007,8 @@ int main(string[] args)
|
|||
// Configure flag to sync business folders
|
||||
sync.setSyncBusinessFolders();
|
||||
} else {
|
||||
log.error("ERROR: Unsupported account type for syncing OneDrive Business Shared Folders");
|
||||
// "ERROR: Unsupported account type for syncing OneDrive Business Shared Folders"
|
||||
log.error(provideLanguageTranslation(languageIdentifier,43));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,7 +1036,8 @@ int main(string[] args)
|
|||
// Does the directory we want to sync actually exist?
|
||||
if (!exists(cfg.getValueString("single_directory"))) {
|
||||
// The requested path to use with --single-directory does not exist locally within the configured 'sync_dir'
|
||||
log.logAndNotify("WARNING: The requested path for --single-directory does not exist locally. Creating requested path within ", syncDir);
|
||||
// "WARNING: The requested path for --single-directory does not exist locally. Creating requested path within: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,44), syncDir);
|
||||
// Make the required --single-directory path locally
|
||||
string singleDirectoryPath = cfg.getValueString("single_directory");
|
||||
mkdirRecurse(singleDirectoryPath);
|
||||
|
@ -1007,52 +1058,68 @@ int main(string[] args)
|
|||
}
|
||||
|
||||
if (cfg.getValueBool("monitor")) {
|
||||
log.logAndNotify("Initializing monitor ...");
|
||||
log.log("OneDrive monitor interval (seconds): ", cfg.getValueLong("monitor_interval"));
|
||||
// "Initialising monitor ..."
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,45));
|
||||
// "OneDrive monitor interval (seconds): "
|
||||
log.log(provideLanguageTranslation(languageIdentifier,46), cfg.getValueLong("monitor_interval"));
|
||||
|
||||
m.onDirCreated = delegate(string path) {
|
||||
// Handle .folder creation if skip_dotfiles is enabled
|
||||
if ((cfg.getValueBool("skip_dotfiles")) && (selectiveSync.isDotFile(path))) {
|
||||
log.vlog("[M] Skipping watching path - .folder found & --skip-dot-files enabled: ", path);
|
||||
// "[M] Skipping watching path - .folder found & --skip-dot-files enabled: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,47), path);
|
||||
} else {
|
||||
log.vlog("[M] Directory created: ", path);
|
||||
// "[M] Directory created: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,48), path);
|
||||
try {
|
||||
sync.scanForDifferences(path);
|
||||
} catch (CurlException e) {
|
||||
log.vlog("Offline, cannot create remote dir!");
|
||||
// "Offline, cannot create remote directory!"
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,49));
|
||||
} catch(Exception e) {
|
||||
log.logAndNotify("Cannot create remote directory: ", e.msg);
|
||||
// "Cannot create remote directory: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,50), e.msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
m.onFileChanged = delegate(string path) {
|
||||
log.vlog("[M] File changed: ", path);
|
||||
// "[M] File changed: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,51), path);
|
||||
try {
|
||||
sync.scanForDifferences(path);
|
||||
} catch (CurlException e) {
|
||||
log.vlog("Offline, cannot upload changed item!");
|
||||
// "Offline, cannot upload changed item!"
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,52));
|
||||
} catch(Exception e) {
|
||||
log.logAndNotify("Cannot upload file changes/creation: ", e.msg);
|
||||
// "Cannot upload file changes/creation: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,53), e.msg);
|
||||
}
|
||||
};
|
||||
m.onDelete = delegate(string path) {
|
||||
log.vlog("[M] Item deleted: ", path);
|
||||
// "[M] Item deleted: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,54), path);
|
||||
try {
|
||||
sync.deleteByPath(path);
|
||||
} catch (CurlException e) {
|
||||
log.vlog("Offline, cannot delete item!");
|
||||
// "Offline, cannot delete item!"
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,55));
|
||||
} catch(SyncException e) {
|
||||
// this error is thrown from sync.d
|
||||
if (e.msg == "The item to delete is not in the local database") {
|
||||
log.vlog("Item cannot be deleted from OneDrive because it was not found in the local database");
|
||||
// "Item cannot be deleted from OneDrive because it was not found in the local database"
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,56));
|
||||
} else {
|
||||
log.logAndNotify("Cannot delete remote item: ", e.msg);
|
||||
// "Cannot delete remote item: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,57), e.msg);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
log.logAndNotify("Cannot delete remote item: ", e.msg);
|
||||
// "Cannot delete remote item: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,57), e.msg);
|
||||
}
|
||||
};
|
||||
m.onMove = delegate(string from, string to) {
|
||||
log.vlog("[M] Item moved: ", from, " -> ", to);
|
||||
// "[M] Item moved: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,58), from, " -> ", to);
|
||||
try {
|
||||
// Handle .folder -> folder if skip_dotfiles is enabled
|
||||
if ((cfg.getValueBool("skip_dotfiles")) && (selectiveSync.isDotFile(from))) {
|
||||
|
@ -1062,9 +1129,11 @@ int main(string[] args)
|
|||
sync.uploadMoveItem(from, to);
|
||||
}
|
||||
} catch (CurlException e) {
|
||||
log.vlog("Offline, cannot move item!");
|
||||
// "Offline, cannot move item!"
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,59));
|
||||
} catch(Exception e) {
|
||||
log.logAndNotify("Cannot move item: ", e.msg);
|
||||
// "Cannot move item: "
|
||||
log.logAndNotify(provideLanguageTranslation(languageIdentifier,60), e.msg);
|
||||
}
|
||||
};
|
||||
signal(SIGINT, &exitHandler);
|
||||
|
@ -1076,7 +1145,8 @@ int main(string[] args)
|
|||
m.init(cfg, cfg.getValueLong("verbose") > 0, cfg.getValueBool("skip_symlinks"), cfg.getValueBool("check_nosync"));
|
||||
} catch (MonitorException e) {
|
||||
// monitor initialisation failed
|
||||
log.error("ERROR: ", e.msg);
|
||||
// "ERROR: " + e.msg
|
||||
log.error(provideLanguageTranslation(languageIdentifier,61), e.msg);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
@ -1105,7 +1175,8 @@ int main(string[] args)
|
|||
m.update(online);
|
||||
} catch (MonitorException e) {
|
||||
// Catch any exceptions thrown by inotify / monitor engine
|
||||
log.error("ERROR: The following inotify error was generated: ", e.msg);
|
||||
// "ERROR: The following inotify error was generated: "
|
||||
log.error(provideLanguageTranslation(languageIdentifier,62), e.msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1176,7 +1247,8 @@ int main(string[] args)
|
|||
}
|
||||
try {
|
||||
// perform a --monitor sync
|
||||
if ((cfg.getValueLong("verbose") > 0) || (logMonitorCounter == logInterval)) log.log("Starting a sync with OneDrive");
|
||||
// "Starting a sync with OneDrive"
|
||||
if ((cfg.getValueLong("verbose") > 0) || (logMonitorCounter == logInterval)) log.log(provideLanguageTranslation(languageIdentifier,63));
|
||||
performSync(sync, cfg.getValueString("single_directory"), cfg.getValueBool("download_only"), cfg.getValueBool("local_first"), cfg.getValueBool("upload_only"), (logMonitorCounter == logInterval ? MONITOR_LOG_QUIET : MONITOR_LOG_SILENT), fullScanRequired, syncListConfiguredFullScanOverride, displaySyncOptions, cfg.getValueBool("monitor"), m);
|
||||
if (!cfg.getValueBool("download_only")) {
|
||||
// discard all events that may have been generated by the sync that have not already been handled
|
||||
|
@ -1184,19 +1256,23 @@ int main(string[] args)
|
|||
m.update(false);
|
||||
} catch (MonitorException e) {
|
||||
// Catch any exceptions thrown by inotify / monitor engine
|
||||
log.error("ERROR: The following inotify error was generated: ", e.msg);
|
||||
// "ERROR: The following inotify error was generated: "
|
||||
log.error(provideLanguageTranslation(languageIdentifier,62), e.msg);
|
||||
}
|
||||
}
|
||||
if ((cfg.getValueLong("verbose") > 0) || (logMonitorCounter == logInterval)) log.log("Sync with OneDrive is complete");
|
||||
// "Sync with OneDrive is complete"
|
||||
if ((cfg.getValueLong("verbose") > 0) || (logMonitorCounter == logInterval)) log.log(provideLanguageTranslation(languageIdentifier,64));
|
||||
} catch (CurlException e) {
|
||||
// we already tried three times in the performSync routine
|
||||
// if we still have problems, then the sync handle might have
|
||||
// gone stale and we need to re-initialize the sync engine
|
||||
log.log("Persistent connection errors, reinitializing connection");
|
||||
// "Persistent connection errors, reinitialising connection"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,65));
|
||||
sync.reset();
|
||||
}
|
||||
} catch (CurlException e) {
|
||||
log.log("Cannot initialize connection to OneDrive");
|
||||
// "Unable to reach Microsoft OneDrive API service, unable to initialise application"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,20));
|
||||
}
|
||||
// performSync complete, set lastCheckTime to current time
|
||||
fullScanRequired = false;
|
||||
|
@ -1233,6 +1309,7 @@ int main(string[] args)
|
|||
// developer set option to limit --monitor loops
|
||||
if (monitorLoopFullCount == (cfg.getValueLong("monitor_max_loop"))) {
|
||||
performMonitor = false;
|
||||
// No internationalisation for this log output - it is a developer set option
|
||||
log.log("Exiting after ", monitorLoopFullCount, " loops due to developer set option");
|
||||
}
|
||||
}
|
||||
|
@ -1275,7 +1352,8 @@ bool initSyncEngine(SyncEngine sync)
|
|||
} catch (OneDriveException e) {
|
||||
if (e.httpStatusCode == 400 || e.httpStatusCode == 401) {
|
||||
// Authorization is invalid
|
||||
log.log("\nAuthorization token invalid, use --logout to authorize the client again\n");
|
||||
// "Authorisation token invalid, use --logout to authorise the client again"
|
||||
log.log("\n", provideLanguageTranslation(languageIdentifier,66),"\n");
|
||||
return false;
|
||||
}
|
||||
if (e.httpStatusCode >= 500) {
|
||||
|
@ -1287,6 +1365,7 @@ bool initSyncEngine(SyncEngine sync)
|
|||
}
|
||||
|
||||
// try to synchronize the folder three times
|
||||
// we cant pass cfg into this function ...
|
||||
void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, bool localFirst, bool uploadOnly, long logLevel, bool fullScanRequired, bool syncListConfiguredFullScanOverride, bool displaySyncOptions, bool monitorEnabled, Monitor m)
|
||||
{
|
||||
int count;
|
||||
|
@ -1326,21 +1405,28 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
|||
}
|
||||
if (singleDirectory != ""){
|
||||
// we were requested to sync a single directory
|
||||
log.vlog("Syncing changes from this selected path: ", singleDirectory);
|
||||
// "Syncing changes from this selected path: "
|
||||
log.vlog(provideLanguageTranslation(languageIdentifier,67), singleDirectory);
|
||||
if (uploadOnly){
|
||||
// Upload Only of selected single directory
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log("Syncing changes from selected local path only - NOT syncing data changes from OneDrive ...");
|
||||
// "Syncing changes from selected local path only - NOT syncing data changes from OneDrive ..."
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log(provideLanguageTranslation(languageIdentifier,68));
|
||||
sync.scanForDifferences(localPath);
|
||||
} else {
|
||||
// No upload only
|
||||
if (localFirst) {
|
||||
// Local First
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log("Syncing changes from selected local path first before downloading changes from OneDrive ...");
|
||||
// "Syncing changes from selected local path first before downloading changes from OneDrive ..."
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log(provideLanguageTranslation(languageIdentifier,69));
|
||||
sync.scanForDifferences(localPath);
|
||||
sync.applyDifferencesSingleDirectory(remotePath);
|
||||
} else {
|
||||
// OneDrive First
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log("Syncing changes from selected OneDrive path ...");
|
||||
// "Syncing changes from selected OneDrive path ..."
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log(provideLanguageTranslation(languageIdentifier,70));
|
||||
// If we are doing a --download-only sync, indicate that only changes from OneDrive will be downloaded
|
||||
// "Syncing changes from OneDrive only - NOT syncing local data changes to OneDrive ..."
|
||||
if (downloadOnly) log.log(provideLanguageTranslation(languageIdentifier,77));
|
||||
sync.applyDifferencesSingleDirectory(remotePath);
|
||||
// is this a download only request?
|
||||
if (!downloadOnly) {
|
||||
|
@ -1355,14 +1441,16 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
|||
// no single directory sync
|
||||
if (uploadOnly){
|
||||
// Upload Only of entire sync_dir
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log("Syncing changes from local path only - NOT syncing data changes from OneDrive ...");
|
||||
// "Syncing changes from local path only - NOT syncing data changes from OneDrive ..."
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log(provideLanguageTranslation(languageIdentifier,71));
|
||||
sync.scanForDifferences(localPath);
|
||||
} else {
|
||||
// No upload only
|
||||
string syncCallLogOutput;
|
||||
if (localFirst) {
|
||||
// sync local files first before downloading from OneDrive
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log("Syncing changes from local path first before downloading changes from OneDrive ...");
|
||||
// "Syncing changes from local path first before downloading changes from OneDrive ..."
|
||||
if (logLevel < MONITOR_LOG_QUIET) log.log(provideLanguageTranslation(languageIdentifier,72));
|
||||
sync.scanForDifferences(localPath);
|
||||
// if syncListConfiguredFullScanOverride = true
|
||||
if (syncListConfiguredFullScanOverride) {
|
||||
|
@ -1374,7 +1462,8 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
|||
}
|
||||
} else {
|
||||
// sync from OneDrive first before uploading files to OneDrive
|
||||
if (logLevel < MONITOR_LOG_SILENT) log.log("Syncing changes from OneDrive ...");
|
||||
// "Syncing changes from OneDrive ..."
|
||||
if (logLevel < MONITOR_LOG_SILENT) log.log(provideLanguageTranslation(languageIdentifier,73));
|
||||
|
||||
// For the initial sync, always use the delta link so that we capture all the right delta changes including adds, moves & deletes
|
||||
logOutputMessage = "Initial Scan: Call OneDrive Delta API for delta changes as compared to last successful sync.";
|
||||
|
@ -1386,6 +1475,9 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
|||
log.vdebug(logOutputMessage);
|
||||
log.vdebug(syncCallLogOutput);
|
||||
}
|
||||
// If we are doing a --download-only sync, indicate that only changes from OneDrive will be downloaded
|
||||
// "Syncing changes from OneDrive only - NOT syncing local data changes to OneDrive ..."
|
||||
if (downloadOnly) log.log(provideLanguageTranslation(languageIdentifier,77));
|
||||
sync.applyDifferences(false);
|
||||
|
||||
// is this a download only request?
|
||||
|
@ -1508,10 +1600,13 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
|||
count = -1;
|
||||
} catch (Exception e) {
|
||||
if (++count == 3) {
|
||||
log.log("Giving up on sync after three attempts: ", e.msg);
|
||||
// "Giving up on sync after three attempts: "
|
||||
log.log(provideLanguageTranslation(languageIdentifier,74), e.msg);
|
||||
throw e;
|
||||
} else
|
||||
log.log("Retry sync count: ", count, ": ", e.msg);
|
||||
} else {
|
||||
// "Retry sync count: "
|
||||
log.log(provideLanguageTranslation(languageIdentifier,75), count, ": ", e.msg);
|
||||
}
|
||||
}
|
||||
} while (count != -1);
|
||||
}
|
||||
|
@ -1527,7 +1622,9 @@ auto assumeNoGC(T) (T t) if (isFunctionPointer!T || isDelegate!T)
|
|||
extern(C) nothrow @nogc @system void exitHandler(int value) {
|
||||
try {
|
||||
assumeNoGC ( () {
|
||||
log.log("Got termination signal, shutting down db connection");
|
||||
// Generate log message
|
||||
// " Got termination signal, shutting down DB connection"
|
||||
log.log(provideLanguageTranslation(languageIdentifier,76));
|
||||
// was itemDb initialised?
|
||||
if (itemDb !is null) {
|
||||
// Make sure the .wal file is incorporated into the main db before we exit
|
||||
|
|
414
src/sync.d
414
src/sync.d
File diff suppressed because it is too large
Load diff
236
src/translations.d
Normal file
236
src/translations.d
Normal file
|
@ -0,0 +1,236 @@
|
|||
// The aim is to provide language translations for the following application logging output:
|
||||
// - log.log
|
||||
// - log.vlog
|
||||
// - log.error
|
||||
// - log.logAndNotify
|
||||
import std.string, std.stdio, std.json, std.file;
|
||||
|
||||
ulong defaultMessageCount = 0;
|
||||
string[] languageResponsesEN_AU;
|
||||
string[] languageResponsesEN_US;
|
||||
string defaultBadLookupResponse = "ERROR: BAD LOOKUP INDEX ";
|
||||
|
||||
// Initialise default message lookup using EN-AU
|
||||
void initialize() {
|
||||
// Initialise default messages
|
||||
initialise_EN_AU();
|
||||
defaultMessageCount = count(languageResponsesEN_AU);
|
||||
}
|
||||
|
||||
// Load user configured translation files from a file
|
||||
void initializeUserConfiguredLanguageTranslations(string languageIdentifier) {
|
||||
// Path to translation files
|
||||
string translationPath = "/usr/share/onedrive/";
|
||||
|
||||
// Translation files
|
||||
string EN_US_TranslationFile = translationPath ~ "EN-US.json";
|
||||
|
||||
switch (languageIdentifier) {
|
||||
case "EN-US":
|
||||
// Load Translation Files if they exist
|
||||
if (exists(EN_US_TranslationFile)) {
|
||||
// Load the file
|
||||
auto fileContents = readText(EN_US_TranslationFile);
|
||||
JSONValue languageList = parseJSON(fileContents);
|
||||
|
||||
// Load the message into the required array
|
||||
foreach (translationItem; languageList["list"].array) {
|
||||
string responseString = translationItem.toString;
|
||||
responseString = responseString[1 .. $-1];
|
||||
languageResponsesEN_US ~= responseString;
|
||||
}
|
||||
// If the loaded responses != defaultMessageCount there will be an issue in translation .. warn
|
||||
writeln("WARNING: " ~ EN_US_TranslationFile ~ " is out of sync with default application messages - application output will be inaccurate");
|
||||
}
|
||||
break;
|
||||
|
||||
case "DE":
|
||||
//logMessageResponse = getResponseFromIndex_EN_US(requiredResponseIndex);
|
||||
break;
|
||||
default:
|
||||
//logMessageResponse = getResponseFromIndex_EN_AU(requiredResponseIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Provide a language response based on the setting of a 'config' file language option
|
||||
string provideLanguageTranslation(string languageIdentifier, int requiredResponseIndex) {
|
||||
string logMessageResponse;
|
||||
// Application message indexes start at '1', however array index's start at '0'
|
||||
// Need to decrement the requiredResponseIndex so we get the right message
|
||||
requiredResponseIndex--;
|
||||
|
||||
switch (languageIdentifier) {
|
||||
case "EN-AU":
|
||||
// Language Maintainer: abraunegg
|
||||
logMessageResponse = getResponseFromIndex_EN_AU(requiredResponseIndex);
|
||||
break;
|
||||
case "EN-US":
|
||||
// Language Maintainer: abraunegg
|
||||
logMessageResponse = getResponseFromIndex_EN_US(requiredResponseIndex);
|
||||
break;
|
||||
default:
|
||||
logMessageResponse = getResponseFromIndex_EN_AU(requiredResponseIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
// Return log message to application
|
||||
return logMessageResponse;
|
||||
}
|
||||
|
||||
// Load EN-AU application messages
|
||||
void initialise_EN_AU(){
|
||||
// The below JSON array contains all the default application messages
|
||||
JSONValue languageList = [ "language": "EN-AU"];
|
||||
languageList.object["list"] = JSONValue([
|
||||
"No user or system config file found, using application defaults",
|
||||
"System configuration file successfully loaded",
|
||||
"System configuration file has errors - please check your configuration",
|
||||
"Configuration file successfully loaded",
|
||||
"Configuration file has errors - please check your configuration",
|
||||
"Using config option for Global Azure AD Endpoints",
|
||||
"Using config option for Azure AD for US Government Endpoints",
|
||||
"Using config option for Azure AD for US Government Endpoints (DOD)",
|
||||
"Using config option for Azure AD Germany",
|
||||
"Using config option for Azure AD China operated by 21Vianet",
|
||||
"Unknown Azure AD Endpoint - using Global Azure AD Endpoints",
|
||||
"Unknown key in config file: ",
|
||||
"Malformed config line: ",
|
||||
"config file has been updated, checking if --resync needed",
|
||||
"An application configuration change has been detected where a --resync is required",
|
||||
"DRY-RUN Configured. Output below shows what 'would' have occurred",
|
||||
"Using logfile dir: ",
|
||||
"Database schema changed, resync needed",
|
||||
"Deleting the saved status ...",
|
||||
"ERROR: Unable to reach Microsoft OneDrive API service, unable to initialise application",
|
||||
"ERROR: Unable to reach Microsoft OneDrive API service at this point in time, re-trying network tests",
|
||||
"Internet connectivity to Microsoft OneDrive service has been restored",
|
||||
"ERROR: The OneDrive Linux Client was unable to reconnect to the Microsoft OneDrive service after 10000 attempts lasting over 1.2 years!",
|
||||
"Initialising the OneDrive API ...",
|
||||
"Could not initialise the OneDrive API",
|
||||
"Application has been successfully authorised, however no additional command switches were provided",
|
||||
"Please use 'onedrive --help' for further assistance in regards to running this application",
|
||||
"Application has not been successfully authorised. Please check your URI response entry and try again",
|
||||
"ERROR: --synchronize or --monitor switches missing from your command line input. Please add one (not both) of these switches to your command line",
|
||||
"No OneDrive sync will be performed without one of these two arguments being present",
|
||||
"ERROR: --synchronize and --monitor cannot be used together",
|
||||
"Opening the item database ...",
|
||||
"ERROR: Invalid 'User|Group|Other' permissions set within config file. Please check your config file.",
|
||||
"All operations will be performed in: ",
|
||||
"ERROR: Unable to create local OneDrive syncDir - ",
|
||||
"ERROR: Invalid skip_file entry '.*' detected",
|
||||
"Initialising the Synchronisation Engine ...",
|
||||
"Cannot connect to Microsoft OneDrive Service - Network Connection Issue",
|
||||
"WARNING: Application has been configured to bypass local data preservation in the event of file conflict",
|
||||
"WARNING: Local data loss MAY occur in this scenario",
|
||||
"ERROR: .nosync file found. Aborting synchronisation process to safeguard data",
|
||||
"ERROR: Unsupported account type for listing OneDrive Business Shared Folders",
|
||||
"ERROR: Unsupported account type for syncing OneDrive Business Shared Folders",
|
||||
"WARNING: The requested path for --single-directory does not exist locally. Creating requested path within: ",
|
||||
"Initialising monitor ...",
|
||||
"OneDrive monitor interval (seconds): ",
|
||||
"[M] Skipping watching path - .folder found & --skip-dot-files enabled: ",
|
||||
"[M] Directory created: ",
|
||||
"Offline, cannot create remote directory!",
|
||||
"Cannot create remote directory: ",
|
||||
"[M] File changed: ",
|
||||
"Offline, cannot upload changed item!",
|
||||
"Cannot upload file changes/creation: ",
|
||||
"[M] Item deleted: ",
|
||||
"Offline, cannot delete item!",
|
||||
"Item cannot be deleted from OneDrive because it was not found in the local database",
|
||||
"Cannot delete remote item: ",
|
||||
"[M] Item moved: ",
|
||||
"Offline, cannot move item!",
|
||||
"Cannot move item: ",
|
||||
"ERROR: ",
|
||||
"ERROR: The following inotify error was generated: ",
|
||||
"Starting a sync with OneDrive",
|
||||
"Sync with OneDrive is complete",
|
||||
"Persistent connection errors, reinitialising connection",
|
||||
"Authorisation token invalid, use --logout to authorise the client again",
|
||||
"Syncing changes from this selected path: ",
|
||||
"Syncing changes from selected local path only - NOT syncing data changes from OneDrive ...",
|
||||
"Syncing changes from selected local path first before downloading changes from OneDrive ...",
|
||||
"Syncing changes from selected OneDrive path ...",
|
||||
"Syncing changes from local path only - NOT syncing data changes from OneDrive ...",
|
||||
"Syncing changes from local path first before downloading changes from OneDrive ...",
|
||||
"Syncing changes from OneDrive ...",
|
||||
"Giving up on sync after three attempts: ",
|
||||
"Retry sync count: ",
|
||||
" Got termination signal, shutting down DB connection",
|
||||
"Syncing changes from OneDrive only - NOT syncing local data changes to OneDrive ...",
|
||||
"The file does not have any hash",
|
||||
"ERROR: Check your 'drive_id' entry in your configuration file as it may be incorrect",
|
||||
"ERROR: Check your configuration as your refresh_token may be empty or invalid. You may need to issue a --logout and re-authorise this client.",
|
||||
"ERROR: OneDrive account currently has zero space available. Please free up some space online.",
|
||||
"WARNING: OneDrive quota information is being restricted or providing a zero value. Please fix by speaking to your OneDrive / Office 365 Administrator.",
|
||||
"ERROR: OneDrive quota information is missing. Potentially your OneDrive account currently has zero space available. Please free up some space online.",
|
||||
"ERROR: OneDrive quota information is being restricted. Please fix by speaking to your OneDrive / Office 365 Administrator.",
|
||||
"Application version: ",
|
||||
"Account Type: ",
|
||||
"Default Drive ID: ",
|
||||
"Default Root ID: ",
|
||||
"Remaining Free Space: ",
|
||||
"Continuing the upload session ...",
|
||||
"Removing local file as --upload-only & --remove-source-files configured",
|
||||
"ERROR: File failed to upload. Increase logging verbosity to determine why.",
|
||||
"Skipping item - excluded by skip_dir config: ",
|
||||
"Syncing this OneDrive Personal Shared Folder: ",
|
||||
"Attempting to sync OneDrive Business Shared Folders",
|
||||
"Syncing this OneDrive Business Shared Folder: ",
|
||||
"OneDrive Business Shared Folder - Shared By: ",
|
||||
"WARNING: Skipping shared folder due to existing name conflict: ",
|
||||
"WARNING: Skipping changes of Path ID: ",
|
||||
"WARNING: To sync this shared folder, this shared folder needs to be renamed",
|
||||
"WARNING: Conflict Shared By: ",
|
||||
"WARNING: Not syncing this OneDrive Business Shared File: ",
|
||||
"OneDrive Business Shared File - Shared By: ",
|
||||
"WARNING: Not syncing this OneDrive Business Shared item: ",
|
||||
"ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object",
|
||||
"Getting path details from OneDrive ...",
|
||||
"ERROR: The requested single directory to sync was not found on OneDrive",
|
||||
"Fetching details for OneDrive Root",
|
||||
"OneDrive Root does not exist in the database. We need to add it.",
|
||||
"Added OneDrive Root to the local database",
|
||||
"OneDrive Root exists in the database",
|
||||
"ERROR: Unable to query OneDrive for account details",
|
||||
]);
|
||||
|
||||
// Load the message into the array
|
||||
foreach (translationItem; languageList["list"].array) {
|
||||
string responseString = translationItem.toString;
|
||||
responseString = responseString[1 .. $-1];
|
||||
languageResponsesEN_AU ~= responseString;
|
||||
}
|
||||
}
|
||||
|
||||
// Provide the application message based on the index as provided
|
||||
string getResponseFromIndex_EN_AU(int requiredResponseIndex) {
|
||||
string requiredResponse;
|
||||
// get response from message array
|
||||
try {
|
||||
// try and get the message from the required index
|
||||
requiredResponse = languageResponsesEN_AU[requiredResponseIndex];
|
||||
} catch (core.exception.RangeError e) {
|
||||
// invalid index provided
|
||||
requiredResponse = defaultBadLookupResponse;
|
||||
}
|
||||
// Return language response
|
||||
return requiredResponse;
|
||||
}
|
||||
|
||||
// Provide the application message based on the index as provided
|
||||
string getResponseFromIndex_EN_US(int requiredResponseIndex) {
|
||||
string requiredResponse;
|
||||
// get response from message array
|
||||
try {
|
||||
// try and get the message from the required index
|
||||
requiredResponse = languageResponsesEN_US[requiredResponseIndex];
|
||||
} catch (core.exception.RangeError e) {
|
||||
// invalid index provided
|
||||
requiredResponse = defaultBadLookupResponse;
|
||||
}
|
||||
// Return language response
|
||||
return requiredResponse;
|
||||
}
|
Loading…
Reference in a new issue