mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-15 20:26:53 +02:00
better handle the case when cTag is null
This commit is contained in:
parent
e33f566ecf
commit
9ad9394b98
112
src/itemdb.d
112
src/itemdb.d
|
@ -1,4 +1,4 @@
|
|||
import std.datetime, std.path, std.string;
|
||||
import std.datetime, std.path, std.exception, std.string;
|
||||
import sqlite;
|
||||
|
||||
enum ItemType
|
||||
|
@ -21,6 +21,9 @@ struct Item
|
|||
|
||||
final class ItemDatabase
|
||||
{
|
||||
// increment this for every change in the db schema
|
||||
immutable int itemDatabaseVersion = 1;
|
||||
|
||||
Database db;
|
||||
Statement insertItemStmt;
|
||||
Statement updateItemStmt;
|
||||
|
@ -35,7 +38,7 @@ final class ItemDatabase
|
|||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
eTag TEXT NOT NULL,
|
||||
cTag TEXT NOT NULL,
|
||||
cTag TEXT,
|
||||
mtime TEXT NOT NULL,
|
||||
parentId TEXT,
|
||||
crc32 TEXT,
|
||||
|
@ -44,6 +47,8 @@ final class ItemDatabase
|
|||
db.exec("CREATE INDEX IF NOT EXISTS name_idx ON item (name)");
|
||||
db.exec("PRAGMA foreign_keys = ON");
|
||||
db.exec("PRAGMA recursive_triggers = ON");
|
||||
db.setVersion(itemDatabaseVersion);
|
||||
|
||||
insertItemStmt = db.prepare("INSERT OR REPLACE INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
updateItemStmt = db.prepare("
|
||||
UPDATE item
|
||||
|
@ -54,70 +59,28 @@ final class ItemDatabase
|
|||
selectItemByParentIdStmt = db.prepare("SELECT id FROM item WHERE parentId = ?");
|
||||
}
|
||||
|
||||
void insert(const(char)[] id, const(char)[] name, ItemType type, const(char)[] eTag, const(char)[] cTag, const(char)[] mtime, const(char)[] parentId, const(char)[] crc32)
|
||||
void insert(const ref Item item)
|
||||
{
|
||||
with (insertItemStmt) {
|
||||
bind(1, id);
|
||||
bind(2, name);
|
||||
string typeStr = void;
|
||||
final switch (type) {
|
||||
case ItemType.file: typeStr = "file"; break;
|
||||
case ItemType.dir: typeStr = "dir"; break;
|
||||
}
|
||||
bind(3, typeStr);
|
||||
bind(4, eTag);
|
||||
bind(5, cTag);
|
||||
bind(6, mtime);
|
||||
bind(7, parentId);
|
||||
bind(8, crc32);
|
||||
exec();
|
||||
}
|
||||
bindItem(item, insertItemStmt);
|
||||
insertItemStmt.exec();
|
||||
}
|
||||
|
||||
void update(const(char)[] id, const(char)[] name, ItemType type, const(char)[] eTag, const(char)[] cTag, const(char)[] mtime, const(char)[] parentId, const(char)[] crc32)
|
||||
void update(const ref Item item)
|
||||
{
|
||||
with (updateItemStmt) {
|
||||
bind(1, id);
|
||||
bind(2, name);
|
||||
string typeStr = void;
|
||||
final switch (type) {
|
||||
case ItemType.file: typeStr = "file"; break;
|
||||
case ItemType.dir: typeStr = "dir"; break;
|
||||
}
|
||||
bind(3, typeStr);
|
||||
bind(4, eTag);
|
||||
bind(5, cTag);
|
||||
bind(6, mtime);
|
||||
bind(7, parentId);
|
||||
bind(8, crc32);
|
||||
exec();
|
||||
}
|
||||
bindItem(item, updateItemStmt);
|
||||
updateItemStmt.exec();
|
||||
}
|
||||
|
||||
void upsert(const(char)[] id, const(char)[] name, ItemType type, const(char)[] eTag, const(char)[] cTag, const(char)[] mtime, const(char)[] parentId, const(char)[] crc32)
|
||||
void upsert(const ref Item item)
|
||||
{
|
||||
auto s = db.prepare("SELECT COUNT(*) FROM item WHERE id = ?");
|
||||
s.bind(1, id);
|
||||
s.bind(1, item.id);
|
||||
auto r = s.exec();
|
||||
Statement* p;
|
||||
if (r.front[0] == "0") p = &insertItemStmt;
|
||||
else p = &updateItemStmt;
|
||||
with (p) {
|
||||
bind(1, id);
|
||||
bind(2, name);
|
||||
string typeStr = void;
|
||||
final switch (type) {
|
||||
case ItemType.file: typeStr = "file"; break;
|
||||
case ItemType.dir: typeStr = "dir"; break;
|
||||
}
|
||||
bind(3, typeStr);
|
||||
bind(4, eTag);
|
||||
bind(5, cTag);
|
||||
bind(6, mtime);
|
||||
bind(7, parentId);
|
||||
bind(8, crc32);
|
||||
exec();
|
||||
}
|
||||
Statement* stmt;
|
||||
if (r.front[0] == "0") stmt = &insertItemStmt;
|
||||
else stmt = &updateItemStmt;
|
||||
bindItem(item, *stmt);
|
||||
stmt.exec();
|
||||
}
|
||||
|
||||
Item[] selectChildren(const(char)[] id)
|
||||
|
@ -218,6 +181,25 @@ final class ItemDatabase
|
|||
return false;
|
||||
}
|
||||
|
||||
private void bindItem(const ref Item item, ref Statement stmt)
|
||||
{
|
||||
with (stmt) with (item) {
|
||||
bind(1, id);
|
||||
bind(2, name);
|
||||
string typeStr = null;
|
||||
final switch (type) with (ItemType) {
|
||||
case file: typeStr = "file"; break;
|
||||
case dir: typeStr = "dir"; break;
|
||||
}
|
||||
bind(3, typeStr);
|
||||
bind(4, eTag);
|
||||
bind(5, cTag);
|
||||
bind(6, mtime.toISOExtString());
|
||||
bind(7, parentId);
|
||||
bind(8, crc32);
|
||||
}
|
||||
}
|
||||
|
||||
private Item buildItem(Statement.Result result)
|
||||
{
|
||||
assert(!result.empty && result.front.length == 8);
|
||||
|
@ -231,25 +213,25 @@ final class ItemDatabase
|
|||
crc32: result.front[7].dup
|
||||
};
|
||||
switch (result.front[2]) {
|
||||
case "file": item.type = ItemType.file; break;
|
||||
case "dir": item.type = ItemType.dir; break;
|
||||
default: assert(0);
|
||||
case "file": item.type = ItemType.file; break;
|
||||
case "dir": item.type = ItemType.dir; break;
|
||||
default: assert(0);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// computes the path of the given item id
|
||||
// the path is relative to the sync directory ex: "./Music/Turbo Killer.mp3"
|
||||
// a trailing slash is never added
|
||||
string computePath(const(char)[] id)
|
||||
{
|
||||
if (!id) return null;
|
||||
string path;
|
||||
auto s = db.prepare("SELECT name, parentId FROM item WHERE id = ?");
|
||||
while (true) {
|
||||
s.bind(1, id);
|
||||
auto r = s.exec();
|
||||
if (r.empty) {
|
||||
// no results
|
||||
break;
|
||||
} else if (r.front[1]) {
|
||||
enforce(!r.empty, "Unknow item id");
|
||||
if (r.front[1]) {
|
||||
if (path) path = r.front[0].idup ~ "/" ~ path;
|
||||
else path = r.front[0].idup;
|
||||
} else {
|
||||
|
|
|
@ -16,7 +16,7 @@ private immutable {
|
|||
class OneDriveException: Exception
|
||||
{
|
||||
int httpStatusCode;
|
||||
// error details
|
||||
// https://dev.onedrive.com/misc/errors.htm
|
||||
JSONValue error;
|
||||
|
||||
@nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
|
||||
|
@ -36,7 +36,7 @@ class OneDriveException: Exception
|
|||
{
|
||||
this.httpStatusCode = httpStatusCode;
|
||||
this.error = error;
|
||||
string msg = format("HTTP request returned status code %d (%s)\n%s", httpStatusCode, reason, toJSON(&error, true));
|
||||
string msg = format("HTTP request returned status code %d (%s)\n%s", httpStatusCode, reason, toJSON(error, true));
|
||||
super(msg, file, line, next);
|
||||
}
|
||||
}
|
||||
|
|
46
src/sync.d
46
src/sync.d
|
@ -190,17 +190,6 @@ final class SyncEngine
|
|||
return;
|
||||
}
|
||||
|
||||
string cTag;
|
||||
try {
|
||||
cTag = item["cTag"].str;
|
||||
} catch (JSONException e) {
|
||||
// cTag is not returned if the Item is a folder
|
||||
// https://dev.onedrive.com/resources/item.htm
|
||||
cTag = "";
|
||||
}
|
||||
|
||||
string mtime = item["fileSystemInfo"]["lastModifiedDateTime"].str;
|
||||
|
||||
string crc32;
|
||||
if (type == ItemType.file) {
|
||||
try {
|
||||
|
@ -215,8 +204,8 @@ final class SyncEngine
|
|||
name: name,
|
||||
type: type,
|
||||
eTag: eTag,
|
||||
cTag: cTag,
|
||||
mtime: SysTime.fromISOExtString(mtime),
|
||||
cTag: "cTag" in item ? item["cTag"].str : null,
|
||||
mtime: SysTime.fromISOExtString(item["fileSystemInfo"]["lastModifiedDateTime"].str),
|
||||
parentId: parentId,
|
||||
crc32: crc32
|
||||
};
|
||||
|
@ -229,9 +218,9 @@ final class SyncEngine
|
|||
|
||||
// save the item in the db
|
||||
if (oldItem.id) {
|
||||
itemdb.update(id, name, type, eTag, cTag, mtime, parentId, crc32);
|
||||
itemdb.update(newItem);
|
||||
} else {
|
||||
itemdb.insert(id, name, type, eTag, cTag, mtime, parentId, crc32);
|
||||
itemdb.insert(newItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,31 +515,32 @@ final class SyncEngine
|
|||
saveItem(res);
|
||||
}
|
||||
|
||||
private void saveItem(JSONValue item)
|
||||
private void saveItem(JSONValue jsonItem)
|
||||
{
|
||||
string id = item["id"].str;
|
||||
string id = jsonItem["id"].str;
|
||||
ItemType type;
|
||||
if (isItemFile(item)) {
|
||||
if (isItemFile(jsonItem)) {
|
||||
type = ItemType.file;
|
||||
} else if (isItemFolder(item)) {
|
||||
} else if (isItemFolder(jsonItem)) {
|
||||
type = ItemType.dir;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
string name = item["name"].str;
|
||||
string eTag = item["eTag"].str;
|
||||
string cTag = item["cTag"].str;
|
||||
string mtime = item["fileSystemInfo"]["lastModifiedDateTime"].str;
|
||||
string parentId = item["parentReference"]["id"].str;
|
||||
string crc32;
|
||||
Item item = {
|
||||
name: jsonItem["name"].str,
|
||||
eTag: jsonItem["eTag"].str,
|
||||
cTag: "cTag" in jsonItem ? jsonItem["cTag"].str : null,
|
||||
mtime: SysTime.fromISOExtString(jsonItem["fileSystemInfo"]["lastModifiedDateTime"].str),
|
||||
parentId: jsonItem["parentReference"]["id"].str
|
||||
};
|
||||
if (type == ItemType.file) {
|
||||
try {
|
||||
crc32 = item["file"]["hashes"]["crc32Hash"].str;
|
||||
item.crc32 = jsonItem["file"]["hashes"]["crc32Hash"].str;
|
||||
} catch (JSONException e) {
|
||||
// swallow exception
|
||||
log.vlog("The hash is not available");
|
||||
}
|
||||
}
|
||||
itemdb.upsert(id, name, type, eTag, cTag, mtime, parentId, crc32);
|
||||
itemdb.upsert(item);
|
||||
}
|
||||
|
||||
void uploadMoveItem(string from, string to)
|
||||
|
|
Loading…
Reference in a new issue