Re: [PATCH 02/18] is_refname_available(): explain the reason for an early exit
- From
Michael Haggerty <mhagger@alum.mit.edu>
- Date
- May 5, 2015, 15:03 UTC
- Message-ID
- <5548DBDA.1000009@alum.mit.edu>
- In-Reply-To
- <CAGZ79kZDCMj1P1H3+LiW-Lk8S8TS91yJ_G4scmVSvg++3n7dvw@mail.gmail.com>
On 05/01/2015 07:21 PM, Stefan Beller wrote:
Show 42 quoted lines
> On Fri, May 1, 2015 at 5:25 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> The reason why we can exit early if we find a reference in skip whose
>> name is a prefix of refname is a bit subtle, so explain it in a
>> comment.
>>
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>> refs.c | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/refs.c b/refs.c
>> index 2bdd93c..ab438a5 100644
>> --- a/refs.c
>> +++ b/refs.c
>> @@ -907,8 +907,20 @@ static int is_refname_available(const char *refname,
>> pos = search_ref_dir(dir, refname, slash - refname);
>> if (pos >= 0) {
>> struct ref_entry *entry = dir->entries[pos];
>> - if (entry_matches(entry, skip))
>> + if (entry_matches(entry, skip)) {
>> + /*
>> + * The fact that entry is a ref whose
>> + * name is a prefix of refname means
>> + * that there cannot be any other ref
>> + * whose name starts with that prefix
>> + * (because it would have been a D/F
>> + * conflict with entry). So, since we
>> + * don't care about entry (because it
>> + * is in skip), we can stop looking
>> + * now and return true.
>
> At first I thought this is not true, what about:
> refs/heads/foo
> refs/heads/foobar
> They go well together and one is a prefix of the other.
> What is crucial is the existence of a '/' just between the
> prefix and the ending part, so
> refs/heads/foo/bar doesn't fly here.
>
> The assumption may be the case if the prefix itself always
> ends with a /, which is probably the case here?
> I don't know if that is worth noting as well.Yes, this is all rather subtle. Here we have found a reference whose name is *exactly* a proper prefix of refname; for example, refname is "refs/foo/bar" and we just found "refs/foo". But "refs/foo" is in skip, so it is not a conflict. Moreover, its existence means that there cannot be any other references in the "refs/foo/*" namespace (e.g., "refs/foo/bar/banana") because such a reference would have conflicted with "refs/foo".
If it's any consolation, this logic will be simplified a bit later in the patch series. Nevertheless, I will try to explain this better in v2.
Michael
-- Michael Haggerty mhagger@alum.mit.edu