diff --git a/README.md b/README.md index d177618..60107af 100644 --- a/README.md +++ b/README.md @@ -227,17 +227,17 @@ gitlink-cli repo +readme --owner Gitlink --repo forgeplus --ref master gitlink-cli repo +tree --owner Gitlink --repo forgeplus --ref master gitlink-cli repo +tree --owner Gitlink --repo forgeplus --path src --ref main -# Line-by-line blame for a file -gitlink-cli repo +blame --owner Gitlink --repo forgeplus -p README.md --ref master - # Show language breakdown gitlink-cli repo +languages --owner Gitlink --repo forgeplus # List contributors gitlink-cli repo +contributors --owner Gitlink --repo forgeplus -# Repository activity feed, filterable by type/action/time window -gitlink-cli repo +activity --owner Gitlink --repo forgeplus -t Issue -s close --time 30 +# List users who forked the repository +gitlink-cli repo +forks --owner Gitlink --repo forgeplus + +# Top-line counts (tags, branches, commits, releases, size) +gitlink-cli repo +top-counts --owner Gitlink --repo forgeplus # Show contributor code-line stats for a branch, tag, or commit gitlink-cli repo +contributor-stats --owner Gitlink --repo forgeplus --ref master --pass-year 1 diff --git a/internal/i18n/locales/en-US.json b/internal/i18n/locales/en-US.json index a654db3..a69e8e3 100644 --- a/internal/i18n/locales/en-US.json +++ b/internal/i18n/locales/en-US.json @@ -85,9 +85,11 @@ "cmd.repo.create.short": "Create a new repository", "cmd.repo.delete.short": "Delete a repository", "cmd.repo.fork.short": "Fork a repository", + "cmd.repo.forks.short": "List users who forked the repository", "cmd.repo.info.short": "Show repository details", "cmd.repo.list.short": "List repositories for a user or organization", "cmd.repo.short": "Repository operations", + "cmd.repo.top_counts.short": "Show repository top-line counts (tags, branches, commits, releases, size)", "cmd.repo.tree.short": "List repository files and directories", "cmd.root.long": "Manage repositories, issues, pull requests, releases, CI and workflows on GitLink.", "cmd.root.short": "GitLink CLI - command-line tool for GitLink", diff --git a/internal/i18n/locales/zh-CN.json b/internal/i18n/locales/zh-CN.json index c942a66..15a992f 100644 --- a/internal/i18n/locales/zh-CN.json +++ b/internal/i18n/locales/zh-CN.json @@ -85,9 +85,11 @@ "cmd.repo.create.short": "创建新仓库", "cmd.repo.delete.short": "删除仓库", "cmd.repo.fork.short": "Fork 仓库", + "cmd.repo.forks.short": "列出 fork 该仓库的用户", "cmd.repo.info.short": "显示仓库详情", "cmd.repo.list.short": "列出用户或组织的仓库", "cmd.repo.short": "仓库操作", + "cmd.repo.top_counts.short": "显示仓库概览计数(标签/分支/提交/发行版/体积)", "cmd.repo.tree.short": "列出仓库文件和目录", "cmd.root.long": "用于管理 GitLink 上的仓库、议题、拉取请求、发布、CI 和工作流。", "cmd.root.short": "GitLink CLI - GitLink 命令行工具", diff --git a/shortcuts/repo/repo.go b/shortcuts/repo/repo.go index 4e35569..165554c 100644 --- a/shortcuts/repo/repo.go +++ b/shortcuts/repo/repo.go @@ -216,6 +216,28 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { return runCommunityList(ctx, "stargazers") }, }, + { + Name: "forks", + Description: tr.T("cmd.repo.forks.short"), + Flags: communityListFlags(), + Run: func(ctx *common.RuntimeContext) error { + return runCommunityList(ctx, "forks") + }, + }, + { + Name: "top-counts", + Description: tr.T("cmd.repo.top_counts.short"), + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + env, err := ctx.CallAPI("GET", ctx.RepoPath()+"/top_counts", nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, { Name: "follow", Description: "Follow a repository", diff --git a/shortcuts/repo/repo_test.go b/shortcuts/repo/repo_test.go index dbabde7..5bef25c 100644 --- a/shortcuts/repo/repo_test.go +++ b/shortcuts/repo/repo_test.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "net/http/httptest" - "strings" "testing" "github.com/gitlink-org/gitlink-cli/internal/client" @@ -636,28 +635,30 @@ func assertEqual(t *testing.T, got interface{}, want interface{}) { } } -func TestRepoActivityForwardsFilters(t *testing.T) { - var query string +func TestRepoForksListsForkUsers(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != "GET" || r.URL.Path != "/owner/repo/activity.json" { + if r.Method != "GET" || r.URL.Path != "/owner/repo/forks.json" { t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) } - query = r.URL.RawQuery - writeJSON(t, w, map[string]interface{}{"project_trends": []interface{}{}}) + writeJSON(t, w, map[string]interface{}{"count": 0, "users": []interface{}{}}) })) defer server.Close() - args := map[string]string{"type": "Issue", "status": "create", "time": "30", "page": "1", "limit": "20"} - if err := runShortcut(t, server, "activity", args); err != nil { - t.Fatalf("activity failed: %v", err) - } - for _, want := range []string{"type=Issue", "status=create", "time=30"} { - if !strings.Contains(query, want) { - t.Fatalf("expected %q in query, got %q", want, query) - } - } - - if err := runShortcut(t, server, "activity", map[string]string{"time": "abc", "page": "1", "limit": "20"}); err == nil { - t.Fatal("expected error for non-integer --time") + if err := runShortcut(t, server, "forks", map[string]string{}); err != nil { + t.Fatalf("forks failed: %v", err) + } +} + +func TestRepoTopCountsUsesTopCountsEndpoint(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" || r.URL.Path != "/owner/repo/top_counts.json" { + t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) + } + writeJSON(t, w, map[string]interface{}{"tags_count": float64(1)}) + })) + defer server.Close() + + if err := runShortcut(t, server, "top-counts", map[string]string{}); err != nil { + t.Fatalf("top-counts failed: %v", err) } }