Skip to content

Instantly share code, notes, and snippets.

@luuuis
Forked from dahjelle/pre-commit.sh
Last active September 19, 2021 16:18
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luuuis/e41fd71134ce88ac5e9359cbdbfb6273 to your computer and use it in GitHub Desktop.
Save luuuis/e41fd71134ce88ac5e9359cbdbfb6273 to your computer and use it in GitHub Desktop.
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
@wojpawlik
Copy link

wojpawlik 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
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.

@wojpawlik
Copy link

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

@Artoria2e5
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.

@wojpawlik
Copy link

wojpawlik commented Mar 16, 2020

react-boilerplate/react-boilerplate#1064 (comment)

Btw., I was trying to sidestep the issue by linting before staging instead, but thedevs-network/the-guard-bot@b379aab :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment