mirror of
https://github.com/tj/git-extras.git
synced 2026-09-10 07:26:17 -04:00
feat(mr): support Forgejo/Codeberg pull request URLs (#1267)
* feat(mr): support Forgejo/Codeberg pull request URLs Codeberg and other Forgejo instances expose pull requests under refs/pull/<id>/head instead of GitLab's refs/merge-requests/<id>/head, so passing a Codeberg pull request URL to git mr fetched the wrong ref. Recognize the /pulls/<id> URL shape and switch to the matching ref for that case, leaving the GitLab URL and bare numeric id behavior unchanged. Closes #1213 * test(git-mr): cover Forgejo/Codeberg URLs, regenerate man docs Add a bats test that exercises the pulls URL branch via a local insteadOf remote rewrite (no real HTTP endpoint needed), and bring git-mr.1/git-mr.html in line with the git-mr.md changes. --------- Co-authored-by: vjymisal0 <vijay.looprai@gmail.com>
This commit is contained in:
parent
dbf68bac59
commit
4c38988ba9
13
Commands.md
13
Commands.md
|
|
@ -1428,8 +1428,8 @@ $ git reset-file .htaccess dc82b19
|
||||||
|
|
||||||
## git mr
|
## git mr
|
||||||
|
|
||||||
Checks out a merge request from GitLab. Usage: `git mr <ID|URL> [REMOTE]`.
|
Checks out a merge request from GitLab, or a pull request from Forgejo/Codeberg.
|
||||||
Default remote is `origin`.
|
Usage: `git mr <ID|URL> [REMOTE]`. Default remote is `origin`.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ git mr 51
|
$ git mr 51
|
||||||
|
|
@ -1447,6 +1447,15 @@ From gitlab.com:owner/repository
|
||||||
Switched to branch 'mr/51'
|
Switched to branch 'mr/51'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A Forgejo/Codeberg pull request URL is also supported:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ git mr https://codeberg.org/owner/repository/pulls/51
|
||||||
|
From codeberg.org:owner/repository
|
||||||
|
* [new ref] refs/pull/51/head -> mr/51
|
||||||
|
Switched to branch 'mr/51'
|
||||||
|
```
|
||||||
|
|
||||||
Just like [git pr](#git-pr), `git mr` accepts a `clean` argument to trash all
|
Just like [git pr](#git-pr), `git mr` accepts a `clean` argument to trash all
|
||||||
`mr/` branches. Ensure current branch is not one.
|
`mr/` branches. Ensure current branch is not one.
|
||||||
|
|
||||||
|
|
|
||||||
10
bin/git-mr
10
bin/git-mr
|
|
@ -7,6 +7,8 @@ if [ -z "${1-}" ] ; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
remote_ref_kind=merge-requests
|
||||||
|
|
||||||
if test "$1" = "clean"; then
|
if test "$1" = "clean"; then
|
||||||
git for-each-ref refs/heads/mr/* --format='%(refname)' | while read -r ref; do
|
git for-each-ref refs/heads/mr/* --format='%(refname)' | while read -r ref; do
|
||||||
git branch -D "${ref#refs/heads/}"
|
git branch -D "${ref#refs/heads/}"
|
||||||
|
|
@ -15,13 +17,19 @@ if test "$1" = "clean"; then
|
||||||
elif [[ $1 =~ ^(https?://[^/]+/(.+))/merge_requests/([0-9]+).*$ ]]; then
|
elif [[ $1 =~ ^(https?://[^/]+/(.+))/merge_requests/([0-9]+).*$ ]]; then
|
||||||
remote=${BASH_REMATCH[1]}.git
|
remote=${BASH_REMATCH[1]}.git
|
||||||
id=${BASH_REMATCH[3]}
|
id=${BASH_REMATCH[3]}
|
||||||
|
elif [[ $1 =~ ^(https?://[^/]+/(.+))/pulls/([0-9]+).*$ ]]; then
|
||||||
|
# Forgejo/Codeberg pull request URL, e.g.
|
||||||
|
# https://codeberg.org/owner/repository/pulls/453
|
||||||
|
remote=${BASH_REMATCH[1]}.git
|
||||||
|
id=${BASH_REMATCH[3]}
|
||||||
|
remote_ref_kind=pull
|
||||||
else
|
else
|
||||||
id=$1
|
id=$1
|
||||||
remote=${2:-origin}
|
remote=${2:-origin}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
branch=mr/$id
|
branch=mr/$id
|
||||||
remote_ref=refs/merge-requests/$id/head
|
remote_ref=refs/$remote_ref_kind/$id/head
|
||||||
git fetch -fu "$remote" "$remote_ref:$branch"
|
git fetch -fu "$remote" "$remote_ref:$branch"
|
||||||
git checkout "$branch"
|
git checkout "$branch"
|
||||||
git config --local --replace "branch.$branch.merge" "$remote_ref"
|
git config --local --replace "branch.$branch.merge" "$remote_ref"
|
||||||
|
|
|
||||||
18
man/git-mr.1
18
man/git-mr.1
|
|
@ -28,7 +28,7 @@ The name of the remote to fetch from\. Defaults to \fBorigin\fR\.
|
||||||
<url>
|
<url>
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
GitLab merge request URL in the format \fBhttps://gitlab\.tld/owner/repository/merge_requests/453\fR\.
|
GitLab merge request URL in the format \fBhttps://gitlab\.tld/owner/repository/merge_requests/453\fR, or a Forgejo/Codeberg pull request URL in the format \fBhttps://codeberg\.tld/owner/repository/pulls/453\fR\.
|
||||||
.
|
.
|
||||||
.SH "EXAMPLES"
|
.SH "EXAMPLES"
|
||||||
This checks out merge request \fB!51\fR from remote \fBorigin\fR to branch \fBmr/51\fR\.
|
This checks out merge request \fB!51\fR from remote \fBorigin\fR to branch \fBmr/51\fR\.
|
||||||
|
|
@ -46,6 +46,22 @@ Switched to branch \'mr/51\'
|
||||||
.
|
.
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
.
|
.
|
||||||
|
.P
|
||||||
|
This checks out pull request \fB#51\fR from a Forgejo/Codeberg URL to branch \fBmr/51\fR\.
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
$ git mr https://codeberg\.org/owner/repository/pulls/51
|
||||||
|
From codeberg\.org:owner/repository
|
||||||
|
* [new ref] refs/pull/51/head \-> mr/51
|
||||||
|
Switched to branch \'mr/51\'
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
Written by Étienne BERSAC \fIbersace03@gmail\.com\fR from git\-pr(1)\.
|
Written by Étienne BERSAC \fIbersace03@gmail\.com\fR from git\-pr(1)\.
|
||||||
.
|
.
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,9 @@
|
||||||
<p> <url></p>
|
<p> <url></p>
|
||||||
|
|
||||||
<p> GitLab merge request URL in the format
|
<p> GitLab merge request URL in the format
|
||||||
<code>https://gitlab.tld/owner/repository/merge_requests/453</code>.</p>
|
<code>https://gitlab.tld/owner/repository/merge_requests/453</code>, or a
|
||||||
|
Forgejo/Codeberg pull request URL in the format
|
||||||
|
<code>https://codeberg.tld/owner/repository/pulls/453</code>.</p>
|
||||||
|
|
||||||
<h2 id="EXAMPLES">EXAMPLES</h2>
|
<h2 id="EXAMPLES">EXAMPLES</h2>
|
||||||
|
|
||||||
|
|
@ -106,6 +108,14 @@ From gitlab.com:owner/repository
|
||||||
Switched to branch 'mr/51'
|
Switched to branch 'mr/51'
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
|
<p>This checks out pull request <code>#51</code> from a Forgejo/Codeberg URL to branch <code>mr/51</code>.</p>
|
||||||
|
|
||||||
|
<pre><code>$ git mr https://codeberg.org/owner/repository/pulls/51
|
||||||
|
From codeberg.org:owner/repository
|
||||||
|
* [new ref] refs/pull/51/head -> mr/51
|
||||||
|
Switched to branch 'mr/51'
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
<h2 id="AUTHOR">AUTHOR</h2>
|
<h2 id="AUTHOR">AUTHOR</h2>
|
||||||
|
|
||||||
<p>Written by Étienne BERSAC <a href="mailto:bersace03@gmail.com" data-bare-link="true">bersace03@gmail.com</a> from <a class="man-ref" href="git-pr.html">git-pr<span class="s">(1)</span></a>.</p>
|
<p>Written by Étienne BERSAC <a href="mailto:bersace03@gmail.com" data-bare-link="true">bersace03@gmail.com</a> from <a class="man-ref" href="git-pr.html">git-pr<span class="s">(1)</span></a>.</p>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ git-mr(1) -- Checks out a merge request locally
|
||||||
<url>
|
<url>
|
||||||
|
|
||||||
GitLab merge request URL in the format
|
GitLab merge request URL in the format
|
||||||
`https://gitlab.tld/owner/repository/merge_requests/453`.
|
`https://gitlab.tld/owner/repository/merge_requests/453`, or a
|
||||||
|
Forgejo/Codeberg pull request URL in the format
|
||||||
|
`https://codeberg.tld/owner/repository/pulls/453`.
|
||||||
|
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
@ -33,6 +35,13 @@ This checks out merge request `!51` from remote `origin` to branch `mr/51`.
|
||||||
* [new ref] refs/merge-requests/51/head -> mr/51
|
* [new ref] refs/merge-requests/51/head -> mr/51
|
||||||
Switched to branch 'mr/51'
|
Switched to branch 'mr/51'
|
||||||
|
|
||||||
|
This checks out pull request `#51` from a Forgejo/Codeberg URL to branch `mr/51`.
|
||||||
|
|
||||||
|
$ git mr https://codeberg.org/owner/repository/pulls/51
|
||||||
|
From codeberg.org:owner/repository
|
||||||
|
* [new ref] refs/pull/51/head -> mr/51
|
||||||
|
Switched to branch 'mr/51'
|
||||||
|
|
||||||
## AUTHOR
|
## AUTHOR
|
||||||
|
|
||||||
Written by Étienne BERSAC <bersace03@gmail.com> from git-pr(1).
|
Written by Étienne BERSAC <bersace03@gmail.com> from git-pr(1).
|
||||||
|
|
|
||||||
68
tests/git-mr.bats
Normal file
68
tests/git-mr.bats
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
source "$BATS_TEST_DIRNAME/test_util.sh"
|
||||||
|
|
||||||
|
setup_file() {
|
||||||
|
test_util.setup_file
|
||||||
|
|
||||||
|
PATH="$BATS_TEST_DIRNAME/bin:$PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
test_util.cd_test
|
||||||
|
|
||||||
|
test_util.git_init
|
||||||
|
touch ./tracked
|
||||||
|
git add ./tracked
|
||||||
|
git commit -m 'Initial commit'
|
||||||
|
|
||||||
|
# Local bare "remote" standing in for a real GitLab/Forgejo instance,
|
||||||
|
# with a merge-requests ref and a pull ref pointing at the same commit.
|
||||||
|
remote_dir="$BATS_TEST_TMPDIR/remote.git"
|
||||||
|
git init --bare --initial-branch main "$remote_dir"
|
||||||
|
git push "$remote_dir" HEAD:refs/merge-requests/51/head
|
||||||
|
git push "$remote_dir" HEAD:refs/pull/51/head
|
||||||
|
|
||||||
|
git remote add origin "$remote_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "checks out a merge request by numeric id" {
|
||||||
|
run git mr 51
|
||||||
|
assert_success
|
||||||
|
assert_output --partial "refs/merge-requests/51/head"
|
||||||
|
|
||||||
|
run git rev-parse --abbrev-ref HEAD
|
||||||
|
assert_output 'mr/51'
|
||||||
|
|
||||||
|
run git config --get branch.mr/51.merge
|
||||||
|
assert_output 'refs/merge-requests/51/head'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "checks out a merge request by numeric id and explicit remote" {
|
||||||
|
run git mr 51 "$remote_dir"
|
||||||
|
assert_success
|
||||||
|
assert_output --partial "refs/merge-requests/51/head"
|
||||||
|
|
||||||
|
run git rev-parse --abbrev-ref HEAD
|
||||||
|
assert_output 'mr/51'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "checks out a Forgejo/Codeberg pull request by URL" {
|
||||||
|
# git-mr only recognizes http(s) URLs, so rewrite the fake Codeberg URL
|
||||||
|
# to our local bare "remote" via insteadOf rather than needing a real
|
||||||
|
# HTTP(S) endpoint.
|
||||||
|
git config --local url."$remote_dir".insteadOf "https://codeberg.org/owner/repository.git"
|
||||||
|
|
||||||
|
run git mr "https://codeberg.org/owner/repository/pulls/51"
|
||||||
|
assert_success
|
||||||
|
assert_output --partial "refs/pull/51/head"
|
||||||
|
|
||||||
|
run git rev-parse --abbrev-ref HEAD
|
||||||
|
assert_output 'mr/51'
|
||||||
|
|
||||||
|
run git config --get branch.mr/51.merge
|
||||||
|
assert_output 'refs/pull/51/head'
|
||||||
|
|
||||||
|
run git config --get branch.mr/51.remote
|
||||||
|
assert_output 'https://codeberg.org/owner/repository.git'
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue