From 1f96a6beab890a821761b88493974eaf2ab7d097 Mon Sep 17 00:00:00 2001 From: azivner Date: Sun, 8 Apr 2018 13:14:30 -0400 Subject: [PATCH] export & import work correctly with clones --- src/routes/api/export.js | 108 ++++++++++++++++++++++----------------- src/routes/api/import.js | 27 ++++++++-- src/services/notes.js | 1 + 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/src/routes/api/export.js b/src/routes/api/export.js index e5cf87aeb..414fbf6a7 100644 --- a/src/routes/api/export.js +++ b/src/routes/api/export.js @@ -13,7 +13,68 @@ async function exportNote(req, res) { const pack = tar.pack(); - const name = await exportNoteInner(branchId, '', pack); + const exportedNoteIds = []; + const name = await exportNoteInner(branchId, ''); + + async function exportNoteInner(branchId, directory) { + const branch = await repository.getBranch(branchId); + const note = await branch.getNote(); + const childFileName = directory + sanitize(note.title); + + if (exportedNoteIds.includes(note.noteId)) { + saveMetadataFile(childFileName, { + version: 1, + clone: true, + noteId: note.noteId, + prefix: branch.prefix + }); + + return; + } + + const metadata = { + version: 1, + clone: false, + noteId: note.noteId, + title: note.title, + prefix: branch.prefix, + type: note.type, + mime: note.mime, + labels: (await note.getLabels()).map(label => { + return { + name: label.name, + value: label.value + }; + }) + }; + + if (metadata.labels.find(label => label.name === 'excludeFromExport')) { + return; + } + + saveMetadataFile(childFileName, metadata); + saveDataFile(childFileName, note); + + exportedNoteIds.push(note.noteId); + + for (const child of await note.getChildBranches()) { + await exportNoteInner(child.branchId, childFileName + "/"); + } + + return childFileName; + } + + function saveDataFile(childFileName, note) { + const content = note.type === 'text' ? html.prettyPrint(note.content, {indent_size: 2}) : note.content; + + pack.entry({name: childFileName + ".dat", size: content.length}, content); + } + + function saveMetadataFile(childFileName, metadata) { + const metadataJson = JSON.stringify(metadata, null, '\t'); + + pack.entry({name: childFileName + ".meta", size: metadataJson.length}, metadataJson); + } pack.finalize(); @@ -23,51 +84,6 @@ async function exportNote(req, res) { pack.pipe(res); } -async function exportNoteInner(branchId, directory, pack) { - const branch = await repository.getBranch(branchId); - const note = await branch.getNote(); - - if (note.isProtected) { - return; - } - - const metadata = await getMetadata(note); - - if (metadata.labels.find(label => label.name === 'excludeFromExport')) { - return; - } - - const metadataJson = JSON.stringify(metadata, null, '\t'); - const childFileName = directory + sanitize(note.title); - - pack.entry({ name: childFileName + ".meta", size: metadataJson.length }, metadataJson); - - const content = note.type === 'text' ? html.prettyPrint(note.content, {indent_size: 2}) : note.content; - - pack.entry({ name: childFileName + ".dat", size: content.length }, content); - - for (const child of await note.getChildBranches()) { - await exportNoteInner(child.branchId, childFileName + "/", pack); - } - - return childFileName; -} - -async function getMetadata(note) { - return { - version: 1, - title: note.title, - type: note.type, - mime: note.mime, - labels: (await note.getLabels()).map(label => { - return { - name: label.name, - value: label.value - }; - }) - }; -} - module.exports = { exportNote }; \ No newline at end of file diff --git a/src/routes/api/import.js b/src/routes/api/import.js index a2db68927..f89ffabe0 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -3,6 +3,7 @@ const repository = require('../../services/repository'); const labelService = require('../../services/labels'); const noteService = require('../../services/notes'); +const Branch = require('../../entities/branch'); const tar = require('tar-stream'); const stream = require('stream'); const path = require('path'); @@ -31,7 +32,7 @@ async function parseImportFile(file) { const extract = tar.extract(); extract.on('entry', function(header, stream, next) { - let {name, key} = getFileName(header.name); + const {name, key} = getFileName(header.name); let file = fileMap[name]; @@ -97,30 +98,46 @@ async function importTar(req) { const files = await parseImportFile(file); - await importNotes(files, parentNoteId); + // maps from original noteId (in tar file) to newly generated noteId + const noteIdMap = {}; + + await importNotes(files, parentNoteId, noteIdMap); } -async function importNotes(files, parentNoteId) { +async function importNotes(files, parentNoteId, noteIdMap) { for (const file of files) { if (file.meta.version !== 1) { throw new Error("Can't read meta data version " + file.meta.version); } + if (file.meta.clone) { + await new Branch({ + parentNoteId: parentNoteId, + noteId: noteIdMap[file.meta.noteId], + prefix: file.meta.prefix + }).save(); + + return; + } + if (file.meta.type !== 'file') { file.data = file.data.toString("UTF-8"); } const {note} = await noteService.createNote(parentNoteId, file.meta.title, file.data, { type: file.meta.type, - mime: file.meta.mime + mime: file.meta.mime, + prefix: file.meta.prefix }); + noteIdMap[file.meta.noteId] = note.noteId; + for (const label of file.meta.labels) { await labelService.createLabel(note.noteId, label.name, label.value); } if (file.children.length > 0) { - await importNotes(file.children, note.noteId); + await importNotes(file.children, note.noteId, noteIdMap); } } } diff --git a/src/services/notes.js b/src/services/notes.js index 29a011e82..e4fb74557 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -56,6 +56,7 @@ async function createNewNote(parentNoteId, noteData) { noteId: note.noteId, parentNoteId: parentNoteId, notePosition: newNotePos, + prefix: noteData.prefix, isExpanded: 0 }).save();