1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-29 22:48:10 +02:00

Handle delta api for filesystem

This commit is contained in:
Laurent Cozic
2017-07-18 23:14:20 +01:00
parent 0c30c1b70b
commit 7aa21174f6
16 changed files with 185 additions and 106 deletions

View File

@@ -1,6 +1,7 @@
import fs from 'fs-extra';
import { promiseChain } from 'lib/promise-utils.js';
import moment from 'moment';
import { BaseItem } from 'lib/models/base-item.js';
import { time } from 'lib/time-utils.js';
class FileApiDriverLocal {
@@ -20,6 +21,10 @@ class FileApiDriverLocal {
return output;
}
supportsDelta() {
return false;
}
stat(path) {
return new Promise((resolve, reject) => {
fs.stat(path, (error, s) => {
@@ -68,6 +73,49 @@ class FileApiDriverLocal {
});
}
async delta(path, options) {
try {
let items = await fs.readdir(path);
let output = [];
for (let i = 0; i < items.length; i++) {
let stat = await this.stat(path + '/' + items[i]);
if (!stat) continue; // Has been deleted between the readdir() call and now
stat.path = items[i];
output.push(stat);
}
if (!Array.isArray(options.itemIds)) throw new Error('Delta API not supported - local IDs must be provided');
let deletedItems = [];
for (let i = 0; i < options.itemIds.length; i++) {
const itemId = options.itemIds[i];
let found = false;
for (let j = 0; j < output.length; j++) {
const item = output[j];
if (BaseItem.pathToId(item.path) == itemId) {
found = true;
break;
}
}
if (!found) {
deletedItems.push({
path: BaseItem.systemPath(itemId),
isDeleted: true,
});
}
}
return {
hasMore: false,
context: null,
items: output,
};
} catch(error) {
throw this.fsErrorToJsError_(error);
}
}
async list(path, options) {
try {
let items = await fs.readdir(path);

View File

@@ -15,6 +15,10 @@ class FileApiDriverMemory {
this.deletedItems_ = [];
}
supportsDelta() {
return true;
}
itemIndexByPath(path) {
for (let i = 0; i < this.items_.length; i++) {
if (this.items_[i].path == path) return i;

View File

@@ -21,6 +21,10 @@ class FileApiDriverOneDrive {
return this.api_;
}
supportsDelta() {
return true;
}
itemFilter_() {
return {
select: 'name,file,folder,fileSystemInfo',

View File

@@ -13,6 +13,10 @@ class FileApi {
return this.driver_;
}
supportsDelta() {
return this.driver_.supportsDelta();
}
setLogger(l) {
this.logger_ = l;
}

View File

@@ -79,7 +79,8 @@ class BaseItem extends BaseModel {
}
static pathToId(path) {
let s = path.split('.');
let p = path.split('/');
let s = p[p.length - 1].split('.');
return s[0];
}

View File

@@ -102,6 +102,9 @@ class Synchronizer {
for (let n in report) {
if (!report.hasOwnProperty(n)) continue;
if (n == 'errors') continue;
if (n == 'starting') continue;
if (n == 'finished') continue;
if (n == 'state') continue;
this.logger().info(n + ': ' + (report[n] ? report[n] : '-'));
}
let folderCount = await Folder.count();
@@ -327,7 +330,15 @@ class Synchronizer {
while (true) {
if (this.cancelling()) break;
let listResult = await this.api().delta('', { context: context });
let allIds = null;
if (!this.api().supportsDelta()) {
allIds = await BaseItem.syncedItems(syncTargetId);
}
let listResult = await this.api().delta('', {
context: context,
itemIds: allIds,
});
let remotes = listResult.items;
for (let i = 0; i < remotes.length; i++) {
if (this.cancelling()) break;
@@ -335,8 +346,6 @@ class Synchronizer {
let remote = remotes[i];
if (!BaseItem.isSystemPath(remote.path)) continue; // The delta API might return things like the .sync, .resource or the root folder
//console.info(remote);
let path = remote.path;
let action = null;
let reason = '';
@@ -410,34 +419,13 @@ class Synchronizer {
outputContext.delta = newDeltaContext ? newDeltaContext : lastContext.delta;
// // ------------------------------------------------------------------------
// // Search, among the local IDs, those that don't exist remotely, which
// // means the item has been deleted.
// // ------------------------------------------------------------------------
// if (this.randomFailure(options, 4)) return;
// let localFoldersToDelete = [];
// if (!this.cancelling()) {
// let syncItems = await BaseItem.syncedItems(syncTargetId);
// for (let i = 0; i < syncItems.length; i++) {
// if (this.cancelling()) break;
// let syncItem = syncItems[i];
// if (remoteIds.indexOf(syncItem.item_id) < 0) {
// if (syncItem.item_type == Folder.modelType()) {
// localFoldersToDelete.push(syncItem);
// continue;
// }
// this.logSyncOperation('deleteLocal', { id: syncItem.item_id }, null, 'remote has been deleted');
// let ItemClass = BaseItem.itemClass(syncItem.item_type);
// await ItemClass.delete(syncItem.item_id, { trackDeleted: false });
// }
// }
// }
// ------------------------------------------------------------------------
// Delete the folders that have been collected in the loop above.
// Folders are always deleted last, and only if they are empty.
// If they are not empty it's considered a conflict since whatever deleted
// them should have deleted their content too. In that case, all its notes
// are marked as "is_conflict".
// ------------------------------------------------------------------------
if (!this.cancelling()) {
for (let i = 0; i < localFoldersToDelete.length; i++) {