Merge branch 'mh/separate-ref-cache'

The internals of the refs API around the cached refs has been
streamlined.

* mh/separate-ref-cache:
  do_for_each_entry_in_dir(): delete function
  files_pack_refs(): use reference iteration
  commit_packed_refs(): use reference iteration
  cache_ref_iterator_begin(): make function smarter
  get_loose_ref_cache(): new function
  get_loose_ref_dir(): function renamed from get_loose_refs()
  do_for_each_entry_in_dir(): eliminate `offset` argument
  refs: handle "refs/bisect/" in `loose_fill_ref_dir()`
  ref-cache: use a callback function to fill the cache
  refs: record the ref_store in ref_cache, not ref_dir
  ref-cache: introduce a new type, ref_cache
  refs: split `ref_cache` code into separate files
  ref-cache: rename `remove_entry()` to `remove_entry_from_dir()`
  ref-cache: rename `find_ref()` to `find_ref_entry()`
  ref-cache: rename `add_ref()` to `add_ref_entry()`
  refs_verify_refname_available(): use function in more places
  refs_verify_refname_available(): implement once for all backends
  refs_ref_iterator_begin(): new function
  refs_read_raw_ref(): new function
  get_ref_dir(): don't call read_loose_refs() for "refs/bisect"
This commit is contained in:
Junio C Hamano
2017-04-26 15:39:13 +09:00
7 changed files with 1066 additions and 1089 deletions

111
refs.c
View File

@ -5,6 +5,7 @@
#include "cache.h"
#include "hashmap.h"
#include "lockfile.h"
#include "iterator.h"
#include "refs.h"
#include "refs/refs-internal.h"
#include "object.h"
@ -1238,6 +1239,18 @@ int head_ref(each_ref_fn fn, void *cb_data)
return head_ref_submodule(NULL, fn, cb_data);
}
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix, int trim, int flags)
{
struct ref_iterator *iter;
iter = refs->be->iterator_begin(refs, prefix, flags);
iter = prefix_ref_iterator_begin(iter, prefix, trim);
return iter;
}
/*
* Call fn for each reference in the specified submodule for which the
* refname begins with prefix. If trim is non-zero, then trim that
@ -1255,8 +1268,7 @@ static int do_for_each_ref(struct ref_store *refs, const char *prefix,
if (!refs)
return 0;
iter = refs->be->iterator_begin(refs, prefix, flags);
iter = prefix_ref_iterator_begin(iter, prefix, trim);
iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
return do_for_each_ref_iterator(iter, fn, cb_data);
}
@ -1334,6 +1346,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
return refs_for_each_rawref(get_main_ref_store(), fn, cb_data);
}
int refs_read_raw_ref(struct ref_store *ref_store,
const char *refname, unsigned char *sha1,
struct strbuf *referent, unsigned int *type)
{
return ref_store->be->read_raw_ref(ref_store, refname, sha1, referent, type);
}
/* This function needs to return a meaningful errno on failure */
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
@ -1370,8 +1389,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
unsigned int read_flags = 0;
if (refs->be->read_raw_ref(refs, refname,
sha1, &sb_refname, &read_flags)) {
if (refs_read_raw_ref(refs, refname,
sha1, &sb_refname, &read_flags)) {
*flags |= read_flags;
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
return NULL;
@ -1654,11 +1673,91 @@ int ref_transaction_commit(struct ref_transaction *transaction,
int refs_verify_refname_available(struct ref_store *refs,
const char *refname,
const struct string_list *extra,
const struct string_list *extras,
const struct string_list *skip,
struct strbuf *err)
{
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
const char *slash;
const char *extra_refname;
struct strbuf dirname = STRBUF_INIT;
struct strbuf referent = STRBUF_INIT;
struct object_id oid;
unsigned int type;
struct ref_iterator *iter;
int ok;
int ret = -1;
/*
* For the sake of comments in this function, suppose that
* refname is "refs/foo/bar".
*/
assert(err);
strbuf_grow(&dirname, strlen(refname) + 1);
for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
/* Expand dirname to the new prefix, not including the trailing slash: */
strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
/*
* We are still at a leading dir of the refname (e.g.,
* "refs/foo"; if there is a reference with that name,
* it is a conflict, *unless* it is in skip.
*/
if (skip && string_list_has_string(skip, dirname.buf))
continue;
if (!refs_read_raw_ref(refs, dirname.buf, oid.hash, &referent, &type)) {
strbuf_addf(err, "'%s' exists; cannot create '%s'",
dirname.buf, refname);
goto cleanup;
}
if (extras && string_list_has_string(extras, dirname.buf)) {
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
refname, dirname.buf);
goto cleanup;
}
}
/*
* We are at the leaf of our refname (e.g., "refs/foo/bar").
* There is no point in searching for a reference with that
* name, because a refname isn't considered to conflict with
* itself. But we still need to check for references whose
* names are in the "refs/foo/bar/" namespace, because they
* *do* conflict.
*/
strbuf_addstr(&dirname, refname + dirname.len);
strbuf_addch(&dirname, '/');
iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
DO_FOR_EACH_INCLUDE_BROKEN);
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
if (skip &&
string_list_has_string(skip, iter->refname))
continue;
strbuf_addf(err, "'%s' exists; cannot create '%s'",
iter->refname, refname);
ref_iterator_abort(iter);
goto cleanup;
}
if (ok != ITER_DONE)
die("BUG: error while iterating over references");
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
if (extra_refname)
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
refname, extra_refname);
else
ret = 0;
cleanup:
strbuf_release(&referent);
strbuf_release(&dirname);
return ret;
}
int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)