From 89225e6851cbf8c5b77f3ef87f330256be7e3ecd Mon Sep 17 00:00:00 2001 From: Surponess Date: Mon, 1 Jun 2026 12:02:02 +0800 Subject: [PATCH] =?UTF-8?q?11.1=09=F0=9F=94=B4=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E7=AC=A6=E6=B3=84=E6=BC=8F=09=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E5=86=85=20defer=20=E6=94=B9=E4=B8=BA=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=20Close()=09release.go=2011.2=09=F0=9F=94=B4=20Requir?= =?UTF-8?q?eArg=20=E9=94=99=E8=AF=AF=E5=BF=BD=E7=95=A5=0910=20=E5=A4=84=20?= =?UTF-8?q?=5F,=20=5F=20=E6=94=B9=E4=B8=BA=E6=A3=80=E6=9F=A5=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=20error=09release.go=20+=20snippet.go=2011.3=09?= =?UTF-8?q?=F0=9F=9F=A1=20download=20=E6=B6=88=E6=81=AF=E4=B8=AD=E8=8B=B1?= =?UTF-8?q?=E6=B7=B7=E6=9D=82=09"No=20assets"=20=E2=86=92=20"=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=8F=AF=E4=B8=8B=E8=BD=BD=E7=9A=84=E8=B5=84=E6=BA=90?= =?UTF-8?q?"=09release.go=2011.4=09=F0=9F=9F=A1=20=E7=BC=BA=E5=B0=91?= =?UTF-8?q?=E5=88=86=E9=A1=B5=E5=8F=82=E6=95=B0=09=E8=BF=BD=E5=8A=A0=20--p?= =?UTF-8?q?age/--limit=20+=20CallAPIWithQuery=09webhook.go=20+=20label.go?= =?UTF-8?q?=2011.5=09=F0=9F=9F=A2=20=E8=BE=93=E5=87=BA=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=B8=8D=E7=BB=9F=E4=B8=80=09output.SuccessEnvelope()=20?= =?UTF-8?q?=E2=86=92=20ctx.OutputData()=09release.go=2011.6=09=F0=9F=9F=A2?= =?UTF-8?q?=20=E9=94=99=E8=AF=AF=E5=8C=85=E8=A3=85=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E9=93=BE=09%v=20=E2=86=92=20%w=EF=BC=88=E8=AF=AD=E5=BA=8F?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=BA=E8=AE=A9=20%w=20=E5=9C=A8=E6=9C=AB?= =?UTF-8?q?=E5=B0=BE=EF=BC=89=09file.go=20=E8=AF=A6=E7=BB=86=E7=9A=84?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=89=8D=E5=90=8E=E4=BB=A3=E7=A0=81=E5=AF=B9?= =?UTF-8?q?=E6=AF=94=E5=92=8C=E5=AE=9E=E7=8E=B0=E8=AF=B4=E6=98=8E=E5=B7=B2?= =?UTF-8?q?=E5=86=99=E5=85=A5=20=E6=88=90=E5=91=98B=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E6=96=B9=E6=A1=88.md=20=E7=9A=84=E3=80=8C?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E8=AE=B0=E5=BD=95=EF=BC=88=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=2011=EF=BC=89=E3=80=8D=E7=AB=A0=E8=8A=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shortcuts/file/file.go | 4 +-- shortcuts/label/label.go | 4 +++ shortcuts/release/release.go | 51 ++++++++++++++++++++++++------------ shortcuts/snippet/snippet.go | 25 ++++++++++++++---- shortcuts/webhook/webhook.go | 10 ++++++- 5 files changed, 69 insertions(+), 25 deletions(-) diff --git a/shortcuts/file/file.go b/shortcuts/file/file.go index 4971fd9..8f146d6 100644 --- a/shortcuts/file/file.go +++ b/shortcuts/file/file.go @@ -126,7 +126,7 @@ func Shortcuts() []*common.Shortcut { if sha == "" { fetchedSHA, err := fetchFileSHA(ctx, path) if err != nil { - return fmt.Errorf("获取文件 SHA 失败: %v(请使用 --sha 手动指定)", err) + return fmt.Errorf("请使用 --sha 手动指定(获取文件 SHA 失败: %w)", err) } sha = fetchedSHA } @@ -170,7 +170,7 @@ func Shortcuts() []*common.Shortcut { if sha == "" { fetchedSHA, err := fetchFileSHA(ctx, path) if err != nil { - return fmt.Errorf("获取文件 SHA 失败: %v(请使用 --sha 手动指定)", err) + return fmt.Errorf("请使用 --sha 手动指定(获取文件 SHA 失败: %w)", err) } sha = fetchedSHA } diff --git a/shortcuts/label/label.go b/shortcuts/label/label.go index 9929304..ba27143 100644 --- a/shortcuts/label/label.go +++ b/shortcuts/label/label.go @@ -15,6 +15,8 @@ func Shortcuts() []*common.Shortcut { Description: "List issue labels (tags)", Flags: []common.Flag{ {Name: "keyword", Short: "k", Usage: "Search keyword"}, + {Name: "page", Short: "p", Usage: "Page number", Default: "1"}, + {Name: "limit", Short: "l", Usage: "Items per page", Default: "20"}, {Name: "order-by", Usage: "Sort field: updated_on, created_on, issues_count", Default: "created_on"}, {Name: "order-direction", Usage: "Sort direction: asc, desc", Default: "desc"}, }, @@ -23,6 +25,8 @@ func Shortcuts() []*common.Shortcut { return err } q := url.Values{} + q.Set("page", ctx.Arg("page")) + q.Set("limit", ctx.Arg("limit")) if k := ctx.Arg("keyword"); k != "" { q.Set("keyword", k) } diff --git a/shortcuts/release/release.go b/shortcuts/release/release.go index a4c6217..c1eab3b 100644 --- a/shortcuts/release/release.go +++ b/shortcuts/release/release.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" - "github.com/gitlink-org/gitlink-cli/internal/output" "github.com/gitlink-org/gitlink-cli/shortcuts/common" ) @@ -49,8 +48,14 @@ func Shortcuts() []*common.Shortcut { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - tag, _ := ctx.RequireArg("tag") - name, _ := ctx.RequireArg("name") + tag, err := ctx.RequireArg("tag") + if err != nil { + return err + } + name, err := ctx.RequireArg("name") + if err != nil { + return err + } payload := map[string]interface{}{ "tag_name": tag, "name": name, @@ -81,7 +86,10 @@ func Shortcuts() []*common.Shortcut { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } env, err := ctx.CallAPI("GET", fmt.Sprintf("%s/releases/%s", ctx.RepoPath(), id), nil) if err != nil { return err @@ -99,7 +107,10 @@ func Shortcuts() []*common.Shortcut { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } _, delErr := ctx.CallAPI("DELETE", fmt.Sprintf("%s/releases/%s", ctx.RepoPath(), id), nil) if delErr != nil { // GitLink API bug: delete succeeds but returns error status. @@ -107,16 +118,16 @@ func Shortcuts() []*common.Shortcut { _, viewErr := ctx.CallAPI("GET", fmt.Sprintf("%s/releases/%s", ctx.RepoPath(), id), nil) if viewErr != nil { // Release no longer exists — delete actually succeeded - return ctx.Output(output.SuccessEnvelope(map[string]interface{}{ + return ctx.OutputData(map[string]interface{}{ "message": "删除成功", - }, nil)) + }) } // Release still exists — delete truly failed return delErr } - return ctx.Output(output.SuccessEnvelope(map[string]interface{}{ + return ctx.OutputData(map[string]interface{}{ "message": "删除成功", - }, nil)) + }) }, }, { @@ -130,7 +141,10 @@ func Shortcuts() []*common.Shortcut { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } outputDir := ctx.Arg("output") // Fetch release details to find assets @@ -146,9 +160,9 @@ func Shortcuts() []*common.Shortcut { assets, _ := data["assets"].([]interface{}) if len(assets) == 0 { - return ctx.Output(output.SuccessEnvelope(map[string]interface{}{ - "message": "No assets to download", - }, nil)) + return ctx.OutputData(map[string]interface{}{ + "message": "没有可下载的资源", + }) } if err := os.MkdirAll(outputDir, 0o755); err != nil { @@ -173,29 +187,32 @@ func Shortcuts() []*common.Shortcut { if err != nil { return fmt.Errorf("下载 %s 失败: %w", filename, err) } - defer resp.Body.Close() if resp.StatusCode != http.StatusOK { + resp.Body.Close() return fmt.Errorf("下载 %s 失败: HTTP %d", filename, resp.StatusCode) } destPath := filepath.Join(outputDir, filename) f, err := os.Create(destPath) if err != nil { + resp.Body.Close() return fmt.Errorf("创建文件 %s 失败: %w", destPath, err) } if _, err := io.Copy(f, resp.Body); err != nil { f.Close() + resp.Body.Close() return fmt.Errorf("写入文件 %s 失败: %w", destPath, err) } f.Close() + resp.Body.Close() downloaded = append(downloaded, filename) } - return ctx.Output(output.SuccessEnvelope(map[string]interface{}{ - "message": fmt.Sprintf("Downloaded %d asset(s)", len(downloaded)), + return ctx.OutputData(map[string]interface{}{ + "message": fmt.Sprintf("已下载 %d 个资源", len(downloaded)), "downloaded": downloaded, - }, nil)) + }) }, }, } diff --git a/shortcuts/snippet/snippet.go b/shortcuts/snippet/snippet.go index 0b0ee5f..717045b 100644 --- a/shortcuts/snippet/snippet.go +++ b/shortcuts/snippet/snippet.go @@ -101,7 +101,10 @@ func Shortcuts() []*common.Shortcut { {Name: "id", Short: "i", Usage: "Snippet ID", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } store := getStore() snippets, err := store.Load() if err != nil { @@ -121,7 +124,10 @@ func Shortcuts() []*common.Shortcut { {Name: "query", Short: "q", Usage: "Search query", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { - query, _ := ctx.RequireArg("query") + query, err := ctx.RequireArg("query") + if err != nil { + return err + } store := getStore() snippets, err := store.Load() if err != nil { @@ -152,7 +158,10 @@ func Shortcuts() []*common.Shortcut { {Name: "content", Short: "c", Usage: "New content"}, }, Run: func(ctx *common.RuntimeContext) error { - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } title := ctx.Arg("title") language := ctx.Arg("language") @@ -201,7 +210,10 @@ func Shortcuts() []*common.Shortcut { {Name: "id", Short: "i", Usage: "Snippet ID", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } store := getStore() snippets, err := store.Load() if err != nil { @@ -234,7 +246,10 @@ func Shortcuts() []*common.Shortcut { {Name: "output", Short: "o", Usage: "Output file path (default: stdout)"}, }, Run: func(ctx *common.RuntimeContext) error { - id, _ := ctx.RequireArg("id") + id, err := ctx.RequireArg("id") + if err != nil { + return err + } store := getStore() snippets, err := store.Load() if err != nil { diff --git a/shortcuts/webhook/webhook.go b/shortcuts/webhook/webhook.go index 87d4a01..8bae314 100644 --- a/shortcuts/webhook/webhook.go +++ b/shortcuts/webhook/webhook.go @@ -2,6 +2,7 @@ package webhook import ( "fmt" + "net/url" "strings" "github.com/gitlink-org/gitlink-cli/shortcuts/common" @@ -13,11 +14,18 @@ func Shortcuts() []*common.Shortcut { { Name: "list", Description: "List webhooks", + Flags: []common.Flag{ + {Name: "page", Short: "p", Usage: "Page number", Default: "1"}, + {Name: "limit", Short: "l", Usage: "Items per page", Default: "20"}, + }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - env, err := ctx.CallAPI("GET", v1Path(ctx)+"/webhooks", nil) + q := url.Values{} + q.Set("page", ctx.Arg("page")) + q.Set("limit", ctx.Arg("limit")) + env, err := ctx.CallAPIWithQuery("GET", v1Path(ctx)+"/webhooks", q) if err != nil { return err }