Skip to content
This repository was archived by the owner on Aug 10, 2023. It is now read-only.

Commit d3ca256

Browse files
committed
refactor: Everything
Since I've made up my mind on subcommand naming, this finalizes that. This also just fixes up a lot of small (and large) things, making the UX significantly better
1 parent 7010bc0 commit d3ca256

File tree

11 files changed

+210
-31
lines changed

11 files changed

+210
-31
lines changed

Bakefile.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# shellcheck shell=bash
22

3+
task.docs() {
4+
shdoc < './pkg/share/lib.sh' > './docs/api.md'
5+
}
6+
37
task.test() {
48
bats "$@" ./tests
59
}

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ An elegantly minimal solution for Git hooks
77
```sh
88
cd some-git-repo-that-uses-hookah
99
hookah init
10-
# And you're done!
10+
# Boom! You're done
1111
```
1212

13-
- To update internal Hookah scripts, simply run `init` again (a message will be printed if anything has been updated)
14-
1513
## Features
1614

15+
- Simply run `init` again to update the Hookah scripts (a message will be printed if anything has been updated)
1716
- Has `check` subcommand to test if scripts will work _before_ running Git
1817
- Has `create` subcommand to list all templates and how they work
18+
- _No configuration_
1919

2020
## Installation
2121

basalt.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ authors = ['Edwin Kofler <[email protected]>']
77
description = 'A hook helper for Git'
88

99
[run]
10-
dependencies = ['https://github.com/hyperupcall/[email protected]']
10+
dependencies = ['https://github.com/hyperupcall/[email protected]', 'https://github.com/hyperupcall/[email protected]']
1111
binDirs = []
1212
sourceDirs = ['pkg/src/util', 'pkg/src/commands']
1313
builtinDirs = []

docs/api.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# lib.sh
2+
3+
## Overview
4+
5+
Function library for Git hooks configured with Hookah
6+
7+
## Index
8+
9+
* [hookah.init()](#hookahinit)
10+
* [hookah.run()](#hookahrun)
11+
* [hookah.run_allow_fail()](#hookahrun_allow_fail)
12+
* [hookah.is_ci()](#hookahis_ci)
13+
14+
### hookah.init()
15+
16+
initiates the environment, sets up stacktrace printing on 'ERR' trap,
17+
and sets the directory to the root of the Git repository
18+
19+
_Function has no arguments._
20+
21+
### hookah.run()
22+
23+
Prints a command before running it
24+
25+
### hookah.run_allow_fail()
26+
27+
Prints a command before running it. If the command fails, print a message,
28+
but do not abort execution
29+
30+
### hookah.is_ci()
31+
32+
Tests if currently in CI
33+
34+
#### Variables set
35+
36+
* **REPLY** (Current): provider for CI
37+
38+
#### Exit codes
39+
40+
* **0**: If in CI
41+
* **1**: If not in CI
42+

pkg/share/lib.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ hookah.init() {
3030
return 1
3131
fi
3232

33+
# Prevent bugs like:
34+
# - https://github.com/typicode/husky/issues/627
35+
# - https://github.com/yarnpkg/yarn/issues/743
36+
# - https://github.com/typicode/husky/issues/850
37+
# - https://github.com/yarnpkg/yarn/issues/2998
38+
if command -v &>/dev/null 'winpty' && [ -t 1 ]; then
39+
exec </dev/tty
40+
fi
41+
3342
# TODO print large
3443
printf '%s\n' "Hookah: Running ${BASH_SOURCE[1]##*/}"
3544
}
@@ -48,6 +57,95 @@ hookah.run_allow_fail() {
4857
fi
4958
}
5059

60+
# @description Tests if currently in CI
61+
# @exitcode 0 If in CI
62+
# @exitcode 1 If not in CI
63+
# @set REPLY Current provider for CI
64+
hookah.is_ci() {
65+
unset -v REPLY; REPLY=
66+
67+
# See https://github.com/watson/ci-info/blob/master/vendors.json
68+
# node -e $'for (const ci of JSON.parse(require("fs").readFileSync("vendors.json"))) { console.info(`\\telif [[ -v \047${ci.env}\047 ]]; then\\n\\t\\tREPLY=\047${ci.name}\047`) }'
69+
70+
if [[ -v 'APPVEYOR' ]]; then
71+
REPLY='AppVeyor'
72+
elif [[ -v 'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI' ]]; then
73+
REPLY='Azure Pipelines'
74+
elif [[ -v 'AC_APPCIRCLE' ]]; then
75+
REPLY='Appcircle'
76+
elif [[ -v 'bamboo_planKey' ]]; then
77+
REPLY='Bamboo'
78+
elif [[ -v 'BITBUCKET_COMMIT' ]]; then
79+
REPLY='Bitbucket Pipelines'
80+
elif [[ -v 'BITRISE_IO' ]]; then
81+
REPLY='Bitrise'
82+
elif [[ -v 'BUDDY_WORKSPACE_ID' ]]; then
83+
REPLY='Buddy'
84+
elif [[ -v 'BUILDKITE' ]]; then
85+
REPLY='Buildkite'
86+
elif [[ -v 'CIRCLECI' ]]; then
87+
REPLY='CircleCI'
88+
elif [[ -v 'CIRRUS_CI' ]]; then
89+
REPLY='Cirrus CI'
90+
elif [[ -v 'CODEBUILD_BUILD_ARN' ]]; then
91+
REPLY='AWS CodeBuild'
92+
elif [[ -v 'CF_BUILD_ID' ]]; then
93+
REPLY='Codefresh'
94+
elif [[ -v '[object Object]' ]]; then
95+
REPLY='Codeship'
96+
elif [[ -v 'DRONE' ]]; then
97+
REPLY='Drone'
98+
elif [[ -v 'DSARI' ]]; then
99+
REPLY='dsari'
100+
elif [[ -v 'EAS_BUILD' ]]; then
101+
REPLY='Expo Application Services'
102+
elif [[ -v 'GITHUB_ACTIONS' ]]; then
103+
REPLY='GitHub Actions'
104+
elif [[ -v 'GITLAB_CI' ]]; then
105+
REPLY='GitLab CI'
106+
elif [[ -v 'GO_PIPELINE_LABEL' ]]; then
107+
REPLY='GoCD'
108+
elif [[ -v 'LAYERCI' ]]; then
109+
REPLY='LayerCI'
110+
elif [[ -v 'HUDSON_URL' ]]; then
111+
REPLY='Hudson'
112+
elif [[ -v 'JENKINS_URL,BUILD_ID' ]]; then
113+
REPLY='Jenkins'
114+
elif [[ -v 'MAGNUM' ]]; then
115+
REPLY='Magnum CI'
116+
elif [[ -v 'NETLIFY' ]]; then
117+
REPLY='Netlify CI'
118+
elif [[ -v 'NEVERCODE' ]]; then
119+
REPLY='Nevercode'
120+
elif [[ -v 'RENDER' ]]; then
121+
REPLY='Render'
122+
elif [[ -v 'SAILCI' ]]; then
123+
REPLY='Sail CI'
124+
elif [[ -v 'SEMAPHORE' ]]; then
125+
REPLY='Semaphore'
126+
elif [[ -v 'SCREWDRIVER' ]]; then
127+
REPLY='Screwdriver'
128+
elif [[ -v 'SHIPPABLE' ]]; then
129+
REPLY='Shippable'
130+
elif [[ -v 'TDDIUM' ]]; then
131+
REPLY='Solano CI'
132+
elif [[ -v 'STRIDER' ]]; then
133+
REPLY='Strider CD'
134+
elif [[ -v 'TASK_ID,RUN_ID' ]]; then
135+
REPLY='TaskCluster'
136+
elif [[ -v 'TEAMCITY_VERSION' ]]; then
137+
REPLY='TeamCity'
138+
elif [[ -v 'TRAVIS' ]]; then
139+
REPLY='Travis CI'
140+
elif [[ -v 'NOW_BUILDER' ]]; then
141+
REPLY='Vercel'
142+
elif [[ -v 'APPCENTER_BUILD_ID' ]]; then
143+
REPLY='Visual Studio App Center'
144+
else
145+
return 1
146+
fi
147+
}
148+
51149
# @description Test whether color should be outputed
52150
# @exitcode 0 if should print color
53151
# @exitcode 1 if should not print color

pkg/src/bin/hookah.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
# shellcheck shell=bash
22

3+
global_trap_exit() {
4+
local exit_code=$?
5+
core.stacktrace_print
6+
exit $exit_code
7+
}
8+
39
main.hookah() {
4-
local subcommand="$1"
10+
core.init
11+
core.trap_add 'global_trap_exit' ERR
512

613
local arg=
714
for arg; do case $arg in
@@ -11,14 +18,15 @@ main.hookah() {
1118
;;
1219
esac done; unset -v arg
1320

21+
local subcommand="$1"
1422
case $subcommand in
1523
init)
1624
if ! shift; then print.die 'Failed shift'; fi
1725
hookah-init "$@"
1826
;;
19-
create)
27+
new)
2028
if ! shift; then print.die 'Failed shift'; fi
21-
hookah-create "$@"
29+
hookah-new "$@"
2230
;;
2331
check)
2432
if ! shift; then print.die 'Failed shift'; fi

pkg/src/commands/hookah-check.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ hookah-check() {
2121
print.hint "You may need to \`chmod +x '$hookFile'\`"
2222
fi
2323

24+
# TODO: Instead of disallow-list type fltering, create an allow-list of
25+
# valid script/hook names
2426
if [[ $line == *.* ]]; then
2527
print.warn "File should not have an excention"
2628
print.hint "For example, the hook 'pre-commit' should be at './hooks/pre-commit'"
@@ -51,4 +53,6 @@ hookah-check() {
5153
# Do not place anything under here unless 'continue's are placed in the
5254
# previous if-elif branches
5355
done; unset -v hookFile
56+
57+
printf '%s\n' 'Done.'
5458
}

pkg/src/commands/hookah-create.sh renamed to pkg/src/commands/hookah-new.sh

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
# shellcheck shell=bash
22

3-
hookah-create() {
3+
hookah-new() {
4+
local hook_name="$1"
5+
46
local -r hooks_dir='./.hooks'
7+
local -r hookah_dir="$hooks_dir/.hookah"
58

69
if ! util.cd_to_closest_git_repo; then
710
print.die "Failed to 'cd' to closest Git repository"
811
fi
912

13+
if [ ! -d "$hookah_dir" ]; then
14+
print.die "Hookah directory does not exist. Did you forget to run 'hookah init'?"
15+
fi
16+
1017
# post-update undocumented?
1118
# TODO: figure out where these hooks come from: https://github.com/rycus86/githooks#supported-hooks
1219
local -Ar hooks=(
@@ -35,32 +42,37 @@ hookah-create() {
3542
[post-receive]=
3643
)
3744

38-
printf '%s\n' "Hooks: "
39-
local hook=
40-
for hook in "${!hooks[@]}"; do
41-
printf '%s\n' " $hook: ${hooks[$hook]}"
42-
done; unset -v hook
43-
44-
printf '%s' 'Choose: '
45-
read -re
45+
if [ -z "$hook_name" ]; then
46+
printf '%s\n' "Hooks: "
47+
local hook=
48+
for hook in "${!hooks[@]}"; do
49+
printf '%s\n' " $hook: ${hooks[$hook]}"
50+
done; unset -v hook
4651

47-
local user_hook="$REPLY"
48-
# TODO
49-
if [[ ${!hooks[*]} != *"$user_hook"* ]]; then
50-
print.die "Did not enter valid commit hook"
52+
printf '%s' 'Choose: '
53+
read -re hook_name
5154
fi
5255

53-
if [ -z "$user_hook" ]; then
56+
if [ -z "$hook_name" ]; then
5457
print.die "Cannot be empty"
5558
fi
5659

57-
# TODO: hardcoded lib.sh
58-
cat > "$hooks_dir/$user_hook.sh" <<-"EOF"
60+
local is_valid_hook='no' valid_hook_name=
61+
for valid_hook_name in "${!hooks[@]}"; do
62+
if [ "$valid_hook_name" = "$hook_name" ]; then
63+
is_valid_hook='yes'
64+
fi
65+
done
66+
if [ "$is_valid_hook" != 'yes' ]; then
67+
print.die "Did not enter valid commit hook"
68+
fi
69+
70+
cat > "$hooks_dir/$hook_name" <<-"EOF"
5971
#!/usr/bin/env bash
6072
6173
source "${0%/*}/.hookah/lib.sh"
6274
hookah.init
6375
6476
EOF
65-
chmod +x "$hooks_dir/$user_hook.sh"
77+
chmod +x "$hooks_dir/$hook_name"
6678
}

pkg/src/util/util.sh

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,18 @@ util.run() {
3939
util.show_help() {
4040
cat <<"EOF"
4141
Usage:
42-
hookah [--help] <subcommand> [args...]
42+
hookah [--help] <subcommand> [args...]
43+
4344
Subcommands:
44-
setup
45-
Setup the hooks directory if it doesn't exist and execute sanity checks against the hooks (is readable, executable, shebangs, etc.)
46-
check
47-
Checks to ensure that the hooks directory is setup correctly
48-
create
49-
Menu to create one of the various Git hooks
45+
init
46+
Initializes the hooks directory or updates it if it already exists
47+
48+
new
49+
Opens a menu for creating a new Git hook. Once chosen, a corresponding
50+
minimal hook template will be created in the hooks directory
51+
52+
check
53+
Run sanity checks in the hooks directory. It ensures the scripts are
54+
readable, executable, has the proper shabangs, and other things
5055
EOF
5156
}

tests/hookah-check.bats

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bats
2+
3+
load './util/init.sh'

0 commit comments

Comments
 (0)