You've already forked joplin
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,6 +21,10 @@ class FileApiDriverOneDrive {
|
||||
return this.api_;
|
||||
}
|
||||
|
||||
supportsDelta() {
|
||||
return true;
|
||||
}
|
||||
|
||||
itemFilter_() {
|
||||
return {
|
||||
select: 'name,file,folder,fileSystemInfo',
|
||||
|
||||
@@ -13,6 +13,10 @@ class FileApi {
|
||||
return this.driver_;
|
||||
}
|
||||
|
||||
supportsDelta() {
|
||||
return this.driver_.supportsDelta();
|
||||
}
|
||||
|
||||
setLogger(l) {
|
||||
this.logger_ = l;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user