lint-staged 17.0.7 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,12 +2,15 @@ import crypto from 'node:crypto'
2
2
  import fs from 'node:fs/promises'
3
3
  import path from 'node:path'
4
4
 
5
+ import { dim } from './colors.js'
5
6
  import { createDebug } from './debug.js'
6
7
  import { execGit } from './execGit.js'
8
+ import * as figures from './figures.js'
7
9
  import { readFile, unlink, writeFile } from './file.js'
8
10
  import { getDiffCommand } from './getDiffCommand.js'
9
11
  import { normalizePath } from './normalizePath.js'
10
12
  import { parseGitZOutput } from './parseGitZOutput.js'
13
+ import { runParallelTasks } from './runParallelTasks.js'
11
14
  import {
12
15
  ApplyEmptyCommitError,
13
16
  FailOnChangesError,
@@ -17,6 +20,7 @@ import {
17
20
  RestoreMergeStatusError,
18
21
  RestoreOriginalStateError,
19
22
  RestoreUnstagedChangesError,
23
+ TaskError,
20
24
  } from './symbols.js'
21
25
 
22
26
  const debugLog = createDebug('lint-staged:GitWorkflow')
@@ -27,7 +31,7 @@ const MERGE_MSG = 'MERGE_MSG'
27
31
 
28
32
  // In git status machine output, renames are presented as `to`NUL`from`
29
33
  // When diffing, both need to be taken into account, but in some cases on the `to`.
30
- // eslint-disable-next-line no-control-regex
34
+ // oxlint-disable-next-line no-control-regex
31
35
  const RENAME = /\x00/
32
36
 
33
37
  /**
@@ -63,12 +67,6 @@ const GIT_DIFF_ARGS = [
63
67
  ]
64
68
  const GIT_APPLY_ARGS = ['-v', '--whitespace=nowarn', '--recount', '--unidiff-zero']
65
69
 
66
- const handleError = (error, ctx, symbol) => {
67
- ctx.errors.add(GitError)
68
- if (symbol) ctx.errors.add(symbol)
69
- throw error
70
- }
71
-
72
70
  const calculateSha256 = (input) => crypto.createHash('sha256').update(input, 'utf-8').digest('hex')
73
71
 
74
72
  /**
@@ -87,6 +85,7 @@ export class GitWorkflow {
87
85
  diffFilter,
88
86
  failOnChanges,
89
87
  gitConfigDir,
88
+ logger,
90
89
  matchedFileChunks,
91
90
  topLevelDir,
92
91
  }) {
@@ -96,6 +95,7 @@ export class GitWorkflow {
96
95
  this.diffFilter = diffFilter
97
96
  this.gitConfigDir = gitConfigDir
98
97
  this.failOnChanges = !!failOnChanges
98
+ this.logger = logger
99
99
  /** @type {import('./getStagedFiles.js').StagedFile[][]} */
100
100
  this.matchedFileChunks = matchedFileChunks
101
101
  this.topLevelDir = topLevelDir
@@ -130,6 +130,7 @@ export class GitWorkflow {
130
130
 
131
131
  if (index === -1) {
132
132
  ctx.errors.add(GetBackupStashError)
133
+ this.logger.error(`${figures.error()} lint-staged automatic backup is missing!`)
133
134
  throw new Error('lint-staged automatic backup is missing!')
134
135
  }
135
136
 
@@ -162,13 +163,13 @@ export class GitWorkflow {
162
163
  ])
163
164
  debugLog('Done restoring merge state!')
164
165
  } catch (error) {
166
+ ctx.errors.add(GitError)
167
+ ctx.errors.add(RestoreMergeStatusError)
168
+
165
169
  debugLog('Failed restoring merge state with error:')
166
170
  debugLog(error)
167
- handleError(
168
- new Error('Merge state could not be restored due to an error!'),
169
- ctx,
170
- RestoreMergeStatusError
171
- )
171
+
172
+ throw error
172
173
  }
173
174
  }
174
175
 
@@ -190,7 +191,7 @@ export class GitWorkflow {
190
191
  * (e.g. `to`\0`from`)
191
192
  */
192
193
  const unstagedFiles = status
193
- // eslint-disable-next-line no-control-regex
194
+ // oxlint-disable-next-line no-control-regex
194
195
  .split(/\x00(?=[ AMDRCU?!]{2} |$)/)
195
196
  .filter((line) => {
196
197
  const [index, workingTree] = line
@@ -212,10 +213,14 @@ export class GitWorkflow {
212
213
  /**
213
214
  * Create a diff of unstaged or partially staged files and backup stash if enabled.
214
215
  */
215
- async prepare(ctx, task) {
216
- try {
217
- debugLog(task.title)
216
+ async prepare(ctx) {
217
+ this.logger.log(
218
+ dim(
219
+ `${figures.wip()} ${ctx.shouldBackup ? 'Backing up original state…' : 'Preparing lint-staged…'}`
220
+ )
221
+ )
218
222
 
223
+ try {
219
224
  if (ctx.shouldBackup) {
220
225
  // When backup is enabled, the revert will clear ongoing merge status.
221
226
  await this.backupMergeStatus()
@@ -249,120 +254,183 @@ export class GitWorkflow {
249
254
 
250
255
  /** The stash line starts with the short hash, so we split from space and choose the first part */
251
256
  ctx.backupHash = stashes.find((line) => line.includes(STASH))?.split(' ')[0]
257
+
258
+ await this.restoreMergeStatus(ctx)
252
259
  } else {
253
260
  /** Save stash of all changes, keeping all files as-is */
254
261
  const stashHash = await this.execGit(['stash', 'create'])
255
262
  ctx.backupHash = await this.execGit(['rev-parse', '--short', stashHash])
256
263
  await this.execGit(['stash', 'store', '--quiet', '--message', STASH, ctx.backupHash])
257
264
  }
258
-
259
- task.title = `Backed up original state in git stash (${ctx.backupHash})`
260
- debugLog(task.title)
261
265
  }
266
+
267
+ this.logger.log(
268
+ `${figures.done()} ${
269
+ ctx.shouldBackup
270
+ ? `Done backing up original state (${ctx.backupHash})!`
271
+ : 'Done preparing lint-staged!'
272
+ }`
273
+ )
262
274
  } catch (error) {
263
- handleError(error, ctx)
275
+ ctx.errors.add(GitError)
276
+
277
+ const errorMessage = ctx.shouldBackup
278
+ ? 'Failed to back up original state!'
279
+ : 'Failed to prepare lint-staged!'
280
+
281
+ this.logger.error(`${figures.error()} ${errorMessage}`)
282
+ debugLog(error)
264
283
  }
265
284
  }
266
285
 
267
286
  async hidePartiallyStagedChanges(ctx) {
287
+ this.logger.log(dim(`${figures.wip()} Hiding unstaged changes to partially staged files…`))
288
+
268
289
  try {
269
290
  const files = processRenames(this.unstagedFiles, false)
270
291
  await this.execGit(['restore', '--worktree', '--', ...files])
292
+ this.logger.log(`${figures.done()} Done hiding unstaged changes to partially staged files!`)
271
293
  } catch (error) {
272
294
  /**
273
295
  * `git checkout --force` doesn't throw errors, so it shouldn't be possible to get here.
274
- * If this does fail, the handleError method will set ctx.gitError and lint-staged will fail.
275
296
  */
276
- handleError(error, ctx, HideUnstagedChangesError)
277
- }
278
- }
297
+ ctx.errors.add(GitError)
298
+ ctx.errors.add(HideUnstagedChangesError)
279
299
 
280
- async runTasks(ctx, task, { listrTasks, concurrent }) {
281
- if (ctx.shouldFailOnChanges) {
282
- debugLog(
283
- 'Calculating SHA-256 hash of unstaged changes because "--fail-on-changes" was used...'
284
- )
285
- const diff = await this.execGit(['diff', '--patch', '--unified=0'])
286
- ctx.unstagedDiffSha256 = calculateSha256(diff)
287
- debugLog('SHA-256 hash of unstaged changes is %s', ctx.unstagedDiffSha256)
288
- }
300
+ const errorMessage = `${figures.error()} Failed to hude unstaged changes to partially staged files!`
289
301
 
290
- return task.newListr(listrTasks, { concurrent })
302
+ this.logger.error(errorMessage)
303
+ debugLog(error)
304
+ }
291
305
  }
292
306
 
293
- /** Update Git index again for the originally staged files to stage task modifications. */
294
- async updateIndex(ctx) {
307
+ async runTasks(ctx, tasks, { abortController, concurrent }) {
308
+ this.logger.log(
309
+ dim(`${figures.wip()} Running tasks for ${this.diff ? 'changed' : 'staged'} files…`)
310
+ )
311
+
295
312
  if (ctx.shouldFailOnChanges) {
296
- debugLog(
297
- 'Calculating SHA-256 hash of changes after tasks because "--fail-on-changes" was used...'
298
- )
299
- const diff = await this.execGit(['diff', '--patch', '--unified=0'])
300
- const diffSha256 = calculateSha256(diff)
301
- debugLog('SHA-256 hash of changes after tasks is %s', diffSha256)
302
- if (ctx.unstagedDiffSha256 !== diffSha256) {
303
- ctx.errors.add(FailOnChangesError)
304
- throw new Error('Tasks modified files and --fail-on-changes was used!')
313
+ try {
314
+ debugLog(
315
+ 'Calculating SHA-256 hash of unstaged changes because "--fail-on-changes" was used...'
316
+ )
317
+ const diff = await this.execGit(['diff', '--patch', '--unified=0'])
318
+ ctx.unstagedDiffSha256 = calculateSha256(diff)
319
+ debugLog('SHA-256 hash of unstaged changes is %s', ctx.unstagedDiffSha256)
320
+ } catch (error) {
321
+ ctx.errors.add(GitError)
322
+ this.logger.error('Failed to calculate SHA-256 hash of unstaged changes!')
323
+ debugLog(error)
324
+ return
305
325
  }
306
326
  }
307
327
 
308
- // This looks confusing but the intent is to only normalize truthy values
309
- const activeIndexFile = process.env.GIT_INDEX_FILE
310
- ? normalizePath(process.env.GIT_INDEX_FILE)
311
- : process.env.GIT_INDEX_FILE
312
-
313
- /** Needs to be run serially because of locking Git operation */
314
- for (const files of this.matchedFileChunks) {
315
- const accessCheckedFiles = await Promise.allSettled(
316
- files.map(async (f) => {
317
- if (f.status === 'D') {
318
- await fs.access(f.filepath)
319
- return f.filepath // File is no longer deleted and can be added
320
- } else {
321
- return f.filepath
322
- }
323
- })
324
- )
328
+ const failureMessage = `${figures.error()} Failed to run tasks for ${this.diff ? 'changed' : 'staged'} files!`
325
329
 
326
- const addableFiles = accessCheckedFiles.flatMap((r) =>
327
- r.status === 'fulfilled' ? [r.value] : []
330
+ try {
331
+ await runParallelTasks(ctx, tasks, { abortController, concurrent, logger: this.logger })
332
+
333
+ this.logger.log(
334
+ ctx.errors.has(TaskError)
335
+ ? failureMessage
336
+ : `${figures.done()} Done running tasks for ${this.diff ? 'changed' : 'staged'} files!`
328
337
  )
338
+ } catch (error) {
339
+ ctx.errors.add(TaskError)
340
+ this.logger.error(failureMessage)
341
+ debugLog(error)
342
+ }
343
+ }
329
344
 
330
- debugLog('Updating active Git index: %s', activeIndexFile)
331
- await this.execGit(['add', '--', ...addableFiles])
332
- debugLog('Done updating Git index: %s', activeIndexFile)
345
+ /** Update Git index again for the originally staged files to stage task modifications. */
346
+ async updateIndex(ctx) {
347
+ this.logger.log(dim(`${figures.wip()} Staging changes from tasks…`))
333
348
 
334
- if (activeIndexFile?.endsWith('.lock')) {
335
- const defaultIndexLock = normalizePath(
336
- await this.execGit(['rev-parse', '--path-format=absolute', '--git-path', 'index.lock'])
349
+ try {
350
+ if (ctx.shouldFailOnChanges) {
351
+ debugLog(
352
+ 'Calculating SHA-256 hash of changes after tasks because "--fail-on-changes" was used...'
337
353
  )
354
+ const diff = await this.execGit(['diff', '--patch', '--unified=0'])
355
+ const diffSha256 = calculateSha256(diff)
356
+ debugLog('SHA-256 hash of changes after tasks is %s', diffSha256)
357
+
358
+ if (ctx.unstagedDiffSha256 !== diffSha256) {
359
+ ctx.errors.add(FailOnChangesError)
360
+ this.logger.error(
361
+ `${figures.error()} Tasks modified files and --fail-on-changes was used!`
362
+ )
363
+ return
364
+ }
365
+ }
338
366
 
339
- /**
340
- * If the active index file is a non-default lockfile, we are committing with a pathspec
341
- * without having explicitly run `git add`. In this case we need to also update the
342
- * default index, otherwise there will be leftover diff after committing
343
- */
344
- if (activeIndexFile !== defaultIndexLock) {
345
- debugLog('Updating default Git index again: %s', defaultIndexLock)
346
- await this.execGit(['add', '--', ...addableFiles], {
347
- env: {
348
- GIT_INDEX_FILE: defaultIndexLock,
349
- },
367
+ // This looks confusing but the intent is to only normalize truthy values
368
+ const activeIndexFile = process.env.GIT_INDEX_FILE
369
+ ? normalizePath(process.env.GIT_INDEX_FILE)
370
+ : process.env.GIT_INDEX_FILE
371
+
372
+ /** Needs to be run serially because of locking Git operation */
373
+ for (const files of this.matchedFileChunks) {
374
+ const accessCheckedFiles = await Promise.allSettled(
375
+ files.map(async (f) => {
376
+ if (f.status === 'D') {
377
+ await fs.access(f.filepath)
378
+ return f.filepath // File is no longer deleted and can be added
379
+ } else {
380
+ return f.filepath
381
+ }
350
382
  })
351
- debugLog('Done updating default Git index lock: %s', defaultIndexLock)
383
+ )
384
+
385
+ const addableFiles = accessCheckedFiles.flatMap((r) =>
386
+ r.status === 'fulfilled' ? [r.value] : []
387
+ )
388
+
389
+ debugLog('Updating active Git index: %s', activeIndexFile)
390
+ await this.execGit(['add', '--', ...addableFiles])
391
+ debugLog('Done updating Git index: %s', activeIndexFile)
392
+
393
+ if (activeIndexFile?.endsWith('.lock')) {
394
+ const defaultIndexLock = normalizePath(
395
+ await this.execGit(['rev-parse', '--path-format=absolute', '--git-path', 'index.lock'])
396
+ )
397
+
398
+ /**
399
+ * If the active index file is a non-default lockfile, we are committing with a pathspec
400
+ * without having explicitly run `git add`. In this case we need to also update the
401
+ * default index, otherwise there will be leftover diff after committing
402
+ */
403
+ if (activeIndexFile !== defaultIndexLock) {
404
+ debugLog('Updating default Git index again: %s', defaultIndexLock)
405
+ await this.execGit(['add', '--', ...addableFiles], {
406
+ env: {
407
+ GIT_INDEX_FILE: defaultIndexLock,
408
+ },
409
+ })
410
+ debugLog('Done updating default Git index lock: %s', defaultIndexLock)
411
+ }
352
412
  }
353
413
  }
354
- }
355
414
 
356
- const stagedFilesAfterAdd = await this.execGit([
357
- ...getDiffCommand(this.diff, this.diffFilter),
358
- '--name-only',
359
- '-z',
360
- ])
415
+ const stagedFilesAfterAdd = await this.execGit([
416
+ ...getDiffCommand(this.diff, this.diffFilter),
417
+ '--name-only',
418
+ '-z',
419
+ ])
361
420
 
362
- if (!stagedFilesAfterAdd && !this.allowEmpty) {
363
- // Tasks reverted all staged changes and the commit would be empty
364
- // Throw error to stop commit unless `--allow-empty` was used
365
- handleError(new Error('Prevented an empty git commit!'), ctx, ApplyEmptyCommitError)
421
+ if (!stagedFilesAfterAdd && !this.allowEmpty) {
422
+ // Tasks reverted all staged changes and the commit would be empty
423
+ // Stop commit unless `--allow-empty` was used
424
+ ctx.errors.add(ApplyEmptyCommitError)
425
+ this.logger.error(`${figures.error()} Prevented an empty git commit!`)
426
+ } else {
427
+ this.logger.log(`${figures.done()} Done staging changes from tasks!`)
428
+ }
429
+ } catch (error) {
430
+ ctx.errors.add(GitError)
431
+
432
+ this.logger.log(`${figures.error()} Failed to stage changes from tasks!`)
433
+ debugLog(error)
366
434
  }
367
435
  }
368
436
 
@@ -372,8 +440,10 @@ export class GitWorkflow {
372
440
  * 3-way merge usually fixes this, and in case it doesn't we should just give up and throw.
373
441
  */
374
442
  async restoreUnstagedChanges(ctx) {
375
- debugLog('Restoring unstaged changes...')
443
+ this.logger.log(dim(`${figures.wip()} Restoring unstaged changes…`))
444
+
376
445
  const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
446
+
377
447
  try {
378
448
  await this.execGit(['apply', ...GIT_APPLY_ARGS, unstagedPatch])
379
449
  } catch (applyError) {
@@ -384,20 +454,19 @@ export class GitWorkflow {
384
454
  try {
385
455
  await this.execGit(['apply', ...GIT_APPLY_ARGS, '--3way', unstagedPatch])
386
456
  } catch (threeWayApplyError) {
387
- debugLog('Error while restoring unstaged changes using 3-way merge:')
457
+ ctx.errors.add(GitError)
458
+ ctx.errors.add(RestoreUnstagedChangesError)
459
+
460
+ this.logger.error(`${figures.error()} Failed to restore unstaged changes!`)
388
461
  debugLog(threeWayApplyError)
389
- handleError(
390
- new Error('Unstaged changes could not be restored due to a merge conflict!'),
391
- ctx,
392
- RestoreUnstagedChangesError
393
- )
394
462
  }
395
463
  }
396
464
  }
397
465
 
398
466
  async restoreUntrackedFiles(ctx) {
467
+ this.logger.log(dim(`${figures.wip()} Restoring untracked files…`))
468
+
399
469
  try {
400
- debugLog('Restoring untracked files...')
401
470
  const backupStash = await this.getBackupStash(ctx)
402
471
  const untrackedFiles = await this.execGit([
403
472
  'stash',
@@ -417,17 +486,17 @@ export class GitWorkflow {
417
486
  '--',
418
487
  ...untrackedFiles.map(normalizePath),
419
488
  ])
489
+
490
+ this.logger.log(`${figures.done()} ${'Done restoring untracked files!'}`)
420
491
  } else {
421
- debugLog('No untracked files to restore!')
492
+ this.logger.log(`${figures.cancelled()} ${dim('No untracked files to restore!')}`)
422
493
  }
423
494
  } catch (restoreUntrackedFilesError) {
424
- debugLog('Error while restoring untracked files:')
495
+ ctx.errors.add(GitError)
496
+ ctx.errors.add(RestoreUnstagedChangesError)
497
+
498
+ this.logger.error(`${figures.error()} ${'Failed to restore untracked files!'}`)
425
499
  debugLog(restoreUntrackedFilesError)
426
- handleError(
427
- new Error('Untracked files could not be restored!'),
428
- ctx,
429
- RestoreUnstagedChangesError
430
- )
431
500
  }
432
501
  }
433
502
 
@@ -435,20 +504,25 @@ export class GitWorkflow {
435
504
  * Restore original HEAD state in case of errors
436
505
  */
437
506
  async restoreOriginalState(ctx) {
507
+ this.logger.log(dim(`${figures.wip()} Reverting to original state because of errors…`))
508
+
438
509
  try {
439
510
  debugLog('Restoring original state...')
440
511
  await this.execGit(['reset', '--hard', 'HEAD'])
441
512
  await this.execGit(['stash', 'apply', '--quiet', '--index', await this.getBackupStash(ctx)])
442
513
 
443
- // Restore meta information about ongoing git merge
444
514
  await this.restoreMergeStatus(ctx)
445
515
 
446
516
  // Clean out patch
447
517
  await unlink(this.getHiddenFilepath(PATCH_UNSTAGED))
448
518
 
449
- debugLog('Done restoring original state!')
519
+ this.logger.log(`${figures.done()} Done reverting to original state!`)
450
520
  } catch (error) {
451
- handleError(error, ctx, RestoreOriginalStateError)
521
+ ctx.errors.add(GitError)
522
+ ctx.errors.add(RestoreOriginalStateError)
523
+
524
+ this.logger.error(`${figures.error()} Failed to revert to original state!`)
525
+ debugLog(error)
452
526
  }
453
527
  }
454
528
 
@@ -456,12 +530,15 @@ export class GitWorkflow {
456
530
  * Drop the created stashes after everything has run
457
531
  */
458
532
  async cleanup(ctx) {
533
+ this.logger.log(dim(`${figures.wip()} Cleaning up temporary files…`))
534
+
459
535
  try {
460
- debugLog('Dropping backup stash...')
461
536
  await this.execGit(['stash', 'drop', '--quiet', await this.getBackupStash(ctx)])
462
- debugLog('Done dropping backup stash!')
537
+ this.logger.log(`${figures.done()} Done cleaning up temporary files!`)
463
538
  } catch (error) {
464
- handleError(error, ctx)
539
+ ctx.errors.add(GitError)
540
+ this.logger.error(`${figures.error()} Failed to clean up temporary files!`)
541
+ debugLog(error)
465
542
  }
466
543
  }
467
544
  }
package/lib/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { assertGitVersion, MIN_GIT_VERSION } from './assertGitVersion.js'
2
- import { SUPPORTS_COLOR } from './colors.js'
2
+ import { enableColors } from './colors.js'
3
3
  import { createDebug, enableDebug } from './debug.js'
4
4
  import { execGit } from './execGit.js'
5
5
  import {
6
- GIT_ERROR,
6
+ gitError,
7
7
  minGitVersionRequired,
8
- NO_CONFIGURATION,
9
- PREVENTED_EMPTY_COMMIT,
10
- PREVENTED_TASK_MODIFICATIONS,
8
+ noConfiguration,
9
+ preventedEmptyCommit,
10
+ preventedTaskModifications,
11
11
  restoreStashExample,
12
- UNSTAGED_CHANGES_BACKUP_STASH_LOCATION,
12
+ unstagedChangesBackupStashLocation,
13
13
  } from './messages.js'
14
14
  import { printTaskOutput } from './printTaskOutput.js'
15
15
  import { runAll } from './runAll.js'
@@ -78,7 +78,7 @@ const getMaxArgLength = () => {
78
78
  const lintStaged = async (
79
79
  {
80
80
  allowEmpty = false,
81
- color = SUPPORTS_COLOR,
81
+ color = !!process.stdout.hasColors?.(),
82
82
  concurrent = true,
83
83
  config: configObject,
84
84
  configPath,
@@ -102,6 +102,8 @@ const lintStaged = async (
102
102
  } = {},
103
103
  logger = console
104
104
  ) => {
105
+ enableColors(color)
106
+
105
107
  // Seemingly enable debug twice (also done in bin), so that it also works when using the Node.js API
106
108
  if (debug) {
107
109
  enableDebug(logger)
@@ -160,20 +162,20 @@ const lintStaged = async (
160
162
  const { ctx } = runAllError
161
163
 
162
164
  if (ctx.errors.has(ConfigNotFoundError)) {
163
- logger.error(NO_CONFIGURATION)
165
+ logger.error(noConfiguration())
164
166
  } else if (ctx.errors.has(ApplyEmptyCommitError)) {
165
- logger.warn(PREVENTED_EMPTY_COMMIT)
167
+ logger.warn(preventedEmptyCommit())
166
168
  } else if (ctx.errors.has(FailOnChangesError)) {
167
- logger.warn(PREVENTED_TASK_MODIFICATIONS + '\n')
169
+ logger.warn(preventedTaskModifications() + '\n')
168
170
  logger.warn(restoreStashExample(ctx.backupHash))
169
171
  } else if (ctx.errors.has(RestoreUnstagedChangesError)) {
170
- logger.warn(UNSTAGED_CHANGES_BACKUP_STASH_LOCATION)
172
+ logger.warn(unstagedChangesBackupStashLocation())
171
173
  logger.warn(ctx.unstagedPatch)
172
174
  } else if (
173
175
  (ctx.errors.has(GitError) || cleanupSkipped(ctx)) &&
174
176
  !ctx.errors.has(GetBackupStashError)
175
177
  ) {
176
- logger.error(GIT_ERROR)
178
+ logger.error(gitError())
177
179
  if (ctx.shouldBackup) {
178
180
  // No sense to show this if the backup stash itself is missing.
179
181
  logger.error(restoreStashExample(ctx.backupHash) + '\n')
package/lib/messages.js CHANGED
@@ -1,30 +1,32 @@
1
1
  import { inspect } from 'node:util'
2
2
 
3
3
  import { bold, red, yellow } from './colors.js'
4
- import { error, info, warning } from './figures.js'
4
+ import * as figures from './figures.js'
5
5
 
6
6
  export const configurationError = (opt, helpMsg, value) =>
7
- `${red(`${error} Validation Error:`)}
7
+ `${red(`${figures.error()} Validation Error:`)}
8
8
 
9
9
  Invalid value for '${bold(opt)}': ${bold(inspect(value))}
10
10
 
11
11
  ${helpMsg}`
12
12
 
13
- export const NOT_GIT_REPO = red(`${error} Current directory is not a git directory!`)
13
+ export const notGitRepo = () => red(`${figures.error()} Current directory is not a git directory!`)
14
14
 
15
- export const FAILED_GET_STAGED_FILES = red(`${error} Failed to get staged files!`)
15
+ export const failedGetStagedFiles = () => red(`${figures.error()} Failed to get staged files!`)
16
16
 
17
17
  export const incorrectBraces = (before, after) =>
18
18
  yellow(
19
- `${warning} Detected incorrect braces with only single value: \`${before}\`. Reformatted as: \`${after}\`
19
+ `${figures.warning()} Detected incorrect braces with only single value: \`${before}\`. Reformatted as: \`${after}\`
20
20
  `
21
21
  )
22
22
 
23
- export const NO_CONFIGURATION = `${error} lint-staged could not find any valid configuration.`
23
+ export const noConfiguration = () =>
24
+ `${figures.error()} lint-staged could not find any valid configuration.`
24
25
 
25
- export const NO_STAGED_FILES = `${info} lint-staged could not find any staged files.`
26
+ export const noStagedFiles = () => `${figures.info()} lint-staged could not find any staged files.`
26
27
 
27
- export const NO_TASKS = `${info} lint-staged could not find any staged files matching configured tasks.`
28
+ export const noTasks = () =>
29
+ `${figures.info()} lint-staged could not find any staged files matching configured tasks.`
28
30
 
29
31
  export const skippingBackup = (hasInitialCommit, diff) => {
30
32
  const reason =
@@ -33,27 +35,33 @@ export const skippingBackup = (hasInitialCommit, diff) => {
33
35
  : (hasInitialCommit ? '`--no-stash` was used' : 'there’s no initial commit yet') +
34
36
  '. This might result in data loss'
35
37
 
36
- return yellow(`${warning} Skipping backup because ${reason}.\n`)
38
+ return yellow(`${figures.warning()} Skipping backup because ${reason}.\n`)
37
39
  }
38
40
 
39
- export const SKIPPING_HIDE_PARTIALLY_CHANGED = yellow(
40
- `${warning} Skipping hiding unstaged changes from partially staged files because \`--no-hide-partially-staged\` was used.\n`
41
- )
41
+ export const skippingHidePartiallyChanged = () =>
42
+ yellow(
43
+ `${figures.warning()} Skipping hiding unstaged changes from partially staged files because \`--no-hide-partially-staged\` was used.\n`
44
+ )
42
45
 
43
- export const DEPRECATED_GIT_ADD = yellow(
44
- `${warning} Some of your tasks use \`git add\` command. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.
46
+ export const deprecatedGitAdd = () =>
47
+ yellow(
48
+ `${figures.warning()} Some of your tasks use \`git add\` command. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.
45
49
  `
46
- )
47
-
48
- export const TASK_ERROR = 'Skipped because of errors from tasks.'
50
+ )
49
51
 
50
- export const PREVENTED_TASK_MODIFICATIONS = `\n${error} lint-staged failed because \`--fail-on-changes\` was used.`
52
+ export const taskError = () => 'Skipped because of errors from tasks.'
51
53
 
52
- export const SKIPPED_GIT_ERROR = 'Skipped because of previous git error.'
54
+ export const preventedTaskModifications = () =>
55
+ `\n${figures.error()} lint-staged failed because \`--fail-on-changes\` was used.`
53
56
 
54
- export const GIT_ERROR = `\n ${red(`${error} lint-staged failed due to a git error.`)}`
57
+ export const gitError = () =>
58
+ `\n ${red(`${figures.error()} lint-staged failed due to a git error.`)}`
55
59
 
56
- export const invalidOption = (name, value, message) => `${red(`${error} Validation Error:`)}
60
+ export const invalidOption = (
61
+ name,
62
+ value,
63
+ message
64
+ ) => `${red(`${figures.error()} Validation Error:`)}
57
65
 
58
66
  Invalid value for option '${bold(name)}': ${bold(value)}
59
67
 
@@ -61,8 +69,8 @@ export const invalidOption = (name, value, message) => `${red(`${error} Validati
61
69
 
62
70
  See https://github.com/lint-staged/lint-staged#command-line-flags`
63
71
 
64
- export const PREVENTED_EMPTY_COMMIT = `
65
- ${yellow(`${warning} lint-staged prevented an empty git commit.
72
+ export const preventedEmptyCommit = () => `
73
+ ${yellow(`${figures.warning()} lint-staged prevented an empty git commit.
66
74
  Use the --allow-empty option to continue, or check your task configuration`)}
67
75
  `
68
76
 
@@ -75,23 +83,22 @@ export const restoreStashExample = (
75
83
  > git apply --index ${hash}
76
84
  `
77
85
 
78
- export const CONFIG_STDIN_ERROR = red(`${error} Failed to read config from stdin.`)
79
-
80
86
  export const failedToLoadConfig = (filepath) =>
81
- red(`${error} Failed to read config from file "${filepath}".`)
87
+ red(`${figures.error()} Failed to read config from file "${filepath}".`)
82
88
 
83
89
  export const failedToParseConfig = (
84
90
  filepath,
85
91
  error
86
- ) => `${red(`${error} Failed to parse config from file "${filepath}".`)}
92
+ ) => `${red(`${figures.error()} Failed to parse config from file "${filepath}".`)}
87
93
 
88
94
  ${error}
89
95
 
90
96
  See https://github.com/lint-staged/lint-staged#configuration.`
91
97
 
92
- export const UNSTAGED_CHANGES_BACKUP_STASH_LOCATION = `Unstaged changes have been kept back in a patch file:`
98
+ export const unstagedChangesBackupStashLocation = () =>
99
+ 'Unstaged changes have been kept back in a patch file:'
93
100
 
94
101
  export const minGitVersionRequired = (expected) =>
95
- red(`${error} lint-staged requires at least Git version ${bold(expected)}.
102
+ red(`${figures.error()} lint-staged requires at least Git version ${bold(expected)}.
96
103
 
97
104
  Please update Git: https://git-scm.com/downloads`)