diff --git a/doc/changes/list-all-pagination.md b/doc/changes/list-all-pagination.md index 00ab336e..68bf5504 100644 --- a/doc/changes/list-all-pagination.md +++ b/doc/changes/list-all-pagination.md @@ -16,10 +16,15 @@ - 遵循 `total_count`:达到总数即停止;另设最大页数护栏,防止 忽略 `page` 参数的端点造成死循环。 - `PaginateAll` 保持原签名,委托给 `PaginateAllKey`。 -- 四个 list 命令新增 `--all` 布尔参数(默认 false): +- 九个分页 list 命令新增 `--all` 布尔参数(默认 false): - `issue +list --all`(合并结果同样应用 number/database_id 规范化) - `pr +list --all`、`branch +list --all`、`release +list --all` + - `milestone +list --all`、`org +list --all`、`repo +list --all` + - `search +repos --all`、`search +users --all` + - 对应资源键:`issues`/`pulls`/`branches`/`releases`/`milestones`/ + `organizations`/`projects`/`users`(均生产实测确认) - 输出与单页响应同构:`{"total_count": N, "<资源名>": [...]}`。 +- 总数字段兼容 `total_count` 与 `count`(如 `/users/:login/projects`)。 - 中英文 i18n 新增 `flag.all` 文案。 ## 命令示例 @@ -28,10 +33,16 @@ # 拉取仓库全部 open issue(自动翻页合并) gitlink-cli issue +list --state open --all --format json -# 全部分支 / 全部 PR / 全部 release +# 全部分支 / 全部 PR / 全部 release / 全部里程碑 gitlink-cli branch +list --all gitlink-cli pr +list --state all --all gitlink-cli release +list --all +gitlink-cli milestone +list --all + +# 全部组织 / 某用户全部仓库 / 搜索结果全量 +gitlink-cli org +list --all +gitlink-cli repo +list --user Taoyouce --all +gitlink-cli search +repos --keyword gitlink --all ``` ## 测试 diff --git a/internal/client/pagination.go b/internal/client/pagination.go index 02d3bd1c..fe72a304 100644 --- a/internal/client/pagination.go +++ b/internal/client/pagination.go @@ -84,6 +84,9 @@ func extractListItems(data interface{}, listKey string) ([]json.RawMessage, int, total := -1 if tc, ok := v["total_count"].(float64); ok { total = int(tc) + } else if tc, ok := v["count"].(float64); ok { + // Some endpoints (e.g. /users/:login/projects) report "count". + total = int(tc) } if listKey != "" { if slice, ok := v[listKey].([]interface{}); ok { diff --git a/shortcuts/milestone/milestone.go b/shortcuts/milestone/milestone.go index 1ec2b302..1de3b86d 100644 --- a/shortcuts/milestone/milestone.go +++ b/shortcuts/milestone/milestone.go @@ -21,6 +21,7 @@ func Shortcuts() []*common.Shortcut { {Name: "sort-direction", Usage: "Sort direction: asc or desc"}, {Name: "page", Short: "p", Usage: "Page number", Default: "1"}, {Name: "limit", Short: "l", Usage: "Items per page", Default: "20"}, + {Name: "all", Usage: "Fetch all pages automatically (ignores --page)", Bool: true, Default: "false"}, }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { @@ -34,6 +35,13 @@ func Shortcuts() []*common.Shortcut { setQueryIfPresent(q, "only_name", ctx.Arg("only-name")) setQueryIfPresent(q, "sort_by", ctx.Arg("sort-by")) setQueryIfPresent(q, "sort_direction", ctx.Arg("sort-direction")) + if ctx.Arg("all") == "true" { + items, err := ctx.PaginateAllKey(milestonePath(ctx), q, "milestones") + if err != nil { + return err + } + return ctx.Output(common.NewListEnvelope("milestones", items)) + } env, err := ctx.CallAPIWithQuery("GET", milestonePath(ctx), q) if err != nil { return err diff --git a/shortcuts/org/org.go b/shortcuts/org/org.go index f0b5e721..bdd244b5 100644 --- a/shortcuts/org/org.go +++ b/shortcuts/org/org.go @@ -17,11 +17,19 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { Flags: []common.Flag{ {Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"}, {Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"}, + {Name: "all", Usage: tr.T("flag.all"), Bool: true, Default: "false"}, }, Run: func(ctx *common.RuntimeContext) error { q := url.Values{} q.Set("page", ctx.Arg("page")) q.Set("limit", ctx.Arg("limit")) + if ctx.Arg("all") == "true" { + items, err := ctx.PaginateAllKey("/organizations", q, "organizations") + if err != nil { + return err + } + return ctx.Output(common.NewListEnvelope("organizations", items)) + } env, err := ctx.CallAPIWithQuery("GET", "/organizations", q) if err != nil { return err diff --git a/shortcuts/repo/repo.go b/shortcuts/repo/repo.go index 06774a6e..85b76305 100644 --- a/shortcuts/repo/repo.go +++ b/shortcuts/repo/repo.go @@ -21,6 +21,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { {Name: "category", Short: "c", Usage: tr.T("flag.repo.category"), Default: "manage"}, {Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"}, {Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"}, + {Name: "all", Usage: tr.T("flag.all"), Bool: true, Default: "false"}, }, Run: func(ctx *common.RuntimeContext) error { user := ctx.Arg("user") @@ -35,6 +36,13 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { if user != "" { path = fmt.Sprintf("/users/%s/projects", user) } + if ctx.Arg("all") == "true" { + items, err := ctx.PaginateAllKey(path, q, "projects") + if err != nil { + return err + } + return ctx.Output(common.NewListEnvelope("projects", items)) + } env, err := ctx.CallAPIWithQuery("GET", path, q) if err != nil { return err diff --git a/shortcuts/search/search.go b/shortcuts/search/search.go index a0ee4c2a..a98f1c2b 100644 --- a/shortcuts/search/search.go +++ b/shortcuts/search/search.go @@ -17,6 +17,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { {Name: "keyword", Short: "k", Usage: tr.T("flag.search.keyword"), Required: true}, {Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"}, {Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"}, + {Name: "all", Usage: tr.T("flag.all"), Bool: true, Default: "false"}, }, Run: func(ctx *common.RuntimeContext) error { keyword, _ := ctx.RequireArg("keyword") @@ -24,6 +25,13 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { q.Set("search", keyword) q.Set("page", ctx.Arg("page")) q.Set("limit", ctx.Arg("limit")) + if ctx.Arg("all") == "true" { + items, err := ctx.PaginateAllKey("/projects", q, "projects") + if err != nil { + return err + } + return ctx.Output(common.NewListEnvelope("projects", items)) + } env, err := ctx.CallAPIWithQuery("GET", "/projects", q) if err != nil { return err @@ -38,6 +46,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { {Name: "keyword", Short: "k", Usage: tr.T("flag.search.keyword"), Required: true}, {Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"}, {Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"}, + {Name: "all", Usage: tr.T("flag.all"), Bool: true, Default: "false"}, }, Run: func(ctx *common.RuntimeContext) error { keyword, _ := ctx.RequireArg("keyword") @@ -45,6 +54,13 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { q.Set("search", keyword) q.Set("page", ctx.Arg("page")) q.Set("limit", ctx.Arg("limit")) + if ctx.Arg("all") == "true" { + items, err := ctx.PaginateAllKey("/users/list", q, "users") + if err != nil { + return err + } + return ctx.Output(common.NewListEnvelope("users", items)) + } env, err := ctx.CallAPIWithQuery("GET", "/users/list", q) if err != nil { return err