From 7b1cc80f46978d5b390fb55f0fc5fb624af1d928 Mon Sep 17 00:00:00 2001 From: olavostauros Date: Fri, 26 Jun 2026 14:19:48 -0300 Subject: [PATCH] fix(init): suppress detached-HEAD advice for pinned modules (#50) Add -c advice.detachedHead=false to the git checkout call so pinned-module checkout during modules init does not print Git's verbose detached-HEAD advice block. Also add a pinned status line matching the tracked format. Tracked modules already use -q (quiet) checkouts and are unaffected. Real checkout errors (invalid SHA, corrupt object) still surface through the fatal: prefix. Closes #50 --- .mise/tasks/init | 4 +++- README.md | 4 ++-- test/init.bats | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/.mise/tasks/init b/.mise/tasks/init index 5ff9e5b..3b6a18d 100755 --- a/.mise/tasks/init +++ b/.mise/tasks/init @@ -108,11 +108,13 @@ while IFS=$'\t' read -r name url pin track; do if [ -n "$track" ]; then sync_to_track "$name" "$mod_path" "$track" || errors=$((errors + 1)) else - git -C "$mod_path" checkout "$pin" 2>&1 + git -C "$mod_path" -c advice.detachedHead=false checkout "$pin" 2>&1 actual="$(git -C "$mod_path" rev-parse HEAD)" if [ "$actual" != "$pin" ]; then echo " $name: warning — expected $pin, at $actual" >&2 + else + echo " $name: pinned ${actual:0:12}" fi fi done < "$MANIFEST" diff --git a/README.md b/README.md index 7e7c766..ebf91ec 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Manage repo-level dependencies with an encrypted manifest and a gitignored clone A public observer sees only 'this repo uses modules' — no names, no pinned commits, no count. ![lang: bash](https://img.shields.io/badge/lang-bash-4EAA25?style=flat&logo=gnubash&logoColor=white) -[![tests: 136 passing](https://img.shields.io/badge/tests-136%20passing-brightgreen?style=flat)](test/) +[![tests: 138 passing](https://img.shields.io/badge/tests-138%20passing-brightgreen?style=flat)](test/) ![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat) @@ -122,7 +122,7 @@ cd modules && mise trust && mise install mise run test ``` -**136 tests** across 13 suites, using [BATS](https://github.com/bats-core/bats-core). All tests use local git repos in temp directories — no network, no external dependencies. +**138 tests** across 13 suites, using [BATS](https://github.com/bats-core/bats-core). All tests use local git repos in temp directories — no network, no external dependencies. The `git-mechanics` suite verifies git's behavior around gitignored nested repos. The `merge-driver` suite simulates concurrent pin bumps to validate the manifest merge logic. The `roundtrip` suite drives the full setup → add → lock → fresh-clone → unlock → init path end-to-end with git-crypt. diff --git a/test/init.bats b/test/init.bats index d324f1a..a00f4b6 100644 --- a/test/init.bats +++ b/test/init.bats @@ -57,6 +57,47 @@ setup() { [ "$actual" = "$pin" ] } +@test "init prints pinned status line for pinned modules" { + modules add "$REMOTE" --name my-repo + git -C "$PARENT" commit -m "add module" + + local pin + pin="$(manifest_pin_of "$PARENT/.modules/manifest" "my-repo")" + + # Remove clone so init re-clones and checks out + rm -rf "$PARENT/modules/my-repo" + + run modules init + [ "$status" -eq 0 ] + + # Should print a pinned status line with the short SHA (not the long advice block) + [[ "$output" == *"pinned "* ]] + [[ "$output" == *"my-repo"* ]] + [[ "$output" != *"Note: switching to"* ]] + [[ "$output" != *"detached HEAD"* ]] +} + +@test "init preserves real checkout errors for pinned modules" { + modules add "$REMOTE" --name my-repo + + # Use a SHA that doesn't exist in the remote + local bad_pin="0000000000000000000000000000000000000000" + + # Replace the pin in the manifest directly via awk (TSV: nameurlpin) + local url + url="$(manifest_url_of "$PARENT/.modules/manifest" "my-repo")" + awk -F' ' -v n="my-repo" -v u="$url" -v p="$bad_pin" 'BEGIN{OFS=" "} $1==n{$3=p} 1' "$PARENT/.modules/manifest" > "$PARENT/.modules/manifest.tmp" + mv "$PARENT/.modules/manifest.tmp" "$PARENT/.modules/manifest" + git -C "$PARENT" add .modules/manifest + git -C "$PARENT" commit -m "bad pin" + + rm -rf "$PARENT/modules/my-repo" + + run modules init + [ "$status" -ne 0 ] + [[ "$output" == *"fatal"* || "$output" == *"paths"* || "$output" == *"not a valid object"* ]] +} + @test "init skips already-cloned untracked modules" { modules add "$REMOTE" --name my-repo