- ninja login forces account selection (interactive when >1); creds now carry ActiveAccountID/Slug. New `ninja account` group. - ninja plugin list / delete / delete-version split public vs active-account @private sections; `publish --private` is sticky in plugin.mod. - GetPluginRequest gains active_account_id so @private resolution works alongside the public (scope, name) path. - publish auto-commits a dirty plugin.mod (path-scoped, leaves other staged paths alone) so the bump→publish loop never trips the dirty check. --allow-dirty is replaced with --strict (default now ships dirty trees via stash-create). - bump auto-commits its plugin.mod write with `bump to X.Y.Z`; --no-commit opts out. - Design doc updated to match the new defaults.
566 lines
16 KiB
Go
566 lines
16 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
core "git.dev.alexdunmow.com/block/core/plugin"
|
|
)
|
|
|
|
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 TestAutoCommitPluginMod_CommitsWhenDirty(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)
|
|
if err := autoCommitPluginMod("Add plugin.mod"); err != nil {
|
|
t.Fatalf("autoCommitPluginMod: %v", err)
|
|
}
|
|
|
|
subject := gitLogSubject(t, dir)
|
|
if subject != "Add plugin.mod" {
|
|
t.Errorf("expected latest commit subject 'Add plugin.mod', got %q", subject)
|
|
}
|
|
}
|
|
|
|
func TestAutoCommitPluginMod_NoopWhenClean(t *testing.T) {
|
|
dir := t.TempDir()
|
|
runGit(t, dir, "init", "-q")
|
|
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)
|
|
}
|
|
runGit(t, dir, "add", "plugin.mod")
|
|
runGit(t, dir, "commit", "-qm", "seed")
|
|
|
|
beforeSHA := gitHeadSHA(t, dir)
|
|
|
|
t.Chdir(dir)
|
|
if err := autoCommitPluginMod("Add plugin.mod"); err != nil {
|
|
t.Fatalf("autoCommitPluginMod: %v", err)
|
|
}
|
|
|
|
afterSHA := gitHeadSHA(t, dir)
|
|
if afterSHA != beforeSHA {
|
|
t.Errorf("expected no new commit, HEAD moved %s -> %s", beforeSHA, afterSHA)
|
|
}
|
|
}
|
|
|
|
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("Add plugin.mod"); 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_UsesProvidedMessage(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.3.0\"\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Chdir(dir)
|
|
if err := autoCommitPluginMod("bump to 0.3.0"); err != nil {
|
|
t.Fatalf("autoCommitPluginMod: %v", err)
|
|
}
|
|
|
|
if got := gitLogSubject(t, dir); got != "bump to 0.3.0" {
|
|
t.Errorf("expected commit subject 'bump to 0.3.0', got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAutoCommitPluginMod_LeavesOtherStagedPathsAlone(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")
|
|
|
|
// Stage an unrelated change that publish should NOT sweep up into the
|
|
// plugin.mod auto-commit.
|
|
if err := os.WriteFile(filepath.Join(dir, "other.txt"), []byte("scratch"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", "other.txt")
|
|
|
|
if err := os.WriteFile(filepath.Join(dir, "plugin.mod"),
|
|
[]byte("[plugin]\nname = \"x\"\nscope = \"@s\"\nversion = \"0.3.0\"\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Chdir(dir)
|
|
if err := autoCommitPluginMod("bump to 0.3.0"); err != nil {
|
|
t.Fatalf("autoCommitPluginMod: %v", err)
|
|
}
|
|
|
|
// The new commit should touch plugin.mod only.
|
|
filesCmd := exec.Command("git", "show", "--name-only", "--pretty=", "HEAD")
|
|
filesCmd.Dir = dir
|
|
filesOut, err := filesCmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git show: %v\n%s", err, filesOut)
|
|
}
|
|
files := strings.Fields(strings.TrimSpace(string(filesOut)))
|
|
if len(files) != 1 || files[0] != "plugin.mod" {
|
|
t.Errorf("expected commit to touch only plugin.mod, got %v", files)
|
|
}
|
|
|
|
// other.txt should still be staged (waiting for the developer to deal with).
|
|
statusCmd := exec.Command("git", "status", "--porcelain", "other.txt")
|
|
statusCmd.Dir = dir
|
|
statusOut, _ := statusCmd.Output()
|
|
if !strings.HasPrefix(strings.TrimSpace(string(statusOut)), "A ") {
|
|
t.Errorf("expected other.txt to remain staged ('A '), got %q", string(statusOut))
|
|
}
|
|
}
|
|
|
|
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("Add plugin.mod")
|
|
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")
|
|
cmd.Dir = dir
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git log: %v\n%s", err, out)
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
|
|
func gitHeadSHA(t *testing.T, dir string) string {
|
|
t.Helper()
|
|
cmd := exec.Command("git", "rev-parse", "HEAD")
|
|
cmd.Dir = dir
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git rev-parse: %v\n%s", err, out)
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
|
|
func TestGitignoredTrackedWarning_FiresWhenTrackedFileMatchesGitignore(t *testing.T) {
|
|
dir := t.TempDir()
|
|
runGit(t, dir, "init", "-q")
|
|
if err := os.WriteFile(filepath.Join(dir, "secret.env"), []byte("token=abc"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", "secret.env")
|
|
runGit(t, dir, "commit", "-qm", "init")
|
|
if err := os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.env\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", ".gitignore")
|
|
runGit(t, dir, "commit", "-qm", "ignore")
|
|
|
|
var buf bytes.Buffer
|
|
gitignoredTrackedWarning(dir, &buf)
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "secret.env") {
|
|
t.Errorf("warning should list secret.env, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "git rm --cached") {
|
|
t.Errorf("warning should suggest `git rm --cached`, got: %q", out)
|
|
}
|
|
if !strings.HasSuffix(out, "\n") {
|
|
t.Errorf("warning should end with a newline (Fprintln), got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestGitignoredTrackedWarning_NoopWhenNothingMatches(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")
|
|
|
|
var buf bytes.Buffer
|
|
gitignoredTrackedWarning(dir, &buf)
|
|
if buf.Len() != 0 {
|
|
t.Errorf("expected empty output for clean repo, got: %q", buf.String())
|
|
}
|
|
}
|
|
|
|
func TestUntrackedFilesWarning_FiresWithUntrackedFile(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, "notes.txt"), []byte("scratch"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
untrackedFilesWarning(dir, &buf)
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "notes.txt") {
|
|
t.Errorf("warning should list notes.txt, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "git add") {
|
|
t.Errorf("warning should suggest `git add`, got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestUntrackedFilesWarning_NoopWithNoUntracked(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")
|
|
|
|
var buf bytes.Buffer
|
|
untrackedFilesWarning(dir, &buf)
|
|
if buf.Len() != 0 {
|
|
t.Errorf("expected empty output, got: %q", buf.String())
|
|
}
|
|
}
|
|
|
|
func TestSubmoduleWarning_FiresWithGitmodules(t *testing.T) {
|
|
dir := t.TempDir()
|
|
runGit(t, dir, "init", "-q")
|
|
gitmodules := `[submodule "vendor/foo"]
|
|
path = vendor/foo
|
|
url = https://example.com/foo.git
|
|
`
|
|
if err := os.WriteFile(filepath.Join(dir, ".gitmodules"), []byte(gitmodules), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
submoduleWarning(dir, &buf)
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "vendor/foo") {
|
|
t.Errorf("warning should mention vendor/foo, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "submodules") {
|
|
t.Errorf("warning should mention submodules, got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestSubmoduleWarning_NoopWithoutGitmodules(t *testing.T) {
|
|
dir := t.TempDir()
|
|
runGit(t, dir, "init", "-q")
|
|
|
|
var buf bytes.Buffer
|
|
submoduleWarning(dir, &buf)
|
|
if buf.Len() != 0 {
|
|
t.Errorf("expected empty output, got: %q", buf.String())
|
|
}
|
|
}
|
|
|
|
func TestEmitPublishWarnings_WarnsAboutGitignoreTracked(t *testing.T) {
|
|
dir := t.TempDir()
|
|
runGit(t, dir, "init", "-q")
|
|
if err := os.WriteFile(filepath.Join(dir, "secret.env"), []byte("token=abc"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", "secret.env")
|
|
runGit(t, dir, "commit", "-qm", "init")
|
|
if err := os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.env\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", ".gitignore")
|
|
runGit(t, dir, "commit", "-qm", "ignore")
|
|
|
|
var buf bytes.Buffer
|
|
if err := emitPublishWarnings(dir, false, &buf); err != nil {
|
|
t.Fatalf("emitPublishWarnings: %v", err)
|
|
}
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "secret.env") {
|
|
t.Errorf("expected gitignored-tracked warning to mention secret.env, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "match .gitignore") {
|
|
t.Errorf("expected gitignored-tracked warning fragment, got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestEmitPublishWarnings_WarnsAboutSubmodules(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")
|
|
|
|
gitmodules := `[submodule "vendor/foo"]
|
|
path = vendor/foo
|
|
url = https://example.com/foo.git
|
|
`
|
|
if err := os.WriteFile(filepath.Join(dir, ".gitmodules"), []byte(gitmodules), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runGit(t, dir, "add", ".gitmodules")
|
|
runGit(t, dir, "commit", "-qm", "add submodule decl")
|
|
|
|
var buf bytes.Buffer
|
|
if err := emitPublishWarnings(dir, false, &buf); err != nil {
|
|
t.Fatalf("emitPublishWarnings: %v", err)
|
|
}
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "vendor/foo") {
|
|
t.Errorf("expected submodule warning to mention vendor/foo, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "submodules") {
|
|
t.Errorf("expected submodule warning fragment, got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestEmitPublishWarnings_WarnsAboutUntrackedWithAllowDirty(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, "scratch.txt"), []byte("notes"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Run("allowDirty=true surfaces untracked warning", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
if err := emitPublishWarnings(dir, true, &buf); err != nil {
|
|
t.Fatalf("emitPublishWarnings: %v", err)
|
|
}
|
|
out := buf.String()
|
|
if !strings.Contains(out, "scratch.txt") {
|
|
t.Errorf("expected untracked-files warning to mention scratch.txt, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "NOT be in the archive") {
|
|
t.Errorf("expected untracked-files warning fragment, got: %q", out)
|
|
}
|
|
})
|
|
|
|
t.Run("allowDirty=false aborts before untracked warning", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
err := emitPublishWarnings(dir, false, &buf)
|
|
if err == nil {
|
|
t.Fatal("expected dirty-tree error, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "working tree dirty") {
|
|
t.Errorf("expected dirty-tree error, got: %v", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "--strict") {
|
|
t.Errorf("expected dirty-tree error to reference --strict, got: %v", err)
|
|
}
|
|
if strings.Contains(buf.String(), "untracked files will NOT be in the archive") {
|
|
t.Errorf("untracked-files warning should not fire on dirty-abort path, got: %q", buf.String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestWriteMod_PrivateTrueSerializes(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "plugin.mod")
|
|
m := &core.ModFile{Plugin: core.ModPlugin{
|
|
Name: "myplugin",
|
|
Scope: "themes",
|
|
Version: "0.1.0",
|
|
Private: true,
|
|
}}
|
|
if err := writeMod(path, m); err != nil {
|
|
t.Fatalf("writeMod: %v", err)
|
|
}
|
|
got, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read back: %v", err)
|
|
}
|
|
if !strings.Contains(string(got), "private = true") {
|
|
t.Errorf("expected `private = true` line in plugin.mod, got:\n%s", got)
|
|
}
|
|
}
|
|
|
|
func TestWriteMod_PrivateFalseOmitted(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "plugin.mod")
|
|
m := &core.ModFile{Plugin: core.ModPlugin{
|
|
Name: "publicthing",
|
|
Scope: "themes",
|
|
Version: "0.1.0",
|
|
}}
|
|
if err := writeMod(path, m); err != nil {
|
|
t.Fatalf("writeMod: %v", err)
|
|
}
|
|
got, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read back: %v", err)
|
|
}
|
|
if strings.Contains(string(got), "private") {
|
|
t.Errorf("expected no `private` line, got:\n%s", got)
|
|
}
|
|
}
|
|
|
|
func TestParsePrivateCoord(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{in: "myplugin", want: "myplugin"},
|
|
{in: "@private/myplugin", want: "myplugin"},
|
|
{in: " myplugin ", want: "myplugin"},
|
|
{in: "@themes/myplugin", wantErr: true},
|
|
{in: "@private", wantErr: true},
|
|
}
|
|
for _, c := range cases {
|
|
got, err := parsePrivateCoord(c.in)
|
|
if c.wantErr {
|
|
if err == nil {
|
|
t.Errorf("parsePrivateCoord(%q) = %q, want error", c.in, got)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil {
|
|
t.Errorf("parsePrivateCoord(%q) err: %v", c.in, err)
|
|
continue
|
|
}
|
|
if got != c.want {
|
|
t.Errorf("parsePrivateCoord(%q) = %q, want %q", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|