git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 02/38] rename_ref_available(): add docstring

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Jun 9, 2016, 13:09 UTC
Message-ID
<57596A7E.9020407@alum.mit.edu>
In-Reply-To
<xmqq7fe0rhts.fsf@gitster.mtv.corp.google.com>
On 06/07/2016 08:10 PM, Junio C Hamano wrote:
Show 29 quoted lines
> Michael Haggerty <mhagger@alum.mit.edu> writes:
> 
>> From: David Turner <dturner@twopensource.com>
>>
>> Signed-off-by: David Turner <dturner@twopensource.com>
>> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>>  refs/refs-internal.h | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/refs/refs-internal.h b/refs/refs-internal.h
>> index efe5847..d8a2606 100644
>> --- a/refs/refs-internal.h
>> +++ b/refs/refs-internal.h
>> @@ -240,6 +240,11 @@ const char *find_descendant_ref(const char *dirname,
>>  				const struct string_list *extras,
>>  				const struct string_list *skip);
>>  
>> +/*
>> + * Check if the new name does not conflict with any existing refs
>> + * (other than possibly the old ref).  Return 0 if the ref can be
>> + * renamed to the new name.
>> + */
>>  int rename_ref_available(const char *oldname, const char *newname);
> 
> I do not quite understand the comment.  Partly because it is unclear
> what "conflict" means here, but I guess it means a D/F conflict that
> is explained near verify_refname_available()?
Yes.
Show 7 quoted lines
> A new name can conflict with an existing, possibly old ref?  Are you
> referring to this condition?
> 
>     You are trying to rename "refs/a/b" to "refs/a", which would
>     conflict, but as long as there is no other ref that share the
>     prefix "refs/a/", e.g. "refs/a/c", the new name "refs/a" is
>     available.
That is correct.
Show 11 quoted lines
> I wonder if it is necessary to document that this function is not
> meant to protect us from others racing with us.  That is, when you
> are renaming something to "refs/a", you call this function and it
> finds, by calling verify_refname_available(), that the repository
> has nothing that conflicts with the name and says "OK", but before
> you actually do the rename, somebody may push from sideways to
> create "refs/a/b", making the result of an earlier check with this
> function invalid.
> 
> Or is this to be called only under a lock that protects us from such
> a race?

It would be really awkward (maybe impossible?) to guard against all such races even using locks. One problem is that the lockfiles for the old and new refnames would themselves, in some cases, not be able to coexist due to D/F conflicts. Also, there is no way to prevent the creation of "any reference in `refs/a/*`" except by creating the reference `refs/a` (the presence of `refs/a.lock` is not enough), but by that time it is too late.

In the end, this function mostly exists as a pre-check that `rename_ref()` is *likely* to succeed, so that the latter function is less likely to detect a problem after it has started moving things around. But `rename_ref()` is the final arbiter and is a bit more robust than this check.

I also noticed that the docstring in this patch got the polarity of the return value backwards.

I propose to change the parameter names to `old_refname` and `new_refname` and to change the docstring to

/*
 * Check whether an attempt to rename old_refname to new_refname would
 * cause a D/F conflict with any existing reference (other than
 * possibly old_refname). If there would be a conflict, emit an error
 * message and return false; otherwise, return true.
 *
 * Note that this function is not safe against all races with other
 * processes (though rename_ref() catches some races that might get by
 * this check).
 */
