mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-15 20:26:53 +02:00
WIP for remote items support
This commit is contained in:
parent
7de0d97e6e
commit
65bb14ad37
|
@ -150,14 +150,12 @@ final class ItemDatabase
|
||||||
auto r = s.exec();
|
auto r = s.exec();
|
||||||
if (r.empty) return false;
|
if (r.empty) return false;
|
||||||
currItem = buildItem(r);
|
currItem = buildItem(r);
|
||||||
// if the item of type remote jump to the child
|
// if the item is of type remote substitute it with the child
|
||||||
if (currItem.type == ItemType.remote) {
|
if (currItem.type == ItemType.remote) {
|
||||||
auto children = selectChildren(currItem.driveId, currItem.id);
|
auto children = selectChildren(currItem.driveId, currItem.id);
|
||||||
enforce(children.length == 1, "The remote item does not have exactly 1 child");
|
enforce(children.length == 1, "The remote item does not have exactly 1 child");
|
||||||
// keep some characteristics of the remote item
|
// keep the name of the remote item
|
||||||
children[0].name = currItem.name;
|
children[0].name = currItem.name;
|
||||||
children[0].eTag = currItem.eTag;
|
|
||||||
children[0].cTag = currItem.cTag;
|
|
||||||
currItem = children[0];
|
currItem = children[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
118
src/sync.d
118
src/sync.d
|
@ -31,6 +31,11 @@ private bool isItemRoot(const ref JSONValue item)
|
||||||
return ("root" in item) != null;
|
return ("root" in item) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool isItemRemote(const ref JSONValue item)
|
||||||
|
{
|
||||||
|
return ("remoteItem" in item) != null;
|
||||||
|
}
|
||||||
|
|
||||||
private Item makeItem(const ref JSONValue jsonItem)
|
private Item makeItem(const ref JSONValue jsonItem)
|
||||||
{
|
{
|
||||||
ItemType type;
|
ItemType type;
|
||||||
|
@ -38,8 +43,8 @@ private Item makeItem(const ref JSONValue jsonItem)
|
||||||
type = ItemType.file;
|
type = ItemType.file;
|
||||||
} else if (isItemFolder(jsonItem)) {
|
} else if (isItemFolder(jsonItem)) {
|
||||||
type = ItemType.dir;
|
type = ItemType.dir;
|
||||||
} else {
|
} else if (isItemRemote(jsonItem)) {
|
||||||
assert(0);
|
type = ItemType.remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item item = {
|
Item item = {
|
||||||
|
@ -49,7 +54,7 @@ private Item makeItem(const ref JSONValue jsonItem)
|
||||||
type: type,
|
type: type,
|
||||||
eTag: isItemRoot(jsonItem) ? null : jsonItem["eTag"].str, // eTag is not returned for the root in OneDrive Biz
|
eTag: isItemRoot(jsonItem) ? null : jsonItem["eTag"].str, // eTag is not returned for the root in OneDrive Biz
|
||||||
cTag: "cTag" !in jsonItem ? null : jsonItem["cTag"].str, // cTag is missing in old files (plus all folders)
|
cTag: "cTag" !in jsonItem ? null : jsonItem["cTag"].str, // cTag is missing in old files (plus all folders)
|
||||||
mtime: SysTime.fromISOExtString(jsonItem["fileSystemInfo"]["lastModifiedDateTime"].str),
|
mtime: isItemRemote(jsonItem) ? SysTime(0) : SysTime.fromISOExtString(jsonItem["fileSystemInfo"]["lastModifiedDateTime"].str),
|
||||||
parentDriveId: isItemRoot(jsonItem) ? null : jsonItem["parentReference"]["driveId"].str,
|
parentDriveId: isItemRoot(jsonItem) ? null : jsonItem["parentReference"]["driveId"].str,
|
||||||
parentId: isItemRoot(jsonItem) ? null : jsonItem["parentReference"]["id"].str
|
parentId: isItemRoot(jsonItem) ? null : jsonItem["parentReference"]["id"].str
|
||||||
};
|
};
|
||||||
|
@ -182,39 +187,56 @@ final class SyncEngine
|
||||||
assumeSafeAppend(skippedItems);
|
assumeSafeAppend(skippedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyDifference(JSONValue item)
|
private void applyDifference(JSONValue jsonItem)
|
||||||
{
|
{
|
||||||
string driveId = item["parentReference"]["driveId"].str;
|
Item item = makeItem(jsonItem);
|
||||||
string id = item["id"].str;
|
log.vlog(item.id, " ", item.name);
|
||||||
string name = item["name"].str;
|
|
||||||
|
|
||||||
log.vlog(id, " ", name);
|
|
||||||
|
|
||||||
// eTag and parentId do not exists for the root in OneDrive Biz
|
|
||||||
string eTag, parentId;
|
|
||||||
if (!isItemRoot(item)) {
|
|
||||||
eTag = item["eTag"].str;
|
|
||||||
parentId = item["parentReference"]["id"].str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip unwanted items early
|
// skip unwanted items early
|
||||||
if (skippedItems.find(parentId).length != 0) {
|
bool unwanted;
|
||||||
|
unwanted |= skippedItems.find(item.parentId).length != 0;
|
||||||
|
unwanted |= selectiveSync.isNameExcluded(item.name);
|
||||||
|
unwanted |= selectiveSync.isPathExcluded(path);
|
||||||
|
if (unwanted) {
|
||||||
log.vlog("Filtered out");
|
log.vlog("Filtered out");
|
||||||
skippedItems ~= id;
|
skippedItems ~= item.id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectiveSync.isNameExcluded(name)) {
|
|
||||||
log.vlog("Filtered out");
|
// compute the path of the item
|
||||||
skippedItems ~= id;
|
string path = ".";
|
||||||
|
if (!isItemRoot(jsonItem)) {
|
||||||
|
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the item is to be deleted
|
||||||
|
if (isItemDeleted(jsonItem)) {
|
||||||
|
log.vlog("The item is marked for deletion");
|
||||||
|
idsToDelete ~= [item.driveId, item.id];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the item type
|
||||||
|
if (isItemRemote(jsonItem)) {
|
||||||
|
// TODO
|
||||||
|
// check name change
|
||||||
|
// scan the children later
|
||||||
|
// fix child references
|
||||||
|
log.vlog("Remote items are not supported yet");
|
||||||
|
skippedItems ~= item.id;
|
||||||
|
return;
|
||||||
|
} else if (!isItemFile(jsonItem) && !isItemFolder(jsonItem)) {
|
||||||
|
log.vlog("The item is neither a file nor a directory, skipping");
|
||||||
|
skippedItems ~= item.id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rename the local item if it is unsynced and there is a new version of it
|
// rename the local item if it is unsynced and there is a new version of it
|
||||||
Item oldItem;
|
Item oldItem;
|
||||||
string oldPath;
|
string oldPath;
|
||||||
bool cached = itemdb.selectById(driveId, id, oldItem);
|
bool cached = itemdb.selectById(item.driveId, item.id, oldItem);
|
||||||
if (cached && eTag != oldItem.eTag) {
|
if (cached && item.eTag != oldItem.eTag) {
|
||||||
oldPath = itemdb.computePath(driveId, id);
|
oldPath = itemdb.computePath(item.driveId, item.id);
|
||||||
if (!isItemSynced(oldItem, oldPath)) {
|
if (!isItemSynced(oldItem, oldPath)) {
|
||||||
log.vlog("The local item is unsynced, renaming");
|
log.vlog("The local item is unsynced, renaming");
|
||||||
if (exists(oldPath)) safeRename(oldPath);
|
if (exists(oldPath)) safeRename(oldPath);
|
||||||
|
@ -222,44 +244,17 @@ final class SyncEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the item is to be deleted
|
|
||||||
if (isItemDeleted(item)) {
|
|
||||||
log.vlog("The item is marked for deletion");
|
|
||||||
if (cached) idsToDelete ~= [driveId, id];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the path of the item
|
|
||||||
string path = ".";
|
|
||||||
if (parentId) {
|
|
||||||
path = itemdb.computePath(driveId, parentId) ~ "/" ~ name;
|
|
||||||
// selective sync
|
|
||||||
if (selectiveSync.isPathExcluded(path)) {
|
|
||||||
log.vlog("Filtered out: ", path);
|
|
||||||
skippedItems ~= id;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isItemFile(item) && !isItemFolder(item)) {
|
|
||||||
log.vlog("The item is neither a file nor a directory, skipping");
|
|
||||||
skippedItems ~= id;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item newItem = makeItem(item);
|
|
||||||
|
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
applyNewItem(newItem, path);
|
applyNewItem(item, path);
|
||||||
} else {
|
} else {
|
||||||
applyChangedItem(oldItem, newItem, path);
|
applyChangedItem(oldItem, oldPath, item, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the item in the db
|
// save the item in the db
|
||||||
if (oldItem.id) {
|
if (oldItem.id) {
|
||||||
itemdb.update(newItem);
|
itemdb.update(item);
|
||||||
} else {
|
} else {
|
||||||
itemdb.insert(newItem);
|
itemdb.insert(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +267,7 @@ final class SyncEngine
|
||||||
setTimes(path, item.mtime, item.mtime);
|
setTimes(path, item.mtime, item.mtime);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
log.vlog("The local item is out of sync, renaming ...");
|
log.vlog("The local item is out of sync, renaming...");
|
||||||
safeRename(path);
|
safeRename(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,24 +280,25 @@ final class SyncEngine
|
||||||
log.log("Creating directory: ", path);
|
log.log("Creating directory: ", path);
|
||||||
mkdir(path);
|
mkdir(path);
|
||||||
break;
|
break;
|
||||||
case ItemType.remote:
|
case ItemType.remote:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
setTimes(path, item.mtime, item.mtime);
|
setTimes(path, item.mtime, item.mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyChangedItem(Item oldItem, Item newItem, string newPath)
|
// update a local item
|
||||||
|
// the local item is assumed to be in sync with the local db
|
||||||
|
private void applyChangedItem(Item oldItem, string oldPath, Item newItem, string newPath)
|
||||||
{
|
{
|
||||||
assert(oldItem.driveId == newItem.driveId);
|
assert(oldItem.driveId == newItem.driveId);
|
||||||
assert(oldItem.id == newItem.id);
|
assert(oldItem.id == newItem.id);
|
||||||
assert(oldItem.type == newItem.type);
|
assert(oldItem.type == newItem.type);
|
||||||
|
|
||||||
if (oldItem.eTag != newItem.eTag) {
|
if (oldItem.eTag != newItem.eTag) {
|
||||||
string oldPath = itemdb.computePath(oldItem.driveId, oldItem.id);
|
|
||||||
if (oldPath != newPath) {
|
if (oldPath != newPath) {
|
||||||
log.log("Moving: ", oldPath, " -> ", newPath);
|
log.log("Moving: ", oldPath, " -> ", newPath);
|
||||||
if (exists(newPath)) {
|
if (exists(newPath)) {
|
||||||
log.vlog("The destination is occupied, renaming ...");
|
log.vlog("The destination is occupied, renaming the conflicting file...");
|
||||||
safeRename(newPath);
|
safeRename(newPath);
|
||||||
}
|
}
|
||||||
rename(oldPath, newPath);
|
rename(oldPath, newPath);
|
||||||
|
|
Loading…
Reference in a new issue