mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-14 03:36:52 +02:00
better path handling
This commit is contained in:
parent
a877bad3ad
commit
30504d7034
69
src/itemdb.d
69
src/itemdb.d
|
@ -1,4 +1,4 @@
|
|||
import std.datetime, std.path;
|
||||
import std.datetime, std.path, std.string;
|
||||
import sqlite;
|
||||
|
||||
enum ItemType
|
||||
|
@ -147,40 +147,46 @@ final class ItemDatabase
|
|||
|
||||
bool selectByPath(const(char)[] path, out Item item)
|
||||
{
|
||||
if (path == ".") path = "root"; // HACK
|
||||
path = "root/" ~ path.chompPrefix("."); // HACK
|
||||
|
||||
// initialize the search
|
||||
string[2][] candidates; // [id, parentId]
|
||||
auto s = db.prepare("SELECT id, parentId FROM item WHERE name = ?");
|
||||
s.bind(1, baseName(path));
|
||||
auto r = s.exec();
|
||||
foreach (row; r) candidates ~= [row[0].dup, row[1].dup];
|
||||
if (candidates.length > 1) {
|
||||
path = dirName(path);
|
||||
|
||||
if (path != ".") {
|
||||
s = db.prepare("SELECT parentId FROM item WHERE id = ? AND name = ?");
|
||||
// discard the candidates that do not have the correct parent
|
||||
do {
|
||||
s.bind(2, baseName(path));
|
||||
string[2][] newCandidates;
|
||||
newCandidates.reserve(candidates.length);
|
||||
path = dirName(path);
|
||||
if (path.length != 0) {
|
||||
s.bind(2, baseName(path));
|
||||
foreach (candidate; candidates) {
|
||||
s.bind(1, candidate[1]);
|
||||
r = s.exec();
|
||||
if (!r.empty) {
|
||||
string[2] c = [candidate[0], r.front[0].idup];
|
||||
newCandidates ~= c;
|
||||
}
|
||||
foreach (candidate; candidates) {
|
||||
s.bind(1, candidate[1]);
|
||||
r = s.exec();
|
||||
if (!r.empty) {
|
||||
string[2] c = [candidate[0], r.front[0].idup];
|
||||
newCandidates ~= c;
|
||||
}
|
||||
} else {
|
||||
// reached the root
|
||||
foreach (candidate; candidates) {
|
||||
if (!candidate[1]) {
|
||||
newCandidates ~= candidate;
|
||||
}
|
||||
}
|
||||
assert(newCandidates.length <= 1);
|
||||
}
|
||||
candidates = newCandidates;
|
||||
} while (candidates.length > 1);
|
||||
path = dirName(path);
|
||||
} while (path != ".");
|
||||
}
|
||||
|
||||
// reached the root
|
||||
string[2][] newCandidates;
|
||||
foreach (candidate; candidates) {
|
||||
if (!candidate[1]) {
|
||||
newCandidates ~= candidate;
|
||||
}
|
||||
}
|
||||
candidates = newCandidates;
|
||||
assert(candidates.length <= 1);
|
||||
|
||||
if (candidates.length == 1) return selectById(candidates[0][0], item);
|
||||
return false;
|
||||
}
|
||||
|
@ -240,13 +246,20 @@ final class ItemDatabase
|
|||
while (true) {
|
||||
s.bind(1, id);
|
||||
auto r = s.exec();
|
||||
if (r.empty) break;
|
||||
if (path) path = r.front[0].idup ~ "/" ~ path;
|
||||
else path = r.front[0].dup;
|
||||
if (r.empty) {
|
||||
// no results
|
||||
break;
|
||||
} else if (r.front[1]) {
|
||||
if (path) path = r.front[0].idup ~ "/" ~ path;
|
||||
else path = r.front[0].idup;
|
||||
} else {
|
||||
// root
|
||||
if (path) path = "./" ~ path;
|
||||
else path = ".";
|
||||
break;
|
||||
}
|
||||
id = r.front[1].dup;
|
||||
}
|
||||
// HACK: skip "root/"
|
||||
if (path.length < 5) return ".";
|
||||
return path[5 .. $];
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class MonitorException: ErrnoException
|
|||
struct Monitor
|
||||
{
|
||||
bool verbose;
|
||||
// regexes that match files/dirs to skip
|
||||
// regex that match files/dirs to skip
|
||||
private Regex!char skipDir, skipFile;
|
||||
// inotify file descriptor
|
||||
private int fd;
|
||||
|
@ -70,7 +70,7 @@ struct Monitor
|
|||
{
|
||||
int wd = inotify_add_watch(fd, toStringz(dirname), mask);
|
||||
if (wd == -1) throw new MonitorException("inotify_add_watch failed");
|
||||
wdToDirName[wd] = chompPrefix(dirname ~ "/", "./");
|
||||
wdToDirName[wd] = dirname ~ "/";
|
||||
if (verbose) writeln("Monitor directory: ", dirname);
|
||||
}
|
||||
|
||||
|
|
28
src/sync.d
28
src/sync.d
|
@ -1,5 +1,6 @@
|
|||
import core.exception: RangeError;
|
||||
import std.algorithm, std.datetime, std.file, std.json, std.path, std.regex, std.stdio;
|
||||
import std.algorithm, std.datetime, std.file, std.json, std.path, std.regex;
|
||||
import std.stdio, std.string;
|
||||
import config, itemdb, onedrive, util;
|
||||
|
||||
private bool isItemFolder(const ref JSONValue item)
|
||||
|
@ -132,7 +133,7 @@ final class SyncEngine
|
|||
if (parentId) {
|
||||
path = itemdb.computePath(parentId) ~ "/" ~ name;
|
||||
} else {
|
||||
path = name;
|
||||
path = ".";
|
||||
}
|
||||
|
||||
ItemType type;
|
||||
|
@ -260,6 +261,8 @@ final class SyncEngine
|
|||
// returns true if the given item corresponds to the local one
|
||||
private bool isItemSynced(Item item, string path)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln(path);
|
||||
if (!exists(path)) return false;
|
||||
final switch (item.type) {
|
||||
case ItemType.file:
|
||||
|
@ -408,8 +411,6 @@ final class SyncEngine
|
|||
{
|
||||
if (isDir(path)) {
|
||||
if (path.matchFirst(skipDir).empty) {
|
||||
import std.string: chompPrefix;
|
||||
path = chompPrefix(path, "./");
|
||||
Item item;
|
||||
if (!itemdb.selectByPath(path, item)) {
|
||||
uploadCreateDir(path);
|
||||
|
@ -434,7 +435,7 @@ final class SyncEngine
|
|||
writeln("Creating remote directory: ", path);
|
||||
JSONValue item = ["name": baseName(path).idup];
|
||||
item["folder"] = parseJSON("{}");
|
||||
auto res = onedrive.createByPath(dirName(path), item);
|
||||
auto res = onedrive.createByPath(path.dirName ~ "/", item);
|
||||
saveItem(res);
|
||||
}
|
||||
|
||||
|
@ -511,19 +512,24 @@ final class SyncEngine
|
|||
void uploadMoveItem(string from, string to)
|
||||
{
|
||||
writeln("Moving remote item: ", from, " -> ", to);
|
||||
Item item;
|
||||
if (!itemdb.selectByPath(from, item) || !isItemSynced(item, from)) {
|
||||
Item fromItem, toItem, parentItem;
|
||||
if (!itemdb.selectByPath(from, fromItem)) {
|
||||
writeln("Can't move an unsynced item");
|
||||
return;
|
||||
}
|
||||
if (itemdb.selectByPath(to, item)) {
|
||||
uploadDeleteItem(item, to);
|
||||
if (itemdb.selectByPath(to, toItem)) {
|
||||
// the destination has been overridden
|
||||
uploadDeleteItem(toItem, to);
|
||||
}
|
||||
if (!itemdb.selectByPath(to.dirName, parentItem)) {
|
||||
writeln("Can't move an item to an unsynced directory");
|
||||
return;
|
||||
}
|
||||
JSONValue diff = ["name": baseName(to)];
|
||||
diff["parentReference"] = JSONValue([
|
||||
"path": "/drive/root:/" ~ dirName(to)
|
||||
"id": parentItem.id
|
||||
]);
|
||||
auto res = onedrive.updateById(item.id, diff, item.eTag);
|
||||
auto res = onedrive.updateById(fromItem.id, diff, fromItem.eTag);
|
||||
saveItem(res);
|
||||
string id = res["id"].str;
|
||||
string eTag = res["eTag"].str;
|
||||
|
|
Loading…
Reference in a new issue