Files
carbon-lang/scripts/jj_prek.sh
T
Chandler Carruth 681b3b10c4 Add a jj push wrapper that runs prek before pushing. (#7805)
`scripts/jj_push.sh` takes the same arguments as `jj git push`, runs
prek over the commits that push would send, and pushes only if they
pass. It learns what is being sent by running `jj git push --dry-run`
and reading back the plan, so `--bookmark`, `--change`, `--all` and the
rest work without reimplementing how they select commits.

Hooks that rewrite files need a commit to write into, so the checks run
with the working copy on top of the commit being pushed. When the
working copy is already an empty commit there, which is the common case,
it is used directly; otherwise one is created, and named in the error so
the fixes can be squashed.

`scripts/jj_prek.sh` gets two changes. It forwards its arguments to
`prek run`, so `jj_push.sh` can ask for a specific range, and it now
changes to the workspace root before running. It exports `GIT_DIR`,
which makes git treat the current directory as the work tree, so prek
could not find its configuration from a subdirectory.

`jj` does not expand aliases when completing arguments, so `jj push`
completed file names. `scripts/completions` has Bash, Zsh, and Fish
completions that give it the same completions as `jj git push`.

`docs/project/contribution_tools.md` documents the `push` alias, and a
`prek` alias for `jj_prek.sh`, with the other per-repository `jj`
configuration. Both are opt-in.

Assisted-by: Claude Code
2026-09-18 19:40:25 +00:00

40 lines
1.5 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
# Exceptions. See /LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# Runs prek within a jj repository that is backed by a git repository, including
# the case where the repository is a non-colocated jj workspace.
set -eu
# Map `@` to a git commit. This deliberately doesn't pass
# `--ignore-working-copy`, so that jj first snapshots the files on disk into `@`;
# otherwise the index built below can describe stale file contents, and hooks
# both check the wrong thing and fail to write back their fixes.
HEAD="$(jj show --no-patch -r @ --template 'commit_id')"
# Run from the workspace root. Setting `GIT_DIR` makes git treat the current
# directory as the work tree, and prek looks there for its configuration, so
# running from a subdirectory would find neither. Hooks also expect paths
# relative to the root.
cd "$(jj workspace root --ignore-working-copy)"
# Find the .git directory. The working copy was snapshotted above, so this
# doesn't need to do so again.
export GIT_DIR="$(jj git root --ignore-working-copy)"
# Create a git index file describing `@`.
export GIT_INDEX_FILE="$(mktemp)"
trap 'rm -f "$GIT_INDEX_FILE"' EXIT
git read-tree "$HEAD"
# Run prek with the `.git` directory and index we built earlier. Arguments
# select what gets checked; with none, check everything between `trunk` and `@`.
if (($# > 0)); then
prek run "$@"
else
prek run --from-ref trunk --to-ref "$HEAD"
fi