From 3d62071f77d8ecc6deb8316f857516b8b0324da5 Mon Sep 17 00:00:00 2001 From: Alex Dunmow Date: Wed, 3 Jun 2026 10:13:53 +0800 Subject: [PATCH] test(cli): cover autoCommitPluginMod detached HEAD and missing git Adds coverage for two git-edge cases: commits land correctly on a detached HEAD with the prior commit as parent, and an empty PATH produces a git-mentioning error rather than a panic. --- cmd/ninja/cmd/plugin_test.go | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/cmd/ninja/cmd/plugin_test.go b/cmd/ninja/cmd/plugin_test.go index b84113e..1ca84c8 100644 --- a/cmd/ninja/cmd/plugin_test.go +++ b/cmd/ninja/cmd/plugin_test.go @@ -87,6 +87,76 @@ func TestAutoCommitPluginMod_NoopWhenClean(t *testing.T) { } } +func TestAutoCommitPluginMod_WorksOnDetachedHEAD(t *testing.T) { + dir := t.TempDir() + runGit(t, dir, "init", "-q") + if err := os.WriteFile(filepath.Join(dir, "README.md"), []byte("hi"), 0o644); err != nil { + t.Fatal(err) + } + runGit(t, dir, "add", "README.md") + runGit(t, dir, "commit", "-qm", "init") + + initialSHA := gitHeadSHA(t, dir) + runGit(t, dir, "checkout", "-q", initialSHA) + + if err := os.WriteFile(filepath.Join(dir, "plugin.mod"), + []byte("[plugin]\nname = \"x\"\nscope = \"@s\"\nversion = \"0.1.0\"\n"), 0o644); err != nil { + t.Fatal(err) + } + + t.Chdir(dir) + if err := autoCommitPluginMod(); err != nil { + t.Fatalf("autoCommitPluginMod on detached HEAD: %v", err) + } + + afterSHA := gitHeadSHA(t, dir) + if afterSHA == initialSHA { + t.Fatalf("expected new commit on detached HEAD, HEAD still at %s", afterSHA) + } + + subject := gitLogSubject(t, dir) + if subject != "Add plugin.mod" { + t.Errorf("expected latest commit subject 'Add plugin.mod', got %q", subject) + } + + parentCmd := exec.Command("git", "rev-parse", "HEAD^") + parentCmd.Dir = dir + parentOut, err := parentCmd.CombinedOutput() + if err != nil { + t.Fatalf("git rev-parse HEAD^: %v\n%s", err, parentOut) + } + parentSHA := strings.TrimSpace(string(parentOut)) + if parentSHA != initialSHA { + t.Errorf("expected new commit parent to be %s, got %s", initialSHA, parentSHA) + } +} + +func TestAutoCommitPluginMod_ErrorsWhenGitMissing(t *testing.T) { + dir := t.TempDir() + runGit(t, dir, "init", "-q") + if err := os.WriteFile(filepath.Join(dir, "README.md"), []byte("hi"), 0o644); err != nil { + t.Fatal(err) + } + runGit(t, dir, "add", "README.md") + runGit(t, dir, "commit", "-qm", "init") + + if err := os.WriteFile(filepath.Join(dir, "plugin.mod"), + []byte("[plugin]\nname = \"x\"\nscope = \"@s\"\nversion = \"0.1.0\"\n"), 0o644); err != nil { + t.Fatal(err) + } + + t.Chdir(dir) + t.Setenv("PATH", "") + + err := autoCommitPluginMod() + if err == nil { + t.Fatal("expected error when git is missing from PATH, got nil") + } + if !strings.Contains(err.Error(), "git") { + t.Errorf("error %q should mention 'git'", err.Error()) + } +} + func gitLogSubject(t *testing.T, dir string) string { t.Helper() cmd := exec.Command("git", "log", "-1", "--pretty=%s")