diff --git a/package.json b/package.json index 7df2ba07c..465619557 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "micromatch": "^4.0.2", "normalize-path": "^3.0.0", "please-upgrade-node": "^3.1.1", - "string-argv": "^0.3.0", "stringify-object": "^3.3.0" }, "devDependencies": { diff --git a/src/resolveTaskFn.js b/src/resolveTaskFn.js index 33eafbef6..39d999629 100644 --- a/src/resolveTaskFn.js +++ b/src/resolveTaskFn.js @@ -4,27 +4,9 @@ const chalk = require('chalk') const dedent = require('dedent') const execa = require('execa') const symbols = require('log-symbols') -const stringArgv = require('string-argv') const debug = require('debug')('lint-staged:task') -/** - * Execute the given linter cmd using execa and - * return the promise. - * - * @param {string} cmd - * @param {Array} args - * @param {Object} execaOptions - * @return {Promise} child_process - */ -const execLinter = (cmd, args, execaOptions) => { - debug('cmd:', cmd) - if (args) debug('args:', args) - debug('execaOptions:', execaOptions) - - return args ? execa(cmd, args, execaOptions) : execa(cmd, execaOptions) -} - const successMsg = linter => `${symbols.success} ${linter} passed!` /** @@ -73,21 +55,22 @@ function makeErr(linter, result, context = {}) { } /** - * Returns the task function for the linter. It handles chunking for file paths - * if the OS is Windows. + * Returns the task function for the linter. * * @param {Object} options * @param {string} options.command — Linter task * @param {String} options.gitDir - Current git repo path * @param {Boolean} options.isFn - Whether the linter task is a function - * @param {Array} options.pathsToLint — Filepaths to run the linter task against + * @param {Array} options.files — Filepaths to run the linter task against * @param {Boolean} [options.relative] — Whether the filepaths should be relative * @param {Boolean} [options.shell] — Whether to skip parsing linter task for better shell support * @returns {function(): Promise>} */ module.exports = function resolveTaskFn({ command, files, gitDir, isFn, relative, shell = false }) { - const execaOptions = { preferLocal: true, reject: false, shell } + const cmd = isFn ? command : `${command} ${files.join(' ')}` + debug('cmd:', cmd) + const execaOptions = { preferLocal: true, reject: false, shell } if (relative) { execaOptions.cwd = process.cwd() } else if (/^git(\.exe)?/i.test(command) && gitDir !== process.cwd()) { @@ -95,27 +78,15 @@ module.exports = function resolveTaskFn({ command, files, gitDir, isFn, relative // e.g `npm` should run tasks in the actual CWD execaOptions.cwd = gitDir } + debug('execaOptions:', execaOptions) - let cmd - let args - - if (shell) { - execaOptions.shell = true - // If `shell`, passed command shouldn't be parsed - // If `linter` is a function, command already includes `files`. - cmd = isFn ? command : `${command} ${files.join(' ')}` - } else { - const [parsedCmd, ...parsedArgs] = stringArgv.parseArgsStringToArgv(command) - cmd = parsedCmd - args = isFn ? parsedArgs : parsedArgs.concat(files) - } + return async ctx => { + const result = await execa.command(cmd, execaOptions) - return ctx => - execLinter(cmd, args, execaOptions).then(result => { - if (result.failed || result.killed || result.signal != null) { - throw makeErr(command, result, ctx) - } + if (result.failed || result.killed || result.signal != null) { + throw makeErr(command, result, ctx) + } - return successMsg(command) - }) + return successMsg(command) + } } diff --git a/test/__mocks__/execa.js b/test/__mocks__/execa.js index 9b5606b6a..52bc88fd7 100644 --- a/test/__mocks__/execa.js +++ b/test/__mocks__/execa.js @@ -1,4 +1,4 @@ -module.exports = jest.fn(() => +const execa = jest.fn(() => Promise.resolve({ stdout: 'a-ok', stderr: '', @@ -9,3 +9,7 @@ module.exports = jest.fn(() => signal: null }) ) + +execa.command = execa + +module.exports = execa diff --git a/test/index.spec.js b/test/index.spec.js index 6d2e3c243..880c1b9a6 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -161,7 +161,7 @@ describe('lintStaged', () => { } mockCosmiconfigWith({ config }) getStagedFiles.mockImplementationOnce(async () => ['sample.java']) - const passed = await lintStaged({ quiet: true }, logger) + const passed = await lintStaged({ quiet: true, shell: true }, logger) expect(logger.printHistory()).toMatchSnapshot() expect(passed).toBe(false) }) diff --git a/test/makeCmdTasks.spec.js b/test/makeCmdTasks.spec.js index 284700aae..9caf1893e 100644 --- a/test/makeCmdTasks.spec.js +++ b/test/makeCmdTasks.spec.js @@ -41,7 +41,7 @@ describe('makeCmdTasks', () => { expect(taskPromise).toBeInstanceOf(Promise) await taskPromise expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('test', ['test.js'], { + expect(execa).lastCalledWith('test test.js', { preferLocal: true, reject: false, shell: false @@ -50,7 +50,7 @@ describe('makeCmdTasks', () => { expect(taskPromise).toBeInstanceOf(Promise) await taskPromise expect(execa).toHaveBeenCalledTimes(2) - expect(execa).lastCalledWith('test2', ['test.js'], { + expect(execa).lastCalledWith('test2 test.js', { preferLocal: true, reject: false, shell: false diff --git a/test/resolveTaskFn.spec.js b/test/resolveTaskFn.spec.js index 9b5696670..7ad1a890b 100644 --- a/test/resolveTaskFn.spec.js +++ b/test/resolveTaskFn.spec.js @@ -17,7 +17,7 @@ describe('resolveTaskFn', () => { await taskFn() expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('node', ['--arg=true', './myscript.js', 'test.js'], { + expect(execa).lastCalledWith('node --arg=true ./myscript.js test.js', { preferLocal: true, reject: false, shell: false @@ -34,7 +34,7 @@ describe('resolveTaskFn', () => { await taskFn() expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('node', ['--arg=true', './myscript.js', 'test.js'], { + expect(execa).lastCalledWith('node --arg=true ./myscript.js test.js', { preferLocal: true, reject: false, shell: false @@ -86,7 +86,7 @@ describe('resolveTaskFn', () => { await taskFn() expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('git', ['add', 'test.js'], { + expect(execa).lastCalledWith('git add test.js', { cwd: '../', preferLocal: true, reject: false, @@ -100,7 +100,7 @@ describe('resolveTaskFn', () => { await taskFn() expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('jest', ['test.js'], { + expect(execa).lastCalledWith('jest test.js', { preferLocal: true, reject: false, shell: false @@ -117,7 +117,7 @@ describe('resolveTaskFn', () => { await taskFn() expect(execa).toHaveBeenCalledTimes(1) - expect(execa).lastCalledWith('git', ['add', 'test.js'], { + expect(execa).lastCalledWith('git add test.js', { cwd: process.cwd(), preferLocal: true, reject: false, diff --git a/yarn.lock b/yarn.lock index dc539b1db..23cac436e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5463,11 +5463,6 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -string-argv@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.0.tgz#0ea99e7257fea5e97a1bfcdfc19cf12d68e6ec6a" - integrity sha512-NGZHq3nkSXVtGZXTBjFru3MNfoZyIzN25T7BmvdgnSC0LCJczAGLLMQLyjywSIaAoqSemgLzBRHOsnrHbt60+Q== - string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"