From 92f586486f63aee655d624c02d38b3db3d4a04fd Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 5 Feb 2023 01:12:13 +0200 Subject: [PATCH 1/6] Fix broken reference consistency check If a branch was identified with a missing parent, the branch would be moved to root. However, the ID of the branch would be changed as a result of that, and this resulted in the creation of a new branch instead of updating the old one. Deleting the old one first solves the issue. --- src/services/consistency_checks.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 483048d19..41598733e 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -148,13 +148,20 @@ class ConsistencyChecks { AND notes.noteId IS NULL`, ({branchId, parentNoteId}) => { if (this.autoFix) { - const branch = becca.getBranch(branchId); - branch.parentNoteId = 'root'; - branch.save(); + // Delete the old branch and recreate it with root as parent. + const oldBranch = becca.getBranch(branchId); + const noteId = oldBranch.noteId; + oldBranch.markAsDeleted("missing-parent"); + + const newBranch = new Branch({ + parentNoteId: 'root', + noteId: noteId, + prefix: 'recovered' + }).save(); this.reloadNeeded = true; - logFix(`Branch '${branchId}' was set to root parent since it was referencing missing parent note '${parentNoteId}'`); + logFix(`Branch '${branchId}' was was missing parent note '${parentNoteId}', so it was deleted. ${newBranch.branchId} was created in the root instead.`); } else { logError(`Branch '${branchId}' references missing parent note '${parentNoteId}'`); } From 346f6edd7e52ec184db6359018784a83eb3cc4be Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 10 Feb 2023 08:55:26 +0100 Subject: [PATCH 2/6] fix filing entity changes for deleted notes --- src/services/entity_changes.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/entity_changes.js b/src/services/entity_changes.js index c83b47c06..35831dc1c 100644 --- a/src/services/entity_changes.js +++ b/src/services/entity_changes.js @@ -102,13 +102,14 @@ function fillEntityChanges(entityName, entityPrimaryKey, condition = '') { const entity = becca.getEntity(entityName, entityId); + // entity might be null (not present in becca) when it's deleted addEntityChange({ entityName, entityId, - hash: entity.generateHash(), + hash: entity?.generateHash() || "|deleted", isErased: false, - utcDateChanged: entity.getUtcDateChanged(), - isSynced: entityName !== 'options' || !!entity.isSynced + utcDateChanged: entity?.getUtcDateChanged() || dateUtils.utcNowDateTime(), + isSynced: entityName !== 'options' || !!entity?.isSynced }); } } From c67644a2e32c519fbc9cfad7e003284df57c3bb5 Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 10 Feb 2023 09:16:32 +0100 Subject: [PATCH 3/6] fix filing entity changes for deleted notes --- src/becca/becca.js | 4 ++++ src/services/entity_changes.js | 32 +++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/becca/becca.js b/src/becca/becca.js index 9456c5623..28d64d216 100644 --- a/src/becca/becca.js +++ b/src/becca/becca.js @@ -152,6 +152,10 @@ class Becca { .replace('_', '') ); + if (!(camelCaseEntityName in this)) { + throw new Error(`Unknown entity name '${camelCaseEntityName}' (original argument '${entityName}')`); + } + return this[camelCaseEntityName][entityId]; } diff --git a/src/services/entity_changes.js b/src/services/entity_changes.js index 35831dc1c..ff1492201 100644 --- a/src/services/entity_changes.js +++ b/src/services/entity_changes.js @@ -100,16 +100,38 @@ function fillEntityChanges(entityName, entityPrimaryKey, condition = '') { if (existingRows === 0) { createdCount++; - const entity = becca.getEntity(entityName, entityId); + let hash; + let utcDateChanged; + let isSynced; + + if (entityName.endsWith("_contents")) { + // FIXME: hacky, not sure if it might cause some problems + hash = "fake value"; + utcDateChanged = dateUtils.utcNowDateTime(); + isSynced = true; // contents are always synced + } else { + const entity = becca.getEntity(entityName, entityId); + + if (entity) { + hash = entity?.generateHash() || "|deleted"; + utcDateChanged = entity?.getUtcDateChanged() || dateUtils.utcNowDateTime(); + isSynced = entityName !== 'options' || !!entity?.isSynced; + } else { + // entity might be null (not present in becca) when it's deleted + // FIXME: hacky, not sure if it might cause some problems + hash = "deleted"; + utcDateChanged = dateUtils.utcNowDateTime(); + isSynced = true; // deletable (the ones with isDeleted) entities are synced + } + } - // entity might be null (not present in becca) when it's deleted addEntityChange({ entityName, entityId, - hash: entity?.generateHash() || "|deleted", + hash: hash, isErased: false, - utcDateChanged: entity?.getUtcDateChanged() || dateUtils.utcNowDateTime(), - isSynced: entityName !== 'options' || !!entity?.isSynced + utcDateChanged: utcDateChanged, + isSynced: isSynced }); } } From ade22ea8259591461f3a8f319fc225eabd636bce Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 10 Feb 2023 10:09:06 +0100 Subject: [PATCH 4/6] recover notes into root only if no other valid branch exists, #3590 --- src/services/consistency_checks.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 41598733e..4cc8e6cbb 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -153,15 +153,23 @@ class ConsistencyChecks { const noteId = oldBranch.noteId; oldBranch.markAsDeleted("missing-parent"); - const newBranch = new Branch({ - parentNoteId: 'root', - noteId: noteId, - prefix: 'recovered' - }).save(); + let message = `Branch '${branchId}' was was missing parent note '${parentNoteId}', so it was deleted. `; + + if (becca.getNote(noteId).getParentBranches().length === 0) { + const newBranch = new Branch({ + parentNoteId: 'root', + noteId: noteId, + prefix: 'recovered' + }).save(); + + message += `${newBranch.branchId} was created in the root instead.`; + } else { + message += `There is one or more valid branches, so no new one will be created as a replacement.`; + } this.reloadNeeded = true; - logFix(`Branch '${branchId}' was was missing parent note '${parentNoteId}', so it was deleted. ${newBranch.branchId} was created in the root instead.`); + logFix(message); } else { logError(`Branch '${branchId}' references missing parent note '${parentNoteId}'`); } From adf222b5e851c6978cf7a3e0a77f518bbd46a52d Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 10 Feb 2023 10:12:58 +0100 Subject: [PATCH 5/6] fix consistency check to re-parent note from search parent to root --- src/services/consistency_checks.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 4cc8e6cbb..4ba2cae08 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -443,10 +443,17 @@ class ConsistencyChecks { const branches = branchIds.map(branchId => becca.getBranch(branchId)); for (const branch of branches) { - branch.parentNoteId = 'root'; - branch.save(); + // delete the old wrong branch + branch.markAsDeleted("parent-is-search"); - logFix(`Child branch '${branch.branchId}' has been moved to root since it was a child of a search note '${parentNoteId}'`) + // create a replacement branch in root parent + new Branch({ + parentNoteId: 'root', + noteId: branch.noteId, + prefix: 'recovered' + }).save(); + + logFix(`Note '${branch.noteId}' has been moved to root since it was a child of a search note '${parentNoteId}'`) } this.reloadNeeded = true; From fc7da015fe59c51e69ffce73d154a536eaf21108 Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 10 Feb 2023 10:23:02 +0100 Subject: [PATCH 6/6] fix image display with slash in title, closes #3591 --- src/public/app/widgets/type_widgets/image.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/app/widgets/type_widgets/image.js b/src/public/app/widgets/type_widgets/image.js index 8974b8e61..aeee6c40a 100644 --- a/src/public/app/widgets/type_widgets/image.js +++ b/src/public/app/widgets/type_widgets/image.js @@ -90,7 +90,7 @@ class ImageTypeWidget extends TypeWidget { } async doRefresh(note) { - this.$imageView.prop("src", `api/images/${note.noteId}/${note.title}`); + this.$imageView.prop("src", `api/images/${note.noteId}/${encodeURIComponent(note.title)}`); } copyImageReferenceToClipboardEvent({ntxId}) {