mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-10 01:36:39 +02:00
Resolve sync issues with Shared Folders & Personal OneDrive Accounts (#26)
* Resolve Shared Folders not syncing (OneDrive Personal) * Resolve 'Key not found: fileSystemInfo' when then item is a remote item (OneDrive Personal) * Resolve where file names are being truncated by 5 characters with each sync (OneDrive Business) * remove extra // not required * Remove commented out code to avoid confusion
This commit is contained in:
parent
d6b4930d0a
commit
17e5138b5a
|
@ -190,12 +190,12 @@ final class OneDriveApi
|
|||
|
||||
// Return the details of the specified id
|
||||
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_get
|
||||
JSONValue getPathDetailsById(const(char)[] id)
|
||||
JSONValue getPathDetailsById(const(char)[] driveId, const(char)[] id)
|
||||
{
|
||||
checkAccessTokenExpired();
|
||||
const(char)[] url;
|
||||
// string itemByIdUrl = "https://graph.microsoft.com/v1.0/me/drive/items/";
|
||||
url = itemByIdUrl ~ id;
|
||||
// string driveByIdUrl = "https://graph.microsoft.com/v1.0/drives/";
|
||||
url = driveByIdUrl ~ driveId ~ "/items/" ~ id;
|
||||
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
||||
return get(url);
|
||||
}
|
||||
|
|
98
src/sync.d
98
src/sync.d
|
@ -58,7 +58,13 @@ private Item makeItem(const ref JSONValue driveItem)
|
|||
item.mtime = SysTime(0);
|
||||
} else {
|
||||
// Item is not in a deleted state
|
||||
item.mtime = SysTime.fromISOExtString(driveItem["fileSystemInfo"]["lastModifiedDateTime"].str);
|
||||
// Resolve 'Key not found: fileSystemInfo' when then item is a remote item
|
||||
// https://github.com/abraunegg/onedrive/issues/11
|
||||
if (isItemRemote(driveItem)) {
|
||||
item.mtime = SysTime.fromISOExtString(driveItem["remoteItem"]["fileSystemInfo"]["lastModifiedDateTime"].str);
|
||||
} else {
|
||||
item.mtime = SysTime.fromISOExtString(driveItem["fileSystemInfo"]["lastModifiedDateTime"].str);
|
||||
}
|
||||
}
|
||||
|
||||
if (isItemFile(driveItem)) {
|
||||
|
@ -251,7 +257,7 @@ final class SyncEngine
|
|||
auto deleteDirectoryNoSync(string path)
|
||||
{
|
||||
// Use the global's as initialised via init() rather than performing unnecessary additional HTTPS calls
|
||||
string rootId = defaultRootId;
|
||||
const(char)[] rootId = defaultRootId;
|
||||
|
||||
// Attempt to delete the requested path within OneDrive without performing a sync
|
||||
log.vlog("Attempting to delete the requested path within OneDrive");
|
||||
|
@ -275,7 +281,7 @@ final class SyncEngine
|
|||
} else {
|
||||
// the folder was in the local database
|
||||
// Handle the deletion and saving any update to the local database
|
||||
log.vlog("The requested directory to delete was found in the local database. Processing the delection normally");
|
||||
log.vlog("The requested directory to delete was found in the local database. Processing the deletion normally");
|
||||
deleteByPath(path);
|
||||
}
|
||||
}
|
||||
|
@ -304,26 +310,53 @@ final class SyncEngine
|
|||
{
|
||||
log.vlog("Applying changes of Path ID: " ~ id);
|
||||
JSONValue changes;
|
||||
string syncFolderName;
|
||||
string deltaLink = itemdb.getDeltaLink(driveId, id);
|
||||
JSONValue idDetails = onedrive.getPathDetailsById(id);
|
||||
|
||||
// Set the name of this folder
|
||||
if ((idDetails["id"].str == id) && (isItemFolder(idDetails))){
|
||||
syncFolderName = idDetails["name"].str;
|
||||
// Query the name of this folder id
|
||||
string syncFolderName;
|
||||
JSONValue idDetails = parseJSON("{}");
|
||||
try {
|
||||
idDetails = onedrive.getPathDetailsById(driveId, id);
|
||||
} catch (OneDriveException e) {
|
||||
if (e.httpStatusCode == 404) {
|
||||
// id was not found - possibly a remote (shared) folder
|
||||
log.vlog("No details returned for given Path ID");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the name of this 'Path ID'
|
||||
if (("id" in idDetails) != null) {
|
||||
// valid response from onedrive.getPathDetailsById(driveId, id) - a JSON item object present
|
||||
if ((idDetails["id"].str == id) && (isItemFolder(idDetails))){
|
||||
syncFolderName = encodeComponent(idDetails["name"].str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
// Due to differences in OneDrive API's between personal and business we need to get changes only from defaultRootId
|
||||
// If we used the 'id' passed in & when using --single-directory with a business account we get:
|
||||
// 'HTTP request returned status code 501 (Not Implemented): view.delta can only be called on the root.'
|
||||
// To view changes correctly, we need to use the correct path id for the request
|
||||
const(char)[] idToQuery;
|
||||
if (driveId == defaultDriveId) {
|
||||
// The drive id matches our users default drive id
|
||||
idToQuery = defaultRootId.dup;
|
||||
} else {
|
||||
// The drive id does not match our users default drive id
|
||||
// Potentially the 'path id' we are requesting the details of is a Shared Folder (remote item)
|
||||
// Use the 'id' that was passed in
|
||||
idToQuery = id;
|
||||
}
|
||||
|
||||
try {
|
||||
// Due to differences in OneDrive API's between personal and business we need to get changes only from defaultRootId
|
||||
// If we used the 'id' passed in & when using --single-directory with a business account we get:
|
||||
// 'HTTP request returned status code 501 (Not Implemented): view.delta can only be called on the root.'
|
||||
// To view changes correctly, we need to use 'defaultRootId'
|
||||
changes = onedrive.viewChangesById(driveId, defaultRootId, deltaLink);
|
||||
// Fetch the changes relative to the path id we want to query
|
||||
changes = onedrive.viewChangesById(driveId, idToQuery, deltaLink);
|
||||
|
||||
} catch (OneDriveException e) {
|
||||
// HTTP request returned status code 410 (The requested resource is no longer available at the server)
|
||||
if (e.httpStatusCode == 410) {
|
||||
log.vlog("Delta link expired, resyncing...");
|
||||
log.vlog("Delta link expired, re-syncing...");
|
||||
deltaLink = null;
|
||||
continue;
|
||||
}
|
||||
|
@ -339,9 +372,9 @@ final class SyncEngine
|
|||
|
||||
if (e.httpStatusCode == 504) {
|
||||
// HTTP request returned status code 504 (Gateway Timeout)
|
||||
// Retry
|
||||
//log.vlog("OneDrive returned a 'HTTP 504 - Gateway Timeout' - gracefully handling error");
|
||||
changes = onedrive.viewChangesById(driveId, defaultRootId, deltaLink);
|
||||
// Retry by calling applyDifferences() again
|
||||
log.vlog("OneDrive returned a 'HTTP 504 - Gateway Timeout' - gracefully handling error");
|
||||
applyDifferences(driveId, idToQuery);
|
||||
}
|
||||
|
||||
else throw e;
|
||||
|
@ -354,12 +387,25 @@ final class SyncEngine
|
|||
// Thus we cannot name check for 'root' below on deleted items
|
||||
if(!isItemDeleted(item)){
|
||||
// This is not a deleted item
|
||||
// Test is this is the OneDrive Root?
|
||||
// Test is this is the OneDrive Users Root?
|
||||
// Use the global's as initialised via init() rather than performing unnecessary additional HTTPS calls
|
||||
if ((id == defaultRootId) && (item["name"].str == "root")) { // fix for https://github.com/skilion/onedrive/issues/269
|
||||
if ((id == defaultRootId) && (item["name"].str == "root")) {
|
||||
// This IS the OneDrive Root
|
||||
isRoot = true;
|
||||
}
|
||||
|
||||
// Test is this a Shared Folder - which should also be classified as a 'root' item
|
||||
if (changeHasParentReferenceId(item)) {
|
||||
// item contains parentReference key
|
||||
if (item["parentReference"]["driveId"].str != defaultDriveId) {
|
||||
// The change parentReference driveId does not match the defaultDriveId - this could be a Shared Folder root item
|
||||
string sharedDriveRootPath = "/drives/" ~ item["parentReference"]["driveId"].str ~ "/root:";
|
||||
if (item["parentReference"]["path"].str == sharedDriveRootPath) {
|
||||
// The drive path matches what a shared folder root item would equal
|
||||
isRoot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// How do we handle this change?
|
||||
|
@ -380,10 +426,11 @@ final class SyncEngine
|
|||
// This is a corner edge case - https://github.com/skilion/onedrive/issues/341
|
||||
JSONValue oneDriveMovedNotDeleted;
|
||||
try {
|
||||
oneDriveMovedNotDeleted = onedrive.getPathDetailsById(item["id"].str);
|
||||
oneDriveMovedNotDeleted = onedrive.getPathDetailsById(driveId, item["id"].str);
|
||||
} catch (OneDriveException e) {
|
||||
if (e.httpStatusCode == 404) {
|
||||
// No .. that ID is GONE
|
||||
log.vlog("Remote change discarded - item cannot be found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -514,13 +561,6 @@ final class SyncEngine
|
|||
} else {
|
||||
itemdb.insert(item);
|
||||
}
|
||||
|
||||
// sync remote folder
|
||||
// https://github.com/OneDrive/onedrive-api-docs/issues/764
|
||||
/*if (isItemRemote(driveItem)) {
|
||||
log.log("Syncing remote folder: ", path);
|
||||
applyDifferences(item.remoteDriveId, item.remoteId);
|
||||
}*/
|
||||
}
|
||||
|
||||
// download an item that was not synced before
|
||||
|
@ -542,7 +582,7 @@ final class SyncEngine
|
|||
break;
|
||||
case ItemType.dir:
|
||||
case ItemType.remote:
|
||||
log.log("Creating directory ", path);
|
||||
log.log("Creating directory: ", path);
|
||||
mkdirRecurse(path);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue