Commit Graph

370 Commits

Author SHA1 Message Date
Junio C Hamano
ed20513c8d Merge branch 'jh/update-ref-d-through-symref' into maint
* jh/update-ref-d-through-symref:
  Fix failure to delete a packed ref through a symref
  t1400-update-ref: Add test verifying bug with symrefs in delete_ref()
2012-11-27 13:28:45 -08:00
Johan Herland
b274a7146c Fix failure to delete a packed ref through a symref
When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
to delete refs/heads/master), we would remove the loose ref, but a packed
version of the same ref would remain, the end result being that instead of
deleting refs/heads/master we would appear to reset it to its state as of
the last repack.

This patch fixes the issue, by making sure we pass the correct ref name
when invoking repack_without_ref() from within delete_ref().

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-10-21 12:08:42 -07:00
René Scharfe
547d058fb6 refs: lock symref that is to be deleted, not its target
When delete_ref is called on a symref then it locks its target and then
either deletes the target or the symref, depending on whether the flag
REF_NODEREF was set in the parameter delopt.

Instead, simply pass the flag to lock_ref_sha1_basic, which will then
either lock the target or the symref, and delete the locked ref.

This reimplements part of eca35a25 (Fix git branch -m for symrefs.).

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-10-16 10:08:23 -07:00
Junio C Hamano
a7060009e1 Merge branch 'rs/refs-string-slice'
Avoid unnecessary temporary allocations while looking for matching refs
inside refs API.

By René Scharfe (3) and Junio C Hamano (1)
* rs/refs-string-slice:
  refs: do not create ref_entry when searching
  refs: use strings directly in find_containing_dir()
  refs: convert parameter of create_dir_entry() to length-limited string
  refs: convert parameter of search_ref_dir() to length-limited string
2012-05-29 13:09:02 -07:00
Junio C Hamano
38f2b874ff Merge branch 'mh/ref-api-lazy-loose'
The code to lazily read loose refs unnecessarily read the refs in a
subhierarchy by mistake when we free the data for the subhierarchy.

By Michael Haggerty
* mh/ref-api-lazy-loose:
  free_ref_entry(): do not trigger reading of loose refs
2012-05-29 13:08:35 -07:00
Junio C Hamano
ec04a275b4 Merge branch 'mh/ref-api'
Fixes a performance regression in the earlier series.
2012-05-25 12:04:36 -07:00
Michael Haggerty
654ad400c2 Avoid sorting if references are added to ref_cache in order
The old code allowed many references to be efficiently added to a
single directory, because it just appended the references to the
containing directory unsorted without doing any searching (and
therefore without requiring any intermediate sorting).  But the old
code was inefficient when a large number of subdirectories were added
to a directory, because the directory always had to be searched to see
if the new subdirectory already existed, and this search required the
directory to be sorted first.  The same was repeated for every new
subdirectory, so the time scaled like O(N^2), where N is the number of
subdirectories within a single directory.

In practice, references are often added to the ref_cache in
lexicographic order, for example when reading the packed-refs file.
So build some intelligence into add_entry_to_dir() to optimize for the
case of references and/or subdirectories being added in lexicographic
order: if the existing entries were already sorted, and the new entry
comes after the last existing entry, then adjust ref_dir::sorted to
reflect the fact that the ref_dir is still sorted.

Thanks to Peff for pointing out the performance regression that
inspired this change.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-24 12:16:06 -07:00
Junio C Hamano
e1980c9d23 refs: do not create ref_entry when searching
The search_ref_dir() function is about looking up an existing ref_entry in
a sorted array of ref_entry stored in dir->entries, but it still allocates
a new ref_entry and frees it before returning.  This is only because the
call to bsearch(3) was coded in a suboptimal way. Unlike the comparison
function given to qsort(3), the first parameter to its comparison function
does not need to point at an object that is shaped like an element in the
array.

Introduce a new comparison function that takes a counted string as the key
and an element in an array of ref_entry and give it to bsearch(), so that
we do not have to allocate a new ref_entry that we will never return to
the caller anyway.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-22 14:28:03 -07:00
René Scharfe
dd02e72852 refs: use strings directly in find_containing_dir()
Convert the parameter subdirname of search_for_subdir() to a
length-limted string and then simply pass the interesting slice of the
refname from find_containing_dir(), thereby avoiding to duplicate the
string.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-22 13:32:26 -07:00
René Scharfe
b9146f517a refs: convert parameter of create_dir_entry() to length-limited string
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-22 13:32:24 -07:00
René Scharfe
40ad937d47 refs: convert parameter of search_ref_dir() to length-limited string
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-22 13:32:21 -07:00
Michael Haggerty
27b5587c76 free_ref_entry(): do not trigger reading of loose refs
Do not call get_ref_dir() from within free_ref_entry(), because that
triggers the reading of loose refs, only for them to be freed
immediately.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-20 15:10:49 -07:00
Junio C Hamano
aa6912b081 Merge branch 'mh/ref-api-lazy-loose'
Refs API is updated to lazily read sub-hierarchies of refs/ namespace,
so that we do not have to grab everything from the filesystem when we
are only interested in listing branches, for example.

By Michael Haggerty (17) and Junio C Hamano (1)
* mh/ref-api-lazy-loose:
  refs: fix find_containing_dir() regression
  refs: read loose references lazily
  read_loose_refs(): eliminate ref_cache argument
  struct ref_dir: store a reference to the enclosing ref_cache
  search_for_subdir(): return (ref_dir *) instead of (ref_entry *)
  get_ref_dir(): add function for getting a ref_dir from a ref_entry
  read_loose_refs(): rename function from get_ref_dir()
  refs: wrap top-level ref_dirs in ref_entries
  find_containing_dir(): use strbuf in implementation of this function
  bisect: copy filename string obtained from git_path()
  do_for_each_reflog(): use a strbuf to hold logfile name
  do_for_each_reflog(): return early on error
  get_ref_dir(): take the containing directory as argument
  refs.c: extract function search_for_subdir()
  get_ref_dir(): require that the dirname argument ends in '/'
  get_ref_dir(): rename "base" parameter to "dirname"
  get_ref_dir(): use a strbuf to hold refname
  get_ref_dir(): return early if directory cannot be read
2012-05-10 10:49:08 -07:00
Junio C Hamano
663c1295d8 refs: fix find_containing_dir() regression
The function used to return NULL when asked to find the containing
directory for a ref that does not exist, allowing the caller to
omit iteration altogether. But a misconversion in an earlier change
"refs.c: extract function search_for_subdir()" started returning the
top-level directory entry, forcing callers to walk everything.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-04 09:17:50 -07:00
Michael Haggerty
28e6a34e25 refs: read loose references lazily
Instead of reading the whole directory of loose references the first
time any are needed, only read them on demand, one directory at a
time.

Use a new ref_entry flag bit REF_INCOMPLETE to indicate that the entry
represents a REF_DIR that hasn't been read yet.  Whenever any entries
from such a directory are needed, read all of the loose references
from that directory.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
423a1afc0b read_loose_refs(): eliminate ref_cache argument
The ref_cache can now be read from the ref_dir.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
f006c42a11 struct ref_dir: store a reference to the enclosing ref_cache
This means that a directory ref_entry contains all of the information
needed by read_loose_refs().

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
3f3aa1bc62 search_for_subdir(): return (ref_dir *) instead of (ref_entry *)
That is what all the callers want, so give it to them.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
d7826d5427 get_ref_dir(): add function for getting a ref_dir from a ref_entry
Convert all accesses of a ref_dir within a ref_entry to use this
function.  This function will later be responsible for reading loose
references from disk on demand.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
1900b976a4 read_loose_refs(): rename function from get_ref_dir()
The new name better describes the function's purpose, and also makes
the old name available for a more suitable purpose.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:36 -07:00
Michael Haggerty
d12229f532 refs: wrap top-level ref_dirs in ref_entries
Make it turtles all the way down.  This affects the loose and packed
fields of ref_cache instances.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:35 -07:00
Michael Haggerty
5fa0441844 find_containing_dir(): use strbuf in implementation of this function
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:35 -07:00
Michael Haggerty
989c0e5d02 do_for_each_reflog(): use a strbuf to hold logfile name
This simplifies the bookkeeping and allows an (artificial) restriction
on refname component length to be removed.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:35 -07:00
Michael Haggerty
93c603fcb7 do_for_each_reflog(): return early on error
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Michael Haggerty
9f2fb4a373 get_ref_dir(): take the containing directory as argument
Previously, the "dir" argument to get_ref_dir() was a pointer to the
top-level ref_dir.  Change the function to expect a pointer to the
ref_dir corresponding to dirname.  This allows entries to be added
directly to dir, without having to recurse through the reference trie
each time (i.e., we can use add_entry_to_dir() instead of add_ref()).

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Michael Haggerty
f348ac923c refs.c: extract function search_for_subdir()
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Michael Haggerty
abc390989f get_ref_dir(): require that the dirname argument ends in '/'
This removes some conditional code and makes it consistent with the
way that direntry names are stored.  Please note that this function is
never used on the top-level .git directory; it is always called for
directories at level .git/refs or deeper.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Michael Haggerty
66a3d20b8f get_ref_dir(): rename "base" parameter to "dirname"
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Michael Haggerty
72b64b44e7 get_ref_dir(): use a strbuf to hold refname
This simplifies the bookkeeping and allows an (artificial) restriction
on refname component length to be removed.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-03 13:15:09 -07:00
Junio C Hamano
1be65eda6a Merge branch 'nd/i18n'
More message strings marked for i18n.

