fix(cli): friendly error when publishing from a repo with no commits
Previously a brand-new repo (git init, no commits) surfaced `git stash create: exit status 128: You do not have the initial commit yet` from deep inside the archive helper. Now the publish flow detects this case via `git rev-parse --verify HEAD` up front and prints "no commits in repository; run `git add . && git commit` before publishing". Also updates the init flow's hint to mention `git init && git commit` so users aren't misled into thinking `git init` alone is enough. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
20a7b35e50
commit
4c0104619e
@ -109,7 +109,7 @@ func newPluginInitCmd() *cobra.Command {
|
|||||||
fmt.Fprintf(os.Stderr, "warning: could not commit plugin.mod: %v\n", err)
|
fmt.Fprintf(os.Stderr, "warning: could not commit plugin.mod: %v\n", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Not in a git repo - run `git init` before `ninja plugin publish`")
|
fmt.Println("Not in a git repo - run `git init && git commit` before `ninja plugin publish`")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -294,6 +294,10 @@ func newPluginPublishCmd() *cobra.Command {
|
|||||||
return fmt.Errorf("plugin.mod must have scope, name, and version")
|
return fmt.Errorf("plugin.mod must have scope, name, and version")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkRepoHasHEAD("."); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !allowDirty {
|
if !allowDirty {
|
||||||
out, _ := exec.Command("git", "status", "--porcelain").Output()
|
out, _ := exec.Command("git", "status", "--porcelain").Output()
|
||||||
if len(strings.TrimSpace(string(out))) > 0 {
|
if len(strings.TrimSpace(string(out))) > 0 {
|
||||||
@ -548,6 +552,20 @@ func runCmd(name string, args ...string) error {
|
|||||||
return c.Run()
|
return c.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkRepoHasHEAD returns a friendlier error than the raw git failure when
|
||||||
|
// the publish flow is invoked in a freshly-initialised repository that has
|
||||||
|
// no commits yet. Without this, `git stash create` reports "You do not have
|
||||||
|
// the initial commit yet" via exit status 128, which surfaces as an internal
|
||||||
|
// failure to the user.
|
||||||
|
func checkRepoHasHEAD(repoDir string) error {
|
||||||
|
cmd := exec.Command("git", "rev-parse", "--verify", "HEAD")
|
||||||
|
cmd.Dir = repoDir
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return fmt.Errorf("no commits in repository; run `git add . && git commit` before publishing")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func upsertPluginMod(scope, name, kind string, categories []string) error {
|
func upsertPluginMod(scope, name, kind string, categories []string) error {
|
||||||
const file = "plugin.mod"
|
const file = "plugin.mod"
|
||||||
existing, _ := os.ReadFile(file)
|
existing, _ := os.ReadFile(file)
|
||||||
|
|||||||
55
cmd/ninja/cmd/plugin_test.go
Normal file
55
cmd/ninja/cmd/plugin_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCheckRepoHasHEAD_NoCommitsReturnsFriendlyError(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
runGit(t, dir, "init", "-q")
|
||||||
|
|
||||||
|
err := checkRepoHasHEAD(dir)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for repo with no commits, got nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "no commits in repository") {
|
||||||
|
t.Errorf("error %q should mention 'no commits in repository'", err.Error())
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "git commit") {
|
||||||
|
t.Errorf("error %q should suggest `git commit`", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckRepoHasHEAD_WithCommitReturnsNil(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
runGit(t, dir, "init", "-q")
|
||||||
|
if err := os.WriteFile(filepath.Join(dir, "f"), []byte("hi"), 0o644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
runGit(t, dir, "add", "f")
|
||||||
|
runGit(t, dir, "commit", "-qm", "init")
|
||||||
|
|
||||||
|
if err := checkRepoHasHEAD(dir); err != nil {
|
||||||
|
t.Errorf("expected nil for repo with a commit, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runGit(t *testing.T, dir string, args ...string) {
|
||||||
|
t.Helper()
|
||||||
|
cmd := exec.Command("git", args...)
|
||||||
|
cmd.Dir = dir
|
||||||
|
cmd.Env = append(os.Environ(),
|
||||||
|
"GIT_AUTHOR_NAME=t",
|
||||||
|
"GIT_AUTHOR_EMAIL=t@t",
|
||||||
|
"GIT_COMMITTER_NAME=t",
|
||||||
|
"GIT_COMMITTER_EMAIL=t@t",
|
||||||
|
)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("git %v: %v\n%s", args, err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user