fix(api): 单次调用支持 :owner/:repo 与 {{owner}}/{{repo}} 占位符替换(issue #20)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
604303e953
commit
a383b0a00b
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/gitlink-org/gitlink-cli/cmd/cmdutil"
|
||||
"github.com/gitlink-org/gitlink-cli/internal/client"
|
||||
repocontext "github.com/gitlink-org/gitlink-cli/internal/context"
|
||||
"github.com/gitlink-org/gitlink-cli/internal/i18n"
|
||||
"github.com/gitlink-org/gitlink-cli/internal/output"
|
||||
)
|
||||
|
|
@ -73,6 +74,11 @@ func runAPI(c *cobra.Command, args []string) error {
|
|||
path = "/" + path
|
||||
}
|
||||
|
||||
path, err := resolvePathPlaceholders(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cli, err := client.New()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -107,6 +113,27 @@ func runAPI(c *cobra.Command, args []string) error {
|
|||
return output.Print(env, resolveFormat())
|
||||
}
|
||||
|
||||
// resolvePathPlaceholders substitutes :owner/:repo (and {{owner}}/{{repo}})
|
||||
// segments in a single-call path with the global --owner/--repo flags or the
|
||||
// values auto-resolved from the current git remote, matching the help-text
|
||||
// examples. Paths without placeholders are returned unchanged.
|
||||
func resolvePathPlaceholders(path string) (string, error) {
|
||||
hasColon := strings.Contains(path, "/:owner") || strings.Contains(path, "/:repo")
|
||||
hasBrace := strings.Contains(path, "{{owner}}") || strings.Contains(path, "{{repo}}")
|
||||
if !hasColon && !hasBrace {
|
||||
return path, nil
|
||||
}
|
||||
owner, repo, err := repocontext.ResolveOwnerRepo(cmdutil.Owner, cmdutil.Repo)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("path contains :owner/:repo placeholders: %w", err)
|
||||
}
|
||||
path = strings.ReplaceAll(path, "/:owner", "/"+owner)
|
||||
path = strings.ReplaceAll(path, "/:repo", "/"+repo)
|
||||
path = strings.ReplaceAll(path, "{{owner}}", owner)
|
||||
path = strings.ReplaceAll(path, "{{repo}}", repo)
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func readJSONBody(c *cobra.Command) (interface{}, error) {
|
||||
bodyStr, _ := c.Flags().GetString("body")
|
||||
bodyFile, _ := c.Flags().GetString("body-file")
|
||||
|
|
|
|||
|
|
@ -32,6 +32,55 @@ func TestResolveFormat(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestResolvePathPlaceholders(t *testing.T) {
|
||||
origOwner, origRepo := cmdutil.Owner, cmdutil.Repo
|
||||
t.Cleanup(func() { cmdutil.Owner, cmdutil.Repo = origOwner, origRepo })
|
||||
cmdutil.Owner, cmdutil.Repo = "demo-owner", "demo-repo"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
want string
|
||||
}{
|
||||
{"colon placeholders", "/:owner/:repo/issues", "/demo-owner/demo-repo/issues"},
|
||||
{"colon with suffix", "/:owner/:repo/issues/42", "/demo-owner/demo-repo/issues/42"},
|
||||
{"brace placeholders", "/{{owner}}/{{repo}}/pulls", "/demo-owner/demo-repo/pulls"},
|
||||
{"no placeholders unchanged", "/users/me", "/users/me"},
|
||||
{"literal path unchanged", "/Gitlink/gitlink-cli/issues", "/Gitlink/gitlink-cli/issues"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := resolvePathPlaceholders(tt.path)
|
||||
if err != nil {
|
||||
t.Fatalf("resolvePathPlaceholders(%q): %v", tt.path, err)
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Fatalf("resolvePathPlaceholders(%q) = %q, want %q", tt.path, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePathPlaceholdersUnresolvable(t *testing.T) {
|
||||
origOwner, origRepo := cmdutil.Owner, cmdutil.Repo
|
||||
t.Cleanup(func() { cmdutil.Owner, cmdutil.Repo = origOwner, origRepo })
|
||||
cmdutil.Owner, cmdutil.Repo = "", ""
|
||||
|
||||
tmp := t.TempDir()
|
||||
origWD, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = os.Chdir(origWD) })
|
||||
if err := os.Chdir(tmp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := resolvePathPlaceholders("/:owner/:repo/issues"); err == nil {
|
||||
t.Fatal("expected error when owner/repo cannot be resolved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAPICmd(t *testing.T) {
|
||||
cmd := NewAPICmd()
|
||||
if cmd.Use != "api (<METHOD> <PATH> | --batch-file <FILE>)" {
|
||||
|
|
|
|||
Loading…
Reference in New Issue