By Nguyễn Thái Ngọc Duy (10) and Jonathan Nieder (1)
* nd/i18n:
  help: replace underlining "help -a" headers using hyphens with a blank line
  i18n: bundle: mark strings for translation
  i18n: index-pack: mark strings for translation
  i18n: apply: update say_patch_name to give translators complete sentence
  i18n: apply: mark strings for translation
  i18n: remote: mark strings for translation
  i18n: make warn_dangling_symref() automatically append \n
  i18n: help: mark strings for translation
  i18n: mark relative dates for translation
  strbuf: convenience format functions with \n automatically appended
  Makefile: feed all header files to xgettext
2012-05-02 13:51:35 -07:00
Michael Haggerty
d5fdae6737 get_ref_dir(): return early if directory cannot be read
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-25 10:43:20 -07:00
Nguyễn Thái Ngọc Duy
18986d5377 i18n: make warn_dangling_symref() automatically append \n
This helps remove \n from translatable strings

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-24 14:55:48 -07:00
Michael Haggerty
933ac036d2 do_for_each_ref(): only iterate over the subtree that was requested
If the base argument has a "/" chararacter, then only iterate over the
reference subdir whose name is the part up to the last "/".

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:55:55 -07:00
Michael Haggerty
432ad41e60 refs: store references hierarchically
Store references hierarchically in a tree that matches the
pseudo-directory structure of the reference names.  Add a new kind of
ref_entry (with flag REF_DIR) to represent a whole subdirectory of
references.  Sort ref_dirs one subdirectory at a time.

NOTE: the dirs can now be sorted as a side-effect of other function
calls.  Therefore, it would be problematic to do something from a
each_ref_fn callback that could provoke the sorting of a directory
that is currently being iterated over (i.e., the directory containing
the entry that is being processed or any of its parents).

This is a bit far-fetched, because a directory is always sorted just
before being iterated over.  Therefore, read-only accesses cannot
trigger the sorting of a directory whose iteration has already
started.  But if a callback function would add a reference to a parent
directory of the reference in the iteration, then try to resolve a
reference under that directory, a re-sort could be triggered and cause
the iteration to work incorrectly.

Nevertheless...add a comment in refs.h warning against modifications
during iteration.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:55:55 -07:00
Michael Haggerty
81a79d8e27 sort_ref_dir(): simplify logic
Use the more usual indexing idiom for clarity.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:55:50 -07:00
Michael Haggerty
d3177275ed refs.c: rename ref_array -> ref_dir
This purely textual change is in preparation for storing references
hierarchically, when the old ref_array structure will represent one
"directory" of references.  Rename functions that deal with this
structure analogously, and also rename the structure's "refs" member
to "entries".

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:54:59 -07:00
Michael Haggerty
593f1bb82f struct ref_entry: nest the value part in a union
This change is obviously silly by itself, but it is a step towards
adding a second member to the union.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:54:58 -07:00
Michael Haggerty
dac529e44f check_refname_component(): return 0 for zero-length components
Return 0 (instead of -1) for zero-length components.  Move the
interpretation of zero-length components as illegal to
check_refname_format().

