abraunegg-onedrive/src/main.d

171 lines
4.7 KiB
D
Raw Normal View History

2015-09-20 21:21:51 +02:00
import core.memory, core.time, core.thread;
2015-09-20 14:20:01 +02:00
import std.getopt, std.file, std.path, std.process, std.stdio;
2015-11-29 21:12:44 +01:00
import config, itemdb, monitor, onedrive, sync, util;
2015-09-01 20:45:34 +02:00
2015-09-14 19:21:06 +02:00
void main(string[] args)
2015-09-01 20:45:34 +02:00
{
2015-10-18 10:12:10 +02:00
// always print log messages
stdout = stderr;
2015-09-16 10:29:20 +02:00
bool monitor, resync, verbose;
2015-09-14 19:21:06 +02:00
try {
auto opt = getopt(
args,
"monitor|m", "Keep monitoring for local and remote changes.", &monitor,
2015-09-22 11:52:57 +02:00
"resync", "Forget the last saved state, perform a full sync.", &resync,
2015-09-14 19:21:06 +02:00
"verbose|v", "Print more details, useful for debugging.", &verbose
);
if (opt.helpWanted) {
2015-09-22 11:20:54 +02:00
defaultGetoptPrinter(
"Usage: onedrive [OPTION]...\n\n" ~
"no option Sync and exit.",
opt.options
);
2015-09-14 19:21:06 +02:00
return;
}
} catch (GetOptException e) {
writeln(e.msg);
writeln("Try 'onedrive -h' for more information.");
return;
}
2015-09-20 14:20:01 +02:00
string configDirName = expandTilde(environment.get("XDG_CONFIG_HOME", "~/.config")) ~ "/onedrive";
2015-09-22 14:48:18 +02:00
string configFile1Path = "/etc/onedrive.conf";
string configFile2Path = "/usr/local/etc/onedrive.conf";
string configFile3Path = configDirName ~ "/config";
2015-09-14 19:21:06 +02:00
string refreshTokenFilePath = configDirName ~ "/refresh_token";
string statusTokenFilePath = configDirName ~ "/status_token";
2015-09-16 10:29:20 +02:00
string databaseFilePath = configDirName ~ "/items.db";
2015-09-14 19:21:06 +02:00
2015-09-22 15:26:45 +02:00
if (!exists(configDirName)) mkdir(configDirName);
2015-09-16 10:29:20 +02:00
if (resync) {
if (verbose) writeln("Deleting the saved status ...");
2015-09-14 19:21:06 +02:00
if (exists(databaseFilePath)) remove(databaseFilePath);
if (exists(statusTokenFilePath)) remove(statusTokenFilePath);
}
if (verbose) writeln("Loading config ...");
2015-09-22 14:48:18 +02:00
auto cfg = config.Config(configFile1Path, configFile2Path, configFile3Path);
2015-09-01 20:45:34 +02:00
2015-09-14 19:21:06 +02:00
if (verbose) writeln("Initializing the OneDrive API ...");
2015-11-29 21:12:44 +01:00
bool online = testNetwork();
if (!online && !monitor) {
writeln("No network connection");
return;
}
2015-09-14 19:21:06 +02:00
auto onedrive = new OneDriveApi(cfg, verbose);
onedrive.onRefreshToken = (string refreshToken) {
std.file.write(refreshTokenFilePath, refreshToken);
};
2015-09-01 20:45:34 +02:00
try {
2015-09-14 19:21:06 +02:00
string refreshToken = readText(refreshTokenFilePath);
2015-09-01 20:45:34 +02:00
onedrive.setRefreshToken(refreshToken);
} catch (FileException e) {
2016-06-30 12:51:44 +02:00
if (!onedrive.authorize()) {
// workaround for segfault in std.net.curl.Curl.shutdown() on exit
onedrive.http.shutdown();
return;
}
2015-09-01 20:45:34 +02:00
}
2015-09-16 10:29:20 +02:00
if (verbose) writeln("Opening the item database ...");
auto itemdb = new ItemDatabase(databaseFilePath);
string syncDir = expandTilde(cfg.get("sync_dir"));
if (verbose) writeln("All operations will be performed in: ", syncDir);
2016-06-28 14:21:48 +02:00
if (!exists(syncDir)) mkdir(syncDir);
chdir(syncDir);
2015-09-14 19:21:06 +02:00
if (verbose) writeln("Initializing the Synchronization Engine ...");
auto sync = new SyncEngine(cfg, onedrive, itemdb, configDirName, verbose);
2015-09-16 10:29:20 +02:00
sync.onStatusToken = (string statusToken) {
std.file.write(statusTokenFilePath, statusToken);
};
string statusToken;
2015-09-16 10:29:20 +02:00
try {
statusToken = readText(statusTokenFilePath);
2015-09-16 10:29:20 +02:00
} catch (FileException e) {
// swallow exception
}
sync.init(statusToken);
2015-11-29 21:12:44 +01:00
if (online) performSync(sync);
2015-09-01 20:45:34 +02:00
2015-09-14 19:21:06 +02:00
if (monitor) {
2015-09-17 00:16:23 +02:00
if (verbose) writeln("Initializing monitor ...");
2015-09-14 19:21:06 +02:00
Monitor m;
m.onDirCreated = delegate(string path) {
if (verbose) writeln("[M] Directory created: ", path);
2015-09-20 21:21:51 +02:00
try {
sync.scanForDifferences(path);
} catch(SyncException e) {
writeln(e.msg);
}
2015-09-14 19:21:06 +02:00
};
m.onFileChanged = delegate(string path) {
if (verbose) writeln("[M] File changed: ", path);
2015-09-17 16:28:24 +02:00
try {
2015-09-18 21:42:27 +02:00
sync.scanForDifferences(path);
2015-09-17 16:28:24 +02:00
} catch(SyncException e) {
writeln(e.msg);
}
2015-09-14 19:21:06 +02:00
};
m.onDelete = delegate(string path) {
if (verbose) writeln("[M] Item deleted: ", path);
2015-09-20 21:21:51 +02:00
try {
sync.deleteByPath(path);
} catch(SyncException e) {
writeln(e.msg);
}
2015-09-14 19:21:06 +02:00
};
m.onMove = delegate(string from, string to) {
if (verbose) writeln("[M] Item moved: ", from, " -> ", to);
2015-09-20 21:21:51 +02:00
try {
sync.uploadMoveItem(from, to);
} catch(SyncException e) {
writeln(e.msg);
}
2015-09-14 19:21:06 +02:00
};
m.init(cfg, verbose);
2015-09-17 00:16:23 +02:00
// monitor loop
immutable auto checkInterval = dur!"seconds"(45);
auto lastCheckTime = MonoTime.currTime();
while (true) {
2015-11-29 21:12:44 +01:00
m.update(online);
2015-09-17 00:16:23 +02:00
auto currTime = MonoTime.currTime();
if (currTime - lastCheckTime > checkInterval) {
lastCheckTime = currTime;
2015-11-29 21:12:44 +01:00
online = testNetwork();
if (online) {
performSync(sync);
// discard all events that may have been generated by the sync
m.update(false);
}
GC.collect();
} else {
Thread.sleep(dur!"msecs"(100));
2015-09-17 00:16:23 +02:00
}
}
2015-09-14 19:21:06 +02:00
}
// workaround for segfault in std.net.curl.Curl.shutdown() on exit
onedrive.http.shutdown();
2015-09-01 20:45:34 +02:00
}
2015-09-20 21:21:51 +02:00
// try to synchronize the folder three times
void performSync(SyncEngine sync)
{
int count;
do {
try {
sync.applyDifferences();
sync.scanForDifferences(".");
count = -1;
} catch (SyncException e) {
if (++count == 3) throw e;
else writeln(e.msg);
}
} while (count != -1);
}