Re: [PATCH v2 6/7] update-ref: add support for symref-update

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Patrick Steinhardt <ps@xxxxxx> writes:

> On Sun, Apr 21, 2024 at 03:00:11PM -0400, Karthik Nayak wrote:
>> Patrick Steinhardt <ps@xxxxxx> writes:
>> [snip]
>> >> +	/*
>> >> +	 * Since the user can also send in an old-oid, we try to parse
>> >> +	 * it as such too.
>> >> +	 */
>> >> +	if (old_ref && read_ref(old_ref, NULL)) {
>> >> +		if (!repo_get_oid(the_repository, old_ref, &old_oid)) {
>> >> +			old_ref = NULL;
>> >> +			have_old = 1;
>> >> +		} else
>> >> +			die("symref-update %s: invalid <old-ref> or <old-oid>", refname);
>> >> +	}
>> >
>> > So we first try to parse it as a ref, and then as an object ID? Wouldn't
>> > it preferable to try it the other way round and first check whether it
>> > is a valid object ID? That would likely be cheaper, even though it may
>> > be premature optimization.
>> >
>> > Patrick
>>
>> I think the issue is `repo_get_oid` would also parse a refname to an
>> OID. Whereas we want to first check and keep refnames and only if it
>> isn't a refname, we'd want to parse it as an OID.
>
> Okay. The question is whether this matches precedence rules that we have
> in other places. Namely, whether a reference name that looks like an
> object ID overrides an object with the same name. Testing it:
>
> ```
> $ rm -rf repo/
> $ git init --ref-format=files repo
> Initialized empty Git repository in /tmp/repo/.git/
> $ cd repo/
> $ git commit --allow-empty --message first
> [main (root-commit) 09293d8] first
> $ git commit --allow-empty --message second
> [main 1588e76] second
>
> $ git update-ref $(git rev-parse HEAD~) HEAD
> $ cat .git/09293d82c434cdc1f7f286cf7b90cf35a6e57c43
> 1588e76ce7ef1ab25ee6f846a7b5d7032f83a69e
>
> $ git rev-parse 09293d82c434cdc1f7f286cf7b90cf35a6e57c43
> warning: refname '09293d82c434cdc1f7f286cf7b90cf35a6e57c43' is ambiguous.
> Git normally never creates a ref that ends with 40 hex characters
> because it will be ignored when you just specify 40-hex. These refs
> may be created by mistake. For example,
>
>   git switch -c $br $(git rev-parse ...)
>
> where "$br" is somehow empty and a 40-hex ref is created. Please
> examine these refs and maybe delete them. Turn this message off by
> running "git config advice.objectNameWarning false"
> 09293d82c434cdc1f7f286cf7b90cf35a6e57c43
> ```
>
> So the object ID has precedence over the reference with the same name.
> Unless I'm mistaken, your proposed order would reverse that, wouldn't
> it?
>

I wasn't talking about a reference being mistaken for a object ID,
rather I was talking about how a reference will be `rev-parse`'d into an
object ID.

So instead if we did something like:

```
if (old_target) {
	if (!repo_get_oid(the_repository, old_target, &old_oid)) {
		old_target = NULL;
		have_old = 1;
	} else if (read_ref(old_target, NULL)) {
	} else {
		die("symref-update %s: invalid <old-target> or <old-oid>", refname);
	}
}
```

The problem is that now:

$ git init repo && cd repo
$ git commit --allow-empty -m"c1"
[master (root-commit) af416de] c1
$ git commit --allow-empty -m"c2"
[master 52e95b2] c2
$ git symbolic-ref refs/heads/symref refs/heads/master
$ git branch b1 master~1
$ git branch b2 master
$ cat .git/refs/heads/symref
ref: refs/heads/master
$ git update-ref --no-deref --stdin
symref-update refs/heads/symref refs/heads/b1 refs/heads/b2
$ cat .git/refs/heads/symref
ref: refs/heads/b1

This shouldn't have worked because symref was pointing to master, but
this did work, because `refs/heads/b2` was rev-parse'd to '52e95b2'
which is also what master is at.

The issue is that we call 'repo_get_oid', which takes in a commitish and
this could even be a reference. But ideally in 'symref' commands we want
to first treat refnames as refnames and not have them parsed as an OID.

Since, I'm not moving to 'refs:<target>' with the existing commands.
This is no longer an issue.

>> Also, why do you say it is cheaper?
>
> Checking whether a string can be parsed as an object ID should be faster
> than having to ask the ref backend whether it knows any reference with
> that name. So it should be fast for `repo_get_oid()` to bail out in case
> the provided string doesn't look like an object ID.
>
> Patrick

Yes. But for a valid refname, the `repo_get_oid()` is querying the
reference backend similar to `read_ref()`. Also `read_ref` also does
initial checks with `check_refname_format` which I think doesn't check
the ref backend.

Thanks

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux