From dc67630b643e82d73c6de002f433c99ec7fb3c2d Mon Sep 17 00:00:00 2001 From: Norwin Date: Wed, 16 Dec 2020 01:38:22 +0800 Subject: [PATCH] replace flag globals, require context for commands (#291) introduce TeaContext clean up InitCommand move GetListOptions to TeaContext ensure context for each command so we fail early with a good error message instead of "Error: 404" etc make linter happy Merge branch 'master' into refactor-global-flags move TeaContext & InitCommand to modules/context Merge branch 'master' into refactor-global-flags CI.restart() Merge branch 'master' into refactor-global-flags Merge branch 'master' into refactor-global-flags Co-authored-by: Norwin Roosen Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/291 Reviewed-by: Lunny Xiao Reviewed-by: khmarbaise Reviewed-by: 6543 <6543@obermui.de> Co-Authored-By: Norwin Co-Committed-By: Norwin --- cmd/flags/flags.go | 55 +++-------- cmd/issues.go | 11 ++- cmd/issues/close.go | 9 +- cmd/issues/create.go | 15 +-- cmd/issues/list.go | 13 +-- cmd/labels/create.go | 12 +-- cmd/labels/delete.go | 10 +- cmd/labels/list.go | 14 ++- cmd/labels/update.go | 10 +- cmd/login.go | 3 +- cmd/login/list.go | 5 +- cmd/milestones.go | 13 +-- cmd/milestones/create.go | 9 +- cmd/milestones/delete.go | 11 ++- cmd/milestones/issues.go | 39 ++++---- cmd/milestones/list.go | 14 +-- cmd/milestones/reopen.go | 11 ++- cmd/notifications.go | 16 ++-- cmd/open.go | 9 +- cmd/organizations/delete.go | 9 +- cmd/organizations/list.go | 15 +-- cmd/pulls.go | 15 +-- cmd/pulls/checkout.go | 9 +- cmd/pulls/clean.go | 9 +- cmd/pulls/create.go | 15 +-- cmd/pulls/list.go | 11 ++- cmd/releases/create.go | 11 ++- cmd/releases/delete.go | 15 +-- cmd/releases/edit.go | 13 +-- cmd/releases/list.go | 13 ++- cmd/repos.go | 15 ++- cmd/repos/create.go | 8 +- cmd/repos/list.go | 16 ++-- cmd/repos/search.go | 14 +-- cmd/times.go | 6 +- cmd/times/add.go | 9 +- cmd/times/delete.go | 11 ++- cmd/times/list.go | 17 ++-- cmd/times/reset.go | 11 ++- modules/config/command.go | 130 ------------------------- modules/context/context.go | 184 ++++++++++++++++++++++++++++++++++++ modules/print/login.go | 2 +- 42 files changed, 444 insertions(+), 393 deletions(-) delete mode 100644 modules/config/command.go create mode 100644 modules/context/context.go diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go index d896a74..d9fe526 100644 --- a/cmd/flags/flags.go +++ b/cmd/flags/flags.go @@ -5,53 +5,35 @@ package flags import ( - "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" ) -// create global variables for global Flags to simplify -// access to the options without requiring cli.Context -var ( - // GlobalLoginValue contain value of --login|-l arg - GlobalLoginValue string - // GlobalRepoValue contain value of --repo|-r arg - GlobalRepoValue string - // GlobalOutputValue contain value of --output|-o arg - GlobalOutputValue string - // GlobalRemoteValue contain value of --remote|-R arg - GlobalRemoteValue string -) - // LoginFlag provides flag to specify tea login profile var LoginFlag = cli.StringFlag{ - Name: "login", - Aliases: []string{"l"}, - Usage: "Use a different Gitea login. Optional", - Destination: &GlobalLoginValue, + Name: "login", + Aliases: []string{"l"}, + Usage: "Use a different Gitea Login. Optional", } // RepoFlag provides flag to specify repository var RepoFlag = cli.StringFlag{ - Name: "repo", - Aliases: []string{"r"}, - Usage: "Override local repository path or gitea repository slug to interact with. Optional", - Destination: &GlobalRepoValue, + Name: "repo", + Aliases: []string{"r"}, + Usage: "Override local repository path or gitea repository slug to interact with. Optional", } // RemoteFlag provides flag to specify remote repository var RemoteFlag = cli.StringFlag{ - Name: "remote", - Aliases: []string{"R"}, - Usage: "Discover Gitea login from remote. Optional", - Destination: &GlobalRemoteValue, + Name: "remote", + Aliases: []string{"R"}, + Usage: "Discover Gitea login from remote. Optional", } // OutputFlag provides flag to specify output type var OutputFlag = cli.StringFlag{ - Name: "output", - Aliases: []string{"o"}, - Usage: "Output format. (csv, simple, table, tsv, yaml)", - Destination: &GlobalOutputValue, + Name: "output", + Aliases: []string{"o"}, + Usage: "Output format. (csv, simple, table, tsv, yaml)", } // StateFlag provides flag to specify issue/pr state, defaulting to "open" @@ -109,16 +91,3 @@ var IssuePRFlags = append([]cli.Flag{ &PaginationPageFlag, &PaginationLimitFlag, }, AllDefaultFlags...) - -// GetListOptions return ListOptions based on PaginationFlags -func GetListOptions(ctx *cli.Context) gitea.ListOptions { - page := ctx.Int("page") - limit := ctx.Int("limit") - if limit != 0 && page == 0 { - page = 1 - } - return gitea.ListOptions{ - Page: page, - PageSize: limit, - } -} diff --git a/cmd/issues.go b/cmd/issues.go index 8291003..fd78eb0 100644 --- a/cmd/issues.go +++ b/cmd/issues.go @@ -7,7 +7,7 @@ package cmd import ( "code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/issues" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -33,19 +33,20 @@ var CmdIssues = cli.Command{ func runIssues(ctx *cli.Context) error { if ctx.Args().Len() == 1 { - return runIssueDetail(ctx.Args().First()) + return runIssueDetail(ctx, ctx.Args().First()) } return issues.RunIssuesList(ctx) } -func runIssueDetail(index string) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runIssueDetail(cmd *cli.Context, index string) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) idx, err := utils.ArgToIndex(index) if err != nil { return err } - issue, _, err := login.Client().GetIssue(owner, repo, idx) + issue, _, err := ctx.Login.Client().GetIssue(ctx.Owner, ctx.Repo, idx) if err != nil { return err } diff --git a/cmd/issues/close.go b/cmd/issues/close.go index 19e61d1..1d3c4d8 100644 --- a/cmd/issues/close.go +++ b/cmd/issues/close.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -30,8 +30,9 @@ var CmdIssuesClose = cli.Command{ } // editIssueState abstracts the arg parsing to edit the given issue -func editIssueState(ctx *cli.Context, opts gitea.EditIssueOption) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func editIssueState(cmd *cli.Context, opts gitea.EditIssueOption) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) if ctx.Args().Len() == 0 { log.Fatal(ctx.Command.ArgsUsage) } @@ -41,7 +42,7 @@ func editIssueState(ctx *cli.Context, opts gitea.EditIssueOption) error { return err } - issue, _, err := login.Client().EditIssue(owner, repo, index, opts) + issue, _, err := ctx.Login.Client().EditIssue(ctx.Owner, ctx.Repo, index, opts) if err != nil { return err } diff --git a/cmd/issues/create.go b/cmd/issues/create.go index 12eb0fd..fb535d3 100644 --- a/cmd/issues/create.go +++ b/cmd/issues/create.go @@ -6,7 +6,7 @@ package issues import ( "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/interact" "code.gitea.io/tea/modules/task" @@ -33,17 +33,18 @@ var CmdIssuesCreate = cli.Command{ }, flags.LoginRepoFlags...), } -func runIssuesCreate(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runIssuesCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) if ctx.NumFlags() == 0 { - return interact.CreateIssue(login, owner, repo) + return interact.CreateIssue(ctx.Login, ctx.Owner, ctx.Repo) } return task.CreateIssue( - login, - owner, - repo, + ctx.Login, + ctx.Owner, + ctx.Repo, ctx.String("title"), ctx.String("body"), ) diff --git a/cmd/issues/list.go b/cmd/issues/list.go index 10b64d0..87c3ea9 100644 --- a/cmd/issues/list.go +++ b/cmd/issues/list.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -26,8 +26,9 @@ var CmdIssuesList = cli.Command{ } // RunIssuesList list issues -func RunIssuesList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunIssuesList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) state := gitea.StateOpen switch ctx.String("state") { @@ -39,8 +40,8 @@ func RunIssuesList(ctx *cli.Context) error { state = gitea.StateClosed } - issues, _, err := login.Client().ListRepoIssues(owner, repo, gitea.ListIssueOption{ - ListOptions: flags.GetListOptions(ctx), + issues, _, err := ctx.Login.Client().ListRepoIssues(ctx.Owner, ctx.Repo, gitea.ListIssueOption{ + ListOptions: ctx.GetListOptions(), State: state, Type: gitea.IssueTypeIssue, }) @@ -49,6 +50,6 @@ func RunIssuesList(ctx *cli.Context) error { log.Fatal(err) } - print.IssuesList(issues, flags.GlobalOutputValue) + print.IssuesList(issues, ctx.Output) return nil } diff --git a/cmd/labels/create.go b/cmd/labels/create.go index 83fdd97..afc2856 100644 --- a/cmd/labels/create.go +++ b/cmd/labels/create.go @@ -10,8 +10,7 @@ import ( "os" "strings" - "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" @@ -43,13 +42,14 @@ var CmdLabelCreate = cli.Command{ }, } -func runLabelCreate(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runLabelCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) labelFile := ctx.String("file") var err error if len(labelFile) == 0 { - _, _, err = login.Client().CreateLabel(owner, repo, gitea.CreateLabelOption{ + _, _, err = ctx.Login.Client().CreateLabel(ctx.Owner, ctx.Repo, gitea.CreateLabelOption{ Name: ctx.String("name"), Color: ctx.String("color"), Description: ctx.String("description"), @@ -69,7 +69,7 @@ func runLabelCreate(ctx *cli.Context) error { if color == "" || name == "" { log.Printf("Line %d ignored because lack of enough fields: %s\n", i, line) } else { - _, _, err = login.Client().CreateLabel(owner, repo, gitea.CreateLabelOption{ + _, _, err = ctx.Login.Client().CreateLabel(ctx.Owner, ctx.Repo, gitea.CreateLabelOption{ Name: name, Color: color, Description: description, diff --git a/cmd/labels/delete.go b/cmd/labels/delete.go index 26e69b8..890d628 100644 --- a/cmd/labels/delete.go +++ b/cmd/labels/delete.go @@ -7,8 +7,7 @@ package labels import ( "log" - "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "github.com/urfave/cli/v2" ) @@ -27,10 +26,11 @@ var CmdLabelDelete = cli.Command{ }, } -func runLabelDelete(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runLabelDelete(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) - _, err := login.Client().DeleteLabel(owner, repo, ctx.Int64("id")) + _, err := ctx.Login.Client().DeleteLabel(ctx.Owner, ctx.Repo, ctx.Int64("id")) if err != nil { log.Fatal(err) } diff --git a/cmd/labels/list.go b/cmd/labels/list.go index df7891e..4d8ccda 100644 --- a/cmd/labels/list.go +++ b/cmd/labels/list.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/task" @@ -35,10 +35,14 @@ var CmdLabelsList = cli.Command{ } // RunLabelsList list labels. -func RunLabelsList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunLabelsList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) - labels, _, err := login.Client().ListRepoLabels(owner, repo, gitea.ListLabelsOptions{ListOptions: flags.GetListOptions(ctx)}) + client := ctx.Login.Client() + labels, _, err := client.ListRepoLabels(ctx.Owner, ctx.Repo, gitea.ListLabelsOptions{ + ListOptions: ctx.GetListOptions(), + }) if err != nil { log.Fatal(err) } @@ -47,6 +51,6 @@ func RunLabelsList(ctx *cli.Context) error { return task.LabelsExport(labels, ctx.String("save")) } - print.LabelsList(labels, flags.GlobalOutputValue) + print.LabelsList(labels, ctx.Output) return nil } diff --git a/cmd/labels/update.go b/cmd/labels/update.go index 3731452..41c430d 100644 --- a/cmd/labels/update.go +++ b/cmd/labels/update.go @@ -7,8 +7,7 @@ package labels import ( "log" - "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" @@ -40,8 +39,9 @@ var CmdLabelUpdate = cli.Command{ }, } -func runLabelUpdate(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runLabelUpdate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) id := ctx.Int64("id") var pName, pColor, pDescription *string @@ -61,7 +61,7 @@ func runLabelUpdate(ctx *cli.Context) error { } var err error - _, _, err = login.Client().EditLabel(owner, repo, id, gitea.EditLabelOption{ + _, _, err = ctx.Login.Client().EditLabel(ctx.Owner, ctx.Repo, id, gitea.EditLabelOption{ Name: pName, Color: pColor, Description: pDescription, diff --git a/cmd/login.go b/cmd/login.go index 94f2a4a..5b84e07 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -7,7 +7,6 @@ package cmd import ( "fmt" - "code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/login" "code.gitea.io/tea/modules/config" "code.gitea.io/tea/modules/print" @@ -46,6 +45,6 @@ func runLoginDetail(name string) error { return nil } - print.LoginDetails(l, flags.GlobalOutputValue) + print.LoginDetails(l) return nil } diff --git a/cmd/login/list.go b/cmd/login/list.go index ca03c4c..782c2a8 100644 --- a/cmd/login/list.go +++ b/cmd/login/list.go @@ -25,12 +25,11 @@ var CmdLoginList = cli.Command{ } // RunLoginList list all logins -func RunLoginList(_ *cli.Context) error { +func RunLoginList(cmd *cli.Context) error { logins, err := config.GetLogins() if err != nil { log.Fatal(err) } - - print.LoginsList(logins, flags.GlobalOutputValue) + print.LoginsList(logins, cmd.String("output")) return nil } diff --git a/cmd/milestones.go b/cmd/milestones.go index 8ac9828..74376f1 100644 --- a/cmd/milestones.go +++ b/cmd/milestones.go @@ -7,7 +7,7 @@ package cmd import ( "code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/milestones" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "github.com/urfave/cli/v2" @@ -34,16 +34,17 @@ var CmdMilestones = cli.Command{ func runMilestones(ctx *cli.Context) error { if ctx.Args().Len() == 1 { - return runMilestoneDetail(ctx.Args().First()) + return runMilestoneDetail(ctx, ctx.Args().First()) } return milestones.RunMilestonesList(ctx) } -func runMilestoneDetail(name string) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runMilestoneDetail(cmd *cli.Context, name string) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() - milestone, _, err := client.GetMilestoneByName(owner, repo, name) + milestone, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, name) if err != nil { return err } diff --git a/cmd/milestones/create.go b/cmd/milestones/create.go index 637c666..4b1ff55 100644 --- a/cmd/milestones/create.go +++ b/cmd/milestones/create.go @@ -9,7 +9,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -41,8 +41,9 @@ var CmdMilestonesCreate = cli.Command{ }, flags.AllDefaultFlags...), } -func runMilestonesCreate(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runMilestonesCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) title := ctx.String("title") if len(title) == 0 { @@ -55,7 +56,7 @@ func runMilestonesCreate(ctx *cli.Context) error { state = gitea.StateClosed } - mile, _, err := login.Client().CreateMilestone(owner, repo, gitea.CreateMilestoneOption{ + mile, _, err := ctx.Login.Client().CreateMilestone(ctx.Owner, ctx.Repo, gitea.CreateMilestoneOption{ Title: title, Description: ctx.String("description"), State: state, diff --git a/cmd/milestones/delete.go b/cmd/milestones/delete.go index 639272c..c019b4d 100644 --- a/cmd/milestones/delete.go +++ b/cmd/milestones/delete.go @@ -6,7 +6,7 @@ package milestones import ( "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "github.com/urfave/cli/v2" ) @@ -22,10 +22,11 @@ var CmdMilestonesDelete = cli.Command{ Flags: flags.AllDefaultFlags, } -func deleteMilestone(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func deleteMilestone(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() - _, err := client.DeleteMilestoneByName(owner, repo, ctx.Args().First()) + _, err := client.DeleteMilestoneByName(ctx.Owner, ctx.Repo, ctx.Args().First()) return err } diff --git a/cmd/milestones/issues.go b/cmd/milestones/issues.go index 9ad367b..93d3920 100644 --- a/cmd/milestones/issues.go +++ b/cmd/milestones/issues.go @@ -8,7 +8,7 @@ import ( "fmt" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -65,9 +65,10 @@ var CmdMilestoneRemoveIssue = cli.Command{ Flags: flags.AllDefaultFlags, } -func runMilestoneIssueList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runMilestoneIssueList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() state := gitea.StateOpen switch ctx.String("state") { @@ -91,13 +92,13 @@ func runMilestoneIssueList(ctx *cli.Context) error { milestone := ctx.Args().First() // make sure milestone exist - _, _, err := client.GetMilestoneByName(owner, repo, milestone) + _, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, milestone) if err != nil { return err } - issues, _, err := client.ListRepoIssues(owner, repo, gitea.ListIssueOption{ - ListOptions: flags.GetListOptions(ctx), + issues, _, err := client.ListRepoIssues(ctx.Owner, ctx.Repo, gitea.ListIssueOption{ + ListOptions: ctx.GetListOptions(), Milestones: []string{milestone}, Type: kind, State: state, @@ -106,13 +107,14 @@ func runMilestoneIssueList(ctx *cli.Context) error { return err } - print.IssuesPullsList(issues, flags.GlobalOutputValue) + print.IssuesPullsList(issues, ctx.Output) return nil } -func runMilestoneIssueAdd(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runMilestoneIssueAdd(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() if ctx.Args().Len() != 2 { return fmt.Errorf("need two arguments") } @@ -125,20 +127,21 @@ func runMilestoneIssueAdd(ctx *cli.Context) error { } // make sure milestone exist - mile, _, err := client.GetMilestoneByName(owner, repo, mileName) + mile, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, mileName) if err != nil { return err } - _, _, err = client.EditIssue(owner, repo, idx, gitea.EditIssueOption{ + _, _, err = client.EditIssue(ctx.Owner, ctx.Repo, idx, gitea.EditIssueOption{ Milestone: &mile.ID, }) return err } -func runMilestoneIssueRemove(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runMilestoneIssueRemove(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() if ctx.Args().Len() != 2 { return fmt.Errorf("need two arguments") } @@ -150,7 +153,7 @@ func runMilestoneIssueRemove(ctx *cli.Context) error { return err } - issue, _, err := client.GetIssue(owner, repo, idx) + issue, _, err := client.GetIssue(ctx.Owner, ctx.Repo, idx) if err != nil { return err } @@ -164,7 +167,7 @@ func runMilestoneIssueRemove(ctx *cli.Context) error { } zero := int64(0) - _, _, err = client.EditIssue(owner, repo, idx, gitea.EditIssueOption{ + _, _, err = client.EditIssue(ctx.Owner, ctx.Repo, idx, gitea.EditIssueOption{ Milestone: &zero, }) return err diff --git a/cmd/milestones/list.go b/cmd/milestones/list.go index 780b786..699a00a 100644 --- a/cmd/milestones/list.go +++ b/cmd/milestones/list.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -34,8 +34,9 @@ var CmdMilestonesList = cli.Command{ } // RunMilestonesList list milestones -func RunMilestonesList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunMilestonesList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) state := gitea.StateOpen switch ctx.String("state") { @@ -45,8 +46,9 @@ func RunMilestonesList(ctx *cli.Context) error { state = gitea.StateClosed } - milestones, _, err := login.Client().ListRepoMilestones(owner, repo, gitea.ListMilestoneOption{ - ListOptions: flags.GetListOptions(ctx), + client := ctx.Login.Client() + milestones, _, err := client.ListRepoMilestones(ctx.Owner, ctx.Repo, gitea.ListMilestoneOption{ + ListOptions: ctx.GetListOptions(), State: state, }) @@ -54,6 +56,6 @@ func RunMilestonesList(ctx *cli.Context) error { log.Fatal(err) } - print.MilestonesList(milestones, flags.GlobalOutputValue, state) + print.MilestonesList(milestones, ctx.Output, state) return nil } diff --git a/cmd/milestones/reopen.go b/cmd/milestones/reopen.go index d984f18..fd1d398 100644 --- a/cmd/milestones/reopen.go +++ b/cmd/milestones/reopen.go @@ -6,7 +6,7 @@ package milestones import ( "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" @@ -25,15 +25,16 @@ var CmdMilestonesReopen = cli.Command{ Flags: flags.AllDefaultFlags, } -func editMilestoneStatus(ctx *cli.Context, close bool) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func editMilestoneStatus(cmd *cli.Context, close bool) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() state := gitea.StateOpen if close { state = gitea.StateClosed } - _, _, err := client.EditMilestoneByName(owner, repo, ctx.Args().First(), gitea.EditMilestoneOption{ + _, _, err := client.EditMilestoneByName(ctx.Owner, ctx.Repo, ctx.Args().First(), gitea.EditMilestoneOption{ State: &state, Title: ctx.Args().First(), }) diff --git a/cmd/notifications.go b/cmd/notifications.go index 8ff2736..32cc42f 100644 --- a/cmd/notifications.go +++ b/cmd/notifications.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -43,13 +43,14 @@ var CmdNotifications = cli.Command{ }, flags.AllDefaultFlags...), } -func runNotifications(ctx *cli.Context) error { +func runNotifications(cmd *cli.Context) error { var news []*gitea.NotificationThread var err error - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() - listOpts := flags.GetListOptions(ctx) + listOpts := ctx.GetListOptions() if listOpts.Page == 0 { listOpts.Page = 1 } @@ -63,12 +64,13 @@ func runNotifications(ctx *cli.Context) error { } if ctx.Bool("all") { - news, _, err = login.Client().ListNotifications(gitea.ListNotificationOptions{ + news, _, err = client.ListNotifications(gitea.ListNotificationOptions{ ListOptions: listOpts, Status: status, }) } else { - news, _, err = login.Client().ListRepoNotifications(owner, repo, gitea.ListNotificationOptions{ + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + news, _, err = client.ListRepoNotifications(ctx.Owner, ctx.Repo, gitea.ListNotificationOptions{ ListOptions: listOpts, Status: status, }) @@ -77,6 +79,6 @@ func runNotifications(ctx *cli.Context) error { log.Fatal(err) } - print.NotificationsList(news, flags.GlobalOutputValue, ctx.Bool("all")) + print.NotificationsList(news, ctx.Output, ctx.Bool("all")) return nil } diff --git a/cmd/open.go b/cmd/open.go index 85811ed..78fba30 100644 --- a/cmd/open.go +++ b/cmd/open.go @@ -10,7 +10,7 @@ import ( "strings" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" local_git "code.gitea.io/tea/modules/git" "github.com/skratchdot/open-golang/open" @@ -26,8 +26,9 @@ var CmdOpen = cli.Command{ Flags: append([]cli.Flag{}, flags.LoginRepoFlags...), } -func runOpen(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runOpen(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) var suffix string number := ctx.Args().Get(0) @@ -73,7 +74,7 @@ func runOpen(ctx *cli.Context) error { suffix = number } - u := path.Join(login.URL, owner, repo, suffix) + u := path.Join(ctx.Login.URL, ctx.RepoSlug, suffix) err := open.Run(u) if err != nil { log.Fatal(err) diff --git a/cmd/organizations/delete.go b/cmd/organizations/delete.go index 3cdf82d..5f1f6b6 100644 --- a/cmd/organizations/delete.go +++ b/cmd/organizations/delete.go @@ -7,8 +7,7 @@ package organizations import ( "log" - "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "github.com/urfave/cli/v2" ) @@ -23,10 +22,10 @@ var CmdOrganizationDelete = cli.Command{ } // RunOrganizationDelete delete user organization -func RunOrganizationDelete(ctx *cli.Context) error { - login, _, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunOrganizationDelete(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) - client := login.Client() + client := ctx.Login.Client() if ctx.Args().Len() < 1 { log.Fatal("You have to specify the organization name you want to delete.") diff --git a/cmd/organizations/list.go b/cmd/organizations/list.go index d7c12f4..aea12fd 100644 --- a/cmd/organizations/list.go +++ b/cmd/organizations/list.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -29,17 +29,18 @@ var CmdOrganizationList = cli.Command{ } // RunOrganizationList list user organizations -func RunOrganizationList(ctx *cli.Context) error { - login, _, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunOrganizationList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() - client := login.Client() - - userOrganizations, _, err := client.ListUserOrgs(login.User, gitea.ListOrgsOptions{ListOptions: flags.GetListOptions(ctx)}) + userOrganizations, _, err := client.ListUserOrgs(ctx.Login.User, gitea.ListOrgsOptions{ + ListOptions: ctx.GetListOptions(), + }) if err != nil { log.Fatal(err) } - print.OrganizationsList(userOrganizations, flags.GlobalOutputValue) + print.OrganizationsList(userOrganizations, ctx.Output) return nil } diff --git a/cmd/pulls.go b/cmd/pulls.go index 57c9bc1..05633e0 100644 --- a/cmd/pulls.go +++ b/cmd/pulls.go @@ -9,7 +9,7 @@ import ( "code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/pulls" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -36,25 +36,26 @@ var CmdPulls = cli.Command{ func runPulls(ctx *cli.Context) error { if ctx.Args().Len() == 1 { - return runPullDetail(ctx.Args().First()) + return runPullDetail(ctx, ctx.Args().First()) } return pulls.RunPullsList(ctx) } -func runPullDetail(index string) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runPullDetail(cmd *cli.Context, index string) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) idx, err := utils.ArgToIndex(index) if err != nil { return err } - client := login.Client() - pr, _, err := client.GetPullRequest(owner, repo, idx) + client := ctx.Login.Client() + pr, _, err := client.GetPullRequest(ctx.Owner, ctx.Repo, idx) if err != nil { return err } - reviews, _, err := client.ListPullReviews(owner, repo, idx, gitea.ListPullReviewsOptions{}) + reviews, _, err := client.ListPullReviews(ctx.Owner, ctx.Repo, idx, gitea.ListPullReviewsOptions{}) if err != nil { fmt.Printf("error while loading reviews: %v\n", err) } diff --git a/cmd/pulls/checkout.go b/cmd/pulls/checkout.go index 03b1a29..981a2d4 100644 --- a/cmd/pulls/checkout.go +++ b/cmd/pulls/checkout.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/interact" "code.gitea.io/tea/modules/task" "code.gitea.io/tea/modules/utils" @@ -26,8 +26,9 @@ var CmdPullsCheckout = cli.Command{ Flags: flags.AllDefaultFlags, } -func runPullsCheckout(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runPullsCheckout(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{LocalRepo: true}) if ctx.Args().Len() != 1 { log.Fatal("Must specify a PR index") } @@ -36,5 +37,5 @@ func runPullsCheckout(ctx *cli.Context) error { return err } - return task.PullCheckout(login, owner, repo, idx, interact.PromptPassword) + return task.PullCheckout(ctx.Login, ctx.Owner, ctx.Repo, idx, interact.PromptPassword) } diff --git a/cmd/pulls/clean.go b/cmd/pulls/clean.go index dee4470..157a2d4 100644 --- a/cmd/pulls/clean.go +++ b/cmd/pulls/clean.go @@ -8,7 +8,7 @@ import ( "fmt" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/interact" "code.gitea.io/tea/modules/task" "code.gitea.io/tea/modules/utils" @@ -31,8 +31,9 @@ var CmdPullsClean = cli.Command{ }, flags.AllDefaultFlags...), } -func runPullsClean(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runPullsClean(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{LocalRepo: true}) if ctx.Args().Len() != 1 { return fmt.Errorf("Must specify a PR index") } @@ -42,5 +43,5 @@ func runPullsClean(ctx *cli.Context) error { return err } - return task.PullClean(login, owner, repo, idx, ctx.Bool("ignore-sha"), interact.PromptPassword) + return task.PullClean(ctx.Login, ctx.Owner, ctx.Repo, idx, ctx.Bool("ignore-sha"), interact.PromptPassword) } diff --git a/cmd/pulls/create.go b/cmd/pulls/create.go index 5ca8a3c..e52290a 100644 --- a/cmd/pulls/create.go +++ b/cmd/pulls/create.go @@ -6,7 +6,7 @@ package pulls import ( "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/interact" "code.gitea.io/tea/modules/task" @@ -42,19 +42,20 @@ var CmdPullsCreate = cli.Command{ }, flags.AllDefaultFlags...), } -func runPullsCreate(ctx *cli.Context) error { - login, ownerArg, repoArg := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runPullsCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{LocalRepo: true}) // no args -> interactive mode if ctx.NumFlags() == 0 { - return interact.CreatePull(login, ownerArg, repoArg) + return interact.CreatePull(ctx.Login, ctx.Owner, ctx.Repo) } // else use args to create PR return task.CreatePull( - login, - ownerArg, - repoArg, + ctx.Login, + ctx.Owner, + ctx.Repo, ctx.String("base"), ctx.String("head"), ctx.String("title"), diff --git a/cmd/pulls/list.go b/cmd/pulls/list.go index 66d9325..2010fe7 100644 --- a/cmd/pulls/list.go +++ b/cmd/pulls/list.go @@ -8,7 +8,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -26,8 +26,9 @@ var CmdPullsList = cli.Command{ } // RunPullsList return list of pulls -func RunPullsList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunPullsList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) state := gitea.StateOpen switch ctx.String("state") { @@ -39,7 +40,7 @@ func RunPullsList(ctx *cli.Context) error { state = gitea.StateClosed } - prs, _, err := login.Client().ListRepoPullRequests(owner, repo, gitea.ListPullRequestsOptions{ + prs, _, err := ctx.Login.Client().ListRepoPullRequests(ctx.Owner, ctx.Repo, gitea.ListPullRequestsOptions{ State: state, }) @@ -47,6 +48,6 @@ func RunPullsList(ctx *cli.Context) error { log.Fatal(err) } - print.PullsList(prs, flags.GlobalOutputValue) + print.PullsList(prs, ctx.Output) return nil } diff --git a/cmd/releases/create.go b/cmd/releases/create.go index 6af1177..e9c68e0 100644 --- a/cmd/releases/create.go +++ b/cmd/releases/create.go @@ -12,7 +12,7 @@ import ( "path/filepath" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" @@ -61,10 +61,11 @@ var CmdReleaseCreate = cli.Command{ }, flags.AllDefaultFlags...), } -func runReleaseCreate(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runReleaseCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) - release, resp, err := login.Client().CreateRelease(owner, repo, gitea.CreateReleaseOption{ + release, resp, err := ctx.Login.Client().CreateRelease(ctx.Owner, ctx.Repo, gitea.CreateReleaseOption{ TagName: ctx.String("tag"), Target: ctx.String("target"), Title: ctx.String("title"), @@ -90,7 +91,7 @@ func runReleaseCreate(ctx *cli.Context) error { filePath := filepath.Base(asset) - if _, _, err = login.Client().CreateReleaseAttachment(owner, repo, release.ID, file, filePath); err != nil { + if _, _, err = ctx.Login.Client().CreateReleaseAttachment(ctx.Owner, ctx.Repo, release.ID, file, filePath); err != nil { file.Close() log.Fatal(err) } diff --git a/cmd/releases/delete.go b/cmd/releases/delete.go index db947c2..9f89199 100644 --- a/cmd/releases/delete.go +++ b/cmd/releases/delete.go @@ -8,7 +8,7 @@ import ( "fmt" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "github.com/urfave/cli/v2" ) @@ -33,9 +33,10 @@ var CmdReleaseDelete = cli.Command{ }, flags.AllDefaultFlags...), } -func runReleaseDelete(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runReleaseDelete(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() tag := ctx.Args().First() if len(tag) == 0 { @@ -48,7 +49,7 @@ func runReleaseDelete(ctx *cli.Context) error { return nil } - release, err := getReleaseByTag(owner, repo, tag, client) + release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) if err != nil { return err } @@ -56,13 +57,13 @@ func runReleaseDelete(ctx *cli.Context) error { return nil } - _, err = client.DeleteRelease(owner, repo, release.ID) + _, err = client.DeleteRelease(ctx.Owner, ctx.Repo, release.ID) if err != nil { return err } if ctx.Bool("delete-tag") { - _, err = client.DeleteReleaseTag(owner, repo, tag) + _, err = client.DeleteReleaseTag(ctx.Owner, ctx.Repo, tag) return err } diff --git a/cmd/releases/edit.go b/cmd/releases/edit.go index 14bc6d8..635c6bc 100644 --- a/cmd/releases/edit.go +++ b/cmd/releases/edit.go @@ -9,7 +9,7 @@ import ( "strings" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/sdk/gitea" "github.com/urfave/cli/v2" @@ -56,9 +56,10 @@ var CmdReleaseEdit = cli.Command{ }, flags.AllDefaultFlags...), } -func runReleaseEdit(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runReleaseEdit(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() tag := ctx.Args().First() if len(tag) == 0 { @@ -66,7 +67,7 @@ func runReleaseEdit(ctx *cli.Context) error { return nil } - release, err := getReleaseByTag(owner, repo, tag, client) + release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) if err != nil { return err } @@ -82,7 +83,7 @@ func runReleaseEdit(ctx *cli.Context) error { isPre = gitea.OptionalBool(strings.ToLower(ctx.String("prerelease"))[:1] == "t") } - _, _, err = client.EditRelease(owner, repo, release.ID, gitea.EditReleaseOption{ + _, _, err = client.EditRelease(ctx.Owner, ctx.Repo, release.ID, gitea.EditReleaseOption{ TagName: ctx.String("tag"), Target: ctx.String("target"), Title: ctx.String("title"), diff --git a/cmd/releases/list.go b/cmd/releases/list.go index 6374b26..d2fee37 100644 --- a/cmd/releases/list.go +++ b/cmd/releases/list.go @@ -9,7 +9,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -30,15 +30,18 @@ var CmdReleaseList = cli.Command{ } // RunReleasesList list releases -func RunReleasesList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func RunReleasesList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) - releases, _, err := login.Client().ListReleases(owner, repo, gitea.ListReleasesOptions{ListOptions: flags.GetListOptions(ctx)}) + releases, _, err := ctx.Login.Client().ListReleases(ctx.Owner, ctx.Repo, gitea.ListReleasesOptions{ + ListOptions: ctx.GetListOptions(), + }) if err != nil { log.Fatal(err) } - print.ReleasesList(releases, flags.GlobalOutputValue) + print.ReleasesList(releases, ctx.Output) return nil } diff --git a/cmd/repos.go b/cmd/repos.go index 2558b82..8622a67 100644 --- a/cmd/repos.go +++ b/cmd/repos.go @@ -5,9 +5,8 @@ package cmd import ( - "code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/repos" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -33,20 +32,20 @@ var CmdRepos = cli.Command{ func runRepos(ctx *cli.Context) error { if ctx.Args().Len() == 1 { - return runRepoDetail(ctx.Args().First()) + return runRepoDetail(ctx, ctx.Args().First()) } return repos.RunReposList(ctx) } -func runRepoDetail(path string) error { - login, ownerFallback, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() - repoOwner, repoName := utils.GetOwnerAndRepo(path, ownerFallback) +func runRepoDetail(cmd *cli.Context, path string) error { + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() + repoOwner, repoName := utils.GetOwnerAndRepo(path, ctx.Owner) repo, _, err := client.GetRepo(repoOwner, repoName) if err != nil { return err } - topics, _, err := client.ListRepoTopics(repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{}) + topics, _, err := client.ListRepoTopics(repoOwner, repoName, gitea.ListRepoTopicsOptions{}) if err != nil { return err } diff --git a/cmd/repos/create.go b/cmd/repos/create.go index f146f79..51d989c 100644 --- a/cmd/repos/create.go +++ b/cmd/repos/create.go @@ -8,7 +8,7 @@ import ( "fmt" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -82,9 +82,9 @@ var CmdRepoCreate = cli.Command{ }, flags.LoginOutputFlags...), } -func runRepoCreate(ctx *cli.Context) error { - login, _, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runRepoCreate(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() var ( repo *gitea.Repository err error diff --git a/cmd/repos/list.go b/cmd/repos/list.go index 2a251bc..79cbefc 100644 --- a/cmd/repos/list.go +++ b/cmd/repos/list.go @@ -6,7 +6,7 @@ package repos import ( "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -44,11 +44,11 @@ var CmdReposList = cli.Command{ } // RunReposList list repositories -func RunReposList(ctx *cli.Context) error { - login, _, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func RunReposList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() - typeFilter, err := getTypeFilter(ctx) + typeFilter, err := getTypeFilter(cmd) if err != nil { return err } @@ -60,14 +60,14 @@ func RunReposList(ctx *cli.Context) error { return err } rps, _, err = client.SearchRepos(gitea.SearchRepoOptions{ - ListOptions: flags.GetListOptions(ctx), + ListOptions: ctx.GetListOptions(), StarredByUserID: user.ID, }) } else if ctx.Bool("watched") { rps, _, err = client.GetMyWatchedRepos() // TODO: this does not expose pagination.. } else { rps, _, err = client.ListMyRepos(gitea.ListReposOptions{ - ListOptions: flags.GetListOptions(ctx), + ListOptions: ctx.GetListOptions(), }) } @@ -80,7 +80,7 @@ func RunReposList(ctx *cli.Context) error { reposFiltered = filterReposByType(rps, typeFilter) } - print.ReposList(reposFiltered, flags.GlobalOutputValue, getFields(ctx)) + print.ReposList(reposFiltered, ctx.Output, getFields(cmd)) return nil } diff --git a/cmd/repos/search.go b/cmd/repos/search.go index f9e3462..6c48e4a 100644 --- a/cmd/repos/search.go +++ b/cmd/repos/search.go @@ -9,7 +9,7 @@ import ( "strings" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/sdk/gitea" @@ -56,9 +56,9 @@ var CmdReposSearch = cli.Command{ }, flags.LoginOutputFlags...), } -func runReposSearch(ctx *cli.Context) error { - login, _, _ := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runReposSearch(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + client := ctx.Login.Client() var ownerID int64 if ctx.IsSet("owner") { @@ -93,7 +93,7 @@ func runReposSearch(ctx *cli.Context) error { isPrivate = &private } - mode, err := getTypeFilter(ctx) + mode, err := getTypeFilter(cmd) if err != nil { return err } @@ -109,7 +109,7 @@ func runReposSearch(ctx *cli.Context) error { } rps, _, err := client.SearchRepos(gitea.SearchRepoOptions{ - ListOptions: flags.GetListOptions(ctx), + ListOptions: ctx.GetListOptions(), OwnerID: ownerID, IsPrivate: isPrivate, IsArchived: isArchived, @@ -123,6 +123,6 @@ func runReposSearch(ctx *cli.Context) error { return err } - print.ReposList(rps, flags.GlobalOutputValue, getFields(ctx)) + print.ReposList(rps, ctx.Output, getFields(cmd)) return nil } diff --git a/cmd/times.go b/cmd/times.go index fbb0d31..1326b40 100644 --- a/cmd/times.go +++ b/cmd/times.go @@ -18,7 +18,7 @@ var CmdTrackedTimes = cli.Command{ Depending on your permissions on the repository, only your own tracked times might be listed.`, ArgsUsage: "[username | #issue]", - Action: runTrackedTimes, + Action: times.RunTimesList, Subcommands: []*cli.Command{ ×.CmdTrackedTimesAdd, ×.CmdTrackedTimesDelete, @@ -26,7 +26,3 @@ var CmdTrackedTimes = cli.Command{ ×.CmdTrackedTimesList, }, } - -func runTrackedTimes(ctx *cli.Context) error { - return times.RunTimesList(ctx) -} diff --git a/cmd/times/add.go b/cmd/times/add.go index 0f8a0e7..2de9c49 100644 --- a/cmd/times/add.go +++ b/cmd/times/add.go @@ -11,7 +11,7 @@ import ( "time" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/utils" "code.gitea.io/sdk/gitea" @@ -31,8 +31,9 @@ var CmdTrackedTimesAdd = cli.Command{ Flags: flags.LoginRepoFlags, } -func runTrackedTimesAdd(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) +func runTrackedTimesAdd(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) if ctx.Args().Len() < 2 { return fmt.Errorf("No issue or duration specified.\nUsage:\t%s", ctx.Command.UsageText) @@ -48,7 +49,7 @@ func runTrackedTimesAdd(ctx *cli.Context) error { log.Fatal(err) } - _, _, err = login.Client().AddTime(owner, repo, issue, gitea.AddTimeOption{ + _, _, err = ctx.Login.Client().AddTime(ctx.Owner, ctx.Repo, issue, gitea.AddTimeOption{ Time: int64(duration.Seconds()), }) if err != nil { diff --git a/cmd/times/delete.go b/cmd/times/delete.go index 7d0e7b5..91ed2c6 100644 --- a/cmd/times/delete.go +++ b/cmd/times/delete.go @@ -10,7 +10,7 @@ import ( "strconv" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/utils" "github.com/urfave/cli/v2" @@ -26,9 +26,10 @@ var CmdTrackedTimesDelete = cli.Command{ Flags: flags.LoginRepoFlags, } -func runTrackedTimesDelete(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runTrackedTimesDelete(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() if ctx.Args().Len() < 2 { return fmt.Errorf("No issue or time ID specified.\nUsage:\t%s", ctx.Command.UsageText) @@ -44,7 +45,7 @@ func runTrackedTimesDelete(ctx *cli.Context) error { log.Fatal(err) } - _, err = client.DeleteTime(owner, repo, issue, timeID) + _, err = client.DeleteTime(ctx.Owner, ctx.Repo, issue, timeID) if err != nil { log.Fatal(err) } diff --git a/cmd/times/list.go b/cmd/times/list.go index 62c1887..4a3f4a1 100644 --- a/cmd/times/list.go +++ b/cmd/times/list.go @@ -10,7 +10,7 @@ import ( "time" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/utils" @@ -50,9 +50,10 @@ var CmdTrackedTimesList = cli.Command{ } // RunTimesList list repositories -func RunTimesList(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func RunTimesList(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() var times []*gitea.TrackedTime var err error @@ -61,17 +62,17 @@ func RunTimesList(ctx *cli.Context) error { fmt.Println(ctx.Command.ArgsUsage) if user == "" { // get all tracked times on the repo - times, _, err = client.GetRepoTrackedTimes(owner, repo) + times, _, err = client.GetRepoTrackedTimes(ctx.Owner, ctx.Repo) } else if strings.HasPrefix(user, "#") { // get all tracked times on the specified issue issue, err := utils.ArgToIndex(user) if err != nil { return err } - times, _, err = client.ListTrackedTimes(owner, repo, issue, gitea.ListTrackedTimesOptions{}) + times, _, err = client.ListTrackedTimes(ctx.Owner, ctx.Repo, issue, gitea.ListTrackedTimesOptions{}) } else { // get all tracked times by the specified user - times, _, err = client.GetUserTrackedTimes(owner, repo, user) + times, _, err = client.GetUserTrackedTimes(ctx.Owner, ctx.Repo, user) } if err != nil { @@ -92,6 +93,6 @@ func RunTimesList(ctx *cli.Context) error { } } - print.TrackedTimesList(times, flags.GlobalOutputValue, from, until, ctx.Bool("total")) + print.TrackedTimesList(times, ctx.Output, from, until, ctx.Bool("total")) return nil } diff --git a/cmd/times/reset.go b/cmd/times/reset.go index 99afc29..382af56 100644 --- a/cmd/times/reset.go +++ b/cmd/times/reset.go @@ -9,7 +9,7 @@ import ( "log" "code.gitea.io/tea/cmd/flags" - "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/utils" "github.com/urfave/cli/v2" @@ -25,9 +25,10 @@ var CmdTrackedTimesReset = cli.Command{ Flags: flags.LoginRepoFlags, } -func runTrackedTimesReset(ctx *cli.Context) error { - login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue) - client := login.Client() +func runTrackedTimesReset(cmd *cli.Context) error { + ctx := context.InitCommand(cmd) + ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) + client := ctx.Login.Client() if ctx.Args().Len() != 1 { return fmt.Errorf("No issue specified.\nUsage:\t%s", ctx.Command.UsageText) @@ -38,7 +39,7 @@ func runTrackedTimesReset(ctx *cli.Context) error { log.Fatal(err) } - _, err = client.ResetIssueTime(owner, repo, issue) + _, err = client.ResetIssueTime(ctx.Owner, ctx.Repo, issue) if err != nil { log.Fatal(err) } diff --git a/modules/config/command.go b/modules/config/command.go deleted file mode 100644 index 5accb64..0000000 --- a/modules/config/command.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2020 The Gitea Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package config - -import ( - "errors" - "fmt" - "log" - "strings" - - "code.gitea.io/tea/modules/git" - "code.gitea.io/tea/modules/utils" - - gogit "github.com/go-git/go-git/v5" -) - -// InitCommand resolves the application context, and returns the active login, and if -// available the repo slug. It does this by reading the config file for logins, parsing -// the remotes of the .git repo specified in repoFlag or $PWD, and using overrides from -// command flags. If a local git repo can't be found, repo slug values are unset. -func InitCommand(repoFlag, loginFlag, remoteFlag string) (login *Login, owner string, reponame string) { - err := loadConfig() - if err != nil { - log.Fatal(err) - } - - var repoSlug string - var repoPath string // empty means PWD - var repoFlagPathExists bool - - // check if repoFlag can be interpreted as path to local repo. - if len(repoFlag) != 0 { - repoFlagPathExists, err = utils.PathExists(repoFlag) - if err != nil { - log.Fatal(err.Error()) - } - if repoFlagPathExists { - repoPath = repoFlag - } - } - - // try to read git repo & extract context, ignoring if PWD is not a repo - login, repoSlug, err = contextFromLocalRepo(repoPath, remoteFlag) - if err != nil && err != gogit.ErrRepositoryNotExists { - log.Fatal(err.Error()) - } - - // if repoFlag is not a path, use it to override repoSlug - if len(repoFlag) != 0 && !repoFlagPathExists { - repoSlug = repoFlag - } - - // override login from flag, or use default login if repo based detection failed - if len(loginFlag) != 0 { - login = GetLoginByName(loginFlag) - if login == nil { - log.Fatalf("Login name '%s' does not exist", loginFlag) - } - } else if login == nil { - if login, err = GetDefaultLogin(); err != nil { - log.Fatal(err.Error()) - } - } - - // parse reposlug (owner falling back to login owner if reposlug contains only repo name) - owner, reponame = utils.GetOwnerAndRepo(repoSlug, login.User) - return -} - -// contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo -func contextFromLocalRepo(repoValue, remoteValue string) (*Login, string, error) { - repo, err := git.RepoFromPath(repoValue) - if err != nil { - return nil, "", err - } - gitConfig, err := repo.Config() - if err != nil { - return nil, "", err - } - - // if no remote - if len(gitConfig.Remotes) == 0 { - return nil, "", errors.New("No remote(s) found in this Git repository") - } - - // if only one remote exists - if len(gitConfig.Remotes) >= 1 && len(remoteValue) == 0 { - for remote := range gitConfig.Remotes { - remoteValue = remote - } - if len(gitConfig.Remotes) > 1 { - // if master branch is present, use it as the default remote - masterBranch, ok := gitConfig.Branches["master"] - if ok { - if len(masterBranch.Remote) > 0 { - remoteValue = masterBranch.Remote - } - } - } - } - - remoteConfig, ok := gitConfig.Remotes[remoteValue] - if !ok || remoteConfig == nil { - return nil, "", errors.New("Remote " + remoteValue + " not found in this Git repository") - } - - for _, l := range config.Logins { - for _, u := range remoteConfig.URLs { - p, err := git.ParseURL(strings.TrimSpace(u)) - if err != nil { - return nil, "", fmt.Errorf("Git remote URL parse failed: %s", err.Error()) - } - if strings.EqualFold(p.Scheme, "http") || strings.EqualFold(p.Scheme, "https") { - if strings.HasPrefix(u, l.URL) { - ps := strings.Split(p.Path, "/") - path := strings.Join(ps[len(ps)-2:], "/") - return &l, strings.TrimSuffix(path, ".git"), nil - } - } else if strings.EqualFold(p.Scheme, "ssh") { - if l.GetSSHHost() == strings.Split(p.Host, ":")[0] { - return &l, strings.TrimLeft(strings.TrimSuffix(p.Path, ".git"), "/"), nil - } - } - } - } - - return nil, "", errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") -} diff --git a/modules/context/context.go b/modules/context/context.go new file mode 100644 index 0000000..d7b3cb3 --- /dev/null +++ b/modules/context/context.go @@ -0,0 +1,184 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package context + +import ( + "errors" + "fmt" + "log" + "os" + "strings" + + "code.gitea.io/sdk/gitea" + "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/git" + "code.gitea.io/tea/modules/utils" + + gogit "github.com/go-git/go-git/v5" + "github.com/urfave/cli/v2" +) + +// TeaContext contains all context derived during command initialization and wraps cli.Context +type TeaContext struct { + *cli.Context + Login *config.Login + RepoSlug string // / + Owner string // repo owner as derived from context + Repo string // repo name as derived from context or provided in flag + Output string // value of output flag + LocalRepo *git.TeaRepo // maybe, we have opened it already anyway +} + +// GetListOptions return ListOptions based on PaginationFlags +func (ctx *TeaContext) GetListOptions() gitea.ListOptions { + page := ctx.Int("page") + limit := ctx.Int("limit") + if limit != 0 && page == 0 { + page = 1 + } + return gitea.ListOptions{ + Page: page, + PageSize: limit, + } +} + +// Ensure checks if requirements on the context are set, and terminates otherwise. +func (ctx *TeaContext) Ensure(req CtxRequirement) { + if req.LocalRepo && ctx.LocalRepo == nil { + fmt.Println("Local repository required: Execute from a repo dir, or specify a path with --repo.") + os.Exit(1) + } + + if req.RemoteRepo && len(ctx.RepoSlug) == 0 { + fmt.Println("Remote repository required: Specify ID via --repo or execute from a local git repo.") + os.Exit(1) + } +} + +// CtxRequirement specifies context needed for operation +type CtxRequirement struct { + // ensures a local git repo is available & ctx.LocalRepo is set. Implies .RemoteRepo + LocalRepo bool + // ensures ctx.RepoSlug, .Owner, .Repo are set + RemoteRepo bool +} + +// InitCommand resolves the application context, and returns the active login, and if +// available the repo slug. It does this by reading the config file for logins, parsing +// the remotes of the .git repo specified in repoFlag or $PWD, and using overrides from +// command flags. If a local git repo can't be found, repo slug values are unset. +func InitCommand(ctx *cli.Context) *TeaContext { + // these flags are used as overrides to the context detection via local git repo + repoFlag := ctx.String("repo") + loginFlag := ctx.String("login") + remoteFlag := ctx.String("remote") + + var repoSlug string + var repoPath string // empty means PWD + var repoFlagPathExists bool + + // check if repoFlag can be interpreted as path to local repo. + if len(repoFlag) != 0 { + repoFlagPathExists, err := utils.PathExists(repoFlag) + if err != nil { + log.Fatal(err.Error()) + } + if repoFlagPathExists { + repoPath = repoFlag + } + } + + // try to read git repo & extract context, ignoring if PWD is not a repo + localRepo, login, repoSlug, err := contextFromLocalRepo(repoPath, remoteFlag) + if err != nil && err != gogit.ErrRepositoryNotExists { + log.Fatal(err.Error()) + } + + // if repoFlag is not a path, use it to override repoSlug + if len(repoFlag) != 0 && !repoFlagPathExists { + repoSlug = repoFlag + } + + // override login from flag, or use default login if repo based detection failed + if len(loginFlag) != 0 { + login = config.GetLoginByName(loginFlag) + if login == nil { + log.Fatalf("Login name '%s' does not exist", loginFlag) + } + } else if login == nil { + if login, err = config.GetDefaultLogin(); err != nil { + log.Fatal(err.Error()) + } + } + + // parse reposlug (owner falling back to login owner if reposlug contains only repo name) + owner, reponame := utils.GetOwnerAndRepo(repoSlug, login.User) + + return &TeaContext{ctx, login, repoSlug, owner, reponame, ctx.String("output"), localRepo} +} + +// contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo +func contextFromLocalRepo(repoValue, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { + repo, err := git.RepoFromPath(repoValue) + if err != nil { + return nil, nil, "", err + } + gitConfig, err := repo.Config() + if err != nil { + return repo, nil, "", err + } + + // if no remote + if len(gitConfig.Remotes) == 0 { + return repo, nil, "", errors.New("No remote(s) found in this Git repository") + } + + // if only one remote exists + if len(gitConfig.Remotes) >= 1 && len(remoteValue) == 0 { + for remote := range gitConfig.Remotes { + remoteValue = remote + } + if len(gitConfig.Remotes) > 1 { + // if master branch is present, use it as the default remote + masterBranch, ok := gitConfig.Branches["master"] + if ok { + if len(masterBranch.Remote) > 0 { + remoteValue = masterBranch.Remote + } + } + } + } + + remoteConfig, ok := gitConfig.Remotes[remoteValue] + if !ok || remoteConfig == nil { + return repo, nil, "", fmt.Errorf("Remote '%s' not found in this Git repository", remoteValue) + } + + logins, err := config.GetLogins() + if err != nil { + return repo, nil, "", err + } + for _, l := range logins { + for _, u := range remoteConfig.URLs { + p, err := git.ParseURL(strings.TrimSpace(u)) + if err != nil { + return repo, nil, "", fmt.Errorf("Git remote URL parse failed: %s", err.Error()) + } + if strings.EqualFold(p.Scheme, "http") || strings.EqualFold(p.Scheme, "https") { + if strings.HasPrefix(u, l.URL) { + ps := strings.Split(p.Path, "/") + path := strings.Join(ps[len(ps)-2:], "/") + return repo, &l, strings.TrimSuffix(path, ".git"), nil + } + } else if strings.EqualFold(p.Scheme, "ssh") { + if l.GetSSHHost() == strings.Split(p.Host, ":")[0] { + return repo, &l, strings.TrimLeft(strings.TrimSuffix(p.Path, ".git"), "/"), nil + } + } + } + } + + return repo, nil, "", errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") +} diff --git a/modules/print/login.go b/modules/print/login.go index 61d388c..841f0d4 100644 --- a/modules/print/login.go +++ b/modules/print/login.go @@ -13,7 +13,7 @@ import ( ) // LoginDetails print login entry to stdout -func LoginDetails(login *config.Login, output string) { +func LoginDetails(login *config.Login) { in := fmt.Sprintf("# %s\n\n[@%s](%s/%s)\n", login.Name, login.User,