summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2016-09-09refs: add a backend method structureLibravatar Ronnie Sahlberg4-0/+34
Add a `struct ref_storage_be` to represent types of reference stores. In OO notation, this is the class, and will soon hold some class methods (e.g., a factory to create new ref_store instances) and will also serve as the vtable for ref_store instances of that type. As yet, the backends cannot do anything. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-09refs: rename struct ref_cache to files_ref_storeLibravatar Michael Haggerty1-63/+63
The greater goal of this patch series is to develop the concept of a reference store, which is a place that references, their values, and their reflogs are stored, and to virtualize the reference interface so that different types of ref_stores can be implemented. We will then, for example, use ref_store instances to access submodule references and worktree references. Currently, we keep a ref_cache for each submodule that has had its references iterated over. It is a far cry from a ref_store, but they are stored the way we will want to store ref_stores, and ref_stores will eventually have to hold the reference caches. So let's treat ref_caches as embryo ref_stores, and build them out from there. As the first step, simply rename `ref_cache` to `files_ref_store`, and rename some functions and attributes correspondingly. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-09rename_ref_available(): add docstringLibravatar David Turner2-7/+17
And improve the internal variable names. 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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-09resolve_gitlink_ref(): eliminate temporary variableLibravatar Michael Haggerty1-3/+2
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20for_each_reflog(): reimplement using iteratorsLibravatar Michael Haggerty2-42/+78
Allow references with reflogs to be iterated over using a ref_iterator. The latter is implemented as a files_reflog_iterator, which in turn uses dir_iterator to read the "logs" directory. Note that reflog iteration doesn't correctly handle per-worktree reflogs (either before or after this patch). Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20dir_iterator: new API for iterating over a directory treeLibravatar Michael Haggerty3-0/+290
The iterator interface is modeled on that for references, though no vtable is necessary because there is (so far?) only one type of dir_iterator. There are obviously a lot of features that could easily be added to this class: * Skip/include directory paths in the iteration * Shallow/deep iteration * Letting the caller decide which subdirectories to recurse into (e.g., via a dir_iterator_advance_into() function) * Option to iterate in sorted order * Option to iterate over directory paths before vs. after their contents But these are not needed for the current patch series, so I refrain. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20for_each_reflog(): don't abort for bad referencesLibravatar Michael Haggerty1-1/+1
If there is a file under "$GIT_DIR/logs" with no corresponding reference, the old code was emitting an error message, aborting the reflog iteration, and returning -1. But * None of the callers was checking the exit value * The callers all want to find all legitimate reflogs (sometimes for the purpose of determining object reachability!) and wouldn't benefit from a truncated iteration anyway. So instead, emit an error message and skip the "broken" reflog, but continue with the iteration. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20do_for_each_ref(): reimplement using reference iterationLibravatar Michael Haggerty4-213/+77
Use the reference iterator interface to implement do_for_each_ref(). Delete a bunch of code supporting the old for_each_ref() implementation. And now that do_for_each_ref() is generic code (it is no longer tied to the files backend), move it to refs.c. The implementation is via a new function, do_for_each_ref_iterator(), which takes a reference iterator as argument and calls a callback function for each of the references in the iterator. This change requires the current_ref performance hack for peel_ref() to be implemented via ref_iterator_peel() rather than peel_entry() because we don't have a ref_entry handy (it is hidden under three layers: file_ref_iterator, merge_ref_iterator, and cache_ref_iterator). So: * do_for_each_ref_iterator() records the active iterator in current_ref_iter while it is running. * peel_ref() checks whether current_ref_iter is pointing at the requested reference. If so, it asks the iterator to peel the reference (which it can do efficiently via its "peel" virtual function). For extra safety, we do the optimization only if the refname *addresses* are the same, not only if the refname *strings* are the same, to forestall possible mixups between refnames that come from different ref_iterators. Please note that this optimization of peel_ref() is only available when iterating via do_for_each_ref_iterator() (including all of the for_each_ref() functions, which call it indirectly). It would be complicated to implement a similar optimization when iterating directly using a reference iterator, because multiple reference iterators can be in use at the same time, with interleaved calls to ref_iterator_advance(). (In fact we do exactly that in merge_ref_iterator.) But that is not necessary. peel_ref() is only called while iterating over references. Callers who iterate using the for_each_ref() functions benefit from the optimization described above. Callers who iterate using reference iterators directly have access to the ref_iterator, so they can call ref_iterator_peel() themselves to get an analogous optimization in a more straightforward manner. If we rewrite all callers to use the reference iteration API, then we can remove the current_ref_iter hack permanently. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20refs: introduce an iterator interfaceLibravatar Michael Haggerty6-1/+915
Currently, the API for iterating over references is via a family of for_each_ref()-type functions that invoke a callback function for each selected reference. All of these eventually call do_for_each_ref(), which knows how to do one thing: iterate in parallel through two ref_caches, one for loose and one for packed refs, giving loose references precedence over packed refs. This is rather complicated code, and is quite specialized to the files backend. It also requires callers to encapsulate their work into a callback function, which often means that they have to define and use a "cb_data" struct to manage their context. The current design is already bursting at the seams, and will become even more awkward in the upcoming world of multiple reference storage backends: * Per-worktree vs. shared references are currently handled via a kludge in git_path() rather than iterating over each part of the reference namespace separately and merging the results. This kludge will cease to work when we have multiple reference storage backends. * The current scheme is inflexible. What if we sometimes want to bypass the ref_cache, or use it only for packed or only for loose refs? What if we want to store symbolic refs in one type of storage backend and non-symbolic ones in another? In the future, each reference backend will need to define its own way of iterating over references. The crux of the problem with the current design is that it is impossible to compose for_each_ref()-style iterations, because the flow of control is owned by the for_each_ref() function. There is nothing that a caller can do but iterate through all references in a single burst, so there is no way for it to interleave references from multiple backends and present the result to the rest of the world as a single compound backend. This commit introduces a new iteration primitive for references: a ref_iterator. A ref_iterator is a polymorphic object that a reference storage backend can be asked to instantiate. There are three functions that can be applied to a ref_iterator: * ref_iterator_advance(): move to the next reference in the iteration * ref_iterator_abort(): end the iteration before it is exhausted * ref_iterator_peel(): peel the reference currently being looked at Iterating using a ref_iterator leaves the flow of control in the hands of the caller, which means that ref_iterators from multiple sources (e.g., loose and packed refs) can be composed and presented to the world as a single compound ref_iterator. It also means that the backend code for implementing reference iteration will sometimes be more complicated. For example, the cache_ref_iterator (which iterates over a ref_cache) can't use the C stack to recurse; instead, it must manage its own stack internally as explicit data structures. There is also a lot of boilerplate connected with object-oriented programming in C. Eventually, end-user callers will be able to be written in a more natural way—managing their own flow of control rather than having to work via callbacks. Since there will only be a few reference backends but there are many consumers of this API, this is a good tradeoff. More importantly, we gain composability, and especially the possibility of writing interchangeable parts that can work with any ref_iterator. For example, merge_ref_iterator implements a generic way of merging the contents of any two ref_iterators. It is used to merge loose + packed refs as part of the implementation of the files_ref_iterator. But it will also be possible to use it to merge other pairs of reference sources (e.g., per-worktree vs. shared refs). Another example is prefix_ref_iterator, which can be used to trim a prefix off the front of reference names before presenting them to the caller (e.g., "refs/heads/master" -> "master"). In this patch, we introduce the iterator abstraction and many utilities, and implement a reference iterator for the files ref storage backend. (I've written several other obvious utilities, for example a generic way to filter references being iterated over. These will probably be useful in the future. But they are not needed for this patch series, so I am not including them at this time.) In a moment we will rewrite do_for_each_ref() to work via reference iterators (allowing some special-purpose code to be discarded), and do something similar for reflogs. In future patch series, we will expose the ref_iterator abstraction in the public refs API so that callers can use it directly. Implementation note: I tried abstracting this a layer further to allow generic iterators (over arbitrary types of objects) and generic utilities like a generic merge_iterator. But the implementation in C was very cumbersome, involving (in my opinion) too much boilerplate and too much unsafe casting, some of which would have had to be done on the caller side. However, I did put a few iterator-related constants in a top-level header file, iterator.h, as they will be useful in a moment to implement iteration over directory trees and possibly other types of iterators in the future. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20ref_resolves_to_object(): new functionLibravatar Michael Haggerty1-7/+20
Extract new function ref_resolves_to_object() from entry_resolves_to_object(). It can be used even if there is no ref_entry at hand. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20entry_resolves_to_object(): rename function from ref_resolves_to_object()Libravatar Michael Haggerty1-3/+3
Free up the old name for a more general purpose. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20get_ref_cache(): only create an instance if there is a submoduleLibravatar Michael Haggerty1-11/+22
If there is not a nonbare repository where a submodule is supposedly located, then don't instantiate a ref_cache for it. The analogous check can be removed from resolve_gitlink_ref(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20remote rm: handle symbolic refs correctlyLibravatar Michael Haggerty1-5/+1
In the modern world of reference backends, it is not OK to delete a symref by unlink()ing the file directly. This must be done via the refs API. We do so by adding the symref to the list of references to delete along with the non-symbolic references, then calling delete_refs() with the new flags option set to REF_NODEREF. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20delete_refs(): add a flags argumentLibravatar Michael Haggerty4-7/+8
This will be useful for passing REF_NODEREF through. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20refs: use name "prefix" consistentlyLibravatar Michael Haggerty2-19/+19
In the context of the for_each_ref() functions, call the prefix that references must start with "prefix". (In some places it was called "base".) This is clearer, and also prevents confusion with another planned use of the word "base". Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20do_for_each_ref(): move docstring to the header fileLibravatar Michael Haggerty2-10/+9
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-13refs: remove unnecessary "extern" keywordsLibravatar Michael Haggerty1-61/+73
There's continuing work in this area, so clean up unneeded "extern" keywords rather than schlepping them around. Also split up some overlong lines and add parameter names in a couple of places. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13lock_ref_sha1_basic(): only handle REF_NODEREF modeLibravatar Michael Haggerty1-34/+20
Now lock_ref_sha1_basic() is only called with flags==REF_NODEREF. So we don't have to handle other cases anymore. This enables several simplifications, the most interesting of which come from the fact that ref_lock::orig_ref_name is now always the same as ref_lock::ref_name: * Remove ref_lock::orig_ref_name * Remove local variable orig_refname from lock_ref_sha1_basic() * ref_name can be initialize once and its value reused * commit_ref_update() never has to write to the reflog for lock->orig_ref_name Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13commit_ref_update(): remove the flags parameterLibravatar Michael Haggerty1-7/+7
commit_ref_update() is now only called with flags=0. So remove the flags parameter entirely. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13lock_ref_for_update(): don't resolve symrefsLibravatar Michael Haggerty2-30/+95
If a transaction includes a non-NODEREF update to a symbolic reference, we don't have to look it up in lock_ref_for_update(). The reference will be dereferenced anyway when the split-off update is processed. This change requires that we store a backpointer from the split-off update to its parent update, for two reasons: * We still want to report the original reference name in error messages. So if an error occurs when checking the split-off update's old_sha1, walk the parent_update pointers back to find the original reference name, and report that one. * We still need to write the old_sha1 of the symref to its reflog. So after we read the split-off update's reference value, walk the parent_update pointers back and fill in their old_sha1 fields. Aside from eliminating unnecessary reads, this change fixes a subtle (though not very serious) race condition: in the old code, the old_sha1 of the symref was resolved before the reference that it pointed at was locked. So it was possible that the old_sha1 value logged to the symref's reflog could be wrong if another process changed the downstream reference before it was locked. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13lock_ref_for_update(): don't re-read non-symbolic referencesLibravatar Michael Haggerty1-18/+30
Before the previous patch, our first read of the reference happened before the reference was locked, so we couldn't trust its value and had to read it again. But now that our first read of the reference happens after acquiring the lock, there is no need to read it a second time. So move the read_ref_full() call into the (update->type & REF_ISSYMREF) block. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13refs: resolve symbolic refs firstLibravatar Michael Haggerty3-40/+514
Before committing ref updates, split symbolic ref updates into two parts: an update to the underlying ref, and a log-only update to the symbolic ref. This ensures that both references are locked correctly during the transaction, including while their reflogs are updated. Similarly, if the reference pointed to by HEAD is modified directly, add a separate log-only update to HEAD, rather than leaving the job of updating HEAD's reflog to commit_ref_update(). This change ensures that HEAD is locked correctly while its reflog is being modified, as well as being cheaper (HEAD only needs to be resolved once). This makes use of a new function, lock_raw_ref(), which is analogous to read_raw_ref(), but acquires a lock on the reference before reading it. This change still has two problems: * There are redundant read_ref_full() reference lookups. * It is still possible to get incorrect reflogs for symbolic references if there is a concurrent update by another process, since the old_oid of a symref is determined before the lock on the pointed-to ref is held. Both problems will soon be fixed. 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> WIP
2016-06-13ref_transaction_update(): check refname_is_safe() at a minimumLibravatar Michael Haggerty3-4/+5
If the user has asked that a new value be set for a reference, we use check_refname_format() to verify that the reference name satisfies all of the rules. But in other cases, at least check that refname_is_safe(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13unlock_ref(): move definition higher in the fileLibravatar Michael Haggerty1-10/+10
This avoids the need for a forward declaration in the next patch. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13lock_ref_for_update(): new functionLibravatar Michael Haggerty1-67/+85
Extract a new function, lock_ref_for_update(), from ref_transaction_commit(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13add_update(): initialize the whole ref_updateLibravatar Michael Haggerty2-22/+40
Change add_update() to initialize all of the fields in the new ref_update object. Rename the function to ref_transaction_add_update(), and increase its visibility to all of the refs-related code. All of this makes the function more useful for other future callers. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13verify_refname_available(): adjust constness in declarationLibravatar Michael Haggerty2-4/+4
The two string_list arguments can be const. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13refs: don't dereference on renameLibravatar David Turner2-5/+25
When renaming refs, don't dereference either the origin or the destination before renaming. The origin does not need to be dereferenced because it is presently forbidden to rename symbolic refs. Not dereferencing the destination fixes a bug where renaming on top of a broken symref would use the pointed-to ref name for the moved reflog. Add a test for the reflog bug. 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>
2016-06-13refs: allow log-only updatesLibravatar David Turner2-6/+17
The refs infrastructure learns about log-only ref updates, which only update the reflog. Later, we will use this to separate symbolic reference resolution from ref updating. 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>
2016-06-13delete_branches(): use resolve_refdup()Libravatar Michael Haggerty1-8/+11
The return value of resolve_ref_unsafe() is not guaranteed to stay around as long as we need it, so use resolve_refdup() instead. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13ref_transaction_commit(): correctly report close_ref() failureLibravatar Michael Haggerty1-0/+1
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13ref_transaction_create(): disallow recursive pruningLibravatar Michael Haggerty3-2/+5
It is nonsensical (and a little bit dangerous) to use REF_ISPRUNING without REF_NODEREF. Forbid it explicitly. Change the one REF_ISPRUNING caller to pass REF_NODEREF too. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13refs: make error messages more consistentLibravatar Michael Haggerty3-22/+22
* Always start error messages with a lower-case letter. * Always enclose reference names in single quotes. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13lock_ref_sha1_basic(): remove unneeded local variableLibravatar Michael Haggerty1-6/+3
resolve_ref_unsafe() can cope with being called with NULL passed to its flags argument. So lock_ref_sha1_basic() can just hand its own type parameter through. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13read_raw_ref(): move docstring to header fileLibravatar Michael Haggerty2-38/+38
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13read_raw_ref(): improve docstringLibravatar Michael Haggerty1-17/+24
Among other things, document the (important!) requirement that input refname be checked for safety before calling this function. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13read_raw_ref(): rename symref argument to referentLibravatar Michael Haggerty2-11/+12
After all, it doesn't hold the symbolic reference, but rather the reference referred to. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13read_raw_ref(): clear *type at start of functionLibravatar Michael Haggerty1-0/+1
This is more convenient and less error-prone for callers. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13read_raw_ref(): rename flags argument to typeLibravatar Michael Haggerty2-10/+10
This will hopefully reduce confusion with the "flags" arguments that are used in many functions in this module as an input parameter to choose how the function should operate. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-06-13ref_transaction_commit(): remove local variables n and updatesLibravatar Michael Haggerty1-22/+20
These microoptimizations don't make a significant difference in speed. And they cause problems if somebody ever wants to modify the function to add updates to a transaction as part of processing it, as will happen shortly. Make the same changes in initial_ref_transaction_commit(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05rename_ref(): remove unneeded local variableLibravatar Michael Haggerty1-6/+3
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05commit_ref_update(): write error message to *err, not stderrLibravatar Michael Haggerty1-1/+1
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05refname_is_safe(): insist that the refname already be normalizedLibravatar Michael Haggerty1-2/+7
The reference name is going to be compared to other reference names, so it should be in its normalized form. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05refname_is_safe(): don't allow the empty stringLibravatar Michael Haggerty1-2/+3
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05refname_is_safe(): use skip_prefix()Libravatar Michael Haggerty1-3/+5
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05remove_dir_recursively(): add docstringLibravatar Michael Haggerty1-0/+23
Add a docstring for the remove_dir_recursively() function and the REMOVE_DIR_* flags that can be passed to it. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05safe_create_leading_directories(): improve docstringLibravatar Michael Haggerty1-0/+5
Document the difference between this function and safe_create_leading_directories_const(), and that the former restores path before returning. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05read_raw_ref(): don't get confused by an empty directoryLibravatar Michael Haggerty2-2/+11
Even if there is an empty directory where we look for the loose version of a reference, check for a packed reference before giving up. This fixes the failing test that was introduced two commits ago. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05commit_ref(): if there is an empty dir in the way, delete itLibravatar Michael Haggerty1-0/+24
Part of the bug revealed in the last commit is that resolve_ref_unsafe() incorrectly returns EISDIR if it finds a directory in the place where it is looking for a loose reference, even if the corresponding packed reference exists. lock_ref_sha1_basic() notices the bogus EISDIR, and use it as an indication that it should call remove_empty_directories() and call resolve_ref_unsafe() again. But resolve_ref_unsafe() shouldn't report EISDIR in this case. If we would simply make that change, then remove_empty_directories() wouldn't get called anymore, and the empty directory would get in the way when commit_ref() calls commit_lock_file() to rename the lockfile into place. So instead of relying on lock_ref_sha1_basic() to delete empty directories, teach commit_ref(), just before calling commit_lock_file(), to check whether a directory is in the way, and if so, try to delete it. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
2016-05-05t1404: demonstrate a bug resolving referencesLibravatar Michael Haggerty1-1/+75
Add some tests checking that it is possible to work with a reference even if there is an empty directory where the loose ref would be stored. One of the new tests demonstrates a bug that has been with us since at least 2.5.0--single reference lookup gives up when it sees the directory, even if the reference exists as a packed ref. This probably hasn't been reported before because Git usually cleans up empty directories when packing references. This bug will be fixed shortly. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>