mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-10 01:36:39 +02:00
removed redundant key parentDriveId
This commit is contained in:
parent
4ebc4a8544
commit
d7f6674f60
59
src/itemdb.d
59
src/itemdb.d
|
@ -4,15 +4,13 @@ import std.path;
|
|||
import std.string;
|
||||
import sqlite;
|
||||
|
||||
enum ItemType
|
||||
{
|
||||
enum ItemType {
|
||||
file,
|
||||
dir,
|
||||
remote
|
||||
}
|
||||
|
||||
struct Item
|
||||
{
|
||||
struct Item {
|
||||
string driveId;
|
||||
string id;
|
||||
string name;
|
||||
|
@ -20,7 +18,6 @@ struct Item
|
|||
string eTag;
|
||||
string cTag;
|
||||
SysTime mtime;
|
||||
string parentDriveId;
|
||||
string parentId;
|
||||
string crc32Hash;
|
||||
string sha1Hash;
|
||||
|
@ -53,7 +50,6 @@ final class ItemDatabase
|
|||
eTag TEXT,
|
||||
cTag TEXT,
|
||||
mtime TEXT NOT NULL,
|
||||
parentDriveId TEXT,
|
||||
parentId TEXT,
|
||||
crc32Hash TEXT,
|
||||
sha1Hash TEXT,
|
||||
|
@ -62,7 +58,7 @@ final class ItemDatabase
|
|||
remoteId TEXT,
|
||||
deltaLink TEXT,
|
||||
PRIMARY KEY (driveId, id),
|
||||
FOREIGN KEY (parentDriveId, parentId)
|
||||
FOREIGN KEY (driveId, parentId)
|
||||
REFERENCES item (driveId, id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE RESTRICT
|
||||
|
@ -76,12 +72,12 @@ final class ItemDatabase
|
|||
db.exec("PRAGMA foreign_keys = ON");
|
||||
db.exec("PRAGMA recursive_triggers = ON");
|
||||
insertItemStmt = db.prepare("
|
||||
INSERT OR REPLACE INTO item (driveId, id, name, type, eTag, cTag, mtime, parentDriveId, parentId, crc32Hash, sha1Hash, quickXorHash, remoteDriveId, remoteId)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT OR REPLACE INTO item (driveId, id, name, type, eTag, cTag, mtime, parentId, crc32Hash, sha1Hash, quickXorHash, remoteDriveId, remoteId)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)
|
||||
");
|
||||
updateItemStmt = db.prepare("
|
||||
UPDATE item
|
||||
SET name = ?3, type = ?4, eTag = ?5, cTag = ?6, mtime = ?7, parentDriveId = ?8, parentId = ?9, crc32Hash = ?10, sha1Hash = ?11, quickXorHash = ?12, remoteDriveId = ?13, remoteId = ?14
|
||||
SET name = ?3, type = ?4, eTag = ?5, cTag = ?6, mtime = ?7, parentId = ?8, crc32Hash = ?9, sha1Hash = ?10, quickXorHash = ?11, remoteDriveId = ?12, remoteId = ?13
|
||||
WHERE driveId = ?1 AND id = ?2
|
||||
");
|
||||
selectItemByIdStmt = db.prepare("
|
||||
|
@ -89,7 +85,7 @@ final class ItemDatabase
|
|||
FROM item
|
||||
WHERE driveId = ?1 AND id = ?2
|
||||
");
|
||||
selectItemByParentIdStmt = db.prepare("SELECT * FROM item WHERE parentDriveId = ? AND parentId = ?");
|
||||
selectItemByParentIdStmt = db.prepare("SELECT * FROM item WHERE driveId = ? AND parentId = ?");
|
||||
deleteItemByIdStmt = db.prepare("DELETE FROM item WHERE driveId = ? AND id = ?");
|
||||
}
|
||||
|
||||
|
@ -145,11 +141,11 @@ final class ItemDatabase
|
|||
|
||||
// returns the item with the given path
|
||||
// the path is relative to the sync directory ex: "./Music/Turbo Killer.mp3"
|
||||
bool selectByPath(const(char)[] path, out Item item)
|
||||
bool selectByPath(const(char)[] path, string rootDriveId, out Item item)
|
||||
{
|
||||
Item currItem;
|
||||
Item currItem = { driveId: rootDriveId };
|
||||
path = "root/" ~ path.chompPrefix(".");
|
||||
auto s = db.prepare("SELECT * FROM item WHERE name IS ?1 AND parentDriveId IS ?2 AND parentId IS ?3");
|
||||
auto s = db.prepare("SELECT * FROM item WHERE name = ?1 AND driveId IS ?2 AND parentId IS ?3");
|
||||
foreach (name; pathSplitter(path)) {
|
||||
s.bind(1, name);
|
||||
s.bind(2, currItem.driveId);
|
||||
|
@ -171,11 +167,11 @@ final class ItemDatabase
|
|||
}
|
||||
|
||||
// same as selectByPath() but it does not traverse remote folders
|
||||
bool selectByPathNoRemote(const(char)[] path, out Item item)
|
||||
bool selectByPathNoRemote(const(char)[] path, string rootDriveId, out Item item)
|
||||
{
|
||||
Item currItem;
|
||||
Item currItem = { driveId: rootDriveId };
|
||||
path = "root/" ~ path.chompPrefix(".");
|
||||
auto s = db.prepare("SELECT * FROM item WHERE name IS ?1 AND parentDriveId IS ?2 AND parentId IS ?3");
|
||||
auto s = db.prepare("SELECT * FROM item WHERE name IS ?1 AND driveId IS ?2 AND parentId IS ?3");
|
||||
foreach (name; pathSplitter(path)) {
|
||||
s.bind(1, name);
|
||||
s.bind(2, currItem.driveId);
|
||||
|
@ -211,20 +207,19 @@ final class ItemDatabase
|
|||
bind(5, eTag);
|
||||
bind(6, cTag);
|
||||
bind(7, mtime.toISOExtString());
|
||||
bind(8, parentDriveId);
|
||||
bind(9, parentId);
|
||||
bind(10, crc32Hash);
|
||||
bind(11, sha1Hash);
|
||||
bind(12, quickXorHash);
|
||||
bind(13, remoteDriveId);
|
||||
bind(14, remoteId);
|
||||
bind(8, parentId);
|
||||
bind(9, crc32Hash);
|
||||
bind(10, sha1Hash);
|
||||
bind(11, quickXorHash);
|
||||
bind(12, remoteDriveId);
|
||||
bind(13, remoteId);
|
||||
}
|
||||
}
|
||||
|
||||
private Item buildItem(Statement.Result result)
|
||||
{
|
||||
assert(!result.empty, "The result must not be empty");
|
||||
assert(result.front.length == 15, "The result must have 15 columns");
|
||||
assert(result.front.length == 14, "The result must have 14 columns");
|
||||
Item item = {
|
||||
driveId: result.front[0].dup,
|
||||
id: result.front[1].dup,
|
||||
|
@ -232,13 +227,12 @@ final class ItemDatabase
|
|||
eTag: result.front[4].dup,
|
||||
cTag: result.front[5].dup,
|
||||
mtime: SysTime.fromISOExtString(result.front[6]),
|
||||
parentDriveId: result.front[7].dup,
|
||||
parentId: result.front[8].dup,
|
||||
crc32Hash: result.front[9].dup,
|
||||
sha1Hash: result.front[10].dup,
|
||||
quickXorHash: result.front[11].dup,
|
||||
remoteDriveId: result.front[12].dup,
|
||||
remoteId: result.front[13].dup
|
||||
parentId: result.front[7].dup,
|
||||
crc32Hash: result.front[8].dup,
|
||||
sha1Hash: result.front[9].dup,
|
||||
quickXorHash: result.front[10].dup,
|
||||
remoteDriveId: result.front[11].dup,
|
||||
remoteId: result.front[12].dup
|
||||
};
|
||||
switch (result.front[3]) {
|
||||
case "file": item.type = ItemType.file; break;
|
||||
|
@ -273,7 +267,6 @@ final class ItemDatabase
|
|||
if (path) path = item.name ~ "/" ~ path;
|
||||
else path = item.name;
|
||||
}
|
||||
driveId = item.parentDriveId;
|
||||
id = item.parentId;
|
||||
} else {
|
||||
if (id == null) {
|
||||
|
|
36
src/sync.d
36
src/sync.d
|
@ -60,7 +60,6 @@ private Item makeItem(const ref JSONValue driveItem)
|
|||
// root and remote items do not have parentReference
|
||||
if (!isItemRoot(driveItem) && ("parentReference" in driveItem) != null) {
|
||||
item.driveId = driveItem["parentReference"]["driveId"].str,
|
||||
item.parentDriveId = item.driveId; // TODO: parentDriveId is redundant
|
||||
item.parentId = driveItem["parentReference"]["id"].str;
|
||||
}
|
||||
|
||||
|
@ -116,6 +115,8 @@ final class SyncEngine
|
|||
private string[] skippedItems;
|
||||
// list of items to delete after the changes has been downloaded
|
||||
private string[2][] idsToDelete;
|
||||
// default drive id
|
||||
private string defaultDriveId;
|
||||
|
||||
this(Config cfg, OneDriveApi onedrive, ItemDatabase itemdb, SelectiveSync selectiveSync)
|
||||
{
|
||||
|
@ -141,7 +142,7 @@ final class SyncEngine
|
|||
void applyDifferences()
|
||||
{
|
||||
// root folder
|
||||
string driveId = onedrive.getDefaultDrive()["id"].str;
|
||||
string driveId = defaultDriveId = onedrive.getDefaultDrive()["id"].str;
|
||||
string rootId = onedrive.getDefaultRoot["id"].str;
|
||||
applyDifferences(driveId, rootId);
|
||||
|
||||
|
@ -193,7 +194,7 @@ final class SyncEngine
|
|||
Item item = makeItem(driveItem);
|
||||
log.vlog("Processing ", item.id, " ", item.name);
|
||||
|
||||
if (isItemRoot(driveItem) || !item.parentDriveId) {
|
||||
if (isItemRoot(driveItem) || !item.parentId) {
|
||||
log.vlog("Root");
|
||||
item.driveId = driveId; // HACK: makeItem() cannot set the driveId propery of the root
|
||||
itemdb.upsert(item);
|
||||
|
@ -222,7 +223,7 @@ final class SyncEngine
|
|||
// check for selective sync
|
||||
string path;
|
||||
if (!unwanted) {
|
||||
path = itemdb.computePath(item.parentDriveId, item.parentId) ~ "/" ~ item.name;
|
||||
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name;
|
||||
path = buildNormalizedPath(path);
|
||||
unwanted = selectiveSync.isPathExcluded(path);
|
||||
}
|
||||
|
@ -431,7 +432,7 @@ final class SyncEngine
|
|||
{
|
||||
log.vlog("Uploading differences of ", path);
|
||||
Item item;
|
||||
if (itemdb.selectByPath(path, item)) {
|
||||
if (itemdb.selectByPath(path, defaultDriveId, item)) {
|
||||
uploadDifferences(item);
|
||||
}
|
||||
log.vlog("Uploading new items of ", path);
|
||||
|
@ -533,7 +534,7 @@ final class SyncEngine
|
|||
writeln(" done.");
|
||||
} else {
|
||||
writeln("");
|
||||
response = session.upload(path, item.parentDriveId, item.parentId, baseName(path), eTag);
|
||||
response = session.upload(path, item.driveId, item.parentId, baseName(path), eTag);
|
||||
}
|
||||
// saveItem(response); redundant
|
||||
// use the cTag instead of the eTag because Onedrive may update the metadata of files AFTER they have been uploaded
|
||||
|
@ -573,7 +574,7 @@ final class SyncEngine
|
|||
|
||||
if (isDir(path)) {
|
||||
Item item;
|
||||
if (!itemdb.selectByPath(path, item)) {
|
||||
if (!itemdb.selectByPath(path, defaultDriveId, item)) {
|
||||
uploadCreateDir(path);
|
||||
}
|
||||
// recursively traverse children
|
||||
|
@ -583,7 +584,7 @@ final class SyncEngine
|
|||
}
|
||||
} else {
|
||||
Item item;
|
||||
if (!itemdb.selectByPath(path, item)) {
|
||||
if (!itemdb.selectByPath(path, defaultDriveId, item)) {
|
||||
uploadNewFile(path);
|
||||
}
|
||||
}
|
||||
|
@ -591,23 +592,22 @@ final class SyncEngine
|
|||
|
||||
private void uploadCreateDir(const(char)[] path)
|
||||
{
|
||||
log.log("Creating folder ", path, "...");
|
||||
log.log("Creating folder ", path);
|
||||
Item parent;
|
||||
enforce(itemdb.selectByPath(dirName(path), parent), "The parent item is not in the database");
|
||||
enforce(itemdb.selectByPath(dirName(path), defaultDriveId, parent), "The parent item is not in the database");
|
||||
JSONValue driveItem = [
|
||||
"name": JSONValue(baseName(path)),
|
||||
"folder": parseJSON("{}")
|
||||
];
|
||||
auto res = onedrive.createById(parent.driveId, parent.id, driveItem);
|
||||
saveItem(res);
|
||||
writeln(" done.");
|
||||
}
|
||||
|
||||
private void uploadNewFile(string path)
|
||||
{
|
||||
write("Uploading file ", path, "...");
|
||||
Item parent;
|
||||
enforce(itemdb.selectByPath(dirName(path), parent), "The parent item is not in the database");
|
||||
enforce(itemdb.selectByPath(dirName(path), defaultDriveId, parent), "The parent item is not in the database");
|
||||
JSONValue response;
|
||||
if (getSize(path) <= thresholdFileSize) {
|
||||
response = onedrive.simpleUpload(path, parent.driveId, parent.id, baseName(path));
|
||||
|
@ -660,18 +660,18 @@ final class SyncEngine
|
|||
{
|
||||
log.log("Moving ", from, " to ", to);
|
||||
Item fromItem, toItem, parentItem;
|
||||
if (!itemdb.selectByPath(from, fromItem)) {
|
||||
if (!itemdb.selectByPath(from, defaultDriveId, fromItem)) {
|
||||
throw new SyncException("Can't move an unsynced item");
|
||||
}
|
||||
if (fromItem.parentId == null) {
|
||||
// the item is a remote folder, need to do the operation on the parent
|
||||
enforce(itemdb.selectByPathNoRemote(from, fromItem));
|
||||
enforce(itemdb.selectByPathNoRemote(from, defaultDriveId, fromItem));
|
||||
}
|
||||
if (itemdb.selectByPath(to, toItem)) {
|
||||
if (itemdb.selectByPath(to, defaultDriveId, toItem)) {
|
||||
// the destination has been overwritten
|
||||
uploadDeleteItem(toItem, to);
|
||||
}
|
||||
if (!itemdb.selectByPath(dirName(to), parentItem)) {
|
||||
if (!itemdb.selectByPath(dirName(to), defaultDriveId, parentItem)) {
|
||||
throw new SyncException("Can't move an item to an unsynced directory");
|
||||
}
|
||||
if (fromItem.driveId != parentItem.driveId) {
|
||||
|
@ -698,12 +698,12 @@ final class SyncEngine
|
|||
void deleteByPath(const(char)[] path)
|
||||
{
|
||||
Item item;
|
||||
if (!itemdb.selectByPath(path, item)) {
|
||||
if (!itemdb.selectByPath(path, defaultDriveId, item)) {
|
||||
throw new SyncException("Can't delete an unsynced item");
|
||||
}
|
||||
if (item.parentId == null) {
|
||||
// the item is a remote folder, need to do the operation on the parent
|
||||
enforce(itemdb.selectByPathNoRemote(path, item));
|
||||
enforce(itemdb.selectByPathNoRemote(path, defaultDriveId, item));
|
||||
}
|
||||
try {
|
||||
uploadDeleteItem(item, path);
|
||||
|
|
Loading…
Reference in a new issue