feat: add support of branches, with new commands such as list/protect/unprotect

Signed-off-by: Leonard Vimond <leonard.vimond.e@thalesdigital.io>
This commit is contained in:
Leonard Vimond 2024-04-16 13:55:25 +02:00
parent 5236a89d4c
commit 3b4ca724f1
6 changed files with 302 additions and 0 deletions

36
cmd/branches.go Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"code.gitea.io/tea/cmd/branches"
"github.com/urfave/cli/v2"
)
// CmdBranches represents to login a gitea server.
var CmdBranches = cli.Command{
Name: "branches",
Aliases: []string{"branch", "b"},
Category: catEntities,
Usage: "Consult branches",
Description: `Lists branches when called without argument. If a branch is provided, will show it in detail.`,
ArgsUsage: "[<branch name>]",
Action: runBranches,
Subcommands: []*cli.Command{
&branches.CmdBranchesList,
&branches.CmdBranchesProtect,
&branches.CmdBranchesUnprotect,
},
Flags: append([]cli.Flag{
&cli.BoolFlag{
Name: "comments",
Usage: "Whether to display comments (will prompt if not provided & run interactively)",
},
}, branches.CmdBranchesList.Flags...),
}
func runBranches(ctx *cli.Context) error {
return branches.RunBranchesList(ctx)
}

73
cmd/branches/list.go Normal file
View File

@ -0,0 +1,73 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package branches
import (
"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"
)
var branchFieldsFlag = flags.FieldsFlag(print.BranchFields, []string{
"name", "protected", "user-can-merge", "user-can-push",
})
// CmdBranchesListFlags Flags for command list
var CmdBranchesListFlags = append([]cli.Flag{
branchFieldsFlag,
&flags.PaginationPageFlag,
&flags.PaginationLimitFlag,
}, flags.AllDefaultFlags...)
// CmdBranchesList represents a sub command of branches to list branches
var CmdBranchesList = cli.Command{
Name: "list",
Aliases: []string{"ls"},
Usage: "List branches of the repository",
Description: `List branches of the repository`,
ArgsUsage: " ", // command does not accept arguments
Action: RunBranchesList,
Flags: CmdBranchesListFlags,
}
// RunBranchesList list branches
func RunBranchesList(cmd *cli.Context) error {
ctx := context.InitCommand(cmd)
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
owner := ctx.Owner
if ctx.IsSet("owner") {
owner = ctx.String("owner")
}
var branches []*gitea.Branch
var protections []*gitea.BranchProtection
var err error
branches, _, err = ctx.Login.Client().ListRepoBranches(owner, ctx.Repo, gitea.ListRepoBranchesOptions{
ListOptions: ctx.GetListOptions(),
})
if err != nil {
return err
}
protections, _, err = ctx.Login.Client().ListBranchProtections(owner, ctx.Repo, gitea.ListBranchProtectionsOptions{
ListOptions: ctx.GetListOptions(),
})
if err != nil {
return err
}
fields, err := branchFieldsFlag.GetValues(cmd)
if err != nil {
return err
}
print.BranchesList(branches, protections, ctx.Output, fields)
return nil
}

101
cmd/branches/protect.go Normal file
View File

