Repository navigation
Releases: yantonov/krok
Release list
0.3.0
krok 0.3.0
Two fixes, both about hook installation surviving the way repositories are
actually set up: a build step that repoints core.hooksPath, and a bootstrap
script that runs more than once.
The preserved hook now lives under the git directory
When krok takes over a hook that already exists, it keeps a copy and registers
it as the first job so it keeps running. That copy used to go beside the hook it
replaced, under whatever git rev-parse --git-path hooks answered, and the job
resolved it through KROK_HOOKS_DIR at run time. Both follow core.hooksPath —
which is not krok's to set: husky sets it, from a build step, on every fresh
checkout. Installing before that happened left the copy in .git/hooks while
the job looked in .husky, and every commit then failed on the reserved job
with the preserved hook reported missing. A gerrit commit-msg hook is one of
the ones lost that way, which takes the whole repository with it.
The copy now goes to .git/krok/<hook>/existing, named through a new
KROK_GIT_DIR. Nothing outside git moves the git directory, and it is where the
config naming the copy already lives, so the two cannot come apart. It also
keeps krok out of a hooks directory that may be tracked — .husky is, and a
copy written there is untracked noise in every clone.
Upgrading is safe: a file an earlier krok left is still looked for where it was
left, so an upgrade does not read a hook it already installed as unfinished and
preserve it a second time.
add answers instead of refusing when the job is already registered
Registering a job krok already holds was an error. It did not need to be — the
job list already says what the caller asked for, and the command is the same, so
there is nothing ambiguous to report and nothing to write.
The refusal cost more than it looked. Scripts that register hooks run when a
checkout is set up, and again every time it is set up again; under set -e the
refusal fails them, and in a workspace holding several repositories it fails at
the first one that had been set up before, so none of the later ones get their
hooks. Re-running the bootstrap — the obvious move when hooks look wrong — became
the reason the rest of the workspace had none.
krok now reports that the job is already there and succeeds. The wrapper is
still seen to before the answer, so a re-run remains the way a hook file someone
deleted comes back. A different command whose derived key is already taken is
unaffected: it is numbered, as before.
New job variable
| Variable | Value |
|---|---|
KROK_GIT_DIR |
The git directory shared by every worktree |
KROK_REPO_ROOT and KROK_HOOKS_DIR are unchanged.
0.2.0
krok 0.2.0
First release since 0.1.0. Several fixes here change behaviour you may be relying on — read Before upgrading first.
Before upgrading
Jobs now run under sh, not under $SHELL. Previously each job was handed to whatever interactive shell you happen to use. If a registered command uses bash-only syntax — [[ ... ]], arrays, &> — it will now fail. Wrap it (bash -c '...') or rewrite it in POSIX syntax.
Asset names now carry the architecture. krok-linux-0.2.0.tar.gz is now krok-linux-x86_64-0.2.0.tar.gz, and so on. If you script the download URL, update it.
The install command changed:
curl -fsSL https://raw.githubusercontent.com/yantonov/krok/master/bin/install/install.sh | shExisting hooks report as outdated. The wrapper krok writes into .git/hooks/ changed (its shebang is now sh). Old wrappers keep working, so nothing breaks, but krok recover <hook-name> brings them in step. Any krok add for a hook rewrites its wrapper anyway.
Fixed
- A job holding a path relative to the repository, such as
./scripts/check.sh, never ran. krok rewrote any command whose first word looked like a relative path into.git/hooks/, so the form the README suggests failed at every commit with a path pointing into the wrong directory. Commands now reach the shell exactly as written. - Hook arguments containing a space arrived split. They were pasted into the command as text, so a
commit-msgpath likemy file.txtreached the job as two arguments. They are now passed as positional parameters, which also means nothing git puts in an argument is read as shell syntax. krok addfailed outright in a linked worktree or a submodule with "not inside a git repository". krok now asks git where things are instead of looking for a.gitdirectory.core.hooksPathwas ignored, so hooks were written where git would not look for them.- Two different commands that derive the same key —
cargo clippy -- -D warningsandcargo clippy -D warnings— could not both be registered; the second was refused as already registered. The second is now numbered. Registering the same command twice is still refused, and the message names the command. - The installer could ask for a release that was not published yet. It read the newest tag, but the release built from a tag stays a draft until published, so its assets 404. It now follows the latest published release.
- The installer required
jq, which is not present by default on macOS or a minimal Linux. - The README's install command was a guaranteed 404 — it named the old repository and a script path that predated the
bin/install/split. install-from-source.shprinted a literal${INSTALL_DIR}in its PATH hint, so the line it told you to copy put nothing onPATH.- The config was written in place, so an interrupted write could leave a half-written config. It is now written beside the config and moved onto it.
Added
krok config pathprints the path of the config file in use.- Checksums. Each release asset is published with a
.sha256beside it, and the installer verifies the archive before unpacking it. The pair can also be checked by hand withsha256sum -c. - Builds for more architectures: linux aarch64, and both arm64 and x86_64 macOS. The macOS asset previously published was arm64 only, under a name that did not say so, so it could not run on an Intel Mac.
KROK_REPO_ROOTandKROK_HOOKS_DIRare exported to every job.- Jobs can read the arguments git passed individually, as
$1,$2. bin/install/install.sh, which resolves the release and then takes the installer script from that same release, so the script and the binary always come from one place.bin/dev/tag-release.shandbin/dev/release.sh.- A LICENSE file (Apache 2.0) and the author, description, repository and license fields in
Cargo.toml. The project previously stated no terms at all.
Changed
- Jobs start at the top level of the working tree, which is where git fires hooks from, whichever directory
krok runwas invoked from. - The binary is 47% smaller (1,142,272 → 606,208 bytes on Windows), built for size rather than speed.
- Binaries install to
~/.local/binrather than~/bin. - Every script in
bin/is POSIXsh; none require bash. - The minimum supported Rust version is declared as 1.85 and checked on every build.
- Preserved foreign hooks name themselves through
$KROK_HOOKS_DIRin the config. Configs written by 0.1.0 keep working.
Internal
- CI builds, lints and tests on Linux, Windows and macOS, and enforces
clippy -D warningsandcargo fmt --checkon each. Previously it built and tested on Linux only. - The archived
actions-rs/toolchain,actions/checkout@v2and a third-party tar action are gone; what remains is pinned. - 72 tests, up from 24: the integration suite grew, and the functions that only compute — key derivation, hook-name validation, wrapper state, path handling, command quoting — now have unit tests.