mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-15 20:26:53 +02:00
implement the recommended way to enumerate changes
This commit is contained in:
parent
3d8daa086d
commit
691862b18f
|
@ -5,7 +5,7 @@ static import log;
|
||||||
final class Config
|
final class Config
|
||||||
{
|
{
|
||||||
public string refreshTokenFilePath;
|
public string refreshTokenFilePath;
|
||||||
public string statusTokenFilePath;
|
public string deltaLinkFilePath;
|
||||||
public string databaseFilePath;
|
public string databaseFilePath;
|
||||||
public string uploadStateFilePath;
|
public string uploadStateFilePath;
|
||||||
public string syncListFilePath;
|
public string syncListFilePath;
|
||||||
|
@ -17,7 +17,7 @@ final class Config
|
||||||
this(string configDirName)
|
this(string configDirName)
|
||||||
{
|
{
|
||||||
refreshTokenFilePath = configDirName ~ "/refresh_token";
|
refreshTokenFilePath = configDirName ~ "/refresh_token";
|
||||||
statusTokenFilePath = configDirName ~ "/status_token";
|
deltaLinkFilePath = configDirName ~ "/delta_link";
|
||||||
databaseFilePath = configDirName ~ "/items.sqlite3";
|
databaseFilePath = configDirName ~ "/items.sqlite3";
|
||||||
uploadStateFilePath = configDirName ~ "/resume_upload";
|
uploadStateFilePath = configDirName ~ "/resume_upload";
|
||||||
userConfigFilePath = configDirName ~ "/config";
|
userConfigFilePath = configDirName ~ "/config";
|
||||||
|
|
|
@ -60,7 +60,7 @@ int main(string[] args)
|
||||||
if (resync || logout) {
|
if (resync || logout) {
|
||||||
log.log("Deleting the saved status ...");
|
log.log("Deleting the saved status ...");
|
||||||
safeRemove(cfg.databaseFilePath);
|
safeRemove(cfg.databaseFilePath);
|
||||||
safeRemove(cfg.statusTokenFilePath);
|
safeRemove(cfg.deltaLinkFilePath);
|
||||||
safeRemove(cfg.uploadStateFilePath);
|
safeRemove(cfg.uploadStateFilePath);
|
||||||
if (logout) {
|
if (logout) {
|
||||||
safeRemove(cfg.refreshTokenFilePath);
|
safeRemove(cfg.refreshTokenFilePath);
|
||||||
|
|
|
@ -104,24 +104,24 @@ final class OneDriveApi
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dev.onedrive.com/items/view_delta.htm
|
// https://dev.onedrive.com/items/view_delta.htm
|
||||||
JSONValue viewChangesById(const(char)[] id, const(char)[] statusToken)
|
JSONValue viewChangesById(const(char)[] id, const(char)[] deltaLink)
|
||||||
{
|
{
|
||||||
checkAccessTokenExpired();
|
checkAccessTokenExpired();
|
||||||
|
if (deltaLink) return get(deltaLink);
|
||||||
const(char)[] url = itemByIdUrl ~ id ~ "/delta";
|
const(char)[] url = itemByIdUrl ~ id ~ "/delta";
|
||||||
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
||||||
if (statusToken) url ~= "&token=" ~ statusToken;
|
|
||||||
return get(url);
|
return get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dev.onedrive.com/items/view_delta.htm
|
// https://dev.onedrive.com/items/view_delta.htm
|
||||||
JSONValue viewChangesByPath(const(char)[] path, const(char)[] statusToken)
|
JSONValue viewChangesByPath(const(char)[] path, const(char)[] deltaLink)
|
||||||
{
|
{
|
||||||
checkAccessTokenExpired();
|
checkAccessTokenExpired();
|
||||||
|
if (deltaLink) return get(deltaLink);
|
||||||
string url = itemByPathUrl ~ encodeComponent(path) ~ ":/delta";
|
string url = itemByPathUrl ~ encodeComponent(path) ~ ":/delta";
|
||||||
// HACK
|
// HACK
|
||||||
if (path == ".") url = driveUrl ~ "/root/delta";
|
if (path == ".") url = driveUrl ~ "/root/delta";
|
||||||
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,root,fileSystemInfo,remoteItem,parentReference";
|
||||||
if (statusToken) url ~= "&token=" ~ statusToken;
|
|
||||||
return get(url);
|
return get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
src/sync.d
37
src/sync.d
|
@ -60,8 +60,6 @@ final class SyncEngine
|
||||||
private ItemDatabase itemdb;
|
private ItemDatabase itemdb;
|
||||||
private UploadSession session;
|
private UploadSession session;
|
||||||
private SelectiveSync selectiveSync;
|
private SelectiveSync selectiveSync;
|
||||||
// token representing the last status correctly synced
|
|
||||||
private string statusToken;
|
|
||||||
// list of items to skip while applying the changes
|
// list of items to skip while applying the changes
|
||||||
private string[] skippedItems;
|
private string[] skippedItems;
|
||||||
// list of items to delete after the changes has been downloaded
|
// list of items to delete after the changes has been downloaded
|
||||||
|
@ -79,12 +77,6 @@ final class SyncEngine
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
// restore the previous status token
|
|
||||||
try {
|
|
||||||
statusToken = readText(cfg.statusTokenFilePath);
|
|
||||||
} catch (FileException e) {
|
|
||||||
// swallow exception
|
|
||||||
}
|
|
||||||
// check if there is an interrupted upload session
|
// check if there is an interrupted upload session
|
||||||
if (session.restore()) {
|
if (session.restore()) {
|
||||||
log.log("Continuing the upload session ...");
|
log.log("Continuing the upload session ...");
|
||||||
|
@ -96,33 +88,36 @@ final class SyncEngine
|
||||||
void applyDifferences()
|
void applyDifferences()
|
||||||
{
|
{
|
||||||
log.vlog("Applying differences ...");
|
log.vlog("Applying differences ...");
|
||||||
|
|
||||||
|
// restore the last known state
|
||||||
|
string deltaLink;
|
||||||
|
try {
|
||||||
|
deltaLink = readText(cfg.deltaLinkFilePath);
|
||||||
|
} catch (FileException e) {
|
||||||
|
// swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSONValue changes;
|
JSONValue changes;
|
||||||
do {
|
do {
|
||||||
// get changes from the server
|
// get changes from the server
|
||||||
try {
|
try {
|
||||||
changes = onedrive.viewChangesByPath(".", statusToken);
|
changes = onedrive.viewChangesByPath(".", deltaLink);
|
||||||
} catch (OneDriveException e) {
|
} catch (OneDriveException e) {
|
||||||
if (e.httpStatusCode == 410) {
|
if (e.httpStatusCode == 410) {
|
||||||
log.log("Status token expired, resyncing");
|
log.log("Delta link expired, resyncing");
|
||||||
statusToken = null;
|
deltaLink = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (item; changes["value"].array) {
|
foreach (item; changes["value"].array) {
|
||||||
applyDifference(item);
|
applyDifference(item);
|
||||||
}
|
}
|
||||||
// hack to reuse old code
|
if ("@odata.nextLink" in changes) deltaLink = changes["@odata.nextLink"].str;
|
||||||
string url;
|
if ("@odata.deltaLink" in changes) deltaLink = changes["@odata.deltaLink"].str;
|
||||||
if ("@odata.nextLink" in changes) url = changes["@odata.nextLink"].str;
|
std.file.write(cfg.deltaLinkFilePath, deltaLink);
|
||||||
if ("@odata.deltaLink" in changes) url = changes["@odata.deltaLink"].str;
|
|
||||||
auto c = matchFirst(url, r"(?:token=)([\w\d]+)");
|
|
||||||
c.popFront(); // skip the whole match
|
|
||||||
statusToken = c.front;
|
|
||||||
std.file.write(cfg.statusTokenFilePath, statusToken);
|
|
||||||
} while ("@odata.nextLink" in changes);
|
} while ("@odata.nextLink" in changes);
|
||||||
} catch (ErrnoException e) {
|
} catch (ErrnoException e) {
|
||||||
throw new SyncException(e.msg, e);
|
throw new SyncException(e.msg, e);
|
||||||
|
|
Loading…
Reference in a new issue