fix(git): handle worktrees from forked PRs safely (#2693)
* fix(git): create worktrees from forked PRs via refs/pull/<n>/head fallback A worktree created from a linked GitHub PR whose head branch lives in a fork failed when the fork's head repository was missing (deleted fork) or unfetchable (auth, network): the dialog threw 'PR head repository URL is unavailable' before any git command ran, and the server had no fallback to refs/pull/<n>/head, which GitHub serves on the base repository. - NewWorktreeDialog: when pr.headRepo is absent, send a prRef config (refs/pull/<n>/head from origin) instead of throwing; the fork config now also carries prRef so the server can fall back when the fork fetch fails. - git service: fetchPullRequestHeadRef fetches refs/pull/<n>/head into refs/remotes/<remote>/pr-<n>-head (same refspec shape as fetchRemoteBranchRef) and both validateWorktreeCreate and attachGitWorktreeToCandidate fall back to it when the fork path fails; fallback worktrees get --no-track and no upstream config because a PR ref is not pushable. When both paths fail the original fork error surfaces. - Focused tests cover the prRef-only path and the fork-unreachable fallback. Fixes #2422 * fix(git): harden PR worktree fallback against stale fork refs (#12) After a fork fetch fails, resolve immediately from refs/pull/<n>/head instead of accepting a cached remotes/<fork>/<branch> tracking ref. Match the PR base repository by URL (not a hardcoded origin remote), store fetched PR heads under refs/openchamber/pull/<n>/head, and share one existing-mode resolver between validate and create. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * fix(git): make PR head SHA authoritative and namespace private refs Reuse local/remote branches for linked PRs only when their tip matches pr.headSha; otherwise fall through to fork fetch / refs/pull. Store PR heads under refs/openchamber/github/<owner>/<repo>/pull/<n>/head, prefer HTTPS for direct base-repo fallback, and surface composite fork+fallback errors when both paths fail. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * test(ui): assert validate/create forward deleted-fork PR payload fields Guards the dialog wiring regression where validate omitted prRef while create included it, by asserting worktreeManager forwards prRef, prBaseRepoUrl, and related fields for deleted-fork configs. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * refactor(git): always checkout linked PRs from refs/pull/<n>/head Move PR worktree resolution to the server. The UI now sends only pullRequest identity (number + baseRepoUrl + optional head fields); the server always fetches the authoritative PR head and best-effort configures fork upstream afterward. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * refactor(ui): drop PrWorktreeConfig; send PR identity only Delete the prWorktreeConfig module. NewWorktreeDialog maps linked PRs straight to pullRequest identity, skips upstream defaults for that path, and leaves checkout + optional fork tracking to the server. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * refactor(git): linked PRs are {number, baseRepoUrl} only Drop fork upstream / tracking and head/base owner-repo fields from the linked-PR worktree path. Fetch refs/pull/<n>/head, create --no-track, done. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * fix(git): meet #2422 Must/Should without refs/pull fallback Linked PRs send fork identity only; the server provisions pr-<owner>, fetches the head branch, and fails clearly when the fork is missing or unreachable. Local reuse requires a matching headSha. Prefer HTTPS for headRepoUrl. Do not write upstream tracking when the upstream ref was never fetched. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * fix(git): drop invalid upstream fallback and PR branch collisions Remove setBranchTrackingFallback: if upstream fetch fails, leave tracking unset. When a linked PR's head branch already exists locally with a different tip, create pr-<number> instead of git worktree add -b on the colliding name. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * fix(git): strip PR worktree create back to fork-remote provision (#15) Keep the original ensureRemoteName/Url path for linked fork PRs, prefer HTTPS clone URLs, fail clearly when the fork is unreachable, and leave upstream tracking unset when the upstream ref was never fetched. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
co-authored by
Serhii Dziupin
parent
bf0dfc4e6b
commit
9832c0a4a8
@@ -52,6 +52,14 @@ The following functions are exported and used by the web server:
|
||||
- `removeWorktree(directory, input)`: Remove a worktree (optionally delete local branch).
|
||||
- `isLinkedWorktree(directory)`: Check if directory is a linked worktree (not primary).
|
||||
|
||||
### Worktree creation from a GitHub pull request
|
||||
The UI provisions `pr-<owner>` via `ensureRemoteName`/`ensureRemoteUrl`
|
||||
(HTTPS clone URL preferred over SSH) and checks out
|
||||
`remotes/pr-<owner>/<head>`. A missing head URL or unreachable fork fails with
|
||||
a clear error before a worktree is kept. If upstream fetch fails during
|
||||
bootstrap, tracking is left unset rather than writing `branch.*.remote` /
|
||||
`branch.*.merge` for a ref that was never fetched.
|
||||
|
||||
### Commit and Remote Operations
|
||||
- `commit(directory, message, options)`: Create a commit from the current index. `options.stageFiles` may be provided with `options.files` by older callers to stage only selected unstaged rows before committing, but the shared Git panel now stages/unstages explicitly before commit.
|
||||
- `pull(directory, options)`: Pull changes from remote.
|
||||
|
||||
Reference in New Issue
Block a user