@ -0,0 +1,101 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package branches
import (
"fmt"
"code.gitea.io/tea/cmd/flags"
"code.gitea.io/tea/modules/context"
"code.gitea.io/sdk/gitea"
"github.com/urfave/cli/v2"
)
// CmdBranchesProtectFlags Flags for command protect/unprotect
var CmdBranchesProtectFlags = append([]cli.Flag{
branchFieldsFlag,
&flags.PaginationPageFlag,
&flags.PaginationLimitFlag,
}, flags.AllDefaultFlags...)
// CmdBranchesProtect represents a sub command of branches to protect a branch
var CmdBranchesProtect = cli.Command{
Name: "protect",
Aliases: []string{"P"},
Usage: "Protect branches",
Description: `Block actions push/merge on specified branches`,
ArgsUsage: "<branch>",
Action: RunBranchesProtect,
Flags: CmdBranchesProtectFlags,
}
// CmdBranchesUnprotect represents a sub command of branches to protect a branch
var CmdBranchesUnprotect = cli.Command{
Name: "unprotect",
Aliases: []string{"U"},
Usage: "Unprotect branches",
Description: `Suppress existing protections on specified branches`,
ArgsUsage: "<branch>",
Action: RunBranchesProtect,
Flags: CmdBranchesProtectFlags,
}
// RunBranchesProtect function to protect/unprotect a list of branches
func RunBranchesProtect(cmd *cli.Context) error {
ctx := context.InitCommand(cmd)
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
if !cmd.Args().Present() {
return fmt.Errorf("must specify at least one branch")
}
owner := ctx.Owner
if ctx.IsSet("owner") {
owner = ctx.String("owner")
}
for _, branch := range ctx.Args().Slice() {
var err error
command := ctx.Command.Name
if command == "protect" {
_, _, err = ctx.Login.Client().CreateBranchProtection(owner, ctx.Repo, gitea.CreateBranchProtectionOption{
BranchName: branch,
RuleName: "",
EnablePush: false,
EnablePushWhitelist: false,
PushWhitelistUsernames: []string{},
PushWhitelistTeams: []string{},
PushWhitelistDeployKeys: false,
EnableMergeWhitelist: false,
MergeWhitelistUsernames: []string{},
MergeWhitelistTeams: []string{},
EnableStatusCheck: false,
StatusCheckContexts: []string{},
RequiredApprovals: 1,
EnableApprovalsWhitelist: false,
ApprovalsWhitelistUsernames: []string{},
ApprovalsWhitelistTeams: []string{},
BlockOnRejectedReviews: false,
BlockOnOfficialReviewRequests: false,
BlockOnOutdatedBranch: false,
DismissStaleApprovals: false,
RequireSignedCommits: false,
ProtectedFilePatterns: "",
UnprotectedFilePatterns: "",
})
} else if command == "unprotect" {
_, err = ctx.Login.Client().DeleteBranchProtection(owner, ctx.Repo, branch)
} else {
return fmt.Errorf("command %s is not supported", command)
}
if err != nil {
return err
}
}
return nil
}

View File

@ -153,6 +153,11 @@ List, create and update issues
**--until, -u**="": Filter by activity before this date
## branches, branch, b
Consult branches
### list, ls
List issues of the repository

View File

@ -48,6 +48,7 @@ func main() {
&cmd.CmdTrackedTimes,
&cmd.CmdOrgs,
&cmd.CmdRepos,
&cmd.CmdBranches,
&cmd.CmdAddComment,
&cmd.CmdOpen,

86
modules/print/branch.go Normal file
View File

@ -0,0 +1,86 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package print
import (
"fmt"
"code.gitea.io/sdk/gitea"
)
// BranchesList prints a listing of the branches
func BranchesList(branches []*gitea.Branch, protections []*gitea.BranchProtection, output string, fields []string) {
fmt.Println(fields)
printables := make([]printable, len(branches))
for i, branch := range branches {
var protection *gitea.BranchProtection
for _, p := range protections {
if p.BranchName == branch.Name {
protection = p
}
}
printables[i] = &printableBranch{branch, protection}
}
t := tableFromItems(fields, printables, isMachineReadable(output))
t.print(output)
}
type printableBranch struct {
branch *gitea.Branch
protection *gitea.BranchProtection
}
func (x printableBranch) FormatField(field string, machineReadable bool) string {
switch field {
case "name":
return x.branch.Name
case "protected":
return fmt.Sprintf("%t", x.branch.Protected)
case "user-can-merge":
return fmt.Sprintf("%t", x.branch.UserCanMerge)
case "user-can-push":
return fmt.Sprintf("%t", x.branch.UserCanPush)
case "protection":
if x.protection != nil {
approving := ""
for _, entry := range x.protection.ApprovalsWhitelistTeams {
approving += entry + "/"
}
for _, entry := range x.protection.ApprovalsWhitelistUsernames {
approving += entry + "/"
}
merging := ""
for _, entry := range x.protection.MergeWhitelistTeams {
approving += entry + "/"
}
for _, entry := range x.protection.MergeWhitelistUsernames {
approving += entry + "/"
}
pushing := ""
for _, entry := range x.protection.PushWhitelistTeams {
approving += entry + "/"
}
for _, entry := range x.protection.PushWhitelistUsernames {
approving += entry + "/"
}
return fmt.Sprintf(
"- enable-push: %t\n- approving: %s\n- merging: %s\n- pushing: %s\n",
x.protection.EnablePush, approving, merging, pushing,
)
}
return "<None>"
}
return ""
}
// BranchFields are all available fields to print with BranchesList()
var BranchFields = []string{
"name",
"protected",
"user-can-merge",
"user-can-push",
"protection",
}