diff --git a/src/main.d b/src/main.d index 8a5c4fbd..87f56e15 100644 --- a/src/main.d +++ b/src/main.d @@ -17,7 +17,7 @@ int main(string[] args) // Application Option Variables // Add a check mounts option to resolve https://github.com/abraunegg/onedrive/issues/8 - bool checkMount; + bool checkMount = false; // configuration directory string configDirName; // Create a single root directory on OneDrive @@ -25,7 +25,7 @@ int main(string[] args) // The destination directory if we are using the OneDrive client to rename a directory string destinationDirectory; // Debug the HTTPS submit operations if required - bool debugHttp; + bool debugHttp = false; // Do not use notifications in monitor mode bool disableNotifications = false; // Display application configuration but do not sync @@ -33,45 +33,49 @@ int main(string[] args) // Display sync status bool displaySyncStatus = false; // only download remote changes - bool downloadOnly; + bool downloadOnly = false; // Does the user want to disable upload validation - https://github.com/abraunegg/onedrive/issues/205 // SharePoint will associate some metadata from the library the file is uploaded to directly in the file - thus change file size & checksums bool disableUploadValidation = false; // Do we enable a log file bool enableLogFile = false; + // Force the use of HTTP 1.1 to overcome curl => 7.62.0 where some operations are now sent via HTTP/2 + // Whilst HTTP/2 operations are handled, in some cases the handling of this outside of the client is not being done correctly (router, other) thus the client breaks + // This flag then allows the user to downgrade all HTTP operations to HTTP 1.1 for maximum network path compatibility + bool forceHTTP11 = false; // SharePoint / Office 365 Shared Library name to query string o365SharedLibraryName; // Local sync - Upload local changes first before downloading changes from OneDrive - bool localFirst; + bool localFirst = false; // remove the current user and sync state - bool logout; + bool logout = false; // enable monitor mode - bool monitor; + bool monitor = false; // Add option for no remote delete - bool noRemoteDelete; + bool noRemoteDelete = false; // print the access token - bool printAccessToken; + bool printAccessToken = false; // force a full resync - bool resync; + bool resync = false; // Remove a single directory on OneDrive string removeDirectory; // This allows for selective directory syncing instead of everything under ~/OneDrive/ string singleDirectory; // Add option to skip symlinks - bool skipSymlinks; + bool skipSymlinks = false; // The source directory if we are using the OneDrive client to rename a directory string sourceDirectory; // override the sync directory string syncDirName; // Configure a flag to perform a sync // This is beneficial so that if just running the client itself - without any options, or sync check, the client does not perform a sync - bool synchronize; + bool synchronize = false; // Upload Only - bool uploadOnly; + bool uploadOnly = false; // enable verbose logging - bool verbose; + bool verbose = false; // print the version and exit - bool printVersion; + bool printVersion = false; // Application Startup option validation try { @@ -90,6 +94,7 @@ int main(string[] args) "download-only|d", "Only download remote changes", &downloadOnly, "disable-upload-validation", "Disable upload validation when uploading to OneDrive", &disableUploadValidation, "enable-logging", "Enable client activity to a separate log file", &enableLogFile, + "force-http-1.1", "Force the use of HTTP 1.1 for all operations", &forceHTTP11, "get-O365-drive-id", "Query and return the Office 365 Drive ID for a given Office 365 SharePoint Shared Library", &o365SharedLibraryName, "local-first", "Synchronize from the local directory source first, before downloading changes from OneDrive.", &localFirst, "logout", "Logout the current user", &logout, @@ -276,6 +281,8 @@ int main(string[] args) if (displayConfiguration){ string userConfigFilePath = configDirName ~ "/config"; string userSyncList = configDirName ~ "/sync_list"; + // Display application version + std.stdio.write("onedrive version = ", import("version")); // Display all of the pertinent configuration options writeln("Config path = ", configDirName); @@ -301,6 +308,14 @@ int main(string[] args) // Is sync_list configured? if (exists(userSyncList)){ writeln("Selective sync configured = true"); + writeln("sync_list contents:"); + // Output the sync_list contents + auto syncListFile = File(userSyncList); + auto range = syncListFile.byLine(); + foreach (line; range) + { + writeln(line); + } } else { writeln("Selective sync configured = false"); } @@ -320,7 +335,7 @@ int main(string[] args) } // Initialize OneDrive, check for authorization - oneDrive = new OneDriveApi(cfg, debugHttp); + oneDrive = new OneDriveApi(cfg, debugHttp, forceHTTP11); oneDrive.printAccessToken = printAccessToken; if (!oneDrive.init()) { log.error("Could not initialize the OneDrive API"); @@ -362,6 +377,16 @@ int main(string[] args) // Configure selective sync by parsing and getting a regex for skip_file config component auto selectiveSync = new SelectiveSync(); + if (exists(cfg.syncListFilePath)){ + log.vdebug("Loading user configured sync_list file ..."); + // list what will be synced + auto syncListFile = File(cfg.syncListFilePath); + auto range = syncListFile.byLine(); + foreach (line; range) + { + log.vdebug("sync_list: ", line); + } + } selectiveSync.load(cfg.syncListFilePath); selectiveSync.setMask(cfg.getValue("skip_file")); diff --git a/src/onedrive.d b/src/onedrive.d index c3c70cd5..3a7434c6 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -64,7 +64,7 @@ final class OneDriveApi // if true, every new access token is printed bool printAccessToken; - this(Config cfg, bool debugHttp) + this(Config cfg, bool debugHttp, bool forceHTTP11) { this.cfg = cfg; http = HTTP(); @@ -91,10 +91,19 @@ final class OneDriveApi // Specify how many redirects should be allowed http.maxRedirects(5); + // Do we enable curl debugging? if (debugHttp) { http.verbose = true; .debugResponse = true; } + + // What version of HTTP protocol do we use? + // Curl >= 7.62.0 defaults to http2 for a significant number of operations + if (forceHTTP11) { + log.vdebug("Downgrading all HTTP operations to HTTP 1.1"); + // Downgrade to HTTP 1.1 - yes version = 2 is HTTP 1.1 + http.handle.set(CurlOption.http_version,2); + } } bool init() diff --git a/src/sync.d b/src/sync.d index db25a6ac..4b2bb22b 100644 --- a/src/sync.d +++ b/src/sync.d @@ -491,6 +491,14 @@ final class SyncEngine syncFolderChildPath = ""; } } + + // Debug Output + log.vdebug("Sync Folder Name: ", syncFolderName); + // Debug Output of path if only set, generally only set if using --single-directory + if (hasParentReferencePath(idDetails)) { + log.vdebug("Sync Folder Path: ", syncFolderPath); + log.vdebug("Sync Folder Child Path: ", syncFolderChildPath); + } } for (;;) { @@ -542,6 +550,8 @@ final class SyncEngine // Are there any changes to process? if (("value" in changes) != null) { // There are valid changes + log.vdebug("Number of changes from OneDrive to process: ", count(changes["value"].array)); + foreach (item; changes["value"].array) { bool isRoot = false; string thisItemPath; @@ -642,7 +652,9 @@ final class SyncEngine // Reset the downloadFailed flag for this item downloadFailed = false; + // Is the change from OneDrive a 'root' item if (isItemRoot(driveItem) || !item.parentId || isRoot) { + log.vdebug("Handing a OneDrive 'root' change"); item.parentId = null; // ensures that it has no parent item.driveId = driveId; // HACK: makeItem() cannot set the driveId property of the root itemdb.upsert(item); @@ -656,11 +668,11 @@ final class SyncEngine // check the item type if (!unwanted) { if (isItemFile(driveItem)) { - //log.vlog("The item we are syncing is a file"); + log.vdebug("The item we are syncing is a file"); } else if (isItemFolder(driveItem)) { - //log.vlog("The item we are syncing is a folder"); + log.vdebug("The item we are syncing is a folder"); } else if (isItemRemote(driveItem)) { - //log.vlog("The item we are syncing is a remote item"); + log.vdebug("The item we are syncing is a remote item"); assert(isItemFolder(driveItem["remoteItem"]), "The remote item is not a folder"); } else { log.vlog("This item type (", item.name, ") is not supported"); @@ -676,6 +688,9 @@ final class SyncEngine path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name; path = buildNormalizedPath(path); unwanted = selectiveSync.isPathExcluded(path); + if (unwanted) { + log.vdebug("OneDrive change path is to be excluded by user configuration: ", path); + } } else { unwanted = true; } @@ -683,7 +698,7 @@ final class SyncEngine // skip unwanted items early if (unwanted) { - //log.vlog("Filtered out"); + log.vdebug("Skipping OneDrive change as this is determined to be unwanted"); skippedItems ~= item.id; return; } @@ -695,8 +710,7 @@ final class SyncEngine // check if the item is going to be deleted if (isItemDeleted(driveItem)) { // item.name is not available, so we get a bunch of meaningless log output - // will fix this with wider logging changes being worked on - //log.vlog("This item is marked for deletion:", item.name); + // Item name we will attempt to delete will be printed out later if (cached) { // flag to delete idsToDelete ~= [item.driveId, item.id]; @@ -723,8 +737,10 @@ final class SyncEngine // update the item if (cached) { + log.vdebug("OneDrive change is an update to an existing local item"); applyChangedItem(oldItem, oldPath, item, path); } else { + log.vdebug("OneDrive change is a new local item"); applyNewItem(item, path); }