Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ scripts/
install-resq.sh β€” Installs the `resq` CLI binary from GitHub Releases (SHA-verified)
# Canonical hook templates are owned by resq-software/crates
# (crates/resq-cli/templates/git-hooks/). install-hooks.sh fetches them
# from there (or lets `resq dev install-hooks` scaffold offline). No copy
# from there (or lets `resq hooks install` scaffold offline). No copy
# lives in this repo.
lib/
log.{sh,ps1} β€” Colored log helpers
Expand Down Expand Up @@ -65,7 +65,7 @@ Canonical hook templates live in
[`resq-software/crates`](https://github.com/resq-software/crates/tree/master/crates/resq-cli/templates/git-hooks)
and are installed into any ResQ repo by `scripts/install-hooks.sh` (or
`.ps1`). When the `resq` binary is on PATH, the installer calls
`resq dev install-hooks` which scaffolds from the embedded templates β€”
`resq hooks install` which scaffolds from the embedded templates β€”
offline, no network round-trip. Without `resq`, it falls back to fetching
the templates from the crates repo via raw.githubusercontent.com.

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ Everything is pinned via Nix flakes. No "works on my machine" issues.

Six hook shims live in [`resq-software/crates`](https://github.com/resq-software/crates/tree/master/crates/resq-cli/templates/git-hooks) β€” embedded in the `resq` binary *and* served at a stable raw URL. `install-hooks.sh` picks the best path automatically:

1. **`resq` on PATH** β†’ calls `resq dev install-hooks`, which scaffolds the 6 canonical hooks from the templates embedded in the binary. Offline, versioned with the installed `resq`.
1. **`resq` on PATH** β†’ calls `resq hooks install`, which scaffolds the 6 canonical hooks from the templates embedded in the binary. Offline, versioned with the installed `resq`.
2. **No `resq`** β†’ falls back to `curl` from `resq-software/crates/master/.../templates/git-hooks/`.

The hooks delegate logic back to the `resq` binary (`resq pre-commit`, etc.), so updates roll out via `cargo install --git` (or `install-resq.sh`) without editing every repo.
Expand All @@ -249,12 +249,12 @@ The hooks delegate logic back to the `resq` binary (`resq pre-commit`, etc.), so
Each hook then dispatches to `.git-hooks/local-<hook-name>` (if executable) β€” the **only** place a repo commits hook customization. Generate one with the right language template:

```bash
resq dev scaffold-local-hook --kind auto # detects rust/python/node/dotnet/cpp/nix
resq hooks scaffold-local --kind auto # detects rust/python/node/dotnet/cpp/nix
```

`resq hooks doctor` reports drift, `resq hooks update` re-syncs from the embedded canonical, `resq hooks status` prints a one-line shell-friendly summary.

The canonical content lives in exactly one place: [`crates/resq-cli/templates/git-hooks/`](https://github.com/resq-software/crates/tree/master/crates/resq-cli/templates/git-hooks). The crates repo's own `.git-hooks/` (for dog-fooding) is kept identical via `hooks-sync.yml`. The `dev/` repo used to ship a third copy and was retired in Phase 4 β€” `install-hooks.sh` now fetches from the crates source (or lets `resq dev install-hooks` do it offline). Bats + Rust integration tests cover the hook behavior end-to-end.
The canonical content lives in exactly one place: [`crates/resq-cli/templates/git-hooks/`](https://github.com/resq-software/crates/tree/master/crates/resq-cli/templates/git-hooks). The crates repo's own `.git-hooks/` (for dog-fooding) is kept identical via `hooks-sync.yml`. The `dev/` repo used to ship a third copy and was retired in Phase 4 β€” `install-hooks.sh` now fetches from the crates source (or lets `resq hooks install` do it offline). Bats + Rust integration tests cover the hook behavior end-to-end.

## πŸ“„ License

Expand Down
24 changes: 17 additions & 7 deletions scripts/install-hooks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ if ($onPath) {
}

# ── Path 1: use resq when present (preferred β€” offline, no raw fetch) ───────
# Prefer the new `hooks install` path; fall back to `dev install-hooks`
# for binaries built before resq-software/crates#60.
if ($resqBin) {
Write-Host "info Installing hooks via $resqBin dev install-hooks" -ForegroundColor Cyan
& $resqBin hooks install --help *> $null
$installArgs = if ($LASTEXITCODE -eq 0) { @('hooks', 'install') } else { @('dev', 'install-hooks') }
Write-Host "info Installing hooks via $resqBin $($installArgs -join ' ')" -ForegroundColor Cyan
Push-Location $targetRoot
try { & $resqBin dev install-hooks } finally { Pop-Location }
try { & $resqBin @installArgs } finally { Pop-Location }
} else {
# ── Path 2: fall back to raw fetch from crates templates ────────────────
$hooks = @('pre-commit','commit-msg','prepare-commit-msg','pre-push','post-checkout','post-merge')
Expand Down Expand Up @@ -77,9 +81,15 @@ if (-not $resqBin) {
# ── Local-hook scaffold prompt ──────────────────────────────────────────────
if ((Test-Path (Join-Path $hooksDir 'local-pre-push')) -or $env:RESQ_SKIP_LOCAL_SCAFFOLD) { exit 0 }

# Probe for subcommand support.
$probe = & $resqBin dev scaffold-local-hook --help 2>&1
if ($LASTEXITCODE -ne 0) { exit 0 }
# Probe for subcommand support; prefer the new path.
& $resqBin hooks scaffold-local --help *> $null
if ($LASTEXITCODE -eq 0) {
$scaffoldArgs = @('hooks', 'scaffold-local')
} else {
& $resqBin dev scaffold-local-hook --help *> $null
if ($LASTEXITCODE -ne 0) { exit 0 }
$scaffoldArgs = @('dev', 'scaffold-local-hook')
}

$answer = ''
if ($env:YES -eq '1') {
Expand All @@ -91,9 +101,9 @@ if ($env:YES -eq '1') {
if ($answer -match '^[yY]') {
Push-Location $targetRoot
try {
& $resqBin dev scaffold-local-hook --kind auto
& $resqBin @scaffoldArgs --kind auto
if ($LASTEXITCODE -ne 0) {
Write-Host 'warn scaffold-local-hook failed; run it manually with --kind <name>.' -ForegroundColor Yellow
Write-Host 'warn scaffold-local failed; run it manually with --kind <name>.' -ForegroundColor Yellow
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the bash script, this warning message hardcodes scaffold-local. If the fallback command dev scaffold-local-hook was used and failed, the user is directed to run a command their binary likely doesn't support. Using the actual command attempted from $scaffoldArgs would be more accurate.

            Write-Host "warn  $($scaffoldArgs -join ' ') failed; run it manually with --kind <name>." -ForegroundColor Yellow

}
} finally { Pop-Location }
}
26 changes: 21 additions & 5 deletions scripts/install-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,17 @@ elif [ -x "$HOME/.cargo/bin/resq" ]; then
fi

# ── Path 1: use resq when present (preferred β€” offline, no raw fetch) ───────
# Prefer the new `hooks install` path; fall back to `dev install-hooks` for
# binaries built before resq-software/crates#60.
if [ -n "$RESQ_BIN" ]; then
printf 'info Installing hooks via %s dev install-hooks\n' "$RESQ_BIN" >&2
(cd "$TARGET_ROOT" && "$RESQ_BIN" dev install-hooks)
if "$RESQ_BIN" hooks install --help >/dev/null 2>&1; then
install_cmd="hooks install"
else
install_cmd="dev install-hooks"
fi
printf 'info Installing hooks via %s %s\n' "$RESQ_BIN" "$install_cmd" >&2
# shellcheck disable=SC2086
(cd "$TARGET_ROOT" && "$RESQ_BIN" $install_cmd)
else
# ── Path 2: fall back to raw fetch from crates templates ────────────────
HOOKS="pre-commit commit-msg prepare-commit-msg pre-push post-checkout post-merge"
Expand Down Expand Up @@ -82,7 +90,14 @@ fi
if [ -f "$HOOKS_DIR/local-pre-push" ] || [ -n "${RESQ_SKIP_LOCAL_SCAFFOLD:-}" ]; then
exit 0
fi
if ! "$RESQ_BIN" dev scaffold-local-hook --help >/dev/null 2>&1; then
# Probe for the new `hooks scaffold-local` path first; fall back to the
# legacy `dev scaffold-local-hook` for older binaries. Skip entirely if
# neither is available (very old resq).
if "$RESQ_BIN" hooks scaffold-local --help >/dev/null 2>&1; then
scaffold_cmd="hooks scaffold-local"
elif "$RESQ_BIN" dev scaffold-local-hook --help >/dev/null 2>&1; then
scaffold_cmd="dev scaffold-local-hook"
else
exit 0
fi

Expand All @@ -96,7 +111,8 @@ fi

case "$answer" in
[yY]|[yY][eE][sS])
(cd "$TARGET_ROOT" && "$RESQ_BIN" dev scaffold-local-hook --kind auto) \
|| printf 'warn scaffold-local-hook failed; run it manually with --kind <name>.\n' >&2
# shellcheck disable=SC2086
(cd "$TARGET_ROOT" && "$RESQ_BIN" $scaffold_cmd --kind auto) \
|| printf 'warn scaffold-local failed; run it manually with --kind <name>.\n' >&2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The warning message hardcodes the new command name scaffold-local. If the script falls back to the legacy dev scaffold-local-hook and that command fails, the warning will suggest running a command (scaffold-local) that the user's current binary does not support. It would be better to use the command name that was actually attempted.

Suggested change
|| printf 'warn scaffold-local failed; run it manually with --kind <name>.\n' >&2
|| printf 'warn %s failed; run it manually with --kind <name>.\n' "$scaffold_cmd" >&2

;;
esac
Loading