mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-30 16:55:25 +01:00 
			
		
		
		
	Allow batch operations on multiple entities (#512)
commands now accept multiple arguments where it makes sense. #### before ``` NAME: tea issues close - Change state of an issue to 'closed' USAGE: tea issues close [command options] <issue index> ``` #### after ``` NAME: tea issues close - Change state of one ore more issues to 'closed' USAGE: tea issues close [command options] <issue index> [<issue index>...] ``` Co-authored-by: Norwin <git@nroo.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/512 Reviewed-by: 6543 <6543@obermui.de> Reviewed-by: justusbunsi <justusbunsi@noreply.gitea.io> Co-authored-by: Norwin <noerw@noreply.gitea.io> Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
		| @@ -19,9 +19,9 @@ import ( | ||||
| // CmdIssuesClose represents a sub command of issues to close an issue | ||||
| var CmdIssuesClose = cli.Command{ | ||||
| 	Name:        "close", | ||||
| 	Usage:       "Change state of an issue to 'closed'", | ||||
| 	Description: `Change state of an issue to 'closed'`, | ||||
| 	ArgsUsage:   "<issue index>", | ||||
| 	Usage:       "Change state of one ore more issues to 'closed'", | ||||
| 	Description: `Change state of one ore more issues to 'closed'`, | ||||
| 	ArgsUsage:   "<issue index> [<issue index>...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		var s = gitea.StateClosed | ||||
| 		return editIssueState(ctx, gitea.EditIssueOption{State: &s}) | ||||
| @@ -37,16 +37,23 @@ func editIssueState(cmd *cli.Context, opts gitea.EditIssueOption) error { | ||||
| 		return fmt.Errorf(ctx.Command.ArgsUsage) | ||||
| 	} | ||||
|  | ||||
| 	index, err := utils.ArgToIndex(ctx.Args().First()) | ||||
| 	indices, err := utils.ArgsToIndices(ctx.Args().Slice()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	issue, _, err := ctx.Login.Client().EditIssue(ctx.Owner, ctx.Repo, index, opts) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	client := ctx.Login.Client() | ||||
| 	for _, index := range indices { | ||||
| 		issue, _, err := client.EditIssue(ctx.Owner, ctx.Repo, index, opts) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 	print.IssueDetails(issue, nil) | ||||
| 		if len(indices) > 1 { | ||||
| 			fmt.Println(issue.HTMLURL) | ||||
| 		} else { | ||||
| 			print.IssueDetails(issue, nil) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -15,9 +15,9 @@ import ( | ||||
| var CmdIssuesReopen = cli.Command{ | ||||
| 	Name:        "reopen", | ||||
| 	Aliases:     []string{"open"}, | ||||
| 	Usage:       "Change state of an issue to 'open'", | ||||
| 	Description: `Change state of an issue to 'open'`, | ||||
| 	ArgsUsage:   "<issue index>", | ||||
| 	Usage:       "Change state of one or more issues to 'open'", | ||||
| 	Description: `Change state of one or more issues to 'open'`, | ||||
| 	ArgsUsage:   "<issue index> [<issue index>...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		var s = gitea.StateOpen | ||||
| 		return editIssueState(ctx, gitea.EditIssueOption{State: &s}) | ||||
|   | ||||
| @@ -13,9 +13,9 @@ import ( | ||||
| // CmdMilestonesClose represents a sub command of milestones to close an milestone | ||||
| var CmdMilestonesClose = cli.Command{ | ||||
| 	Name:        "close", | ||||
| 	Usage:       "Change state of an milestone to 'closed'", | ||||
| 	Description: `Change state of an milestone to 'closed'`, | ||||
| 	ArgsUsage:   "<milestone name>", | ||||
| 	Usage:       "Change state of one or more milestones to 'closed'", | ||||
| 	Description: `Change state of one or more milestones to 'closed'`, | ||||
| 	ArgsUsage:   "<milestone name> [<milestone name>...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		if ctx.Bool("force") { | ||||
| 			return deleteMilestone(ctx) | ||||
|   | ||||
| @@ -5,8 +5,11 @@ | ||||
| package milestones | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/tea/cmd/flags" | ||||
| 	"code.gitea.io/tea/modules/context" | ||||
| 	"code.gitea.io/tea/modules/print" | ||||
|  | ||||
| 	"code.gitea.io/sdk/gitea" | ||||
| 	"github.com/urfave/cli/v2" | ||||
| @@ -16,9 +19,9 @@ import ( | ||||
| var CmdMilestonesReopen = cli.Command{ | ||||
| 	Name:        "reopen", | ||||
| 	Aliases:     []string{"open"}, | ||||
| 	Usage:       "Change state of an milestone to 'open'", | ||||
| 	Description: `Change state of an milestone to 'open'`, | ||||
| 	ArgsUsage:   "<milestone name>", | ||||
| 	Usage:       "Change state of one or more milestones to 'open'", | ||||
| 	Description: `Change state of one or more milestones to 'open'`, | ||||
| 	ArgsUsage:   "<milestone name> [<milestone name> ...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		return editMilestoneStatus(ctx, false) | ||||
| 	}, | ||||
| @@ -28,16 +31,31 @@ var CmdMilestonesReopen = cli.Command{ | ||||
| func editMilestoneStatus(cmd *cli.Context, close bool) error { | ||||
| 	ctx := context.InitCommand(cmd) | ||||
| 	ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) | ||||
| 	client := ctx.Login.Client() | ||||
| 	if ctx.Args().Len() == 0 { | ||||
| 		return fmt.Errorf(ctx.Command.ArgsUsage) | ||||
| 	} | ||||
|  | ||||
| 	state := gitea.StateOpen | ||||
| 	if close { | ||||
| 		state = gitea.StateClosed | ||||
| 	} | ||||
| 	_, _, err := client.EditMilestoneByName(ctx.Owner, ctx.Repo, ctx.Args().First(), gitea.EditMilestoneOption{ | ||||
| 		State: &state, | ||||
| 		Title: ctx.Args().First(), | ||||
| 	}) | ||||
|  | ||||
| 	return err | ||||
| 	client := ctx.Login.Client() | ||||
| 	for _, ms := range ctx.Args().Slice() { | ||||
| 		opts := gitea.EditMilestoneOption{ | ||||
| 			State: &state, | ||||
| 			Title: ms, | ||||
| 		} | ||||
| 		milestone, _, err := client.EditMilestoneByName(ctx.Owner, ctx.Repo, ms, opts) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if ctx.Args().Len() > 1 { | ||||
| 			fmt.Printf("%s/milestone/%d\n", ctx.GetRemoteRepoHTMLURL(), milestone.ID) | ||||
| 		} else { | ||||
| 			print.MilestoneDetails(milestone) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -74,6 +74,5 @@ func runOpen(cmd *cli.Context) error { | ||||
| 		suffix = number | ||||
| 	} | ||||
|  | ||||
| 	u := path.Join(ctx.Login.URL, ctx.Owner, ctx.Repo, suffix) | ||||
| 	return open.Run(u) | ||||
| 	return open.Run(path.Join(ctx.GetRemoteRepoHTMLURL(), suffix)) | ||||
| } | ||||
|   | ||||
| @@ -14,9 +14,9 @@ import ( | ||||
| // CmdPullsClose closes a given open pull request | ||||
| var CmdPullsClose = cli.Command{ | ||||
| 	Name:        "close", | ||||
| 	Usage:       "Change state of a pull request to 'closed'", | ||||
| 	Description: `Change state of a pull request to 'closed'`, | ||||
| 	ArgsUsage:   "<pull index>", | ||||
| 	Usage:       "Change state of one or more pull requests to 'closed'", | ||||
| 	Description: `Change state of one or more pull requests to 'closed'`, | ||||
| 	ArgsUsage:   "<pull index> [<pull index>...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		var s = gitea.StateClosed | ||||
| 		return editPullState(ctx, gitea.EditPullRequestOption{State: &s}) | ||||
|   | ||||
| @@ -23,16 +23,23 @@ func editPullState(cmd *cli.Context, opts gitea.EditPullRequestOption) error { | ||||
| 		return fmt.Errorf("Please provide a Pull Request index") | ||||
| 	} | ||||
|  | ||||
| 	index, err := utils.ArgToIndex(ctx.Args().First()) | ||||
| 	indices, err := utils.ArgsToIndices(ctx.Args().Slice()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	pr, _, err := ctx.Login.Client().EditPullRequest(ctx.Owner, ctx.Repo, index, opts) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	client := ctx.Login.Client() | ||||
| 	for _, index := range indices { | ||||
| 		pr, _, err := client.EditPullRequest(ctx.Owner, ctx.Repo, index, opts) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 	print.PullDetails(pr, nil, nil) | ||||
| 		if len(indices) > 1 { | ||||
| 			fmt.Println(pr.HTMLURL) | ||||
| 		} else { | ||||
| 			print.PullDetails(pr, nil, nil) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -15,9 +15,9 @@ import ( | ||||
| var CmdPullsReopen = cli.Command{ | ||||
| 	Name:        "reopen", | ||||
| 	Aliases:     []string{"open"}, | ||||
| 	Usage:       "Change state of a pull request to 'open'", | ||||
| 	Description: `Change state of a pull request to 'open'`, | ||||
| 	ArgsUsage:   "<pull index>", | ||||
| 	Usage:       "Change state of one or more pull requests to 'open'", | ||||
| 	Description: `Change state of one or more pull requests to 'open'`, | ||||
| 	ArgsUsage:   "<pull index> [<pull index>...]", | ||||
| 	Action: func(ctx *cli.Context) error { | ||||
| 		var s = gitea.StateOpen | ||||
| 		return editPullState(ctx, gitea.EditPullRequestOption{State: &s}) | ||||
|   | ||||
| @@ -17,9 +17,9 @@ import ( | ||||
| var CmdReleaseDelete = cli.Command{ | ||||
| 	Name:        "delete", | ||||
| 	Aliases:     []string{"rm"}, | ||||
| 	Usage:       "Delete a release", | ||||
| 	Description: `Delete a release`, | ||||
| 	ArgsUsage:   "<release tag>", | ||||
| 	Usage:       "Delete one or more releases", | ||||
| 	Description: `Delete one or more releases`, | ||||
| 	ArgsUsage:   "<release tag> [<release tag>...]", | ||||
| 	Action:      runReleaseDelete, | ||||
| 	Flags: append([]cli.Flag{ | ||||
| 		&cli.BoolFlag{ | ||||
| @@ -39,9 +39,8 @@ func runReleaseDelete(cmd *cli.Context) error { | ||||
| 	ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) | ||||
| 	client := ctx.Login.Client() | ||||
|  | ||||
| 	tag := ctx.Args().First() | ||||
| 	if len(tag) == 0 { | ||||
| 		fmt.Println("Release tag needed to delete") | ||||
| 	if !ctx.Args().Present() { | ||||
| 		fmt.Println("Release tag needed to edit") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| @@ -50,18 +49,20 @@ func runReleaseDelete(cmd *cli.Context) error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = client.DeleteRelease(ctx.Owner, ctx.Repo, release.ID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, tag := range ctx.Args().Slice() { | ||||
| 		release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		_, err = client.DeleteRelease(ctx.Owner, ctx.Repo, release.ID) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 	if ctx.Bool("delete-tag") { | ||||
| 		_, err = client.DeleteTag(ctx.Owner, ctx.Repo, tag) | ||||
| 		return err | ||||
| 		if ctx.Bool("delete-tag") { | ||||
| 			_, err = client.DeleteTag(ctx.Owner, ctx.Repo, tag) | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
|   | ||||
| @@ -19,9 +19,9 @@ import ( | ||||
| var CmdReleaseEdit = cli.Command{ | ||||
| 	Name:        "edit", | ||||
| 	Aliases:     []string{"e"}, | ||||
| 	Usage:       "Edit a release", | ||||
| 	Description: `Edit a release`, | ||||
| 	ArgsUsage:   "<release tag>", | ||||
| 	Usage:       "Edit one or more releases", | ||||
| 	Description: `Edit one or more releases`, | ||||
| 	ArgsUsage:   "<release tag> [<release tag>...]", | ||||
| 	Action:      runReleaseEdit, | ||||
| 	Flags: append([]cli.Flag{ | ||||
| 		&cli.StringFlag{ | ||||
| @@ -62,16 +62,6 @@ func runReleaseEdit(cmd *cli.Context) error { | ||||
| 	ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) | ||||
| 	client := ctx.Login.Client() | ||||
|  | ||||
| 	tag := ctx.Args().First() | ||||
| 	if len(tag) == 0 { | ||||
| 		fmt.Println("Release tag needed to edit") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var isDraft, isPre *bool | ||||
| 	if ctx.IsSet("draft") { | ||||
| 		isDraft = gitea.OptionalBool(strings.ToLower(ctx.String("draft"))[:1] == "t") | ||||
| @@ -80,13 +70,28 @@ func runReleaseEdit(cmd *cli.Context) error { | ||||
| 		isPre = gitea.OptionalBool(strings.ToLower(ctx.String("prerelease"))[:1] == "t") | ||||
| 	} | ||||
|  | ||||
| 	_, _, err = client.EditRelease(ctx.Owner, ctx.Repo, release.ID, gitea.EditReleaseOption{ | ||||
| 		TagName:      ctx.String("tag"), | ||||
| 		Target:       ctx.String("target"), | ||||
| 		Title:        ctx.String("title"), | ||||
| 		Note:         ctx.String("note"), | ||||
| 		IsDraft:      isDraft, | ||||
| 		IsPrerelease: isPre, | ||||
| 	}) | ||||
| 	return err | ||||
| 	if !ctx.Args().Present() { | ||||
| 		fmt.Println("Release tag needed to edit") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	for _, tag := range ctx.Args().Slice() { | ||||
| 		release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		_, _, err = client.EditRelease(ctx.Owner, ctx.Repo, release.ID, gitea.EditReleaseOption{ | ||||
| 			TagName:      ctx.String("tag"), | ||||
| 			Target:       ctx.String("target"), | ||||
| 			Title:        ctx.String("title"), | ||||
| 			Note:         ctx.String("note"), | ||||
| 			IsDraft:      isDraft, | ||||
| 			IsPrerelease: isPre, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | ||||
| 	"code.gitea.io/sdk/gitea" | ||||
| @@ -51,6 +52,13 @@ func (ctx *TeaContext) GetListOptions() gitea.ListOptions { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // GetRemoteRepoHTMLURL returns the web-ui url of the remote repo, | ||||
| // after ensuring a remote repo is present in the context. | ||||
| func (ctx *TeaContext) GetRemoteRepoHTMLURL() string { | ||||
| 	ctx.Ensure(CtxRequirement{RemoteRepo: true}) | ||||
| 	return path.Join(ctx.Login.URL, ctx.Owner, ctx.Repo) | ||||
| } | ||||
|  | ||||
| // Ensure checks if requirements on the context are set, and terminates otherwise. | ||||
| func (ctx *TeaContext) Ensure(req CtxRequirement) { | ||||
| 	if req.LocalRepo && ctx.LocalRepo == nil { | ||||
|   | ||||
| @@ -10,6 +10,18 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // ArgsToIndices take issue/pull index as string and returns int64s | ||||
| func ArgsToIndices(args []string) ([]int64, error) { | ||||
| 	indices := make([]int64, len(args)) | ||||
| 	for i, arg := range args { | ||||
| 		var err error | ||||
| 		if indices[i], err = ArgToIndex(arg); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return indices, nil | ||||
| } | ||||
|  | ||||
| // ArgToIndex take issue/pull index as string and return int64 | ||||
| func ArgToIndex(arg string) (int64, error) { | ||||
| 	if strings.HasPrefix(arg, "#") { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Norwin
					Norwin