Skip to content

Commit

Permalink
Refactor hooks (#654)
Browse files Browse the repository at this point in the history
  • Loading branch information
typicode committed Jan 21, 2020
1 parent e7af456 commit 27df561
Show file tree
Hide file tree
Showing 18 changed files with 373 additions and 297 deletions.
4 changes: 2 additions & 2 deletions run.js → bin/run.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
/* eslint-disable @typescript-eslint/no-var-requires */
const pleaseUpgradeNode = require('please-upgrade-node')
const pkg = require('./package.json')
const pkg = require('../package.json')

// Node version isn't supported, skip
pleaseUpgradeNode(pkg, {
Expand All @@ -11,4 +11,4 @@ pleaseUpgradeNode(pkg, {
})

// Node version is supported, continue
require('./lib/runner/bin')
require('../lib/runner/bin')
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "4.0.10",
"description": "Prevents bad commit or push (git hooks, pre-commit/precommit, pre-push/prepush, post-merge/postmerge and all that stuff...)",
"bin": {
"husky-run": "./run.js",
"husky-run": "./bin/run.js",
"husky-upgrade": "./lib/upgrader/bin.js"
},
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set -e
# Variables
# ---

HUSKY_DEBUG=1
export HUSKY_DEBUG=1

projectDir=/tmp/husky-project
hookParamsFile=hook-params
Expand Down
88 changes: 88 additions & 0 deletions sh/husky.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
debug () {
if [ "$HUSKY_DEBUG" = "true" ] || [ "$HUSKY_DEBUG" = "1" ]; then
echo "husky:debug $1"
fi
}

command_exists () {
command -v "$1" >/dev/null 2>&1
}

run_command () {
if command_exists "$1"; then
"$@" husky-run $hookName "$gitParams"

exitCode="$?"
debug "$* husky-run exited with $exitCode exit code"

if [ $exitCode -eq 127 ]; then
echo "Can't find Husky, skipping $hookName hook"
echo "You can reinstall it using 'npm install husky --save-dev' or delete this hook"
else
exit $exitCode
fi

else
echo "Can't find $1 in PATH: $PATH"
echo "Skipping $hookName hook"
exit 0
fi
}

hookIsDefined () {
grep -qs $hookName \
package.json \
.huskyrc \
.huskyrc.json \
.huskyrc.yaml \
.huskyrc.yml \
.huskyrc.js \
husky.config.js
}

huskyVersion="0.0.0"
gitParams="$*"
hookName="$(basename "$0")"

debug "husky v$huskyVersion - $hookName"

# Skip if HUSKY_SKIP_HOOKS is set
if [ "$HUSKY_SKIP_HOOKS" = "true" ] || [ "$HUSKY_SKIP_HOOKS" = "1" ]; then
debug "HUSKY_SKIP_HOOKS is set to $HUSKY_SKIP_HOOKS, skipping hook"
exit 0
fi

# Source user var and change directory
. "$(dirname $0)/husky.local.sh"
debug "Current working directory is $(pwd)"

# Skip fast if hookName is not defined
if ! hookIsDefined; then
debug "$hookName config not found, skip"
exit 0
fi

# Source user ~/.huskyrc
if [ -f ~/.huskyrc ]; then
debug "source ~/.huskyrc"
. ~/.huskyrc
fi

# Set HUSKY_GIT_STDIN from stdin
case $hookName in
"pre-push"|"pre-receive"|"post-receive"|"post-rewrite")
export HUSKY_GIT_STDIN="$(cat)";;
esac

# Windows 10, Git Bash and Yarn 1 installer
if command_exists winpty && test -t 1; then
exec < /dev/tty
fi

# Run husky-run with the package manager used to install Husky
case $packageManager in
"npm") run_command npx --no-install;;
"pnpm") run_command pnpx --no-install;;
"yarn") run_command yarn run --silent;;
"*") echo "Unknown package manager: $packageManager"; exit 0;;
esac
2 changes: 1 addition & 1 deletion src/__tests__/getConf.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import tempy from 'tempy'
import getConf from '../getConf'
import { getConf } from '../getConf'

const testConf = { husky: { foo: 'bar' } }

Expand Down
2 changes: 1 addition & 1 deletion src/getConf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface Conf {
hooks?: { [key: string]: string }
}

export default function getConf(dir: string): Conf {
export function getConf(dir: string): Conf {
const explorer = cosmiconfigSync('husky')
const { config = {} } = explorer.search(dir) || {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,29 @@ exports[`hookScript should match snapshot 1`] = `
"#!/bin/sh
# husky
# Hook created by Husky v4.0.10 (https://github.com/typicode/husky#readme)
# Created by Husky v4.0.10 (https://github.com/typicode/husky#readme)
# At: <locale date string>
# From: /home/typicode/projects/foo-package (https://github.com/foo/foo-package)
. \\"$(dirname \\"$0\\")/husky.sh\\"
"
`;
exports[`localScript should match snapshot 1`] = `
"# Created by Husky v4.0.10 (https://github.com/typicode/husky#readme)
# At: <locale date string>
# From: /home/typicode/projects/foo-package (https://github.com/foo/foo-package)
# With: npm
gitRoot=\\"$(git rev-parse --show-toplevel)\\"
gitParams=\\"$*\\"
hookName=\`basename \\"$0\\"\`
packageManager=npm
cd \\".\\"
"
`;
debug() {
exports[`mainScript should match snapshot 1`] = `
"# Created by Husky v4.0.10 (https://github.com/typicode/husky#readme)
# At: <locale date string>
# From: /home/typicode/projects/foo-package (https://github.com/foo/foo-package)
debug () {
if [ \\"$HUSKY_DEBUG\\" = \\"true\\" ] || [ \\"$HUSKY_DEBUG\\" = \\"1\\" ]; then
echo \\"husky:debug $1\\"
fi
Expand Down Expand Up @@ -45,38 +57,57 @@ run_command () {
fi
}
debug \\"husky v4.0.10 (created at <locale date string>)\\"
debug \\"$hookName hook started\\"
debug \\"Current working directory is \`pwd\`\\"
if [ -f ~/.huskyrc ]; then
debug \\"source ~/.huskyrc\\"
. ~/.huskyrc
fi
hookIsDefined () {
grep -qs $hookName \\\\
package.json \\\\
.huskyrc \\\\
.huskyrc.json \\\\
.huskyrc.yaml \\\\
.huskyrc.yml \\\\
.huskyrc.js \\\\
husky.config.js
}
if [ -f \\"$gitRoot\\"/.huskyrc.local ]; then
debug \\"source $gitRoot/.huskyrc.local\\"
. \\"$gitRoot\\"/.huskyrc.local
fi
huskyVersion=\\"4.0.10\\"
gitParams=\\"$*\\"
hookName=\\"$(basename \\"$0\\")\\"
debug \\"$hookName hook started\\"
debug \\"husky v$huskyVersion - $hookName\\"
# Skip if HUSKY_SKIP_HOOKS is set
if [ \\"$HUSKY_SKIP_HOOKS\\" = \\"true\\" ] || [ \\"$HUSKY_SKIP_HOOKS\\" = \\"1\\" ]; then
debug \\"HUSKY_SKIP_HOOKS is set to $HUSKY_SKIP_HOOKS, skipping hook\\"
exit 0
fi
cd \\".\\"
# Source user var and change directory
. \\"$(dirname $0)/husky.local.sh\\"
debug \\"Current working directory is $(pwd)\\"
# Skip fast if hookName is not defined
if ! hookIsDefined; then
debug \\"$hookName config not found, skip\\"
exit 0
fi
# Source user ~/.huskyrc
if [ -f ~/.huskyrc ]; then
debug \\"source ~/.huskyrc\\"
. ~/.huskyrc
fi
# Set HUSKY_GIT_STDIN from stdin
case $hookName in
\\"pre-push\\"|\\"pre-receive\\"|\\"post-receive\\"|\\"post-rewrite\\")
export HUSKY_GIT_STDIN=\\"$(cat)\\";;
esac
# Windows 10, Git Bash and Yarn 1 installer
if command_exists winpty && test -t 1; then
exec < /dev/tty
fi
# Run husky-run with the package manager used to install Husky
case $packageManager in
\\"npm\\") run_command npx --no-install;;
\\"pnpm\\") run_command pnpx --no-install;;
Expand Down
9 changes: 0 additions & 9 deletions src/installer/__tests__/getScript.ts

This file was deleted.

22 changes: 15 additions & 7 deletions src/installer/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import path from 'path'
import tempy from 'tempy'
import './__env__'
import * as installer from '../'
import { huskyIdentifier } from '../getScript'
import { huskyIdentifier } from '../hooks'

// RandomId to verify that scripts get updated
const randomId = Math.random().toString()
Expand Down Expand Up @@ -111,12 +111,16 @@ describe('install', (): void => {
writeFile('package.json', pkg)

install()
expect(exists('.git/hooks/husky.sh')).toBeTruthy()
expect(exists('.git/hooks/husky.local.sh')).toBeTruthy()
expectHookToExist('.git/hooks/pre-commit')

const hook = readFile('.git/hooks/pre-commit')
expect(hook).toMatch('cd "."')
const localScript = readFile('.git/hooks/husky.local.sh')
expect(localScript).toMatch('cd "."')

uninstall()
expect(exists('.git/hooks/husky.sh')).toBeFalsy()
expect(exists('.git/hooks/husky.local.sh')).toBeFalsy()
expect(exists('.git/hooks/pre-commit')).toBeFalsy()
})

Expand Down Expand Up @@ -166,11 +170,13 @@ describe('install', (): void => {
writeFile('A/B/package.json', pkg)

install({ relativeUserPkgDir, userPkgDir: relativeUserPkgDir })
const hook = readFile('.git/hooks/pre-commit')
const localScript = readFile('.git/hooks/husky.local.sh')

expect(hook).toMatch('cd "A/B/"')
expect(localScript).toMatch('cd "A/B/"')
expectHookToExist('.git/hooks/pre-commit')

uninstall({ userPkgDir: relativeUserPkgDir })
expect(exists('.git/hooks/husky.local.sh')).toBeFalsy()
expect(exists('.git/hooks/pre-commit')).toBeFalsy()
})

Expand All @@ -185,11 +191,13 @@ describe('install', (): void => {
gitCommonDir,
userPkgDir
})
const hook = readFile('.git/modules/A/B/hooks/pre-commit')
const localScript = readFile('.git/modules/A/B/hooks/husky.local.sh')

expect(hook).toMatch('cd "."')
expect(localScript).toMatch('cd "."')
expectHookToExist('.git/modules/A/B/hooks/pre-commit')

uninstall({ gitCommonDir, userPkgDir })
expect(exists('.git/modules/A/B/hooks/husky.local.sh')).toBeFalsy()
expect(exists('.git/modules/A/B/hooks/pre-commit')).toBeFalsy()
})

Expand Down
25 changes: 25 additions & 0 deletions src/installer/__tests__/scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import './__env__'
import { getHookScript } from '../hooks'
import { getLocalScript } from '../localScript'
import { getMainScript } from '../mainScript'

describe('hookScript', (): void => {
it('should match snapshot', (): void => {
const script = getHookScript()
expect(script).toMatchSnapshot()
})
})

describe('localScript', (): void => {
it('should match snapshot', (): void => {
const script = getLocalScript('npm', '.')
expect(script).toMatchSnapshot()
})
})

describe('mainScript', (): void => {
it('should match snapshot', (): void => {
const script = getMainScript()
expect(script).toMatchSnapshot()
})
})
16 changes: 16 additions & 0 deletions src/installer/getBanner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import path = require('path')
import { readPkg } from '../read-pkg'

export function getBanner(): string {
const pkgHomepage = process.env.npm_package_homepage
const pkgDirectory = process.env.PWD

const { homepage: huskyHomepage, version: huskyVersion } = readPkg(
path.join(__dirname, '../..')
)

const createdAt = new Date().toLocaleString()
return `# Created by Husky v${huskyVersion} (${huskyHomepage})
# At: ${createdAt}
# From: ${pkgDirectory} (${pkgHomepage})`
}
Loading

0 comments on commit 27df561

Please sign in to comment.