Skip to content

Commit d39573b

Browse files
committed
fix: only run git add on staged files matched to a task
# Conflicts: # lib/gitWorkflow.js
1 parent a85c7b5 commit d39573b

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

lib/gitWorkflow.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const debug = require('debug')('lint-staged:git')
44
const path = require('path')
55

6+
const chunkFiles = require('./chunkFiles')
67
const execGit = require('./execGit')
78
const { readFile, unlink, writeFile } = require('./file')
89

@@ -52,14 +53,15 @@ const handleError = (error, ctx) => {
5253
}
5354

5455
class GitWorkflow {
55-
constructor({ allowEmpty, gitConfigDir, gitDir, stagedFileChunks }) {
56+
constructor({ allowEmpty, gitConfigDir, gitDir, matchedFiles, maxArgLength }) {
5657
this.execGit = (args, options = {}) => execGit(args, { ...options, cwd: gitDir })
5758
this.deletedFiles = []
5859
this.gitConfigDir = gitConfigDir
5960
this.gitDir = gitDir
6061
this.unstagedDiff = null
6162
this.allowEmpty = allowEmpty
62-
this.stagedFileChunks = stagedFileChunks
63+
this.matchedFiles = matchedFiles
64+
this.maxArgLength = maxArgLength
6365

6466
/**
6567
* These three files hold state about an ongoing git merge
@@ -235,12 +237,22 @@ class GitWorkflow {
235237
*/
236238
async applyModifications(ctx) {
237239
debug('Adding task modifications to index...')
238-
// stagedFileChunks includes staged files that lint-staged originally detected.
240+
// `matchedFiles` includes staged files that lint-staged originally detected and matched against a task.
239241
// Add only these files so any 3rd-party edits to other files won't be included in the commit.
240-
// This is run "serially" to prevent race conditions because `git add` is a locking operation.
241-
for (const stagedFiles of this.stagedFileChunks) {
242-
await this.execGit(['add', '--', ...stagedFiles])
242+
const files = Array.from(this.matchedFiles)
243+
// Chunk files for better Windows compatibility
244+
const matchedFileChunks = chunkFiles({
245+
baseDir: this.gitDir,
246+
files,
247+
maxArgLength: this.maxArgLength
248+
})
249+
250+
// These additions per chunk are run "serially" to prevent race conditions.
251+
// Git add creates a lockfile in the repo causing concurrent operations to fail.
252+
for (const files of matchedFileChunks) {
253+
await this.execGit(['add', '--', ...files])
243254
}
255+
244256
debug('Done adding task modifications to index!')
245257

246258
const stagedFilesAfterAdd = await this.execGit(['diff', '--name-only', '--cached'])

lib/runAll.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ const runAll = async (
125125

126126
const listrTasks = []
127127

128+
// Set of all staged files that matched a task glob. Values in a set are unique.
129+
const matchedFiles = new Set()
130+
128131
for (const [index, files] of stagedFileChunks.entries()) {
129132
const chunkTasks = generateTasks({ config, cwd, gitDir, files, relative })
130133
const chunkListrTasks = []
@@ -137,6 +140,11 @@ const runAll = async (
137140
shell
138141
})
139142

143+
// Add files from task to match set
144+
task.fileList.forEach(file => {
145+
matchedFiles.add(file)
146+
})
147+
140148
hasDeprecatedGitAdd = subTasks.some(subTask => subTask.command === 'git add')
141149

142150
chunkListrTasks.push({
@@ -188,7 +196,7 @@ const runAll = async (
188196
return 'No tasks to run.'
189197
}
190198

191-
const git = new GitWorkflow({ allowEmpty, gitConfigDir, gitDir, stagedFileChunks })
199+
const git = new GitWorkflow({ allowEmpty, gitConfigDir, gitDir, matchedFiles, maxArgLength })
192200

193201
const runner = new Listr(
194202
[

0 commit comments

Comments
 (0)