feat: Add support for merge request from fork#546
feat: Add support for merge request from fork#546Clement-Hue wants to merge 4 commits intoharrisoncramer:developfrom
Conversation
When a user selects a merge request from choose_merge_request that originates from a fork, two things previously failed: 1. The Go middleware always filtered by SourceBranch alongside the chosen MR IID. The GitLab API source_branch filter does not match fork MR branches (they belong to a different project), so the query returned zero results and the error 'No MRs Found' was shown. Fix: when ChosenMrIID is set, filter only by IID (sufficient to uniquely identify the MR) and skip the SourceBranch filter. 2. The Lua code attempted to git checkout the source branch, which does not exist locally for fork MRs. Fix: detect fork MRs by comparing source_project_id vs target_project_id and skip the branch switch, proceeding directly to server restart.
For fork MRs, the head_sha from diff_refs points to commits that live in the fork repository and are not present locally. Diffview fails with 'Failed to update files in a diff view' because it cannot resolve these SHAs. Fix: at server startup, when ChosenMrIID is set, fetch the MR head ref from GitLab (refs/merge-requests/:iid/head) and store it as a local ref. This downloads the fork's commits into the local object store, allowing diffview to resolve base_sha..head_sha.
The pipeline handler uses GetLatestCommitOnRemote which runs 'git log origin/<branch>' to find the latest commit. For fork MRs, the source branch does not exist on the origin remote, causing a failure. Fix: when GetLatestCommitOnRemote fails and ChosenMrIID is set, fall back to GetMRHeadCommit which resolves the commit from the locally fetched refs/merge-requests/:iid/head ref.
The function now accepts and forwards head_sha to the git diff command, ensuring the diff is computed between the correct base and head SHAs of the merge request rather than comparing against the working tree.
|
Hi @Clement-Hue, I'm glad to see more contributors to the plugin. Just a note regarding your suggestion to use your new approach also for local merge requests. The benefit of using the local files for a review are that you can use all the benefits of LSP, code navigation, linting, etc. As for the perceived benefits of your approach, you can achieve at least some of them by using git worktrees. With worktrees you can have several versions of the same repo checked out at the same time and you don't worry about switching branches, stashing changes, and a clean tree. I find this a superior workflow for multiple feature branches regardless of merge requests. The only reason I'm missing the possibility to review a MR without a local branch is for a closed MR where the feature branch has already been deleted. I think it would be great if gitlab.nvim could support both these workflows. |
Summary
Add support for choosing and reviewing merge requests originating from forked projects. Previously, the plugin assumed the MR source branch always existed in the local repository, which broke fork-based workflows. This MR makes fork MRs discoverable, fetchable, and reviewable via
choose_merge_request.Problem
When a user selects a merge request that originates from a fork, the plugin fails because:
SourceBranch, which doesn't exist locally for fork MRs.choose_merge_requestaction tries to switch to a branch that doesn't exist locally.Changes
cmd/app/git/git.go— AddFetchMRHead(fetchesrefs/merge-requests/<iid>/head) andGetMRHeadCommit(resolves the fetched ref to a SHA) to theGitManagerinterface andGitimplementation; addFetchMrHeadhelper that skips the fetch when no MR IID is set.cmd/app/git/git_test.go— Add unit tests forFetchMrHead(skip/fetch/error paths) and integration tests forGetMRHeadCommit(success and non-existent ref) using a temporary git repo.cmd/app/middleware.go— WhenChosenMrIIDis set, filter MRs by IID only (skipSourceBranch) so fork MRs are found.cmd/app/middleware_test.go— Add tests verifying the middleware usesIIDsvsSourceBranchdepending onChosenMrIID.cmd/app/pipeline.go— Fall back toGetMRHeadCommitwhen the branch doesn't exist on the remote and an MR IID is set.cmd/app/test_helpers.go— ImplementGetMRHeadCommitandFetchMRHeadon theFakeGitManagerto satisfy the updated interface.cmd/main.go— CallFetchMrHeadat startup so fork MR commits are available locally for diffview.lua/gitlab/actions/merge_requests.lua— Detect fork MRs (source_project_id ≠ target_project_id) and skip the branch switch; extractactivate_mr,select_fork_mr, andselect_local_mrhelpers for clarity.lua/gitlab/hunks.lua— passhead_shatoparse_hunks_and_diff. The function now accepts and forwards head_sha to the git diff command, ensuring the diff is computed between the correct base and head SHAs ofthe merge request rather than comparing against the working tree. This make diff working with the new strategy
Suggestion
Probably it will be a good idea to use this approach also for local merge request and avoid the fetching of branch and checkout to it. This approach has several benefits