From 880631982cc170886a480f25e73f056780cb5006 Mon Sep 17 00:00:00 2001 From: abraunegg Date: Sun, 9 Aug 2020 15:48:27 +1000 Subject: [PATCH] Update --single-directory handling of parent path matching (#1014) * In certain scenarios when using --single-directory (either very first run or with --resync) the parent path for the selected path will not be in the database, thus, all items that should be synced are not. Add another special case handler to handle this scenario. --- src/sync.d | 74 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/sync.d b/src/sync.d index 6d05278b..2734bc0d 100644 --- a/src/sync.d +++ b/src/sync.d @@ -1298,7 +1298,6 @@ final class SyncEngine } } else { log.vdebug("Using /delta call to query drive for items"); - // query for changes = onedrive.viewChangesByItemId(driveId, idToQuery, deltaLink); try { // Fetch the changes relative to the path id we want to query @@ -1554,7 +1553,8 @@ final class SyncEngine foreach (item; changes["value"].array) { bool isRoot = false; - string thisItemPath; + string thisItemParentPath; + string thisItemFullPath; changeCount++; // Change as reported by OneDrive @@ -1594,31 +1594,46 @@ final class SyncEngine log.vdebug("Handling change as 'root item', has no parent reference or is a deleted item"); applyDifference(item, driveId, isRoot); } else { - // What is this item's path? + // What is this item's parent path? if (hasParentReferencePath(item)) { - thisItemPath = item["parentReference"]["path"].str; + thisItemParentPath = item["parentReference"]["path"].str; + thisItemFullPath = thisItemParentPath ~ "/" ~ item["name"].str; } else { - thisItemPath = ""; + thisItemParentPath = ""; } - // Business Shared Folders special case handling + // Special case handling flags + bool singleDirectorySpecialCase = false; bool sharedFoldersSpecialCase = false; // Debug output of change evaluation items log.vdebug("'parentReference id' = ", item["parentReference"]["id"].str); - log.vdebug("syncFolderName = ", syncFolderName); - log.vdebug("syncFolderPath = ", syncFolderPath); - log.vdebug("syncFolderChildPath = ", syncFolderChildPath); + log.vdebug("search criteria: syncFolderName = ", syncFolderName); + log.vdebug("search criteria: syncFolderPath = ", syncFolderPath); + log.vdebug("search criteria: syncFolderChildPath = ", syncFolderChildPath); log.vdebug("thisItemId = ", item["id"].str); - log.vdebug("thisItemPath = ", thisItemPath); + log.vdebug("thisItemParentPath = ", thisItemParentPath); + log.vdebug("thisItemFullPath = ", thisItemFullPath); log.vdebug("'item id' matches search 'id' = ", (item["id"].str == id)); log.vdebug("'parentReference id' matches search 'id' = ", (item["parentReference"]["id"].str == id)); - log.vdebug("'thisItemPath' contains 'syncFolderChildPath' = ", (canFind(thisItemPath, syncFolderChildPath)) ); - log.vdebug("'thisItemPath' contains search 'id' = ", (canFind(thisItemPath, id)) ); + log.vdebug("'thisItemParentPath' contains 'syncFolderChildPath' = ", (canFind(thisItemParentPath, syncFolderChildPath))); + log.vdebug("'thisItemParentPath' contains search 'id' = ", (canFind(thisItemParentPath, id))); - // Special case handling + // Special case handling - --single-directory + // If we are in a --single-directory sync scenario, and, the DB does not contain any parent details, or --single-directory is used with --resync + // all changes will be discarded as 'Remote change discarded - not in --single-directory sync scope (not in DB)' even though, some of the changes + // are actually valid and required as they are part of the parental path + if (singleDirectoryScope){ + // What is the full path for this item from OneDrive + log.vdebug("'syncFolderChildPath' contains 'thisItemFullPath' = ", (canFind(syncFolderChildPath, thisItemFullPath))); + if (canFind(syncFolderChildPath, thisItemFullPath)) { + singleDirectorySpecialCase = true; + } + } + + // Special case handling - Shared Business Folders // - IF we are syncing shared folders, and the shared folder is not the 'top level' folder being shared out - // canFind(thisItemPath, syncFolderChildPath) will never match: + // canFind(thisItemParentPath, syncFolderChildPath) will never match: // Syncing this OneDrive Business Shared Folder: MyFolderName // OneDrive Business Shared By: Firstname Lastname (email@address) // Applying changes of Path ID: pathId @@ -1628,16 +1643,16 @@ final class SyncEngine // ... // [DEBUG] 'item id' matches search 'id' = false // [DEBUG] 'parentReference id' matches search 'id' = false - // [DEBUG] 'thisItemPath' contains 'syncFolderChildPath' = false - // [DEBUG] 'thisItemPath' contains search 'id' = false + // [DEBUG] 'thisItemParentPath' contains 'syncFolderChildPath' = false + // [DEBUG] 'thisItemParentPath' contains search 'id' = false // [DEBUG] Change does not match any criteria to apply // Remote change discarded - not in business shared folders sync scope - if ((!canFind(thisItemPath, syncFolderChildPath)) && (syncBusinessFolders)) { + if ((!canFind(thisItemParentPath, syncFolderChildPath)) && (syncBusinessFolders)) { // Syncing Shared Business folders & we dont have a path match // is this a reverse path match? - log.vdebug("'thisItemPath' contains 'syncFolderName' = ", (canFind(thisItemPath, syncFolderName)) ); - if (canFind(thisItemPath, syncFolderName)) { + log.vdebug("'thisItemParentPath' contains 'syncFolderName' = ", (canFind(thisItemParentPath, syncFolderName))); + if (canFind(thisItemParentPath, syncFolderName)) { sharedFoldersSpecialCase = true; } } @@ -1647,13 +1662,14 @@ final class SyncEngine // 2. 'parentReference id' matches 'id' // 3. 'item path' contains 'syncFolderChildPath' // 4. 'item path' contains 'id' - - if ( (item["id"].str == id) || (item["parentReference"]["id"].str == id) || (canFind(thisItemPath, syncFolderChildPath)) || (canFind(thisItemPath, id)) || (sharedFoldersSpecialCase) ){ + // 5. Special Case was triggered + if ( (item["id"].str == id) || (item["parentReference"]["id"].str == id) || (canFind(thisItemParentPath, syncFolderChildPath)) || (canFind(thisItemParentPath, id)) || (singleDirectorySpecialCase) || (sharedFoldersSpecialCase) ){ // This is a change we want to apply - if (!sharedFoldersSpecialCase) { + if ((!singleDirectorySpecialCase) && (!sharedFoldersSpecialCase)) { log.vdebug("Change matches search criteria to apply"); } else { - log.vdebug("Change matches search criteria to apply - special case criteria - reverse path matching used"); + if (singleDirectorySpecialCase) log.vdebug("Change matches search criteria to apply - special case criteria - reverse path matching used (--single-directory)"); + if (sharedFoldersSpecialCase) log.vdebug("Change matches search criteria to apply - special case criteria - reverse path matching used (Shared Business Folders)"); } // Apply OneDrive change applyDifference(item, driveId, isRoot); @@ -5118,7 +5134,7 @@ final class SyncEngine string folderId; string deltaLink; string thisItemId; - string thisItemPath; + string thisItemParentPath; string syncFolderName; string syncFolderPath; string syncFolderChildPath; @@ -5229,24 +5245,24 @@ final class SyncEngine // Is this change valid for the 'path' we are checking? if (hasParentReferencePath(item)) { thisItemId = item["parentReference"]["id"].str; - thisItemPath = item["parentReference"]["path"].str; + thisItemParentPath = item["parentReference"]["path"].str; } else { thisItemId = item["id"].str; // Is the defaultDriveId == driveId if (driveId == defaultDriveId){ // 'root' items will not have ["parentReference"]["path"] if (isItemRoot(item)){ - thisItemPath = ""; + thisItemParentPath = ""; } else { - thisItemPath = item["parentReference"]["path"].str; + thisItemParentPath = item["parentReference"]["path"].str; } } else { // A remote drive item will not have ["parentReference"]["path"] - thisItemPath = ""; + thisItemParentPath = ""; } } - if ( (thisItemId == folderId) || (canFind(thisItemPath, syncFolderChildPath)) || (canFind(thisItemPath, folderId)) ){ + if ( (thisItemId == folderId) || (canFind(thisItemParentPath, syncFolderChildPath)) || (canFind(thisItemParentPath, folderId)) ){ // This is a change we want count validChanges++; if ((isItemFile(item)) && (hasFileSize(item))) {