Skip to content

Commit

Permalink
fix: restore previous order of jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
iiroj committed Oct 2, 2021
1 parent cecdda3 commit ba62b22
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 51 deletions.
33 changes: 28 additions & 5 deletions lib/gitWorkflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
GitError,
ApplyEmptyCommitError,
HideUnstagedChangesError,
RestoreOriginalStateError,
RestoreUnstagedChangesError,
} = require('./symbols')
const unlink = require('./unlink')
Expand Down Expand Up @@ -39,6 +40,7 @@ const processRenames = (files, includeRenameFrom = true) =>
}, [])

const PATCH_UNSTAGED = 'lint-staged_unstaged.patch'
const PATCH_PARTIAL = 'lint-staged_partial.patch'

const GIT_DIFF_ARGS = [
'--binary', // support binary files
Expand Down Expand Up @@ -122,15 +124,18 @@ class GitWorkflow {
try {
debug('Backing up original state...')

const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
await this.execGit(['diff', ...GIT_DIFF_ARGS, '--output', unstagedPatch, '--', '.'])

// Get a list of files with bot staged and unstaged changes.
// Unstaged changes to these files should be hidden before the tasks run.
this.partiallyStagedFiles = await this.getPartiallyStagedFiles()

if (this.partiallyStagedFiles) {
ctx.hasPartiallyStagedFiles = true
const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
const partialPatch = this.getHiddenFilepath(PATCH_PARTIAL)
const files = processRenames(this.partiallyStagedFiles)
await this.execGit(['diff', ...GIT_DIFF_ARGS, '--output', unstagedPatch, '--', ...files])
await this.execGit(['diff', ...GIT_DIFF_ARGS, '--output', partialPatch, '--', ...files])
} else {
ctx.hasPartiallyStagedFiles = false
}
Expand All @@ -157,6 +162,23 @@ class GitWorkflow {
}
}

/**
* Restore original HEAD state in case of errors
*/
async restoreOriginalState(ctx) {
try {
debug('Restoring original state...')
await this.execGit(['checkout', '--force', '--', '.'])

const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
await this.execGit(['apply', ...GIT_APPLY_ARGS, unstagedPatch])

debug('Done restoring original state!')
} catch (error) {
handleError(error, ctx, RestoreOriginalStateError)
}
}

/** Add all task modifications to index for files that were staged before running. */
async applyModifications(ctx) {
debug('Adding task modifications to index...')
Expand Down Expand Up @@ -188,16 +210,16 @@ class GitWorkflow {
*/
async restorePartialChanges(ctx) {
debug('Restoring unstaged changes...')
const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
const partialPatch = this.getHiddenFilepath(PATCH_PARTIAL)
try {
await this.execGit(['apply', ...GIT_APPLY_ARGS, unstagedPatch])
await this.execGit(['apply', ...GIT_APPLY_ARGS, partialPatch])
} catch (applyError) {
debug('Error while restoring changes:')
debug(applyError)
debug('Retrying with 3-way merge')
try {
// Retry with a 3-way merge if normal apply fails
await this.execGit(['apply', ...GIT_APPLY_ARGS, '--3way', unstagedPatch])
await this.execGit(['apply', ...GIT_APPLY_ARGS, '--3way', partialPatch])
} catch (threeWayApplyError) {
debug('Error while restoring unstaged changes using 3-way merge:')
debug(threeWayApplyError)
Expand All @@ -217,6 +239,7 @@ class GitWorkflow {
async cleanup() {
debug('Removing temp files...')
await unlink(this.getHiddenFilepath(PATCH_UNSTAGED))
await unlink(this.getHiddenFilepath(PATCH_PARTIAL))
debug('Done removing temp files!')
}
}
Expand Down
12 changes: 6 additions & 6 deletions lib/runAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,17 @@ const runAll = async (
enabled: hasPartiallyStagedFiles,
},
...listrTasks,
{
title: 'Reverting because of errors...',
task: (ctx) => git.hideUnstagedChanges(ctx),
enabled: restoreOriginalStateEnabled,
skip: restoreOriginalStateSkipped,
},
{
title: 'Applying modifications...',
task: (ctx) => git.applyModifications(ctx),
skip: applyModificationsSkipped,
},
{
title: 'Reverting because of errors...',
task: (ctx) => git.restoreOriginalState(ctx),
enabled: restoreOriginalStateEnabled,
skip: restoreOriginalStateSkipped,
},
{
title: 'Restoring partial changes...',
task: (ctx) => git.restorePartialChanges(ctx),
Expand Down
7 changes: 7 additions & 0 deletions lib/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,24 @@ const hasPartiallyStagedFiles = (ctx) => ctx.hasPartiallyStagedFiles
const applyModificationsSkipped = (ctx) => {
// Always apply back unstaged modifications when skipping backup
if (!ctx.shouldBackup) return false

// Should be skipped in case of git errors
if (ctx.errors.has(GitError)) {
return GIT_ERROR
}

// Should be skipped when tasks fail
if (ctx.errors.has(TaskError)) {
return TASK_ERROR
}
}

const restorePartialChangesSkipped = (ctx) => {
// Should be skipped when entire state has already been restored
if (restoreOriginalStateEnabled(ctx)) {
return TASK_ERROR
}

// Should be skipped in case of git errors
if (ctx.errors.has(GitError)) {
return GIT_ERROR
Expand Down
2 changes: 1 addition & 1 deletion test/gitWorkflow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('gitWorkflow', () => {
"errors": Set {
Symbol(GitError),
},
"hasPartiallyStagedFiles": true,
"hasPartiallyStagedFiles": null,
"output": Array [],
"quiet": false,
"shouldBackup": null,
Expand Down
35 changes: 0 additions & 35 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,41 +650,6 @@ describe('lint-staged', () => {
expect(await readFile('test2.js')).toEqual(testJsFilePretty)
})

it('should fail when backup stash is missing', async () => {
await appendFile('test.js', testJsFilePretty)
await execGit(['add', 'test.js'])

// Remove backup stash during run
await expect(
gitCommit({ config: { '*.js': () => 'git stash drop' }, shell: true })
).rejects.toThrowError()

expect(console.printHistory()).toMatchInlineSnapshot(`
"
LOG [STARTED] Preparing...
LOG [SUCCESS] Preparing...
LOG [STARTED] Running tasks...
LOG [STARTED] Running tasks for *.js
LOG [STARTED] git stash drop
ERROR [FAILED] git stash drop [FAILED]
ERROR [FAILED] git stash drop [FAILED]
LOG [SUCCESS] Running tasks...
LOG [STARTED] Reverting because of errors...
ERROR [FAILED] Cannot read properties of null (reading 'reduce')
LOG [STARTED] Applying modifications...
INFO [SKIPPED]
[SKIPPED] × lint-staged failed due to a git error.
LOG [STARTED] Cleaning up...
INFO [SKIPPED]
[SKIPPED] × lint-staged failed due to a git error.
ERROR
× lint-staged failed due to a git error.
ERROR
× git stash drop:
No stash entries found."
`)
})

it('should fail when task reverts staged changes, to prevent an empty git commit', async () => {
// Create and commit a pretty file without running lint-staged
// This way the file will be available for the next step
Expand Down
8 changes: 4 additions & 4 deletions test/runAll.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ describe('runAll', () => {
LOG [STARTED] echo \\"sample\\"
ERROR [FAILED] echo \\"sample\\" [1]
LOG [SUCCESS] Running tasks...
LOG [STARTED] Reverting because of errors...
LOG [SUCCESS] Reverting because of errors...
LOG [STARTED] Applying modifications...
INFO [SKIPPED] Skipped because of errors from tasks.
LOG [STARTED] Reverting because of errors...
LOG [SUCCESS] Reverting because of errors...
LOG [STARTED] Cleaning up...
LOG [SUCCESS] Cleaning up..."
`)
Expand Down Expand Up @@ -199,10 +199,10 @@ describe('runAll', () => {
LOG [STARTED] echo \\"sample\\"
ERROR [FAILED] echo \\"sample\\" [SIGINT]
LOG [SUCCESS] Running tasks...
LOG [STARTED] Reverting because of errors...
LOG [SUCCESS] Reverting because of errors...
LOG [STARTED] Applying modifications...
INFO [SKIPPED] Skipped because of errors from tasks.
LOG [STARTED] Reverting because of errors...
LOG [SUCCESS] Reverting because of errors...
LOG [STARTED] Cleaning up...
LOG [SUCCESS] Cleaning up..."
`)
Expand Down

0 comments on commit ba62b22

Please sign in to comment.