From 6cd7609fafe9f455e730ed0f7d69b415ae668873 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 6 Nov 2018 11:04:11 +0700 Subject: [PATCH] Require Node.js 8 --- .gitattributes | 3 +- .travis.yml | 3 +- index.js | 36 +++++++++------- lib/linux.js | 46 ++++++++++++--------- lib/macos.js | 43 +++++++++++-------- lib/win.js | 9 ---- lib/windows.js | 13 ++++++ package.json | 110 ++++++++++++++++++++++++------------------------- readme.md | 6 +-- test.js | 30 +++++++------- 10 files changed, 161 insertions(+), 138 deletions(-) delete mode 100644 lib/win.js create mode 100644 lib/windows.js diff --git a/.gitattributes b/.gitattributes index af19290..1c1cf56 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ -* text=auto -*.js text eol=lf +* text=auto eol=lf lib/macos-trash binary lib/win-trash.exe binary diff --git a/.travis.yml b/.travis.yml index ef86841..8afd19b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,5 @@ os: - osx language: node_js node_js: + - '10' - '8' - - '6' - - '4' diff --git a/index.js b/index.js index 42a1e39..1137e3a 100644 --- a/index.js +++ b/index.js @@ -5,27 +5,32 @@ const globby = require('globby'); const pTry = require('p-try'); const macos = require('./lib/macos'); const linux = require('./lib/linux'); -const win = require('./lib/win'); +const windows = require('./lib/windows'); -module.exports = (iterable, opts) => pTry(() => { - iterable = Array.from(typeof iterable === 'string' ? [iterable] : iterable).map(String); - opts = Object.assign({glob: true}, opts); +module.exports = (iterable, options) => pTry(() => { + iterable = [...(typeof iterable === 'string' ? [iterable] : iterable)].map(String); - const paths = (opts.glob === false ? iterable : globby.sync(iterable, { + options = { + glob: true, + ...options + }; + + // TOOD: Upgrading to latest `globby` version is blocked by https://github.com/mrmlnc/fast-glob/issues/110 + const paths = (options.glob === false ? iterable : globby.sync(iterable, { expandDirectories: false, nodir: false, nonull: true })) - .map(x => path.resolve(x)) - .filter(x => { + .map(filePath => path.resolve(filePath)) + .filter(filePath => { try { - return fs.lstatSync(x); - } catch (err) { - if (err.code === 'ENOENT') { + return fs.lstatSync(filePath); + } catch (error) { + if (error.code === 'ENOENT') { return false; } - throw err; + throw error; } }); @@ -34,8 +39,11 @@ module.exports = (iterable, opts) => pTry(() => { } switch (process.platform) { - case 'darwin': return macos(paths); - case 'win32': return win(paths); - default: return linux(paths); + case 'darwin': + return macos(paths); + case 'win32': + return windows(paths); + default: + return linux(paths); } }); diff --git a/lib/linux.js b/lib/linux.js index 05352c7..5ff6ac2 100644 --- a/lib/linux.js +++ b/lib/linux.js @@ -1,33 +1,41 @@ 'use strict'; +const {promisify} = require('util'); const os = require('os'); const path = require('path'); -const fsExtra = require('fs-extra'); -const pify = require('pify'); +const fs = require('fs'); const uuid = require('uuid'); const xdgTrashdir = require('xdg-trashdir'); const pMap = require('p-map'); +const makeDir = require('make-dir'); +const moveFile = require('move-file'); -const fs = pify(fsExtra); +const pWriteFile = promisify(fs.writeFile); -function trash(src) { - return xdgTrashdir(src).then(dir => { - const name = uuid.v4(); - const dest = path.join(dir, 'files', name); - const info = path.join(dir, 'info', `${name}.trashinfo`); - const msg = ` +const trash = async filePath => { + const trashDirectory = await xdgTrashdir(filePath); + const name = uuid.v4(); + const destination = path.join(trashDirectory, 'files', name); + const trashInfoPath = path.join(trashDirectory, 'info', `${name}.trashinfo`); + + const trashInfoData = ` [Trash Info] -Path=${src.replace(/\s/g, '%20')} +Path=${filePath.replace(/\s/g, '%20')} DeletionDate=${(new Date()).toISOString()} `.trim(); - return Promise.all([ - fs.move(src, dest, {mkdirp: true}), - fs.outputFile(info, msg) - ]).then(() => ({ - path: dest, - info - })); - }); -} + await Promise.all([ + moveFile(filePath, destination), + (async () => { + // TODO: Use the `fs.mkdir` with `recursive` option when targeting Node.js 12. + await makeDir(path.dirname(trashInfoPath)); + await pWriteFile(trashInfoPath, trashInfoData); + })() + ]); + + return { + path: destination, + info: trashInfoPath + }; +}; module.exports = paths => pMap(paths, trash, {concurrency: os.cpus().length}); diff --git a/lib/macos.js b/lib/macos.js index 509581b..3933c81 100644 --- a/lib/macos.js +++ b/lib/macos.js @@ -1,39 +1,46 @@ 'use strict'; +const {promisify} = require('util'); const os = require('os'); const path = require('path'); -const execFile = require('child_process').execFile; +const {execFile} = require('child_process'); const escapeStringApplescript = require('escape-string-applescript'); const runApplescript = require('run-applescript'); -const pify = require('pify'); -const olderThanMountainLion = Number(os.release().split('.')[0]) < 12; +const isOlderThanMountainLion = Number(os.release().split('.')[0]) < 12; +const pExecFile = promisify(execFile); // Binary source: https://github.com/sindresorhus/macos-trash -const bin = path.join(__dirname, 'macos-trash'); +const binary = path.join(__dirname, 'macos-trash'); + +const legacy = async paths => { + const pathString = paths.map(x => `"${escapeStringApplescript(x)}"`).join(','); -function legacy(paths) { - const pathStr = paths.map(x => `"${escapeStringApplescript(x)}"`).join(','); const script = ` set deleteList to {} -repeat with currentPath in {${pathStr}} +repeat with currentPath in {${pathString}} set end of deleteList to POSIX file currentPath end repeat tell app "Finder" to delete deleteList - `.trim(); + `.trim(); + + try { + await runApplescript(script); + } catch (error) { + let newError = error; - return runApplescript(script).catch(err => { - if (/10010/.test(err.message)) { - err = new Error('Item doesn\'t exist'); + if (/10010/.test(newError.message)) { + newError = new Error('Item doesn\'t exist'); } - throw err; - }); -} + throw newError; + } +}; -module.exports = paths => { - if (olderThanMountainLion) { - return legacy(paths); +module.exports = async paths => { + if (isOlderThanMountainLion) { + await legacy(paths); + return; } - return pify(execFile)(bin, paths); + await pExecFile(binary, paths); }; diff --git a/lib/win.js b/lib/win.js deleted file mode 100644 index 8f157c1..0000000 --- a/lib/win.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -const path = require('path'); -const execFile = require('child_process').execFile; -const pify = require('pify'); - -// Binary source: https://github.com/sindresorhus/recycle-bin -const bin = path.join(__dirname, 'win-trash.exe'); - -module.exports = paths => pify(execFile)(bin, paths); diff --git a/lib/windows.js b/lib/windows.js new file mode 100644 index 0000000..5676714 --- /dev/null +++ b/lib/windows.js @@ -0,0 +1,13 @@ +'use strict'; +const {promisify} = require('util'); +const path = require('path'); +const {execFile} = require('child_process'); + +const pExecFile = promisify(execFile); + +// Binary source: https://github.com/sindresorhus/recycle-bin +const binary = path.join(__dirname, 'win-trash.exe'); + +module.exports = async paths => { + await pExecFile(binary, paths); +}; diff --git a/package.json b/package.json index 4dc60c5..f2d81e6 100644 --- a/package.json +++ b/package.json @@ -1,57 +1,57 @@ { - "name": "trash", - "version": "4.3.0", - "description": "Move files and folders to the trash", - "license": "MIT", - "repository": "sindresorhus/trash", - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "engines": { - "node": ">=4" - }, - "scripts": { - "test": "xo && ava" - }, - "files": [ - "index.js", - "lib" - ], - "keywords": [ - "trash", - "recycle", - "bin", - "rm", - "rmrf", - "rimraf", - "remove", - "delete", - "del", - "file", - "files", - "dir", - "directory", - "directories", - "folder", - "folders", - "xdg" - ], - "dependencies": { - "escape-string-applescript": "^2.0.0", - "fs-extra": "^0.30.0", - "globby": "^7.1.1", - "p-map": "^1.2.0", - "p-try": "^1.0.0", - "pify": "^3.0.0", - "run-applescript": "^3.0.0", - "uuid": "^3.1.0", - "xdg-trashdir": "^2.1.1" - }, - "devDependencies": { - "ava": "*", - "tempfile": "^2.0.0", - "xo": "*" - } + "name": "trash", + "version": "4.3.0", + "description": "Move files and folders to the trash", + "license": "MIT", + "repository": "sindresorhus/trash", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava" + }, + "files": [ + "index.js", + "lib" + ], + "keywords": [ + "trash", + "recycle", + "bin", + "rm", + "rmrf", + "rimraf", + "remove", + "delete", + "del", + "file", + "files", + "dir", + "directory", + "directories", + "folder", + "folders", + "xdg" + ], + "dependencies": { + "escape-string-applescript": "^2.0.0", + "globby": "^7.1.1", + "make-dir": "^1.3.0", + "move-file": "^1.0.0", + "p-map": "^2.0.0", + "p-try": "^2.0.0", + "run-applescript": "^3.0.0", + "uuid": "^3.1.0", + "xdg-trashdir": "^2.1.1" + }, + "devDependencies": { + "ava": "^1.0.0-rc.1", + "tempfile": "^2.0.0", + "xo": "^0.23.0" + } } diff --git a/readme.md b/readme.md index 0f5d277..cbf6b14 100644 --- a/readme.md +++ b/readme.md @@ -21,9 +21,9 @@ $ npm install trash ```js const trash = require('trash'); -trash(['*.png', '!rainbow.png']).then(() => { - console.log('done'); -}); +(async () => { + await trash(['*.png', '!rainbow.png']); +})(); ``` diff --git a/test.js b/test.js index f09ba45..138dae5 100644 --- a/test.js +++ b/test.js @@ -2,11 +2,11 @@ import fs from 'fs'; import path from 'path'; import test from 'ava'; import tempfile from 'tempfile'; -import m from '.'; +import trash from '.'; -const tmpdir = tempfile(); -fs.mkdirSync(tmpdir); -process.chdir(tmpdir); +const tempDirectory = tempfile(); +fs.mkdirSync(tempDirectory); +process.chdir(tempDirectory); test('files', async t => { const weirdName = process.platform === 'darwin' ? 'weird\\\\name\\"\'' : 'fixture3'; @@ -20,7 +20,7 @@ test('files', async t => { t.true(fs.existsSync(weirdName)); t.true(fs.existsSync('123')); - await m([ + await trash([ 'fixture', 'fixture2', weirdName, @@ -39,7 +39,7 @@ test('glob', async t => { t.true(fs.existsSync('fixture.jpg')); t.true(fs.existsSync('fixture.png')); - await m([ + await trash([ '*.jpg' ]); @@ -51,7 +51,7 @@ test('no glob', async t => { fs.writeFileSync('fixture-noglob*.js', ''); fs.writeFileSync('fixture-noglob1.js', ''); - await m(['fixture-noglob*.js'], {glob: false}); + await trash(['fixture-noglob*.js'], {glob: false}); t.false(fs.existsSync('fixture-noglob*.js')); t.true(fs.existsSync('fixture-noglob1.js')); @@ -65,9 +65,7 @@ test('string pattern', async t => { t.true(fs.existsSync('b')); t.true(fs.existsSync('ab')); - await m( - 'ab' - ); + await trash('ab'); t.false(fs.existsSync('ab')); t.true(fs.existsSync('a')); @@ -92,7 +90,7 @@ test('directories', async t => { t.true(fs.existsSync(d2f1)); t.true(fs.existsSync(d2f2)); - await m([ + await trash([ 'fdir', 321 ]); @@ -109,7 +107,7 @@ test('directories', async t => { fs.writeFileSync('file' + i, ''); } - await t.notThrows(m(paths)); + await t.notThrowsAsync(trash(paths)); for (let i = 0; i < FILE_COUNT; i++) { t.false(fs.existsSync('file' + i)); @@ -125,7 +123,7 @@ test('symlinks', async t => { t.truthy(fs.lstatSync('bbb')); t.truthy(fs.lstatSync('ccc')); - await m([ + await trash([ 'bbb', 'ccc' ]); @@ -142,7 +140,7 @@ if (process.platform === 'linux') { fs.writeFileSync('f2', ''); const info = `[Trash Info]\nPath=${path.resolve('f2')}`; - const files = await m(['f2']); + const files = await trash(['f2']); const infoFile = fs.readFileSync(files[0].info, 'utf8'); t.is(infoFile.trim().indexOf(info.trim()), 0); @@ -154,7 +152,7 @@ if (process.platform === 'linux') { fs.writeFileSync('f3', ''); const statSrc = fs.statSync('f3'); - const files = await m(['f3']); + const files = await trash(['f3']); const statDest = fs.statSync(files[0].path); t.is(statSrc.mode, statDest.mode); @@ -166,5 +164,5 @@ if (process.platform === 'linux') { test('non-existent files', async t => { t.false(fs.existsSync('fixture-enoent')); - await t.notThrows(m('fixture-enoent')); + await t.notThrowsAsync(trash('fixture-enoent')); });