From d7fd8944f79f1f70a3c8848738afdc22bc9176cd Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Mon, 26 Feb 2018 19:16:01 +0000 Subject: [PATCH] Moved Enex import to InteropService --- CliClient/app/command-import-enex.js | 68 ------------------- CliClient/app/command-import.js | 41 +++++++++-- .../lib/services/InteropService.js | 53 ++++++++++++--- 3 files changed, 80 insertions(+), 82 deletions(-) delete mode 100644 CliClient/app/command-import-enex.js diff --git a/CliClient/app/command-import-enex.js b/CliClient/app/command-import-enex.js deleted file mode 100644 index a1f4dfc800..0000000000 --- a/CliClient/app/command-import-enex.js +++ /dev/null @@ -1,68 +0,0 @@ -const { BaseCommand } = require('./base-command.js'); -const { app } = require('./app.js'); -const { _ } = require('lib/locale.js'); -const Folder = require('lib/models/Folder.js'); -const { importEnex } = require('lib/import-enex'); -const { filename, basename } = require('lib/path-utils.js'); -const { cliUtils } = require('./cli-utils.js'); - -class Command extends BaseCommand { - - usage() { - return 'import-enex [notebook]'; - } - - description() { - return _('Imports an Evernote notebook file (.enex file).'); - } - - options() { - return [ - ['-f, --force', _('Do not ask for confirmation.')], - ]; - } - - async action(args) { - let filePath = args.file; - let folder = null; - let folderTitle = args['notebook']; - let force = args.options.force === true; - - if (!folderTitle) folderTitle = filename(filePath); - folder = await Folder.loadByField('title', folderTitle); - const msg = folder ? _('File "%s" will be imported into existing notebook "%s". Continue?', basename(filePath), folderTitle) : _('New notebook "%s" will be created and file "%s" will be imported into it. Continue?', folderTitle, basename(filePath)); - const ok = force ? true : await this.prompt(msg); - if (!ok) return; - - let lastProgress = ''; - - let options = { - onProgress: (progressState) => { - let line = []; - line.push(_('Found: %d.', progressState.loaded)); - line.push(_('Created: %d.', progressState.created)); - if (progressState.updated) line.push(_('Updated: %d.', progressState.updated)); - if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped)); - if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated)); - if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged)); - lastProgress = line.join(' '); - cliUtils.redraw(lastProgress); - }, - onError: (error) => { - let s = error.trace ? error.trace : error.toString(); - this.stdout(s); - }, - } - - folder = !folder ? await Folder.save({ title: folderTitle }) : folder; - - app().gui().showConsole(); - this.stdout(_('Importing notes...')); - await importEnex(folder.id, filePath, options); - cliUtils.redrawDone(); - this.stdout(_('The notes have been imported: %s', lastProgress)); - } - -} - -module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-import.js b/CliClient/app/command-import.js index a969a7c387..315ca22f8b 100644 --- a/CliClient/app/command-import.js +++ b/CliClient/app/command-import.js @@ -2,6 +2,9 @@ const { BaseCommand } = require('./base-command.js'); const InteropService = require('lib/services/InteropService.js'); const BaseModel = require('lib/BaseModel.js'); const Note = require('lib/models/Note.js'); +const { filename, basename, fileExtension } = require('lib/path-utils.js'); +const { importEnex } = require('lib/import-enex'); +const { cliUtils } = require('./cli-utils.js'); const { reg } = require('lib/registry.js'); const { app } = require('./app.js'); const { _ } = require('lib/locale.js'); @@ -10,7 +13,7 @@ const fs = require('fs-extra'); class Command extends BaseCommand { usage() { - return 'import '; + return 'import [notebook]'; } description() { @@ -19,23 +22,49 @@ class Command extends BaseCommand { options() { return [ - ['--format ', 'auto, jex, md'], - ['--notebook ', 'Notebook to import the notes to.'], + ['-f, --force', _('Do not ask for confirmation.')], + ['--format ', 'auto, jex, enex, md'], ]; } async action(args) { - const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.options.notebook); + let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook); + + if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook)); const importOptions = {}; importOptions.path = args.path; - importOptions.format = args.options.format ? args.options.format : 'jex'; + importOptions.format = args.options.format ? args.options.format : 'auto'; importOptions.destinationFolderId = folder ? folder.id : null; + let lastProgress = ''; + + // onProgress/onError supported by Enex import only + + importOptions.onProgress = (progressState) => { + let line = []; + line.push(_('Found: %d.', progressState.loaded)); + line.push(_('Created: %d.', progressState.created)); + if (progressState.updated) line.push(_('Updated: %d.', progressState.updated)); + if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped)); + if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated)); + if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged)); + lastProgress = line.join(' '); + cliUtils.redraw(lastProgress); + }; + + importOptions.onError = (error) => { + let s = error.trace ? error.trace : error.toString(); + this.stdout(s); + }; + + app().gui().showConsole(); + this.stdout(_('Importing notes...')); const service = new InteropService(); const result = await service.import(importOptions); - result.warnings.map((w) => this.stdout(w)); + cliUtils.redrawDone(); + if (lastProgress) this.stdout(_('The notes have been imported: %s', lastProgress)); } } diff --git a/ReactNativeClient/lib/services/InteropService.js b/ReactNativeClient/lib/services/InteropService.js index 3e5d3f3d71..fff4db832c 100644 --- a/ReactNativeClient/lib/services/InteropService.js +++ b/ReactNativeClient/lib/services/InteropService.js @@ -10,8 +10,10 @@ const fs = require('fs-extra'); const md5 = require('md5'); const { sprintf } = require('sprintf-js'); const { shim } = require('lib/shim'); +const { _ } = require('lib/locale'); const { fileExtension } = require('lib/path-utils'); const { uuid } = require('lib/uuid.js'); +const { importEnex } = require('lib/import-enex'); async function temporaryDirectory(createIt) { const tempDir = require('os').tmpdir() + '/' + md5(Math.random() + Date.now()); @@ -209,12 +211,19 @@ class JexImporter { async exec(result) { const tempDir = await temporaryDirectory(true); - await require('tar').extract({ - strict: true, - portable: true, - file: this.sourcePath_, - cwd: tempDir, - }); + try { + await require('tar').extract({ + strict: true, + portable: true, + file: this.sourcePath_, + cwd: tempDir, + }); + } catch (error) { + let msg = ['Cannot untar file ' + this.sourcePath_, error.message]; + if (error.data) msg.push(JSON.stringify(error.data)); + let e = new Error(msg.join(': ')); + throw e; + } const importer = newImporter('raw'); await importer.init(tempDir, this.options_); @@ -275,6 +284,28 @@ class MdImporter { } +class EnexImporter { + + async init(sourcePath, options) { + this.sourcePath_ = sourcePath; + this.options_ = options; + } + + async exec(result) { + let folder = this.options_.destinationFolder; + + if (!folder) { + const folderTitle = await Folder.findUniqueFolderTitle(filename(this.sourcePath_)); + folder = await Folder.save({ title: folderTitle }); + } + + await importEnex(folder.id, this.sourcePath_, this.options_); + + return result; + } + +} + function newExporter(format) { if (format === 'raw') { return new RawExporter(); @@ -292,6 +323,8 @@ function newImporter(format) { return new JexImporter(); } else if (format === 'md') { return new MdImporter(); + } else if (format === 'enex') { + return new EnexImporter(); } else { throw new Error('Unknown format: ' + format); } @@ -300,6 +333,8 @@ function newImporter(format) { class InteropService { async import(options) { + if (!await shim.fsDriver().exists(options.path)) throw new Error(_('Cannot find "%s".', options.path)); + options = Object.assign({}, { format: 'auto', destinationFolderId: null, @@ -307,9 +342,11 @@ class InteropService { }, options); if (options.format === 'auto') { - const ext = fileExtension(options.path); - if (ext.toLowerCase() === 'jex') { + const ext = fileExtension(options.path).toLowerCase(); + if (ext === 'jex') { options.format = 'jex'; + } else if (ext === 'enex') { + options.format = 'enex'; } else { throw new Error('Cannot automatically detect source format from path: ' + options.path); }