mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-01 21:42:16 +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
|
// Return the details of the specified id
|
||||||
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_get
|
// 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();
|
checkAccessTokenExpired();
|
||||||
const(char)[] url;
|
const(char)[] url;
|
||||||
// string itemByIdUrl = "https://graph.microsoft.com/v1.0/me/drive/items/";
|
// string driveByIdUrl = "https://graph.microsoft.com/v1.0/drives/";
|
||||||
url = itemByIdUrl ~ id;
|
url = driveByIdUrl ~ driveId ~ "/items/" ~ id;
|
||||||
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
||||||
return get(url);
|
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);
|
item.mtime = SysTime(0);
|
||||||
} else {
|
} else {
|
||||||
// Item is not in a deleted state
|
// 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)) {
|
if (isItemFile(driveItem)) {
|
||||||
|
@ -251,7 +257,7 @@ final class SyncEngine
|
||||||
auto deleteDirectoryNoSync(string path)
|
auto deleteDirectoryNoSync(string path)
|
||||||
{
|
{
|
||||||
// Use the global's as initialised via init() rather than performing unnecessary additional HTTPS calls
|
// 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
|
// Attempt to delete the requested path within OneDrive without performing a sync
|
||||||
log.vlog("Attempting to delete the requested path within OneDrive");
|
log.vlog("Attempting to delete the requested path within OneDrive");
|
||||||
|
@ -275,7 +281,7 @@ final class SyncEngine
|
||||||
} else {
|
} else {
|
||||||
// the folder was in the local database
|
// the folder was in the local database
|
||||||
// Handle the deletion and saving any update to 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);
|
deleteByPath(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,26 +310,53 @@ final class SyncEngine
|
||||||
{
|
{
|
||||||
log.vlog("Applying changes of Path ID: " ~ id);
|
log.vlog("Applying changes of Path ID: " ~ id);
|
||||||
JSONValue changes;
|
JSONValue changes;
|
||||||
string syncFolderName;
|
|
||||||
string deltaLink = itemdb.getDeltaLink(driveId, id);
|
string deltaLink = itemdb.getDeltaLink(driveId, id);
|
||||||
JSONValue idDetails = onedrive.getPathDetailsById(id);
|
|
||||||
|
|
||||||
// Set the name of this folder
|
// Query the name of this folder id
|
||||||
if ((idDetails["id"].str == id) && (isItemFolder(idDetails))){
|
string syncFolderName;
|
||||||
syncFolderName = idDetails["name"].str;
|
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 (;;) {
|
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 {
|
try {
|
||||||
// Due to differences in OneDrive API's between personal and business we need to get changes only from defaultRootId
|
// Fetch the changes relative to the path id we want to query
|
||||||
// If we used the 'id' passed in & when using --single-directory with a business account we get:
|
changes = onedrive.viewChangesById(driveId, idToQuery, deltaLink);
|
||||||
// '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);
|
|
||||||
|
|
||||||
} catch (OneDriveException e) {
|
} catch (OneDriveException e) {
|
||||||
|
// HTTP request returned status code 410 (The requested resource is no longer available at the server)
|
||||||
if (e.httpStatusCode == 410) {
|
if (e.httpStatusCode == 410) {
|
||||||
log.vlog("Delta link expired, resyncing...");
|
log.vlog("Delta link expired, re-syncing...");
|
||||||
deltaLink = null;
|
deltaLink = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -339,9 +372,9 @@ final class SyncEngine
|
||||||
|
|
||||||
if (e.httpStatusCode == 504) {
|
if (e.httpStatusCode == 504) {
|
||||||
// HTTP request returned status code 504 (Gateway Timeout)
|
// HTTP request returned status code 504 (Gateway Timeout)
|
||||||
// Retry
|
// Retry by calling applyDifferences() again
|
||||||
//log.vlog("OneDrive returned a 'HTTP 504 - Gateway Timeout' - gracefully handling error");
|
log.vlog("OneDrive returned a 'HTTP 504 - Gateway Timeout' - gracefully handling error");
|
||||||
changes = onedrive.viewChangesById(driveId, defaultRootId, deltaLink);
|
applyDifferences(driveId, idToQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
else throw e;
|
else throw e;
|
||||||
|
@ -354,12 +387,25 @@ final class SyncEngine
|
||||||
// Thus we cannot name check for 'root' below on deleted items
|
// Thus we cannot name check for 'root' below on deleted items
|
||||||
if(!isItemDeleted(item)){
|
if(!isItemDeleted(item)){
|
||||||
// This is not a deleted 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
|
// 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
|
// This IS the OneDrive Root
|
||||||
isRoot = true;
|
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?
|
// 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
|
// This is a corner edge case - https://github.com/skilion/onedrive/issues/341
|
||||||
JSONValue oneDriveMovedNotDeleted;
|
JSONValue oneDriveMovedNotDeleted;
|
||||||
try {
|
try {
|
||||||
oneDriveMovedNotDeleted = onedrive.getPathDetailsById(item["id"].str);
|
oneDriveMovedNotDeleted = onedrive.getPathDetailsById(driveId, item["id"].str);
|
||||||
} catch (OneDriveException e) {
|
} catch (OneDriveException e) {
|
||||||
if (e.httpStatusCode == 404) {
|
if (e.httpStatusCode == 404) {
|
||||||
// No .. that ID is GONE
|
// No .. that ID is GONE
|
||||||
|
log.vlog("Remote change discarded - item cannot be found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,13 +561,6 @@ final class SyncEngine
|
||||||
} else {
|
} else {
|
||||||
itemdb.insert(item);
|
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
|
// download an item that was not synced before
|
||||||
|
@ -542,7 +582,7 @@ final class SyncEngine
|
||||||
break;
|
break;
|
||||||
case ItemType.dir:
|
case ItemType.dir:
|
||||||
case ItemType.remote:
|
case ItemType.remote:
|
||||||
log.log("Creating directory ", path);
|
log.log("Creating directory: ", path);
|
||||||
mkdirRecurse(path);
|
mkdirRecurse(path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue