lint-staged 17.0.8 → 17.1.1

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()
@@ -257,114 +262,175 @@ export class GitWorkflow {
257
262
  ctx.backupHash = await this.execGit(['rev-parse', '--short', stashHash])
258
263
  await this.execGit(['stash', 'store', '--quiet', '--message', STASH, ctx.backupHash])
259
264
  }
260
-
261
- task.title = `Backed up original state in git stash (${ctx.backupHash})`
262
- debugLog(task.title)
263
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
+ )
264
274
  } catch (error) {
265
- 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)
266
283
  }
267
284
  }
268
285
 
269
286
  async hidePartiallyStagedChanges(ctx) {
287
+ this.logger.log(dim(`${figures.wip()} Hiding unstaged changes to partially staged files…`))
288
+
270
289
  try {
271
290
  const files = processRenames(this.unstagedFiles, false)
272
291
  await this.execGit(['restore', '--worktree', '--', ...files])
292
+ this.logger.log(`${figures.done()} Done hiding unstaged changes to partially staged files!`)
273
293
  } catch (error) {
274
294
  /**
275
295
  * `git checkout --force` doesn't throw errors, so it shouldn't be possible to get here.
276
- * If this does fail, the handleError method will set ctx.gitError and lint-staged will fail.
277
296
  */
278
- handleError(error, ctx, HideUnstagedChangesError)
279
- }
280
- }
297
+ ctx.errors.add(GitError)
298
+ ctx.errors.add(HideUnstagedChangesError)
281
299
 
282
- async runTasks(ctx, task, { listrTasks, concurrent }) {
283
- if (ctx.shouldFailOnChanges) {
284
- debugLog(
285
- 'Calculating SHA-256 hash of unstaged changes because "--fail-on-changes" was used...'
286
- )
287
- const diff = await this.execGit(['diff', '--patch', '--unified=0'])
288
- ctx.unstagedDiffSha256 = calculateSha256(diff)
289
- debugLog('SHA-256 hash of unstaged changes is %s', ctx.unstagedDiffSha256)
290
- }
300
+ const errorMessage = `${figures.error()} Failed to hude unstaged changes to partially staged files!`
291
301
 
292
- return task.newListr(listrTasks, { concurrent })
302
+ this.logger.error(errorMessage)
303
+ debugLog(error)
304
+ }
293
305
  }
294
306
 
295
- /** Update Git index again for the originally staged files to stage task modifications. */
296
- 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
+
297
312
  if (ctx.shouldFailOnChanges) {
298
- debugLog(
299
- 'Calculating SHA-256 hash of changes after tasks because "--fail-on-changes" was used...'
300
- )
301
- const diff = await this.execGit(['diff', '--patch', '--unified=0'])
302
- const diffSha256 = calculateSha256(diff)
303
- debugLog('SHA-256 hash of changes after tasks is %s', diffSha256)
304
- if (ctx.unstagedDiffSha256 !== diffSha256) {
305
- ctx.errors.add(FailOnChangesError)
306
- 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
307
325
  }
308
326
  }
309
327
 
310
- // This looks confusing but the intent is to only normalize truthy values
311
- const activeIndexFile = process.env.GIT_INDEX_FILE
312
- ? normalizePath(process.env.GIT_INDEX_FILE)
313
- : process.env.GIT_INDEX_FILE
314
-
315
- /** Needs to be run serially because of locking Git operation */
316
- for (const files of this.matchedFileChunks) {
317
- const accessCheckedFiles = await Promise.allSettled(
318
- files.map(async (f) => {
319
- if (f.status === 'D') {
320
- await fs.access(f.filepath)
321
- return f.filepath // File is no longer deleted and can be added
322
- } else {
323
- return f.filepath
324
- }
325
- })
326
- )
328
+ const failureMessage = `${figures.error()} Failed to run tasks for ${this.diff ? 'changed' : 'staged'} files!`
329
+
330
+ try {
331
+ await runParallelTasks(ctx, tasks, { abortController, concurrent, logger: this.logger })
327
332
 
328
- const addableFiles = accessCheckedFiles.flatMap((r) =>
329
- r.status === 'fulfilled' ? [r.value] : []
333
+ this.logger.log(
334
+ ctx.errors.has(TaskError)
335
+ ? failureMessage
336
+ : `${figures.done()} Done running tasks for ${this.diff ? 'changed' : 'staged'} files!`
330
337
  )
338
+ } catch (error) {
339
+ ctx.errors.add(TaskError)
340
+ this.logger.error(failureMessage)
341
+ debugLog(error)
342
+ }
343
+ }
331
344
 
332
- debugLog('Updating active Git index: %s', activeIndexFile)
333
- await this.execGit(['add', '--', ...addableFiles])
334
- 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…`))
335
348
 
336
- if (activeIndexFile?.endsWith('.lock')) {
337
- const defaultIndexLock = normalizePath(
338
- 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...'
339
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
+ }
340
366
 
341
- /**
342
- * If the active index file is a non-default lockfile, we are committing with a pathspec
343
- * without having explicitly run `git add`. In this case we need to also update the
344
- * default index, otherwise there will be leftover diff after committing
345
- */
346
- if (activeIndexFile !== defaultIndexLock) {
347
- debugLog('Updating default Git index again: %s', defaultIndexLock)
348
- await this.execGit(['add', '--', ...addableFiles], {
349
- env: {
350
- GIT_INDEX_FILE: defaultIndexLock,
351
- },
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
+ }
352
382
  })
353
- 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
+ }
354
412
  }
355
413
  }
356
- }
357
414
 
358
- const stagedFilesAfterAdd = await this.execGit([
359
- ...getDiffCommand(this.diff, this.diffFilter),
360
- '--name-only',
361
- '-z',
362
- ])
415
+ const stagedFilesAfterAdd = await this.execGit([
416
+ ...getDiffCommand(this.diff, this.diffFilter),
417
+ '--name-only',
418
+ '-z',
419
+ ])
420
+
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)
363
431
 
364
- if (!stagedFilesAfterAdd && !this.allowEmpty) {
365
- // Tasks reverted all staged changes and the commit would be empty
366
- // Throw error to stop commit unless `--allow-empty` was used
367
- handleError(new Error('Prevented an empty git commit!'), ctx, ApplyEmptyCommitError)
432
+ this.logger.log(`${figures.error()} Failed to stage changes from tasks!`)
433
+ debugLog(error)
368
434
  }
369
435
  }
370
436
 
@@ -374,8 +440,10 @@ export class GitWorkflow {
374
440
  * 3-way merge usually fixes this, and in case it doesn't we should just give up and throw.
375
441
  */
376
442
  async restoreUnstagedChanges(ctx) {
377
- debugLog('Restoring unstaged changes...')
443
+ this.logger.log(dim(`${figures.wip()} Restoring unstaged changes…`))
444
+
378
445
  const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
446
+
379
447
  try {
380
448
  await this.execGit(['apply', ...GIT_APPLY_ARGS, unstagedPatch])
381
449
  } catch (applyError) {
@@ -386,20 +454,19 @@ export class GitWorkflow {
386
454
  try {
387
455
  await this.execGit(['apply', ...GIT_APPLY_ARGS, '--3way', unstagedPatch])
388
456
  } catch (threeWayApplyError) {
389
- 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!`)
390
461
  debugLog(threeWayApplyError)
391
- handleError(
392
- new Error('Unstaged changes could not be restored due to a merge conflict!'),
393
- ctx,
394
- RestoreUnstagedChangesError
395
- )
396
462
  }
397
463
  }
398
464
  }
399
465
 
400
466
  async restoreUntrackedFiles(ctx) {
467
+ this.logger.log(dim(`${figures.wip()} Restoring untracked files…`))
468
+
401
469
  try {
402
- debugLog('Restoring untracked files...')
403
470
  const backupStash = await this.getBackupStash(ctx)
404
471
  const untrackedFiles = await this.execGit([
405
472
  'stash',
@@ -419,17 +486,17 @@ export class GitWorkflow {
419
486
  '--',
420
487
  ...untrackedFiles.map(normalizePath),
421
488
  ])
489
+
490
+ this.logger.log(`${figures.done()} ${'Done restoring untracked files!'}`)
422
491
  } else {
423
- debugLog('No untracked files to restore!')
492
+ this.logger.log(`${figures.cancelled()} ${dim('No untracked files to restore!')}`)
424
493
  }
425
494
  } catch (restoreUntrackedFilesError) {
426
- 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!'}`)
427
499
  debugLog(restoreUntrackedFilesError)
428
- handleError(
429
- new Error('Untracked files could not be restored!'),
430
- ctx,
431
- RestoreUnstagedChangesError
432
- )
433
500
  }
434
501
  }
435
502
 
@@ -437,6 +504,8 @@ export class GitWorkflow {
437
504
  * Restore original HEAD state in case of errors
438
505
  */
439
506
  async restoreOriginalState(ctx) {
507
+ this.logger.log(dim(`${figures.wip()} Reverting to original state because of errors…`))
508
+
440
509
  try {
441
510
  debugLog('Restoring original state...')
442
511
  await this.execGit(['reset', '--hard', 'HEAD'])
@@ -447,9 +516,13 @@ export class GitWorkflow {
447
516
  // Clean out patch
448
517
  await unlink(this.getHiddenFilepath(PATCH_UNSTAGED))
449
518
 
450
- debugLog('Done restoring original state!')
519
+ this.logger.log(`${figures.done()} Done reverting to original state!`)
451
520
  } catch (error) {
452
- 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)
453
526
  }
454
527
  }
455
528
 
@@ -457,12 +530,15 @@ export class GitWorkflow {
457
530
  * Drop the created stashes after everything has run
458
531
  */
459
532
  async cleanup(ctx) {
533
+ this.logger.log(dim(`${figures.wip()} Cleaning up temporary files…`))
534
+
460
535
  try {
461
- debugLog('Dropping backup stash...')
462
536
  await this.execGit(['stash', 'drop', '--quiet', await this.getBackupStash(ctx)])
463
- debugLog('Done dropping backup stash!')
537
+ this.logger.log(`${figures.done()} Done cleaning up temporary files!`)
464
538
  } catch (error) {
465
- handleError(error, ctx)
539
+ ctx.errors.add(GitError)
540
+ this.logger.error(`${figures.error()} Failed to clean up temporary files!`)
541
+ debugLog(error)
466
542
  }
467
543
  }
468
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'
@@ -28,7 +28,8 @@ import { getVersion } from './version.js'
28
28
  const debugLog = createDebug('lint-staged')
29
29
 
30
30
  /**
31
- * Get the maximum length of a command-line argument string based on current platform
31
+ * Get the maximum length of a command-line argument string based on current platform,
32
+ * roughly half of the real maximum length
32
33
  *
33
34
  * https://serverfault.com/questions/69430/what-is-the-maximum-length-of-a-command-line-in-mac-os-x
34
35
  * https://support.microsoft.com/en-us/help/830473/command-prompt-cmd-exe-command-line-string-limitation
@@ -36,12 +37,12 @@ const debugLog = createDebug('lint-staged')
36
37
  */
37
38
  const getMaxArgLength = () => {
38
39
  switch (process.platform) {
39
- case 'darwin':
40
- return 262144
41
- case 'win32':
42
- return 8191
43
- default:
44
- return 131072
40
+ case 'darwin': // 262_144
41
+ return 131_072
42
+ case 'win32': // 8_191
43
+ return 4_096
44
+ default: // 131_072
45
+ return 65_536
45
46
  }
46
47
  }
47
48
 
@@ -78,7 +79,7 @@ const getMaxArgLength = () => {
78
79
  const lintStaged = async (
79
80
  {
80
81
  allowEmpty = false,
81
- color = SUPPORTS_COLOR,
82
+ color = !!process.stdout.hasColors?.(),
82
83
  concurrent = true,
83
84
  config: configObject,
84
85
  configPath,
@@ -91,7 +92,7 @@ const lintStaged = async (
91
92
  hideAll = false,
92
93
  hideUnstaged = false,
93
94
  hidePartiallyStaged = !(hideAll || hideUnstaged),
94
- maxArgLength = getMaxArgLength() / 2,
95
+ maxArgLength = getMaxArgLength(),
95
96
  quiet = false,
96
97
  relative = false,
97
98
  // Stashing should be disabled by default when the `diff` option is used
@@ -102,6 +103,8 @@ const lintStaged = async (
102
103
  } = {},
103
104
  logger = console
104
105
  ) => {
106
+ enableColors(color)
107
+
105
108
  // Seemingly enable debug twice (also done in bin), so that it also works when using the Node.js API
106
109
  if (debug) {
107
110
  enableDebug(logger)
@@ -160,20 +163,20 @@ const lintStaged = async (
160
163
  const { ctx } = runAllError
161
164
 
162
165
  if (ctx.errors.has(ConfigNotFoundError)) {
163
- logger.error(NO_CONFIGURATION)
166
+ logger.error(noConfiguration())
164
167
  } else if (ctx.errors.has(ApplyEmptyCommitError)) {
165
- logger.warn(PREVENTED_EMPTY_COMMIT)
168
+ logger.warn(preventedEmptyCommit())
166
169
  } else if (ctx.errors.has(FailOnChangesError)) {
167
- logger.warn(PREVENTED_TASK_MODIFICATIONS + '\n')
170
+ logger.warn(preventedTaskModifications() + '\n')
168
171
  logger.warn(restoreStashExample(ctx.backupHash))
169
172
  } else if (ctx.errors.has(RestoreUnstagedChangesError)) {
170
- logger.warn(UNSTAGED_CHANGES_BACKUP_STASH_LOCATION)
173
+ logger.warn(unstagedChangesBackupStashLocation())
171
174
  logger.warn(ctx.unstagedPatch)
172
175
  } else if (
173
176
  (ctx.errors.has(GitError) || cleanupSkipped(ctx)) &&
174
177
  !ctx.errors.has(GetBackupStashError)
175
178
  ) {
176
- logger.error(GIT_ERROR)
179
+ logger.error(gitError())
177
180
  if (ctx.shouldBackup) {
178
181
  // No sense to show this if the backup stash itself is missing.
179
182
  logger.error(restoreStashExample(ctx.backupHash) + '\n')