From 86c9ed2bde1245a702635b42a57b92b809340b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iiro=20J=C3=A4ppinen?= Date: Wed, 17 Jun 2020 13:02:01 +0300 Subject: [PATCH] fix: run all git commands with submodule.recurse=false (#888) This explicitly prevents git commands from recursing into git submodules and thus causing issues with commands like stash or reset. --- lib/execGit.js | 13 ++++++++++++- test/execGit.spec.js | 22 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/execGit.js b/lib/execGit.js index 8597e6c5f..7fb8ef198 100644 --- a/lib/execGit.js +++ b/lib/execGit.js @@ -3,10 +3,18 @@ const debug = require('debug')('lint-staged:git') const execa = require('execa') +/** + * Explicitly never recurse commands into submodules, overriding local/global configuration. + * @see https://git-scm.com/docs/git-config#Documentation/git-config.txt-submodulerecurse + */ +const NO_SUBMODULE_RECURSE = ['-c', 'submodule.recurse=false'] + +const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE] + module.exports = async function execGit(cmd, options = {}) { debug('Running git command', cmd) try { - const { stdout } = await execa('git', [].concat(cmd), { + const { stdout } = await execa('git', GIT_GLOBAL_OPTIONS.concat(cmd), { ...options, all: true, cwd: options.cwd || process.cwd(), @@ -16,3 +24,6 @@ module.exports = async function execGit(cmd, options = {}) { throw new Error(all) } } + +// exported for tests +module.exports.GIT_GLOBAL_OPTIONS = GIT_GLOBAL_OPTIONS diff --git a/test/execGit.spec.js b/test/execGit.spec.js index ac84f60d5..7990ab91e 100644 --- a/test/execGit.spec.js +++ b/test/execGit.spec.js @@ -1,17 +1,33 @@ import path from 'path' import execa from 'execa' -import execGit from '../lib/execGit' + +import execGit, { GIT_GLOBAL_OPTIONS } from '../lib/execGit' + +test('GIT_GLOBAL_OPTIONS', () => { + expect(GIT_GLOBAL_OPTIONS).toMatchInlineSnapshot(` + Array [ + "-c", + "submodule.recurse=false", + ] + `) +}) describe('execGit', () => { it('should execute git in process.cwd if working copy is not specified', async () => { const cwd = process.cwd() await execGit(['init', 'param']) - expect(execa).toHaveBeenCalledWith('git', ['init', 'param'], { all: true, cwd }) + expect(execa).toHaveBeenCalledWith('git', [...GIT_GLOBAL_OPTIONS, 'init', 'param'], { + all: true, + cwd, + }) }) it('should execute git in a given working copy', async () => { const cwd = path.join(process.cwd(), 'test', '__fixtures__') await execGit(['init', 'param'], { cwd }) - expect(execa).toHaveBeenCalledWith('git', ['init', 'param'], { all: true, cwd }) + expect(execa).toHaveBeenCalledWith('git', [...GIT_GLOBAL_OPTIONS, 'init', 'param'], { + all: true, + cwd, + }) }) })