feat(branches): add rename subcommand (#939)

Implements the 'branches rename' command to rename a branch in a repository.
This wraps the Gitea API endpoint PATCH /repos/{owner}/{repo}/branches/{branch}.

Usage: tea branches rename <old_branch_name> <new_branch_name>

Example: tea branches rename -r owner/repo main factory

This resolves issue #938.

Reviewed-on: https://gitea.com/gitea/tea/pulls/939
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Matěj Cepl <mcepl@cepl.eu>
Co-committed-by: Matěj Cepl <mcepl@cepl.eu>
This commit is contained in:
Matěj Cepl
2026-04-15 17:27:47 +00:00
committed by Lunny Xiao
parent 9e0a6203ae
commit 63bc90ea52
4 changed files with 145 additions and 0 deletions

View File

@@ -24,6 +24,7 @@ var CmdBranches = cli.Command{
&branches.CmdBranchesList,
&branches.CmdBranchesProtect,
&branches.CmdBranchesUnprotect,
&branches.CmdBranchesRename,
},
Flags: append([]cli.Flag{
&cli.BoolFlag{

78
cmd/branches/rename.go Normal file
View File

@@ -0,0 +1,78 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package branches
import (
stdctx "context"
"fmt"
"code.gitea.io/tea/cmd/flags"
"code.gitea.io/tea/modules/context"
"code.gitea.io/sdk/gitea"
"github.com/urfave/cli/v3"
)
// CmdBranchesRenameFlags Flags for command rename
var CmdBranchesRenameFlags = append([]cli.Flag{
branchFieldsFlag,
&flags.PaginationPageFlag,
&flags.PaginationLimitFlag,
}, flags.AllDefaultFlags...)
// CmdBranchesRename represents a sub command of branches to rename a branch
var CmdBranchesRename = cli.Command{
Name: "rename",
Aliases: []string{"rn"},
Usage: "Rename a branch",
Description: `Rename a branch in a repository`,
ArgsUsage: "<old_branch_name> <new_branch_name>",
Action: RunBranchesRename,
Flags: CmdBranchesRenameFlags,
}
// RunBranchesRename function to rename a branch
func RunBranchesRename(_ stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
if err := ctx.Ensure(context.CtxRequirement{RemoteRepo: true}); err != nil {
return err
}
if err := ValidateRenameArgs(ctx.Args().Slice()); err != nil {
return err
}
oldBranchName := ctx.Args().Get(0)
newBranchName := ctx.Args().Get(1)
owner := ctx.Owner
if ctx.IsSet("owner") {
owner = ctx.String("owner")
}
successful, _, err := ctx.Login.Client().RenameRepoBranch(owner, ctx.Repo, oldBranchName, gitea.RenameRepoBranchOption{
Name: newBranchName,
})
if err != nil {
return fmt.Errorf("failed to rename branch: %w", err)
}
if !successful {
return fmt.Errorf("failed to rename branch")
}
fmt.Printf("Successfully renamed branch '%s' to '%s'\n", oldBranchName, newBranchName)
return nil
}
// ValidateRenameArgs validates arguments for the rename command
func ValidateRenameArgs(args []string) error {
if len(args) != 2 {
return fmt.Errorf("must specify exactly two arguments: <old_branch_name> <new_branch_name>")
}
return nil
}

View File

@@ -0,0 +1,46 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package branches
import (
"testing"
)
func TestBranchesRenameArgs(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
}{
{
name: "valid args",
args: []string{"main", "develop"},
wantErr: false,
},
{
name: "missing both args",
args: []string{},
wantErr: true,
},
{
name: "missing new branch name",
args: []string{"main"},
wantErr: true,
},
{
name: "too many args",
args: []string{"main", "develop", "extra"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateRenameArgs(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateRenameArgs() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

View File

@@ -1381,6 +1381,26 @@ Unprotect branches
**--repo, -r**="": Override local repository path or gitea repository slug to interact with. Optional
### rename, rn
Rename a branch
**--fields, -f**="": Comma-separated list of fields to print. Available values:
name,protected,user-can-merge,user-can-push,protection
(default: "name,protected,user-can-merge,user-can-push")
**--limit, --lm**="": specify limit of items per page (default: 30)
**--login, -l**="": Use a different Gitea Login. Optional
**--output, -o**="": Output format. (simple, table, csv, tsv, yaml, json)
**--page, -p**="": specify page (default: 1)
**--remote, -R**="": Discover Gitea login from remote. Optional
**--repo, -r**="": Override local repository path or gitea repository slug to interact with. Optional
## actions, action
Manage repository actions