This will make it easier to extend check_refname_format() to also
check whether directory names are valid.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:54:58 -07:00
Michael Haggerty
732134edab free_ref_entry(): new function
Add a function free_ref_entry().  This function will become nontrivial
when ref_entry (soon) becomes polymorphic.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:54:58 -07:00
Michael Haggerty
5a4d494731 names_conflict(): simplify implementation
Save a bunch of lines of code and a couple of strlen() calls.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:54:54 -07:00
Michael Haggerty
d66da478f2 repack_without_ref(): reimplement using do_for_each_ref_in_array()
It costs a bit of boilerplate, but it means that the function can be
ignorant of how cached refs are stored.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:53:28 -07:00
Michael Haggerty
b3fd060f9e do_for_each_ref_in_arrays(): new function
Extract function do_for_each_ref_in_arrays() from do_for_each_ref().
The new function will be a useful building block for storing refs
hierarchically.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:51:52 -07:00
Michael Haggerty
c36b5bc2e4 do_for_each_ref_in_array(): new function
Extract function do_for_each_ref_in_array() from do_for_each_ref().
The new function will be a useful building block for storing refs
hierarchically.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:51:52 -07:00
Michael Haggerty
429213e470 refs: manage current_ref within do_one_ref()
Set and clear current_ref within do_one_ref() instead of setting it
here and leaving it to somebody else to clear it.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:51:52 -07:00
Michael Haggerty
bc5fd6d3c2 refs.c: reorder definitions more logically
Reorder definitions in file: first check_refname_format() and helper
functions, then the functions for managing the ref_entry and ref_array
data structures, then ref_cache, then the more "business-logicky"
stuff.  No code is changed.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-10 15:51:47 -07:00
Michael Haggerty
cf6672edb1 refs: remove the extra_refs API
The extra_refs provided a kludgy way to create fake references at a
global level in the hope that they would only affect some particular
code path.  The last user of this API been rewritten, so strip this
stuff out before somebody else gets the bad idea of using it.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-12 19:50:39 -08:00
Michael Haggerty
30249ee68f add_packed_ref(): new function in the refs API.
Add a new function add_packed_ref() that adds a reference directly to
the in-memory packed reference cache.  This will be useful for
creating local references while cloning.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-17 11:55:04 -08:00
Michael Haggerty
e6ed3ca651 ref_array: keep track of whether references are sorted
Keep track of how many entries at the beginning of a ref_array are already
sorted.  In sort_ref_array(), return early if the the array is already
sorted (i.e., if no new references has been appended to the end of the
list since the last call to sort_ref_array()).

Sort ref_arrays only when needed, namely in search_ref_array() and in
do_for_each_ref().  However, never call sort_ref_array() on the
extra_refs, because extra_refs can contain multiple entries with the same
name and because sort_ref_array() not only sorts, but de-dups its
contents.

This change is currently not useful, because entries are not added to
ref_arrays after they are created.  But in a moment they will be...

Implementation note: we could store a binary "sorted" value instead of
an integer, but storing the number of sorted entries leaves the way
open for a couple of possible future optimizations:

* In sort_ref_array(), sort *only* the unsorted entries, then merge
  them with the sorted entries.  This should be faster if most of the
  entries are already sorted.

* Teach search_ref_array() to do a binary search of any sorted
  entries, and if unsuccessful do a linear search of any unsorted
  entries.  This would avoid the need to sort the list every time that
  search_ref_array() is called, and (given some intelligence about how
  often to sort) could significantly improve the speed in certain
  hypothetical usage patterns.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-17 11:53:21 -08:00
Junio C Hamano
8d68493f20 Merge branch 'mh/ref-api'
* mh/ref-api:
  add_ref(): take a (struct ref_entry *) parameter
  create_ref_entry(): extract function from add_ref()
  repack_without_ref(): remove temporary
  resolve_gitlink_ref_recursive(): change to work with struct ref_cache
  Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
  resolve_gitlink_ref(): improve docstring
  get_ref_dir(): change signature
  refs: change signatures of get_packed_refs() and get_loose_refs()
  is_dup_ref(): extract function from sort_ref_array()
  add_ref(): add docstring
  parse_ref_line(): add docstring
  is_refname_available(): remove the "quiet" argument
  clear_ref_array(): rename from free_ref_array()
  refs: rename parameters result -> sha1
  refs: rename "refname" variables
  struct ref_entry: document name member

Conflicts:
	cache.h
	refs.c
2011-12-20 13:25:53 -08:00
Nguyễn Thái Ngọc Duy
8cad4744ee Rename resolve_ref() to resolve_ref_unsafe()
resolve_ref() may return a pointer to a shared buffer and can be
overwritten by the next resolve_ref() calls. Callers need to
pay attention, not to keep the pointer when the next call happens.

Rename with "_unsafe" suffix to warn developers (or reviewers) before
introducing new call sites.

This patch is generated using the following command

git grep -l 'resolve_ref(' -- '*.[ch]'|xargs sed -i 's/resolve_ref(/resolve_ref_unsafe(/g'

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-13 09:39:46 -08:00