chore(lint-staged): rewritten in JS (#2676)

- simpler code, no need to hack around the shell
- no more double formatting
- no longer use git stash, simply cache files in memory
This commit is contained in:
Julien Fontanet 2018-02-22 11:45:44 +01:00 committed by GitHub
parent 2ff25d1f61
commit 7ef314d9f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,52 +1,75 @@
#!/bin/sh
#!/usr/bin/env node
set -eu
format_files () {
prettier --write "$@"
eslint --ignore-pattern '!*' --fix "$@"
}
test_files () {
jest --findRelatedTests --passWithNoTests "$@"
const formatFiles = files => {
run('./node_modules/.bin/prettier', ['--write'].concat(files))
run(
'./node_modules/.bin/eslint',
['--ignore-pattern', '!*', '--fix'].concat(files)
)
}
const testFiles = files =>
run(
'./node_modules/.bin/jest',
['--findRelatedTests', '--passWithNoTests'].concat(files)
)
# compute the list of staged files we are interested in
set --
buf=$(mktemp -u)
git diff-index --cached --diff-filter=AM --name-only HEAD > "$buf"
while IFS= read -r file
do
case "$file" in
*.js)
set -- "$@" "$file";;
esac
done < "$buf"
rm -f "$buf"
// -----------------------------------------------------------------------------
if [ $# -eq 0 ]
then
exit
fi
const { execFileSync, spawnSync } = require('child_process')
const { readFileSync, writeFileSync } = require('fs')
format_files "$@"
# stash unstaged changes
if stash=$(git stash create --keep-index --quiet)
then
# remove those changes from the worktree
git checkout .
format_files "$@"
# unstash on exit
on_exit () {
git read-tree HEAD
git checkout $stash "$@"
const run = (command, args) => {
const { status } = spawnSync(command, args, { stdio: 'inherit' })
if (status !== 0) {
process.exit(status)
}
trap 'GIT_INDEX_FILE=$buf on_exit "$@"; rm -f "$buf"' EXIT
fi
}
test_files "$@"
const gitDiff = (what, args = []) =>
execFileSync(
'git',
[
'diff-' + what,
'--diff-filter=AM',
'--ignore-submodules',
'--name-only',
].concat(args),
{ encoding: 'utf8' }
)
.split('\n')
.filter(_ => _ !== '')
const gitDiffFiles = (files = []) => gitDiff('files', files)
const gitDiffIndex = () => gitDiff('index', ['--cached', 'HEAD'])
# add any changes made by the commands
git add "$@"
// -----------------------------------------------------------------------------
const files = gitDiffIndex().filter(_ => _.endsWith('.js'))
if (files.length === 0) {
return
}
// save the list of files with unstaged changes
let unstaged = gitDiffFiles(files)
// format all files
formatFiles(files)
if (unstaged.length !== 0) {
// refresh the list of files with unstaged changes, maybe the
// changes have been reverted by the formatting
run('git', ['update-index', '-q', '--refresh'])
unstaged = gitDiffFiles(unstaged)
if (unstaged.length !== 0) {
const contents = unstaged.map(name => readFileSync(name))
process.on('exit', () =>
unstaged.map((name, i) => writeFileSync(name, contents[i]))
)
run('git', ['checkout'].concat(unstaged))
formatFiles(unstaged)
}
}
testFiles(files)
run('git', ['add'].concat(files))