mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Clean up
This commit is contained in:
parent
b36905cb3c
commit
c28323bfab
1
CliClient/.gitignore
vendored
1
CliClient/.gitignore
vendored
@ -10,3 +10,4 @@ tests/fuzzing/client1
|
||||
tests/fuzzing/client2
|
||||
tests/fuzzing/sync
|
||||
tests/fuzzing.*
|
||||
tests/fuzzing -*
|
@ -202,10 +202,10 @@ commands.push({
|
||||
|
||||
if (pattern.indexOf('*') < 0) { // Handle it as a simple title
|
||||
if (pattern.substr(0, 3) == '../') {
|
||||
itemType = BaseModel.MODEL_TYPE_FOLDER;
|
||||
itemType = BaseModel.TYPE_FOLDER;
|
||||
pattern = pattern.substr(3);
|
||||
} else {
|
||||
itemType = BaseModel.MODEL_TYPE_NOTE;
|
||||
itemType = BaseModel.TYPE_NOTE;
|
||||
}
|
||||
|
||||
let item = await BaseItem.loadItemByField(itemType, 'title', pattern);
|
||||
@ -272,9 +272,9 @@ commands.push({
|
||||
action: async function(args, end) {
|
||||
try {
|
||||
let tag = null;
|
||||
if (args.tag) tag = await loadItem(BaseModel.MODEL_TYPE_TAG, args.tag);
|
||||
if (args.tag) tag = await loadItem(BaseModel.TYPE_TAG, args.tag);
|
||||
let note = null;
|
||||
if (args.note) note = await loadItem(BaseModel.MODEL_TYPE_NOTE, args.note);
|
||||
if (args.note) note = await loadItem(BaseModel.TYPE_NOTE, args.note);
|
||||
|
||||
if (args.command == 'remove' && !tag) throw new Error(_('Tag does not exist: "%s"', args.tag));
|
||||
|
||||
|
@ -25,7 +25,7 @@ describe('BaseItem', function() {
|
||||
|
||||
await Folder.delete(folder1.id);
|
||||
|
||||
let items = await BaseModel.deletedItems();
|
||||
let items = await BaseItem.deletedItems();
|
||||
|
||||
expect(items.length).toBe(1);
|
||||
expect(items[0].item_id).toBe(folder1.id);
|
||||
|
@ -38,7 +38,7 @@ async function localItemsSameAsRemote(locals, expect) {
|
||||
expect(remote.updated_time).toBe(dbItem.updated_time);
|
||||
|
||||
let remoteContent = await fileApi().get(path);
|
||||
remoteContent = dbItem.type_ == BaseModel.MODEL_TYPE_NOTE ? await Note.unserialize(remoteContent) : await Folder.unserialize(remoteContent);
|
||||
remoteContent = dbItem.type_ == BaseModel.TYPE_NOTE ? await Note.unserialize(remoteContent) : await Folder.unserialize(remoteContent);
|
||||
expect(remoteContent.title).toBe(dbItem.title);
|
||||
}
|
||||
} catch (error) {
|
||||
@ -238,7 +238,7 @@ describe('Synchronizer', function() {
|
||||
expect(files.length).toBe(1);
|
||||
expect(files[0].path).toBe(Folder.systemPath(folder1));
|
||||
|
||||
let deletedItems = await BaseModel.deletedItems();
|
||||
let deletedItems = await BaseItem.deletedItems();
|
||||
expect(deletedItems.length).toBe(0);
|
||||
|
||||
done();
|
||||
@ -267,7 +267,7 @@ describe('Synchronizer', function() {
|
||||
|
||||
expect(items.length).toBe(1);
|
||||
|
||||
let deletedItems = await BaseModel.deletedItems();
|
||||
let deletedItems = await BaseItem.deletedItems();
|
||||
|
||||
expect(deletedItems.length).toBe(0);
|
||||
|
||||
|
@ -16,7 +16,7 @@ class BaseModel {
|
||||
return output;
|
||||
} else {
|
||||
model = Object.assign({}, model);
|
||||
model.type_ = this.itemType();
|
||||
model.type_ = this.modelType();
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@ -33,14 +33,10 @@ class BaseModel {
|
||||
return false;
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
static modelType() {
|
||||
throw new Error('Must be overriden');
|
||||
}
|
||||
|
||||
static trackDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static byId(items, id) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].id == id) return items[i];
|
||||
@ -69,13 +65,6 @@ class BaseModel {
|
||||
return this.db().tableFields(this.tableName());
|
||||
}
|
||||
|
||||
static identifyItemType(item) {
|
||||
if (!item) throw new Error('Cannot identify undefined item');
|
||||
if ('body' in item || ('parent_id' in item && !!item.parent_id)) return BaseModel.MODEL_TYPE_NOTE;
|
||||
if ('sync_time' in item) return BaseModel.MODEL_TYPE_FOLDER;
|
||||
throw new Error('Cannot identify item: ' + JSON.stringify(item));
|
||||
}
|
||||
|
||||
static new() {
|
||||
let fields = this.fields();
|
||||
let output = {};
|
||||
@ -86,26 +75,14 @@ class BaseModel {
|
||||
return output;
|
||||
}
|
||||
|
||||
static fromApiResult(apiResult) {
|
||||
let fieldNames = this.fieldNames();
|
||||
let output = {};
|
||||
for (let i = 0; i < fieldNames.length; i++) {
|
||||
let f = fieldNames[i];
|
||||
output[f] = f in apiResult ? apiResult[f] : null;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
static modOptions(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
} else {
|
||||
options = Object.assign({}, options);
|
||||
}
|
||||
if (!('trackDeleted' in options)) options.trackDeleted = null;
|
||||
if (!('isNew' in options)) options.isNew = 'auto';
|
||||
if (!('autoTimestamp' in options)) options.autoTimestamp = true;
|
||||
if (!('transactionNextQueries' in options)) options.transactionNextQueries = [];
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -179,15 +156,6 @@ class BaseModel {
|
||||
return this.modelSelectOne('SELECT * FROM `' + this.tableName() + '` WHERE `title` = ?', [fieldValue]);
|
||||
}
|
||||
|
||||
static applyPatch(model, patch) {
|
||||
model = Object.assign({}, model);
|
||||
for (let n in patch) {
|
||||
if (!patch.hasOwnProperty(n)) continue;
|
||||
model[n] = patch[n];
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
static diffObjects(oldModel, newModel) {
|
||||
let output = {};
|
||||
let type = null;
|
||||
@ -256,10 +224,6 @@ class BaseModel {
|
||||
|
||||
queries.push(saveQuery);
|
||||
|
||||
for (let i = 0; i < options.transactionNextQueries.length; i++) {
|
||||
queries.push(options.transactionNextQueries[i]);
|
||||
}
|
||||
|
||||
return this.db().transactionExecBatch(queries).then(() => {
|
||||
o = Object.assign({}, o);
|
||||
o.id = modelId;
|
||||
@ -280,14 +244,6 @@ class BaseModel {
|
||||
return !object.id;
|
||||
}
|
||||
|
||||
static deletedItems() {
|
||||
return this.db().selectAll('SELECT * FROM deleted_items');
|
||||
}
|
||||
|
||||
static remoteDeletedItem(itemId) {
|
||||
return this.db().exec('DELETE FROM deleted_items WHERE item_id = ?', [itemId]);
|
||||
}
|
||||
|
||||
static filterArray(models) {
|
||||
let output = [];
|
||||
for (let i = 0; i < models.length; i++) {
|
||||
@ -312,16 +268,8 @@ class BaseModel {
|
||||
|
||||
static delete(id, options = null) {
|
||||
options = this.modOptions(options);
|
||||
|
||||
if (!id) throw new Error('Cannot delete object without an ID');
|
||||
|
||||
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id = ?', [id]).then(() => {
|
||||
let trackDeleted = this.trackDeleted();
|
||||
if (options.trackDeleted !== null) trackDeleted = options.trackDeleted;
|
||||
if (trackDeleted) {
|
||||
return this.db().exec('INSERT INTO deleted_items (item_type, item_id, deleted_time) VALUES (?, ?, ?)', [this.itemType(), id, time.unixMs()]);
|
||||
}
|
||||
});
|
||||
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id = ?', [id]);
|
||||
}
|
||||
|
||||
static db() {
|
||||
@ -331,11 +279,11 @@ class BaseModel {
|
||||
|
||||
}
|
||||
|
||||
BaseModel.MODEL_TYPE_NOTE = 1;
|
||||
BaseModel.MODEL_TYPE_FOLDER = 2;
|
||||
BaseModel.MODEL_TYPE_SETTING = 3;
|
||||
BaseModel.MODEL_TYPE_RESOURCE = 4;
|
||||
BaseModel.MODEL_TYPE_TAG = 5;
|
||||
BaseModel.TYPE_NOTE = 1;
|
||||
BaseModel.TYPE_FOLDER = 2;
|
||||
BaseModel.TYPE_SETTING = 3;
|
||||
BaseModel.TYPE_RESOURCE = 4;
|
||||
BaseModel.TYPE_TAG = 5;
|
||||
BaseModel.tableInfo_ = null;
|
||||
BaseModel.tableKeys_ = null;
|
||||
BaseModel.db_ = null;
|
||||
|
@ -9,6 +9,10 @@ class BaseItem extends BaseModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
static trackDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Need to dynamically load the classes like this to avoid circular dependencies
|
||||
static getClass(name) {
|
||||
if (!this.classes_) this.classes_ = {};
|
||||
@ -29,10 +33,10 @@ class BaseItem extends BaseModel {
|
||||
if (!('type_' in item)) throw new Error('Item does not have a type_ property');
|
||||
return this.itemClass(item.type_);
|
||||
} else {
|
||||
if (Number(item) === BaseModel.MODEL_TYPE_NOTE) return this.getClass('Note');
|
||||
if (Number(item) === BaseModel.MODEL_TYPE_FOLDER) return this.getClass('Folder');
|
||||
if (Number(item) === BaseModel.MODEL_TYPE_RESOURCE) return this.getClass('Resource');
|
||||
if (Number(item) === BaseModel.MODEL_TYPE_TAG) return this.getClass('Tag');
|
||||
if (Number(item) === BaseModel.TYPE_NOTE) return this.getClass('Note');
|
||||
if (Number(item) === BaseModel.TYPE_FOLDER) return this.getClass('Folder');
|
||||
if (Number(item) === BaseModel.TYPE_RESOURCE) return this.getClass('Resource');
|
||||
if (Number(item) === BaseModel.TYPE_TAG) return this.getClass('Tag');
|
||||
throw new Error('Unknown type: ' + item);
|
||||
}
|
||||
}
|
||||
@ -79,6 +83,25 @@ class BaseItem extends BaseModel {
|
||||
return ItemClass.delete(id);
|
||||
}
|
||||
|
||||
static async delete(id, options = null) {
|
||||
let trackDeleted = this.trackDeleted();
|
||||
if (options && options.trackDeleted !== null && options.trackDeleted !== undefined) trackDeleted = options.trackDeleted;
|
||||
|
||||
await super.delete(id, options);
|
||||
|
||||
if (trackDeleted) {
|
||||
await this.db().exec('INSERT INTO deleted_items (item_type, item_id, deleted_time) VALUES (?, ?, ?)', [this.modelType(), id, time.unixMs()]);
|
||||
}
|
||||
}
|
||||
|
||||
static deletedItems() {
|
||||
return this.db().selectAll('SELECT * FROM deleted_items');
|
||||
}
|
||||
|
||||
static remoteDeletedItem(itemId) {
|
||||
return this.db().exec('DELETE FROM deleted_items WHERE item_id = ?', [itemId]);
|
||||
}
|
||||
|
||||
static serialize_format(propName, propValue) {
|
||||
if (['created_time', 'updated_time'].indexOf(propName) >= 0) {
|
||||
if (!propValue) return '';
|
||||
@ -145,6 +168,7 @@ class BaseItem extends BaseModel {
|
||||
if (line == '') {
|
||||
state = 'readingBody';
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
let p = line.indexOf(':');
|
||||
@ -165,7 +189,7 @@ class BaseItem extends BaseModel {
|
||||
if (!output.type_) throw new Error('Missing required property: type_: ' + content);
|
||||
output.type_ = Number(output.type_);
|
||||
|
||||
if (output.type_ == BaseModel.MODEL_TYPE_NOTE) output.body = body.join("\n");
|
||||
if (output.type_ == BaseModel.TYPE_NOTE) output.body = body.join("\n");
|
||||
|
||||
for (let n in output) {
|
||||
if (!output.hasOwnProperty(n)) continue;
|
||||
|
@ -21,8 +21,8 @@ class Folder extends BaseItem {
|
||||
return super.serialize(folder, 'folder', fieldNames);
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
return BaseModel.MODEL_TYPE_FOLDER;
|
||||
static modelType() {
|
||||
return BaseModel.TYPE_FOLDER;
|
||||
}
|
||||
|
||||
static trackDeleted() {
|
||||
|
@ -20,8 +20,8 @@ class Note extends BaseItem {
|
||||
return super.serialize(note, 'note', fieldNames);
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
return BaseModel.MODEL_TYPE_NOTE;
|
||||
static modelType() {
|
||||
return BaseModel.TYPE_NOTE;
|
||||
}
|
||||
|
||||
static trackDeleted() {
|
||||
|
@ -11,8 +11,8 @@ class Resource extends BaseItem {
|
||||
return 'resources';
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
return BaseModel.MODEL_TYPE_RESOURCE;
|
||||
static modelType() {
|
||||
return BaseModel.TYPE_RESOURCE;
|
||||
}
|
||||
|
||||
static async serialize(item, type = null, shownKeys = null) {
|
||||
|
@ -7,8 +7,8 @@ class Setting extends BaseModel {
|
||||
return 'settings';
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
return BaseModel.MODEL_TYPE_SETTING;
|
||||
static modelType() {
|
||||
return BaseModel.TYPE_SETTING;
|
||||
}
|
||||
|
||||
static defaultSetting(key) {
|
||||
|
@ -11,8 +11,8 @@ class Tag extends BaseItem {
|
||||
return 'tags';
|
||||
}
|
||||
|
||||
static itemType() {
|
||||
return BaseModel.MODEL_TYPE_TAG;
|
||||
static modelType() {
|
||||
return BaseModel.TYPE_TAG;
|
||||
}
|
||||
|
||||
static async serialize(item, type = null, shownKeys = null) {
|
||||
|
@ -156,7 +156,7 @@ class Synchronizer {
|
||||
reason = 'remote does not exist, and local is new and has never been synced';
|
||||
} else {
|
||||
// Note or item was modified after having been deleted remotely
|
||||
action = local.type_ == BaseModel.MODEL_TYPE_NOTE ? 'noteConflict' : 'itemConflict';
|
||||
action = local.type_ == BaseModel.TYPE_NOTE ? 'noteConflict' : 'itemConflict';
|
||||
reason = 'remote has been deleted, but local has changes';
|
||||
}
|
||||
} else {
|
||||
@ -164,7 +164,7 @@ class Synchronizer {
|
||||
// Since, in this loop, we are only dealing with notes that require sync, if the
|
||||
// remote has been modified after the sync time, it means both notes have been
|
||||
// modified and so there's a conflict.
|
||||
action = local.type_ == BaseModel.MODEL_TYPE_NOTE ? 'noteConflict' : 'itemConflict';
|
||||
action = local.type_ == BaseModel.TYPE_NOTE ? 'noteConflict' : 'itemConflict';
|
||||
reason = 'both remote and local have changes';
|
||||
} else {
|
||||
action = 'updateRemote';
|
||||
@ -175,7 +175,7 @@ class Synchronizer {
|
||||
this.logSyncOperation(action, local, remote, reason);
|
||||
|
||||
|
||||
if (local.type_ == BaseModel.MODEL_TYPE_RESOURCE && (action == 'createRemote' || (action == 'itemConflict' && remote))) {
|
||||
if (local.type_ == BaseModel.TYPE_RESOURCE && (action == 'createRemote' || (action == 'itemConflict' && remote))) {
|
||||
let remoteContentPath = this.resourceDirName_ + '/' + local.id;
|
||||
let resourceContent = await Resource.content(local);
|
||||
await this.api().put(remoteContentPath, resourceContent);
|
||||
@ -244,7 +244,7 @@ class Synchronizer {
|
||||
// Delete the remote items that have been deleted locally.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
let deletedItems = await BaseModel.deletedItems();
|
||||
let deletedItems = await BaseItem.deletedItems();
|
||||
report.remotesToDelete = deletedItems.length;
|
||||
options.onProgress(report);
|
||||
for (let i = 0; i < deletedItems.length; i++) {
|
||||
@ -253,7 +253,7 @@ class Synchronizer {
|
||||
this.logSyncOperation('deleteRemote', null, { id: item.item_id }, 'local has been deleted');
|
||||
await this.api().delete(path);
|
||||
if (this.randomFailure(options, 2)) return;
|
||||
await BaseModel.remoteDeletedItem(item.item_id);
|
||||
await BaseItem.remoteDeletedItem(item.item_id);
|
||||
|
||||
report['deleteRemote']++;
|
||||
options.onProgress(report);
|
||||
@ -315,7 +315,7 @@ class Synchronizer {
|
||||
};
|
||||
if (action == 'createLocal') options.isNew = true;
|
||||
|
||||
if (newContent.type_ == BaseModel.MODEL_TYPE_RESOURCE && action == 'createLocal') {
|
||||
if (newContent.type_ == BaseModel.TYPE_RESOURCE && action == 'createLocal') {
|
||||
let localResourceContentPath = Resource.fullPath(newContent);
|
||||
let remoteResourceContentPath = this.resourceDirName_ + '/' + newContent.id;
|
||||
let remoteResourceContent = await this.api().get(remoteResourceContentPath, { encoding: 'binary' });
|
||||
|
Loading…
Reference in New Issue
Block a user