Skip to content

hooks --install --adopt refuses a whole directory for one file, and reads an inlined hook-dir expression as a hook that does something else #209

Description

@HackingGate

What happened

Ten consumer trees carry hand-written
.githooks/{pre-commit,commit-msg,pre-merge-commit,pre-push} delegates
that predate hooks --install. uphold hooks --install --adopt (1.19.0)
refused all ten with exit 2. Three of the four files in each tree spell
the hook directory inline, on the exec line:

exec prek hook-impl --hook-dir "$(cd "$(dirname "$0")" && pwd)" ...

where delegate_hook in src/hooks.rs binds it first:

hook_dir="$(cd "$(dirname "$0")" && pwd)"
exec prek hook-impl --hook-dir "$hook_dir" ...

--check reported the pre-push copy as adoptable and the other three as
"NOT the text this binary writes". The consumers git rm-ed the four
files and ran plain --install, which is the move-aside #199 asked
--adopt to spare them.

Why

install in src/hooks.rs walks STAGES in order and, under
Mode::Adopt, compares effective_lines(&current) with
effective_lines(&body) per file. effective_lines drops comments,
joins continuations and collapses whitespace, so a different wrap is one
spelling, but an inlined $(...) argument and the same expression bound
to hook_dir a line earlier are two lines against three, and the first
mismatch is return Err(...). One differing file refuses the directory,
and a file adopted in an earlier iteration has already been rewritten
with its marker when the loop stops: pre-commit matching and commit-msg
not leaves one marked file, exit 2, and nothing else done.

What would close it

Adopt per file: take over the copies whose lines match, refuse only the
ones that do not, name them, and write nothing until every file has been
judged. Compare a normalised form that reads an inlined $(...)
argument and the same expression assigned to a variable on the preceding
line as one spelling -- or, simpler, compare the argv the exec line would
produce after substituting the local assignments above it. A test with
the three-line and two-line forms of one delegate, adopted as equal.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions