From 18274f1ebc166bc27b31b89c634e376ee22121d0 Mon Sep 17 00:00:00 2001 From: Tyler Date: Thu, 28 May 2026 18:29:11 +0000 Subject: [PATCH] fix(pulls): restore standard fork-flow PR creation (#1010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #1009. ## The standard fork-flow The textbook workflow for opening a PR with any git CLI (gh, glab, hub, tea, etc.) is: 1. Fork `upstream/repo` on the server. 2. Clone the fork locally; add `upstream` as a second remote. 3. Branch off, commit, push the branch to your fork. 4. Tell the tool: "open a PR on `upstream/repo`, source is `fork:branch`". In tea that's: ``` tea pulls create --repo upstream/repo --head fork:branch --base main ``` This is the flow tea supported before #850 and the flow this repo's own contribution model assumes. ## What broke #850 ("Enable git worktree support and improve pr create error handling", Nov 2025) correctly addressed worktree detection by adding `LocalRepo: true` to `runPullsCreate`'s `CtxRequirement`. But that requirement is checked before `--repo` is interpreted, and a slug-style `--repo gitea/tea` doesn't satisfy `LocalRepo` — only a path does. Result: the standard fork-flow invocation above started failing with: ``` Error: local repository required: execute from a repo dir, or specify a path with --repo ``` — which is misleading, because the user IS in a repo dir and `--repo` IS set. ## The fix Only require `LocalRepo` when the command genuinely needs the working tree: - **Interactive mode** (no flags) — uses tree info for prompts. - **`--head` omitted** — defaults head from the current branch. Otherwise the command runs with just `RemoteRepo`, and `task.CreatePull` takes the explicit `--repo` and `--head` as given. The #850 worktree fix is preserved for the in-tree path. ## Behavior table | Invocation | Before | After | |---|---|---| | `tea pulls create` (interactive) | works | works (unchanged) | | `tea pulls create --head my-branch --base main` (in-tree, same repo) | works | works (unchanged) | | `tea pulls create --repo upstream/repo --head fork:branch --base main` (fork-flow) | **fails with misleading error** | **works** | | `tea pulls create --repo upstream/repo --base main` (no `--head`, no working tree) | fails | still fails with the same error (correctly — head can't be defaulted without a working tree or explicit flag) | ## Verification Smoke-tested by opening a PR from `/tmp` (deliberately not a git repo): ``` cd /tmp tea-dev pulls create --login gitea.com --repo dinsmoor/tea-testing \ --head dinsmoor:xfork-smoke --base main \ --title "xfork smoke test" --description "..." → https://gitea.com/dinsmoor/tea-testing/pulls/4 ``` And in fact, **this very PR was opened using the patched binary** invoked from `/tmp`, since the released `tea` still has the bug. --- This patch was authored interactively with an AI assistant, driven and reviewed by a human (Tyler / @dinsmoor) every step. *pull request created by Tyler's lovingly wrangled demon machine <3* --------- Co-authored-by: Lunny Xiao Reviewed-on: https://gitea.com/gitea/tea/pulls/1010 Reviewed-by: Lunny Xiao Co-authored-by: Tyler Co-committed-by: Tyler --- cmd/pulls/create.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cmd/pulls/create.go b/cmd/pulls/create.go index fb1abb34..8bf59dbb 100644 --- a/cmd/pulls/create.go +++ b/cmd/pulls/create.go @@ -54,10 +54,16 @@ func runPullsCreate(requestCtx stdctx.Context, cmd *cli.Command) error { if err != nil { return err } - if err := ctx.Ensure(context.CtxRequirement{ - LocalRepo: true, - RemoteRepo: true, - }); err != nil { + // Interactive mode and head-branch defaulting both need a local repo. + // When --head is given explicitly the user can target a cross-fork PR + // from outside a working tree (e.g. with --repo /); + // task.CreatePull only consults ctx.LocalRepo when head is empty. + needsLocalRepo := ctx.IsInteractiveMode() || len(ctx.String("head")) == 0 + requirement := context.CtxRequirement{RemoteRepo: true} + if needsLocalRepo { + requirement.LocalRepo = true + } + if err := ctx.Ensure(requirement); err != nil { return err }