abraunegg-onedrive/src/main.d

193 lines
5.3 KiB
D
Raw Normal View History

import core.stdc.stdlib: EXIT_SUCCESS, EXIT_FAILURE;
2015-09-20 21:21:51 +02:00
import core.memory, core.time, core.thread;
2017-07-14 11:31:16 +02:00
import std.getopt, std.file, std.path, std.process, std.stdio;
import config, itemdb, monitor, onedrive, selective, sync, util;
static import log;
2015-09-01 20:45:34 +02:00
int main(string[] args)
2015-09-01 20:45:34 +02:00
{
// configuration directory
string configDirName = environment.get("XDG_CONFIG_HOME", "~/.config") ~ "/onedrive";
2017-08-01 19:11:50 +02:00
// override the sync directory
string syncDirName;
// enable monitor mode
bool monitor;
// force a full resync
bool resync;
2016-08-05 00:12:58 +02:00
// remove the current user and sync state
bool logout;
// enable verbose logging
bool verbose;
2017-05-28 20:14:50 +02:00
// print the access token
bool printAccessToken;
2017-07-14 11:31:16 +02:00
// print the version and exit
bool printVersion;
2015-10-18 10:12:10 +02:00
2015-09-14 19:21:06 +02:00
try {
auto opt = getopt(
args,
std.getopt.config.bundling,
2017-07-14 11:31:16 +02:00
std.getopt.config.caseSensitive,
"confdir", "Set the directory used to store the configuration files", &configDirName,
"logout", "Logout the current user", &logout,
"monitor|m", "Keep monitoring for local and remote changes", &monitor,
"print-token", "Print the access token, useful for debugging", &printAccessToken,
"resync", "Forget the last saved state, perform a full sync", &resync,
2017-08-01 19:11:50 +02:00
"syncdir", "Set the directory used to sync the files are synced", &syncDirName,
2017-07-14 11:31:16 +02:00
"verbose|v", "Print more details, useful for debugging", &log.verbose,
"version", "Print the version and exit", &printVersion
2015-09-14 19:21:06 +02:00
);
if (opt.helpWanted) {
2015-09-22 11:20:54 +02:00
defaultGetoptPrinter(
"Usage: onedrive [OPTION]...\n\n" ~
2017-07-14 11:31:16 +02:00
"no option Sync and exit",
2015-09-22 11:20:54 +02:00
opt.options
);
return EXIT_SUCCESS;
2015-09-14 19:21:06 +02:00
}
} catch (GetOptException e) {
log.log(e.msg);
2017-07-14 11:31:16 +02:00
log.log("Try 'onedrive -h' for more information");
return EXIT_FAILURE;
2015-09-14 19:21:06 +02:00
}
2017-07-14 11:31:16 +02:00
if (printVersion) {
2017-08-01 19:11:50 +02:00
std.stdio.write("onedrive ", import("version"));
2017-07-14 11:31:16 +02:00
return EXIT_SUCCESS;
}
log.vlog("Loading config ...");
configDirName = configDirName.expandTilde().absolutePath();
2017-08-01 19:11:50 +02:00
if (!exists(configDirName)) mkdirRecurse(configDirName);
auto cfg = new config.Config(configDirName);
cfg.init();
2017-08-01 19:11:50 +02:00
// command line parameters override the config
if (syncDirName) cfg.setValue("sync_dir", syncDirName);
2016-12-25 19:23:33 +01:00
// upgrades
if (exists(configDirName ~ "/items.db")) {
remove(configDirName ~ "/items.db");
log.log("Database schema changed, resync needed");
resync = true;
}
2016-08-05 00:12:58 +02:00
if (resync || logout) {
2017-05-28 23:14:37 +02:00
log.vlog("Deleting the saved status ...");
2016-08-05 00:12:58 +02:00
safeRemove(cfg.databaseFilePath);
safeRemove(cfg.deltaLinkFilePath);
2016-08-05 00:12:58 +02:00
safeRemove(cfg.uploadStateFilePath);
if (logout) {
safeRemove(cfg.refreshTokenFilePath);
}
2015-09-14 19:21:06 +02:00
}
log.vlog("Initializing the OneDrive API ...");
2015-11-29 21:12:44 +01:00
bool online = testNetwork();
if (!online && !monitor) {
log.log("No network connection");
return EXIT_FAILURE;
2015-11-29 21:12:44 +01:00
}
auto onedrive = new OneDriveApi(cfg);
2017-05-28 20:14:50 +02:00
onedrive.printAccessToken = printAccessToken;
if (!onedrive.init()) {
log.log("Could not initialize the OneDrive API");
// workaround for segfault in std.net.curl.Curl.shutdown() on exit
onedrive.http.shutdown();
return EXIT_FAILURE;
2015-09-01 20:45:34 +02:00
}
log.vlog("Opening the item database ...");
auto itemdb = new ItemDatabase(cfg.databaseFilePath);
2015-09-16 10:29:20 +02:00
string syncDir = expandTilde(cfg.getValue("sync_dir"));
log.vlog("All operations will be performed in: ", syncDir);
2017-08-01 19:11:50 +02:00
if (!exists(syncDir)) mkdirRecurse(syncDir);
chdir(syncDir);
log.vlog("Initializing the Synchronization Engine ...");
auto selectiveSync = new SelectiveSync();
selectiveSync.load(cfg.syncListFilePath);
selectiveSync.setMask(cfg.getValue("skip_file"));
auto sync = new SyncEngine(cfg, onedrive, itemdb, selectiveSync);
sync.init();
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) {
log.vlog("Initializing monitor ...");
Monitor m = new Monitor(selectiveSync);
2015-09-14 19:21:06 +02:00
m.onDirCreated = delegate(string path) {
log.vlog("[M] Directory created: ", path);
2015-09-20 21:21:51 +02:00
try {
sync.scanForDifferences(path);
2017-12-28 15:03:15 +01:00
} catch(Exception e) {
log.log(e.msg);
2015-09-20 21:21:51 +02:00
}
2015-09-14 19:21:06 +02:00
};
m.onFileChanged = delegate(string path) {
log.vlog("[M] File changed: ", path);
2015-09-17 16:28:24 +02:00
try {
2015-09-18 21:42:27 +02:00
sync.scanForDifferences(path);
2017-12-28 15:03:15 +01:00
} catch(Exception e) {
log.log(e.msg);
2015-09-17 16:28:24 +02:00
}
2015-09-14 19:21:06 +02:00
};
m.onDelete = delegate(string path) {
log.vlog("[M] Item deleted: ", path);
2015-09-20 21:21:51 +02:00
try {
sync.deleteByPath(path);
2017-12-28 15:03:15 +01:00
} catch(Exception e) {
log.log(e.msg);
2015-09-20 21:21:51 +02:00
}
2015-09-14 19:21:06 +02:00
};
m.onMove = delegate(string from, string to) {
log.vlog("[M] Item moved: ", from, " -> ", to);
2015-09-20 21:21:51 +02:00
try {
sync.uploadMoveItem(from, to);
2017-12-28 15:03:15 +01:00
} catch(Exception e) {
log.log(e.msg);
2015-09-20 21:21:51 +02:00
}
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();
return EXIT_SUCCESS;
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;
2017-12-28 15:03:15 +01:00
} catch (Exception e) {
2015-09-20 21:21:51 +02:00
if (++count == 3) throw e;
else log.log(e.msg);
2015-09-20 21:21:51 +02:00
}
} while (count != -1);
}