* [PATCH] refspec: allow @ on the left-hand side of refspecs
@ 2018-07-29 19:28 brian m. carlson
2018-07-30 17:50 ` Brandon Williams
0 siblings, 1 reply; 4+ messages in thread
From: brian m. carlson @ 2018-07-29 19:28 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Brandon Williams, Jeff King
The object ID parsing machinery is aware of "@" as a synonym for "HEAD"
and this is documented accordingly in gitrevisions(7). The push
documentation describes the source portion of a refspec as "any
arbitrary 'SHA-1 expression'"; however, "@" is not allowed on the
left-hand side of a refspec, since we attempt to check for it being a
valid ref name and fail (since it is not).
Teach the refspec machinery about this alias and silently substitute
"HEAD" when we see "@". This handles the fact that HEAD is a symref and
preserves its special behavior. We need not handle other arbitrary
object ID expressions (such as "@^") when pushing because the revision
machinery already handles that for us.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
I probably type "git push upstream HEAD" from five to thirty times a
day, many of those where I typo "HEAD", so I decided to implement the
shorter form. This design handles @ as HEAD in both fetch and push,
whereas alternate solutions would not.
check_refname_format explicitly rejects "@"; I tried at first to simply
ignore that with a flag, but we end up calling that from several other
places in the codebase and rejecting it and all of those places would
have needed updating.
I thought about putting the if/else logic in a function, but since it's
just four lines, I decided not to. However, if people think it would be
tidier, I can do so.
Note that the test portion of the patch is best read with git diff -w;
the current version is very noisy.
refspec.c | 6 ++-
t/t5516-fetch-push.sh | 104 +++++++++++++++++++++---------------------
2 files changed, 58 insertions(+), 52 deletions(-)
diff --git a/refspec.c b/refspec.c
index e8010dce0c..57c2f65104 100644
--- a/refspec.c
+++ b/refspec.c
@@ -62,8 +62,12 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
return 0;
}
+ if (llen == 1 && lhs[0] == '@')
+ item->src = xstrdup("HEAD");
+ else
+ item->src = xstrndup(lhs, llen);
+
item->pattern = is_glob;
- item->src = xstrndup(lhs, llen);
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
if (fetch) {
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index a5077d8b7c..cbccbd2f8d 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -436,70 +436,72 @@ test_expect_success 'push ref expression with non-existent, incomplete dest' '
'
-test_expect_success 'push with HEAD' '
+for ref in HEAD @
+do
+ test_expect_success "push with $ref" '
- mk_test testrepo heads/master &&
- git checkout master &&
- git push testrepo HEAD &&
- check_push_result testrepo $the_commit heads/master
+ mk_test testrepo heads/master &&
+ git checkout master &&
+ git push testrepo $ref &&
+ check_push_result testrepo $the_commit heads/master
-'
+ '
-test_expect_success 'push with HEAD nonexisting at remote' '
+ test_expect_success "push with $ref nonexisting at remote" '
- mk_test testrepo heads/master &&
- git checkout -b local master &&
- git push testrepo HEAD &&
- check_push_result testrepo $the_commit heads/local
-'
+ mk_test testrepo heads/master &&
+ git checkout -B local master &&
+ git push testrepo $ref &&
+ check_push_result testrepo $the_commit heads/local
+ '
-test_expect_success 'push with +HEAD' '
+ test_expect_success "push with +$ref" '
- mk_test testrepo heads/master &&
- git checkout master &&
- git branch -D local &&
- git checkout -b local &&
- git push testrepo master local &&
- check_push_result testrepo $the_commit heads/master &&
- check_push_result testrepo $the_commit heads/local &&
+ mk_test testrepo heads/master &&
+ git checkout master &&
+ git branch -D local &&
+ git checkout -b local &&
+ git push testrepo master local &&
+ check_push_result testrepo $the_commit heads/master &&
+ check_push_result testrepo $the_commit heads/local &&
- # Without force rewinding should fail
- git reset --hard HEAD^ &&
- test_must_fail git push testrepo HEAD &&
- check_push_result testrepo $the_commit heads/local &&
+ # Without force rewinding should fail
+ git reset --hard HEAD^ &&
+ test_must_fail git push testrepo $ref &&
+ check_push_result testrepo $the_commit heads/local &&
- # With force rewinding should succeed
- git push testrepo +HEAD &&
- check_push_result testrepo $the_first_commit heads/local
+ # With force rewinding should succeed
+ git push testrepo +$ref &&
+ check_push_result testrepo $the_first_commit heads/local
-'
+ '
-test_expect_success 'push HEAD with non-existent, incomplete dest' '
+ test_expect_success "push $ref with non-existent, incomplete dest" '
- mk_test testrepo &&
- git checkout master &&
- git push testrepo HEAD:branch &&
- check_push_result testrepo $the_commit heads/branch
+ mk_test testrepo &&
+ git checkout master &&
+ git push testrepo $ref:branch &&
+ check_push_result testrepo $the_commit heads/branch
-'
+ '
-test_expect_success 'push with config remote.*.push = HEAD' '
-
- mk_test testrepo heads/local &&
- git checkout master &&
- git branch -f local $the_commit &&
- (
- cd testrepo &&
- git checkout local &&
- git reset --hard $the_first_commit
- ) &&
- test_config remote.there.url testrepo &&
- test_config remote.there.push HEAD &&
- test_config branch.master.remote there &&
- git push &&
- check_push_result testrepo $the_commit heads/master &&
- check_push_result testrepo $the_first_commit heads/local
-'
+ test_expect_success "push with config remote.*.push = $ref" '
+ mk_test testrepo heads/local &&
+ git checkout master &&
+ git branch -f local $the_commit &&
+ (
+ cd testrepo &&
+ git checkout local &&
+ git reset --hard $the_first_commit
+ ) &&
+ test_config remote.there.url testrepo &&
+ test_config remote.there.push $ref &&
+ test_config branch.master.remote there &&
+ git push &&
+ check_push_result testrepo $the_commit heads/master &&
+ check_push_result testrepo $the_first_commit heads/local
+ '
+done
test_expect_success 'push with remote.pushdefault' '
mk_test up_repo heads/master &&
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] refspec: allow @ on the left-hand side of refspecs
2018-07-29 19:28 [PATCH] refspec: allow @ on the left-hand side of refspecs brian m. carlson
@ 2018-07-30 17:50 ` Brandon Williams
2018-07-30 23:14 ` brian m. carlson
0 siblings, 1 reply; 4+ messages in thread
From: Brandon Williams @ 2018-07-30 17:50 UTC (permalink / raw)
To: brian m. carlson; +Cc: git, Junio C Hamano, Jeff King
On 07/29, brian m. carlson wrote:
> The object ID parsing machinery is aware of "@" as a synonym for "HEAD"
> and this is documented accordingly in gitrevisions(7). The push
> documentation describes the source portion of a refspec as "any
> arbitrary 'SHA-1 expression'"; however, "@" is not allowed on the
> left-hand side of a refspec, since we attempt to check for it being a
> valid ref name and fail (since it is not).
>
> Teach the refspec machinery about this alias and silently substitute
> "HEAD" when we see "@". This handles the fact that HEAD is a symref and
> preserves its special behavior. We need not handle other arbitrary
> object ID expressions (such as "@^") when pushing because the revision
> machinery already handles that for us.
So this claims that using "@^" should work despite not accounting for it
explicitly or am I misreading? Unless I'm mistaken, it looks like we
don't really support arbitrary rev syntax in refspecs since "HEAD^"
doesn't work either.
>
> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
> ---
> I probably type "git push upstream HEAD" from five to thirty times a
> day, many of those where I typo "HEAD", so I decided to implement the
> shorter form. This design handles @ as HEAD in both fetch and push,
> whereas alternate solutions would not.
I'm always a fan of finding shortcuts and reducing how much I type, so
thank you :)
>
> check_refname_format explicitly rejects "@"; I tried at first to simply
> ignore that with a flag, but we end up calling that from several other
> places in the codebase and rejecting it and all of those places would
> have needed updating.
>
> I thought about putting the if/else logic in a function, but since it's
> just four lines, I decided not to. However, if people think it would be
> tidier, I can do so.
>
> Note that the test portion of the patch is best read with git diff -w;
> the current version is very noisy.
>
> refspec.c | 6 ++-
> t/t5516-fetch-push.sh | 104 +++++++++++++++++++++---------------------
> 2 files changed, 58 insertions(+), 52 deletions(-)
>
> diff --git a/refspec.c b/refspec.c
> index e8010dce0c..57c2f65104 100644
> --- a/refspec.c
> +++ b/refspec.c
> @@ -62,8 +62,12 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
> return 0;
> }
>
> + if (llen == 1 && lhs[0] == '@')
> + item->src = xstrdup("HEAD");
> + else
> + item->src = xstrndup(lhs, llen);
> +
This is probably the easiest place to put the aliasing logic so I don't
have any issue with including it here.
--
Brandon Williams
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] refspec: allow @ on the left-hand side of refspecs
2018-07-30 17:50 ` Brandon Williams
@ 2018-07-30 23:14 ` brian m. carlson
2018-07-31 16:02 ` Brandon Williams
0 siblings, 1 reply; 4+ messages in thread
From: brian m. carlson @ 2018-07-30 23:14 UTC (permalink / raw)
To: Brandon Williams; +Cc: git, Junio C Hamano, Jeff King
[-- Attachment #1: Type: text/plain, Size: 1857 bytes --]
On Mon, Jul 30, 2018 at 10:50:51AM -0700, Brandon Williams wrote:
> On 07/29, brian m. carlson wrote:
> > The object ID parsing machinery is aware of "@" as a synonym for "HEAD"
> > and this is documented accordingly in gitrevisions(7). The push
> > documentation describes the source portion of a refspec as "any
> > arbitrary 'SHA-1 expression'"; however, "@" is not allowed on the
> > left-hand side of a refspec, since we attempt to check for it being a
> > valid ref name and fail (since it is not).
> >
> > Teach the refspec machinery about this alias and silently substitute
> > "HEAD" when we see "@". This handles the fact that HEAD is a symref and
> > preserves its special behavior. We need not handle other arbitrary
> > object ID expressions (such as "@^") when pushing because the revision
> > machinery already handles that for us.
>
> So this claims that using "@^" should work despite not accounting for it
> explicitly or am I misreading? Unless I'm mistaken, it looks like we
> don't really support arbitrary rev syntax in refspecs since "HEAD^"
> doesn't work either.
Correct, it does indeed work, at least for me:
genre ok % git push castro HEAD^:refs/heads/temp
Total 0 (delta 0), reused 0 (delta 0)
To https://git.crustytoothpaste.net/git/bmc/git.git
* [new branch] HEAD^ -> temp
genre ok % git push castro @^:refs/heads/temp
Total 0 (delta 0), reused 0 (delta 0)
To https://git.crustytoothpaste.net/git/bmc/git.git
* [new branch] @^ -> temp
Note that in this case, I had to specify a full ref since it didn't
exist on the remote and the left side wasn't a ref name.
Now it doesn't work for fetches, only pushes. Only the left side of a
push refspec can be an arbitrary expression.
--
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 867 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] refspec: allow @ on the left-hand side of refspecs
2018-07-30 23:14 ` brian m. carlson
@ 2018-07-31 16:02 ` Brandon Williams
0 siblings, 0 replies; 4+ messages in thread
From: Brandon Williams @ 2018-07-31 16:02 UTC (permalink / raw)
To: brian m. carlson, git, Junio C Hamano, Jeff King
On 07/30, brian m. carlson wrote:
> On Mon, Jul 30, 2018 at 10:50:51AM -0700, Brandon Williams wrote:
> > On 07/29, brian m. carlson wrote:
> > > The object ID parsing machinery is aware of "@" as a synonym for "HEAD"
> > > and this is documented accordingly in gitrevisions(7). The push
> > > documentation describes the source portion of a refspec as "any
> > > arbitrary 'SHA-1 expression'"; however, "@" is not allowed on the
> > > left-hand side of a refspec, since we attempt to check for it being a
> > > valid ref name and fail (since it is not).
> > >
> > > Teach the refspec machinery about this alias and silently substitute
> > > "HEAD" when we see "@". This handles the fact that HEAD is a symref and
> > > preserves its special behavior. We need not handle other arbitrary
> > > object ID expressions (such as "@^") when pushing because the revision
> > > machinery already handles that for us.
> >
> > So this claims that using "@^" should work despite not accounting for it
> > explicitly or am I misreading? Unless I'm mistaken, it looks like we
> > don't really support arbitrary rev syntax in refspecs since "HEAD^"
> > doesn't work either.
>
> Correct, it does indeed work, at least for me:
>
> genre ok % git push castro HEAD^:refs/heads/temp
> Total 0 (delta 0), reused 0 (delta 0)
> To https://git.crustytoothpaste.net/git/bmc/git.git
> * [new branch] HEAD^ -> temp
>
> genre ok % git push castro @^:refs/heads/temp
> Total 0 (delta 0), reused 0 (delta 0)
> To https://git.crustytoothpaste.net/git/bmc/git.git
> * [new branch] @^ -> temp
>
> Note that in this case, I had to specify a full ref since it didn't
> exist on the remote and the left side wasn't a ref name.
That's what I was missing, a full refspec! Thanks for the illustration.
>
> Now it doesn't work for fetches, only pushes. Only the left side of a
> push refspec can be an arbitrary expression.
> --
> brian m. carlson: Houston, Texas, US
> OpenPGP: https://keybase.io/bk2204
--
Brandon Williams
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-07-31 16:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-29 19:28 [PATCH] refspec: allow @ on the left-hand side of refspecs brian m. carlson
2018-07-30 17:50 ` Brandon Williams
2018-07-30 23:14 ` brian m. carlson
2018-07-31 16:02 ` Brandon Williams
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).