mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-05 21:38:13 +02:00
feat(pulls): support branch-validated stack reordering
Assisted-by: Codet:GPT-5-Codex
This commit is contained in:
+2
-1
@@ -15,13 +15,14 @@ import (
|
||||
var CmdPullsStack = cli.Command{
|
||||
Name: "stack",
|
||||
Usage: "Manage pull request stacks",
|
||||
Description: "List, show, push, restack, and merge pull request stacks",
|
||||
Description: "List, show, push, reorder, restack, and merge pull request stacks",
|
||||
Action: runPullsStackDefault,
|
||||
Commands: []*cli.Command{
|
||||
&stack.CmdStackList,
|
||||
&stack.CmdStackShow,
|
||||
&stack.CmdStackPush,
|
||||
&stack.CmdStackRestack,
|
||||
&stack.CmdStackReorder,
|
||||
&stack.CmdStackMerge,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
stdctx "context"
|
||||
"fmt"
|
||||
|
||||
"gitea.dev/tea/cmd/flags"
|
||||
"gitea.dev/tea/modules/context"
|
||||
"gitea.dev/tea/modules/task"
|
||||
"gitea.dev/tea/modules/utils"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdStackReorder stores a validated, already-linked PR branch order.
|
||||
var CmdStackReorder = cli.Command{
|
||||
Name: "reorder", Usage: "Reorder PRs after their branches have been rebased",
|
||||
ArgsUsage: "<stack id> <pull index> <pull index> [more pull indices]",
|
||||
Flags: flags.AllDefaultFlags, Action: RunStackReorder,
|
||||
}
|
||||
|
||||
func RunStackReorder(requestCtx stdctx.Context, cmd *cli.Command) error {
|
||||
if cmd.Args().Len() < 3 {
|
||||
return fmt.Errorf("stack id and at least two pull numbers are required")
|
||||
}
|
||||
stackID, err := utils.ArgToIndex(cmd.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices := make([]int64, 0, cmd.Args().Len()-1)
|
||||
for i := 1; i < cmd.Args().Len(); i++ {
|
||||
index, err := utils.ArgToIndex(cmd.Args().Get(i))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices = append(indices, index)
|
||||
}
|
||||
ctx, err := context.InitCommand(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.Ensure(context.CtxRequirement{RemoteRepo: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := task.ReorderPullStack(requestCtx, ctx.Login, ctx.Owner, ctx.Repo, stackID, indices); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(ctx.Writer, "reordered stack #%d\n", stackID)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStackReorderRequiresCompleteOrder(t *testing.T) {
|
||||
cmd := CmdStackReorder
|
||||
err := cmd.Run(context.Background(), []string{"reorder", "5", "2"})
|
||||
assert.ErrorContains(t, err, "at least two pull numbers")
|
||||
}
|
||||
@@ -120,6 +120,19 @@ func AddPullStackEntry(ctx stdctx.Context, login *config.Login, owner, repo stri
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
// ReorderPullStack records the order of PR branches that are already linked.
|
||||
func ReorderPullStack(ctx stdctx.Context, login *config.Login, owner, repo string, id int64, pullIndices []int64) (*stack.Stack, error) {
|
||||
var s stack.Stack
|
||||
err := postStackJSON(ctx, login, fmt.Sprintf("/repos/%s/%s/stacks/%d/reorder", owner, repo, id),
|
||||
struct {
|
||||
PullIndices []int64 `json:"pull_indices"`
|
||||
}{PullIndices: pullIndices}, http.StatusOK, &s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
// RestackPullStack queues a restack starting at the stack's base branch.
|
||||
func RestackPullStack(ctx stdctx.Context, login *config.Login, owner, repo string, id int64) error {
|
||||
client := api.NewClient(login)
|
||||
|
||||
@@ -134,6 +134,24 @@ func TestAddPullStackEntry(t *testing.T) {
|
||||
assert.Equal(t, int64(5), stack.ID)
|
||||
}
|
||||
|
||||
func TestReorderPullStack(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, http.MethodPost, r.Method)
|
||||
assert.Equal(t, "/api/v1/repos/owner/repo/stacks/5/reorder", r.URL.Path)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{"pull_indices":[2,3]}`, string(body))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":5,"repo_id":2,"owner_id":3,"title":"feat: base","base_branch":"main","state":"open","auto_restack":true,"entries":[]}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
result, err := ReorderPullStack(t.Context(), &config.Login{
|
||||
Name: "test", URL: server.URL, Token: "secret-token",
|
||||
}, "owner", "repo", 5, []int64{2, 3})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(5), result.ID)
|
||||
}
|
||||
|
||||
func TestRestackPullStack(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, http.MethodPost, r.Method)
|
||||
|
||||
Reference in New Issue
Block a user