Skip to content

Instantly share code, notes, and snippets.

@luuuis luuuis/pre-commit.sh forked from dahjelle/pre-commit.sh
Last active Feb 18, 2020

Embed
What would you like to do?
Pre-commit hook for eslint, linting *only* staged changes.
#!/usr/bin/env bash
set -uo pipefail
IFS=$'\n\t'
#
# Improvements from dahjelle/pre-commit.sh:
# - does not lint deleted files,
# - lints all staged files before exiting with an error code,
# - handles spaces and other unusual chars in file names.
#
# Based also on @jancimajek's one liner in that Gist.
#
# ESLint staged changes only
git diff --diff-filter=d --cached --name-only -z -- '*.js' '*.jsx' \
| xargs -0 -I % sh -c 'git show ":%" | ./node_modules/.bin/eslint --stdin --stdin-filename "%";'
eslint_exit=$?
if [ ${eslint_exit} -eq 0 ]; then
echo "✓ ESLint passed"
else
echo "✘ ESLint failed!" 1>&2
exit ${eslint_exit}
fi
@GingerPlusPlus

This comment has been minimized.

Copy link

GingerPlusPlus commented Aug 7, 2019

Perhaps using xargs --max-procs (and eslint >/dev/null) could speed the script up.

I was wondering if the script can be made compatible with batch / cmd as well, but I underestimated how bad cmd is.

Also, I don't see this script taking advantage of bash features, perhaps #!/usr/bin/env sh would be a more portable shebang.

@Artoria2e5

This comment has been minimized.

Copy link

Artoria2e5 commented Nov 25, 2019

@GingerPlusPlus You are right with xargs, although it will only matter for a lot of files. The /dev/null part discards information that may matter though. The pipefail thing is a bash feature, so it's not portable to sh. See https://www.gnu.org/software/bash/manual/html_node/Pipelines.html.

The IFS setting is not needed.


I don't really get the point in having git show the file and then feed it to eslint. Is that an adaption for awful command-line conventions like the one on Windows (where sh's Cygwin/MSYS and Node's MSVCRT cmdline parsing conventions differ)?

On non-DOSish systems that have an explicit concept of argv, it is safer to just do | xargs -0 ./node_modules/.bin/eslint -- since the argument boundary is enforced automatically. The substitution neglects stuff like filenames with quotation marks in them.

@GingerPlusPlus

This comment has been minimized.

Copy link

GingerPlusPlus commented Nov 29, 2019

eslint % would lint working directory, while git show :% | eslint --stdin lints index, which is what actually is about to be committed.

@Artoria2e5

This comment has been minimized.

Copy link

Artoria2e5 commented Dec 1, 2019

would lint working directory

Why would it? eslint has a filename-receiving CLI interface too. Git diff operates on file level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.