Does that sound good?
Michael
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 67 in “Virtualization of the refs API”
  1. 00/38 Virtualization of the refs APIMichael Haggerty, Jun 3, 2016
  2. 01/38 resolve_gitlink_ref(): eliminate temporary variableMichael Haggerty, Jun 3, 2016
  3. 02/38 rename_ref_available(): add docstringMichael Haggerty, Jun 3, 2016
  4. Junio C HamanoJun 7, 2016
  5. Michael HaggertyJun 9, 2016
  6. Junio C HamanoJun 9, 2016
  7. 03/38 refs: rename struct ref_cache to files_ref_storeMichael Haggerty, Jun 3, 2016
  8. 04/38 refs: add a backend method structureMichael Haggerty, Jun 3, 2016
  9. 05/38 refs: create a base class "ref_store" for files_ref_storeMichael Haggerty, Jun 3, 2016
  10. Junio C HamanoJun 7, 2016
  11. René ScharfeJun 9, 2016
  12. Junio C HamanoJun 7, 2016
  13. Michael HaggertyJun 9, 2016
  14. Junio C HamanoJun 9, 2016
  15. Michael HaggertyJun 10, 2016
  16. Junio C HamanoJun 10, 2016
  17. Eric SunshineJun 10, 2016
  18. Michael HaggertyJun 10, 2016
  19. 06/38 add_packed_ref(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  20. 07/38 get_packed_ref(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  21. 08/38 resolve_missing_loose_ref(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  22. 09/38 {lock,commit,rollback}_packed_refs(): add files_ref_store argumentsMichael Haggerty, Jun 3, 2016
  23. 10/38 refs: add a transaction_commit() methodMichael Haggerty, Jun 3, 2016
  24. 11/38 refs: reorder definitionsMichael Haggerty, Jun 3, 2016
  25. 12/38 resolve_packed_ref(): rename function from resolve_missing_loose_ref()Michael Haggerty, Jun 3, 2016
  26. 13/38 resolve_gitlink_packed_ref(): remove functionMichael Haggerty, Jun 3, 2016
  27. 14/38 read_raw_ref(): take a (struct ref_store *) argumentMichael Haggerty, Jun 3, 2016
  28. 15/38 resolve_ref_recursively(): new functionMichael Haggerty, Jun 3, 2016
  29. 16/38 resolve_gitlink_ref(): implement using resolve_ref_recursively()Michael Haggerty, Jun 3, 2016
  30. Junio C HamanoJun 7, 2016
  31. Eric SunshineJun 14, 2016
  32. Michael HaggertyJun 16, 2016
  33. 17/38 resolve_gitlink_ref(): avoid memory allocation in many casesMichael Haggerty, Jun 3, 2016
  34. Junio C HamanoJun 7, 2016
  35. Michael HaggertyJun 9, 2016
  36. 18/38 resolve_gitlink_ref(): rename path parameter to submoduleMichael Haggerty, Jun 3, 2016
  37. 19/38 refs: make read_raw_ref() virtualMichael Haggerty, Jun 3, 2016
  38. 20/38 refs: make verify_refname_available() virtualMichael Haggerty, Jun 3, 2016
  39. 21/38 refs: make pack_refs() virtualMichael Haggerty, Jun 3, 2016
  40. Junio C HamanoJun 7, 2016
  41. Michael HaggertyJun 9, 2016
  42. 22/38 refs: make create_symref() virtualMichael Haggerty, Jun 3, 2016
  43. 23/38 refs: make peel_ref() virtualMichael Haggerty, Jun 3, 2016
  44. Junio C HamanoJun 7, 2016
  45. Michael HaggertyJun 9, 2016
  46. 24/38 repack_without_refs(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  47. 25/38 lock_raw_ref(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  48. 26/38 commit_ref_update(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  49. 27/38 lock_ref_for_update(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  50. 28/38 lock_ref_sha1_basic(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  51. 29/38 split_symref_update(): add a files_ref_store argumentMichael Haggerty, Jun 3, 2016
  52. 30/38 files_ref_iterator_begin(): take a ref_store argumentMichael Haggerty, Jun 3, 2016
  53. 31/38 refs: add method iterator_beginMichael Haggerty, Jun 3, 2016
  54. 32/38 refs: add methods for reflogMichael Haggerty, Jun 3, 2016
  55. 33/38 refs: add method for initial ref transaction commitMichael Haggerty, Jun 3, 2016
  56. 34/38 refs: add method for delete_refsMichael Haggerty, Jun 3, 2016
  57. Junio C HamanoJun 7, 2016
  58. Michael HaggertyJun 9, 2016
  59. 35/38 refs: add methods to init refs dbMichael Haggerty, Jun 3, 2016
  60. 36/38 refs: add method to rename refsMichael Haggerty, Jun 3, 2016
  61. 37/38 refs: make lock genericMichael Haggerty, Jun 3, 2016
  62. Junio C HamanoJun 7, 2016
  63. Michael HaggertyJun 9, 2016
  64. Michael HaggertyJun 9, 2016
  65. 38/38 refs: implement iteration over only per-worktree refsMichael Haggerty, Jun 3, 2016
  66. Duy NguyenJul 10, 2016
  67. Michael HaggertyJul 13, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.