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:
		@@ -1,52 +1,75 @@
 | 
				
			|||||||
#!/bin/sh
 | 
					#!/usr/bin/env node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set -eu
 | 
					const formatFiles = files => {
 | 
				
			||||||
 | 
					  run('./node_modules/.bin/prettier', ['--write'].concat(files))
 | 
				
			||||||
format_files () {
 | 
					  run(
 | 
				
			||||||
  prettier --write "$@"
 | 
					    './node_modules/.bin/eslint',
 | 
				
			||||||
  eslint --ignore-pattern '!*' --fix "$@"
 | 
					    ['--ignore-pattern', '!*', '--fix'].concat(files)
 | 
				
			||||||
}
 | 
					  )
 | 
				
			||||||
test_files () {
 | 
					 | 
				
			||||||
  jest --findRelatedTests --passWithNoTests "$@"
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					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 ]
 | 
					const { execFileSync, spawnSync } = require('child_process')
 | 
				
			||||||
then
 | 
					const { readFileSync, writeFileSync } = require('fs')
 | 
				
			||||||
  exit
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
format_files "$@"
 | 
					const run = (command, args) => {
 | 
				
			||||||
 | 
					  const { status } = spawnSync(command, args, { stdio: 'inherit' })
 | 
				
			||||||
# stash unstaged changes
 | 
					  if (status !== 0) {
 | 
				
			||||||
if stash=$(git stash create --keep-index --quiet)
 | 
					    process.exit(status)
 | 
				
			||||||
then
 | 
					 | 
				
			||||||
  # remove those changes from the worktree
 | 
					 | 
				
			||||||
  git checkout .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  format_files "$@"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # unstash on exit
 | 
					 | 
				
			||||||
  on_exit () {
 | 
					 | 
				
			||||||
    git read-tree HEAD
 | 
					 | 
				
			||||||
    git checkout $stash "$@"
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  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))
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user