about summary refs log tree commit diff
path: root/third_party/git/refs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-09-21T10·03+0300
committerVincent Ambo <mail@tazj.in>2021-09-21T11·29+0300
commit43b1791ec601732ac31195df96781a848360a9ac (patch)
treedaae8d638343295d2f1f7da955e556ef4c958864 /third_party/git/refs
parent2d8e7dc9d9c38127ec4ebd13aee8e8f586a43318 (diff)
chore(3p/git): Unvendor git and track patches instead r/2903
This was vendored a long time ago under the expectation that keeping
it in sync with cgit would be easier this way, but it has proven not
to be a big issue.

On the other hand, a vendored copy of git is an annoying maintenance
burden. It is much easier to rebase the single (dottime) patch that we
have.

This removes the vendored copy of git and instead passes the git
source code to cgit via `pkgs.srcOnly`, which includes the applied
patch so that cgit can continue rendering dottime.

Change-Id: If31f62dea7ce688fd1b9050204e9378019775f2b
Diffstat (limited to 'third_party/git/refs')
-rw-r--r--third_party/git/refs/debug.c398
-rw-r--r--third_party/git/refs/files-backend.c3198
-rw-r--r--third_party/git/refs/iterator.c435
-rw-r--r--third_party/git/refs/packed-backend.c1670
-rw-r--r--third_party/git/refs/packed-backend.h37
-rw-r--r--third_party/git/refs/ref-cache.c551
-rw-r--r--third_party/git/refs/ref-cache.h243
-rw-r--r--third_party/git/refs/refs-internal.h705
8 files changed, 0 insertions, 7237 deletions
diff --git a/third_party/git/refs/debug.c b/third_party/git/refs/debug.c
deleted file mode 100644
index 922e64fa6ad9..000000000000
--- a/third_party/git/refs/debug.c
+++ /dev/null
@@ -1,398 +0,0 @@
-
-#include "refs-internal.h"
-#include "trace.h"
-
-static struct trace_key trace_refs = TRACE_KEY_INIT(REFS);
-
-struct debug_ref_store {
-	struct ref_store base;
-	struct ref_store *refs;
-};
-
-extern struct ref_storage_be refs_be_debug;
-
-struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_store *store)
-{
-	struct debug_ref_store *res;
-	struct ref_storage_be *be_copy;
-
-	if (!trace_want(&trace_refs)) {
-		return store;
-	}
-	res = xmalloc(sizeof(struct debug_ref_store));
-	be_copy = xmalloc(sizeof(*be_copy));
-	*be_copy = refs_be_debug;
-	/* we never deallocate backends, so safe to copy the pointer. */
-	be_copy->name = store->be->name;
-	trace_printf_key(&trace_refs, "ref_store for %s\n", gitdir);
-	res->refs = store;
-	base_ref_store_init((struct ref_store *)res, be_copy);
-	return (struct ref_store *)res;
-}
-
-static int debug_init_db(struct ref_store *refs, struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
-	int res = drefs->refs->be->init_db(drefs->refs, err);
-	trace_printf_key(&trace_refs, "init_db: %d\n", res);
-	return res;
-}
-
-static int debug_transaction_prepare(struct ref_store *refs,
-				     struct ref_transaction *transaction,
-				     struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
-	int res;
-	transaction->ref_store = drefs->refs;
-	res = drefs->refs->be->transaction_prepare(drefs->refs, transaction,
-						   err);
-	trace_printf_key(&trace_refs, "transaction_prepare: %d\n", res);
-	return res;
-}
-
-static void print_update(int i, const char *refname,
-			 const struct object_id *old_oid,
-			 const struct object_id *new_oid, unsigned int flags,
-			 unsigned int type, const char *msg)
-{
-	char o[GIT_MAX_HEXSZ + 1] = "null";
-	char n[GIT_MAX_HEXSZ + 1] = "null";
-	if (old_oid)
-		oid_to_hex_r(o, old_oid);
-	if (new_oid)
-		oid_to_hex_r(n, new_oid);
-
-	type &= 0xf; /* see refs.h REF_* */
-	flags &= REF_HAVE_NEW | REF_HAVE_OLD | REF_NO_DEREF |
-		REF_FORCE_CREATE_REFLOG;
-	trace_printf_key(&trace_refs, "%d: %s %s -> %s (F=0x%x, T=0x%x) \"%s\"\n", i, refname,
-		o, n, flags, type, msg);
-}
-
-static void print_transaction(struct ref_transaction *transaction)
-{
-	int i;
-	trace_printf_key(&trace_refs, "transaction {\n");
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *u = transaction->updates[i];
-		print_update(i, u->refname, &u->old_oid, &u->new_oid, u->flags,
-			     u->type, u->msg);
-	}
-	trace_printf_key(&trace_refs, "}\n");
-}
-
-static int debug_transaction_finish(struct ref_store *refs,
-				    struct ref_transaction *transaction,
-				    struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
-	int res;
-	transaction->ref_store = drefs->refs;
-	res = drefs->refs->be->transaction_finish(drefs->refs, transaction,
-						  err);
-	print_transaction(transaction);
-	trace_printf_key(&trace_refs, "finish: %d\n", res);
-	return res;
-}
-
-static int debug_transaction_abort(struct ref_store *refs,
-				   struct ref_transaction *transaction,
-				   struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
-	int res;
-	transaction->ref_store = drefs->refs;
-	res = drefs->refs->be->transaction_abort(drefs->refs, transaction, err);
-	return res;
-}
-
-static int debug_initial_transaction_commit(struct ref_store *refs,
-					    struct ref_transaction *transaction,
-					    struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
-	int res;
-	transaction->ref_store = drefs->refs;
-	res = drefs->refs->be->initial_transaction_commit(drefs->refs,
-							  transaction, err);
-	return res;
-}
-
-static int debug_pack_refs(struct ref_store *ref_store, unsigned int flags)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->pack_refs(drefs->refs, flags);
-	trace_printf_key(&trace_refs, "pack_refs: %d\n", res);
-	return res;
-}
-
-static int debug_create_symref(struct ref_store *ref_store,
-			       const char *ref_name, const char *target,
-			       const char *logmsg)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->create_symref(drefs->refs, ref_name, target,
-						 logmsg);
-	trace_printf_key(&trace_refs, "create_symref: %s -> %s \"%s\": %d\n", ref_name,
-		target, logmsg, res);
-	return res;
-}
-
-static int debug_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res =
-		drefs->refs->be->delete_refs(drefs->refs, msg, refnames, flags);
-	int i;
-	trace_printf_key(&trace_refs, "delete_refs {\n");
-	for (i = 0; i < refnames->nr; i++)
-		trace_printf_key(&trace_refs, "%s\n", refnames->items[i].string);
-	trace_printf_key(&trace_refs, "}: %d\n", res);
-	return res;
-}
-
-static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
-			    const char *newref, const char *logmsg)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->rename_ref(drefs->refs, oldref, newref,
-					      logmsg);
-	trace_printf_key(&trace_refs, "rename_ref: %s -> %s \"%s\": %d\n", oldref, newref,
-		logmsg, res);
-	return res;
-}
-
-static int debug_copy_ref(struct ref_store *ref_store, const char *oldref,
-			  const char *newref, const char *logmsg)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res =
-		drefs->refs->be->copy_ref(drefs->refs, oldref, newref, logmsg);
-	trace_printf_key(&trace_refs, "copy_ref: %s -> %s \"%s\": %d\n", oldref, newref,
-		logmsg, res);
-	return res;
-}
-
-struct debug_ref_iterator {
-	struct ref_iterator base;
-	struct ref_iterator *iter;
-};
-
-static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct debug_ref_iterator *diter =
-		(struct debug_ref_iterator *)ref_iterator;
-	int res = diter->iter->vtable->advance(diter->iter);
-	if (res)
-		trace_printf_key(&trace_refs, "iterator_advance: (%d)\n", res);
-	else
-		trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
-			diter->iter->refname);
-
-	diter->base.ordered = diter->iter->ordered;
-	diter->base.refname = diter->iter->refname;
-	diter->base.oid = diter->iter->oid;
-	diter->base.flags = diter->iter->flags;
-	return res;
-}
-
-static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct debug_ref_iterator *diter =
-		(struct debug_ref_iterator *)ref_iterator;
-	int res = diter->iter->vtable->peel(diter->iter, peeled);
-	trace_printf_key(&trace_refs, "iterator_peel: %s: %d\n", diter->iter->refname, res);
-	return res;
-}
-
-static int debug_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct debug_ref_iterator *diter =
-		(struct debug_ref_iterator *)ref_iterator;
-	int res = diter->iter->vtable->abort(diter->iter);
-	trace_printf_key(&trace_refs, "iterator_abort: %d\n", res);
-	return res;
-}
-
-static struct ref_iterator_vtable debug_ref_iterator_vtable = {
-	debug_ref_iterator_advance, debug_ref_iterator_peel,
-	debug_ref_iterator_abort
-};
-
-static struct ref_iterator *
-debug_ref_iterator_begin(struct ref_store *ref_store, const char *prefix,
-			 unsigned int flags)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	struct ref_iterator *res =
-		drefs->refs->be->iterator_begin(drefs->refs, prefix, flags);
-	struct debug_ref_iterator *diter = xcalloc(1, sizeof(*diter));
-	base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable, 1);
-	diter->iter = res;
-	trace_printf_key(&trace_refs, "ref_iterator_begin: %s (0x%x)\n", prefix, flags);
-	return &diter->base;
-}
-
-static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,
-			      struct object_id *oid, struct strbuf *referent,
-			      unsigned int *type)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = 0;
-
-	oidcpy(oid, &null_oid);
-	res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,
-					    type);
-
-	if (res == 0) {
-		trace_printf_key(&trace_refs, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
-			refname, oid_to_hex(oid), referent->buf, *type, res);
-	} else {
-		trace_printf_key(&trace_refs, "read_raw_ref: %s: %d\n", refname, res);
-	}
-	return res;
-}
-
-static struct ref_iterator *
-debug_reflog_iterator_begin(struct ref_store *ref_store)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	struct ref_iterator *res =
-		drefs->refs->be->reflog_iterator_begin(drefs->refs);
-	trace_printf_key(&trace_refs, "for_each_reflog_iterator_begin\n");
-	return res;
-}
-
-struct debug_reflog {
-	const char *refname;
-	each_reflog_ent_fn *fn;
-	void *cb_data;
-};
-
-static int debug_print_reflog_ent(struct object_id *old_oid,
-				  struct object_id *new_oid,
-				  const char *committer, timestamp_t timestamp,
-				  int tz, const char *msg, void *cb_data)
-{
-	struct debug_reflog *dbg = (struct debug_reflog *)cb_data;
-	int ret;
-	char o[GIT_MAX_HEXSZ + 1] = "null";
-	char n[GIT_MAX_HEXSZ + 1] = "null";
-	if (old_oid)
-		oid_to_hex_r(o, old_oid);
-	if (new_oid)
-		oid_to_hex_r(n, new_oid);
-
-	ret = dbg->fn(old_oid, new_oid, committer, timestamp, tz, msg,
-		      dbg->cb_data);
-	trace_printf_key(&trace_refs, "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%s\"\n",
-		dbg->refname, ret, o, n, committer, (long int)timestamp, msg);
-	return ret;
-}
-
-static int debug_for_each_reflog_ent(struct ref_store *ref_store,
-				     const char *refname, each_reflog_ent_fn fn,
-				     void *cb_data)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	struct debug_reflog dbg = {
-		.refname = refname,
-		.fn = fn,
-		.cb_data = cb_data,
-	};
-
-	int res = drefs->refs->be->for_each_reflog_ent(
-		drefs->refs, refname, &debug_print_reflog_ent, &dbg);
-	trace_printf_key(&trace_refs, "for_each_reflog: %s: %d\n", refname, res);
-	return res;
-}
-
-static int debug_for_each_reflog_ent_reverse(struct ref_store *ref_store,
-					     const char *refname,
-					     each_reflog_ent_fn fn,
-					     void *cb_data)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	struct debug_reflog dbg = {
-		.refname = refname,
-		.fn = fn,
-		.cb_data = cb_data,
-	};
-	int res = drefs->refs->be->for_each_reflog_ent_reverse(
-		drefs->refs, refname, &debug_print_reflog_ent, &dbg);
-	trace_printf_key(&trace_refs, "for_each_reflog_reverse: %s: %d\n", refname, res);
-	return res;
-}
-
-static int debug_reflog_exists(struct ref_store *ref_store, const char *refname)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->reflog_exists(drefs->refs, refname);
-	trace_printf_key(&trace_refs, "reflog_exists: %s: %d\n", refname, res);
-	return res;
-}
-
-static int debug_create_reflog(struct ref_store *ref_store, const char *refname,
-			       int force_create, struct strbuf *err)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->create_reflog(drefs->refs, refname,
-						 force_create, err);
-	trace_printf_key(&trace_refs, "create_reflog: %s: %d\n", refname, res);
-	return res;
-}
-
-static int debug_delete_reflog(struct ref_store *ref_store, const char *refname)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->delete_reflog(drefs->refs, refname);
-	trace_printf_key(&trace_refs, "delete_reflog: %s: %d\n", refname, res);
-	return res;
-}
-
-static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
-			       const struct object_id *oid, unsigned int flags,
-			       reflog_expiry_prepare_fn prepare_fn,
-			       reflog_expiry_should_prune_fn should_prune_fn,
-			       reflog_expiry_cleanup_fn cleanup_fn,
-			       void *policy_cb_data)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->reflog_expire(drefs->refs, refname, oid,
-						 flags, prepare_fn,
-						 should_prune_fn, cleanup_fn,
-						 policy_cb_data);
-	trace_printf_key(&trace_refs, "reflog_expire: %s: %d\n", refname, res);
-	return res;
-}
-
-struct ref_storage_be refs_be_debug = {
-	NULL,
-	"debug",
-	NULL,
-	debug_init_db,
-	debug_transaction_prepare,
-	debug_transaction_finish,
-	debug_transaction_abort,
-	debug_initial_transaction_commit,
-
-	debug_pack_refs,
-	debug_create_symref,
-	debug_delete_refs,
-	debug_rename_ref,
-	debug_copy_ref,
-
-	debug_ref_iterator_begin,
-	debug_read_raw_ref,
-
-	debug_reflog_iterator_begin,
-	debug_for_each_reflog_ent,
-	debug_for_each_reflog_ent_reverse,
-	debug_reflog_exists,
-	debug_create_reflog,
-	debug_delete_reflog,
-	debug_reflog_expire,
-};
diff --git a/third_party/git/refs/files-backend.c b/third_party/git/refs/files-backend.c
deleted file mode 100644
index 04e85e70029b..000000000000
--- a/third_party/git/refs/files-backend.c
+++ /dev/null
@@ -1,3198 +0,0 @@
-#include "../cache.h"
-#include "../config.h"
-#include "../refs.h"
-#include "refs-internal.h"
-#include "ref-cache.h"
-#include "packed-backend.h"
-#include "../iterator.h"
-#include "../dir-iterator.h"
-#include "../lockfile.h"
-#include "../object.h"
-#include "../dir.h"
-#include "../chdir-notify.h"
-#include "worktree.h"
-
-/*
- * This backend uses the following flags in `ref_update::flags` for
- * internal bookkeeping purposes. Their numerical values must not
- * conflict with REF_NO_DEREF, REF_FORCE_CREATE_REFLOG, REF_HAVE_NEW,
- * REF_HAVE_OLD, or REF_IS_PRUNING, which are also stored in
- * `ref_update::flags`.
- */
-
-/*
- * Used as a flag in ref_update::flags when a loose ref is being
- * pruned. This flag must only be used when REF_NO_DEREF is set.
- */
-#define REF_IS_PRUNING (1 << 4)
-
-/*
- * Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
- * refs (i.e., because the reference is about to be deleted anyway).
- */
-#define REF_DELETING (1 << 5)
-
-/*
- * Used as a flag in ref_update::flags when the lockfile needs to be
- * committed.
- */
-#define REF_NEEDS_COMMIT (1 << 6)
-
-/*
- * Used as a flag in ref_update::flags when the ref_update was via an
- * update to HEAD.
- */
-#define REF_UPDATE_VIA_HEAD (1 << 8)
-
-/*
- * Used as a flag in ref_update::flags when the loose reference has
- * been deleted.
- */
-#define REF_DELETED_LOOSE (1 << 9)
-
-struct ref_lock {
-	char *ref_name;
-	struct lock_file lk;
-	struct object_id old_oid;
-};
-
-struct files_ref_store {
-	struct ref_store base;
-	unsigned int store_flags;
-
-	char *gitcommondir;
-
-	struct ref_cache *loose;
-
-	struct ref_store *packed_ref_store;
-};
-
-static void clear_loose_ref_cache(struct files_ref_store *refs)
-{
-	if (refs->loose) {
-		free_ref_cache(refs->loose);
-		refs->loose = NULL;
-	}
-}
-
-/*
- * Create a new submodule ref cache and add it to the internal
- * set of caches.
- */
-static struct ref_store *files_ref_store_create(const char *gitdir,
-						unsigned int flags)
-{
-	struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
-	struct ref_store *ref_store = (struct ref_store *)refs;
-	struct strbuf sb = STRBUF_INIT;
-
-	ref_store->gitdir = xstrdup(gitdir);
-	base_ref_store_init(ref_store, &refs_be_files);
-	refs->store_flags = flags;
-
-	get_common_dir_noenv(&sb, gitdir);
-	refs->gitcommondir = strbuf_detach(&sb, NULL);
-	strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
-	refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
-	strbuf_release(&sb);
-
-	chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
-	chdir_notify_reparent("files-backend $GIT_COMMONDIR",
-			      &refs->gitcommondir);
-
-	return ref_store;
-}
-
-/*
- * Die if refs is not the main ref store. caller is used in any
- * necessary error messages.
- */
-static void files_assert_main_repository(struct files_ref_store *refs,
-					 const char *caller)
-{
-	if (refs->store_flags & REF_STORE_MAIN)
-		return;
-
-	BUG("operation %s only allowed for main ref store", caller);
-}
-
-/*
- * Downcast ref_store to files_ref_store. Die if ref_store is not a
- * files_ref_store. required_flags is compared with ref_store's
- * store_flags to ensure the ref_store has all required capabilities.
- * "caller" is used in any necessary error messages.
- */
-static struct files_ref_store *files_downcast(struct ref_store *ref_store,
-					      unsigned int required_flags,
-					      const char *caller)
-{
-	struct files_ref_store *refs;
-
-	if (ref_store->be != &refs_be_files)
-		BUG("ref_store is type \"%s\" not \"files\" in %s",
-		    ref_store->be->name, caller);
-
-	refs = (struct files_ref_store *)ref_store;
-
-	if ((refs->store_flags & required_flags) != required_flags)
-		BUG("operation %s requires abilities 0x%x, but only have 0x%x",
-		    caller, required_flags, refs->store_flags);
-
-	return refs;
-}
-
-static void files_reflog_path_other_worktrees(struct files_ref_store *refs,
-					      struct strbuf *sb,
-					      const char *refname)
-{
-	const char *real_ref;
-	const char *worktree_name;
-	int length;
-
-	if (parse_worktree_ref(refname, &worktree_name, &length, &real_ref))
-		BUG("refname %s is not a other-worktree ref", refname);
-
-	if (worktree_name)
-		strbuf_addf(sb, "%s/worktrees/%.*s/logs/%s", refs->gitcommondir,
-			    length, worktree_name, real_ref);
-	else
-		strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir,
-			    real_ref);
-}
-
-static void files_reflog_path(struct files_ref_store *refs,
-			      struct strbuf *sb,
-			      const char *refname)
-{
-	switch (ref_type(refname)) {
-	case REF_TYPE_PER_WORKTREE:
-	case REF_TYPE_PSEUDOREF:
-		strbuf_addf(sb, "%s/logs/%s", refs->base.gitdir, refname);
-		break;
-	case REF_TYPE_OTHER_PSEUDOREF:
-	case REF_TYPE_MAIN_PSEUDOREF:
-		files_reflog_path_other_worktrees(refs, sb, refname);
-		break;
-	case REF_TYPE_NORMAL:
-		strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, refname);
-		break;
-	default:
-		BUG("unknown ref type %d of ref %s",
-		    ref_type(refname), refname);
-	}
-}
-
-static void files_ref_path(struct files_ref_store *refs,
-			   struct strbuf *sb,
-			   const char *refname)
-{
-	switch (ref_type(refname)) {
-	case REF_TYPE_PER_WORKTREE:
-	case REF_TYPE_PSEUDOREF:
-		strbuf_addf(sb, "%s/%s", refs->base.gitdir, refname);
-		break;
-	case REF_TYPE_MAIN_PSEUDOREF:
-		if (!skip_prefix(refname, "main-worktree/", &refname))
-			BUG("ref %s is not a main pseudoref", refname);
-		/* fallthrough */
-	case REF_TYPE_OTHER_PSEUDOREF:
-	case REF_TYPE_NORMAL:
-		strbuf_addf(sb, "%s/%s", refs->gitcommondir, refname);
-		break;
-	default:
-		BUG("unknown ref type %d of ref %s",
-		    ref_type(refname), refname);
-	}
-}
-
-/*
- * Manually add refs/bisect, refs/rewritten and refs/worktree, which, being
- * per-worktree, might not appear in the directory listing for
- * refs/ in the main repo.
- */
-static void add_per_worktree_entries_to_dir(struct ref_dir *dir, const char *dirname)
-{
-	const char *prefixes[] = { "refs/bisect/", "refs/worktree/", "refs/rewritten/" };
-	int ip;
-
-	if (strcmp(dirname, "refs/"))
-		return;
-
-	for (ip = 0; ip < ARRAY_SIZE(prefixes); ip++) {
-		const char *prefix = prefixes[ip];
-		int prefix_len = strlen(prefix);
-		struct ref_entry *child_entry;
-		int pos;
-
-		pos = search_ref_dir(dir, prefix, prefix_len);
-		if (pos >= 0)
-			continue;
-		child_entry = create_dir_entry(dir->cache, prefix, prefix_len, 1);
-		add_entry_to_dir(dir, child_entry);
-	}
-}
-
-/*
- * Read the loose references from the namespace dirname into dir
- * (without recursing).  dirname must end with '/'.  dir must be the
- * directory entry corresponding to dirname.
- */
-static void loose_fill_ref_dir(struct ref_store *ref_store,
-			       struct ref_dir *dir, const char *dirname)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ, "fill_ref_dir");
-	DIR *d;
-	struct dirent *de;
-	int dirnamelen = strlen(dirname);
-	struct strbuf refname;
-	struct strbuf path = STRBUF_INIT;
-	size_t path_baselen;
-
-	files_ref_path(refs, &path, dirname);
-	path_baselen = path.len;
-
-	d = opendir(path.buf);
-	if (!d) {
-		strbuf_release(&path);
-		return;
-	}
-
-	strbuf_init(&refname, dirnamelen + 257);
-	strbuf_add(&refname, dirname, dirnamelen);
-
-	while ((de = readdir(d)) != NULL) {
-		struct object_id oid;
-		struct stat st;
-		int flag;
-
-		if (de->d_name[0] == '.')
-			continue;
-		if (ends_with(de->d_name, ".lock"))
-			continue;
-		strbuf_addstr(&refname, de->d_name);
-		strbuf_addstr(&path, de->d_name);
-		if (stat(path.buf, &st) < 0) {
-			; /* silently ignore */
-		} else if (S_ISDIR(st.st_mode)) {
-			strbuf_addch(&refname, '/');
-			add_entry_to_dir(dir,
-					 create_dir_entry(dir->cache, refname.buf,
-							  refname.len, 1));
-		} else {
-			if (!refs_resolve_ref_unsafe(&refs->base,
-						     refname.buf,
-						     RESOLVE_REF_READING,
-						     &oid, &flag)) {
-				oidclr(&oid);
-				flag |= REF_ISBROKEN;
-			} else if (is_null_oid(&oid)) {
-				/*
-				 * It is so astronomically unlikely
-				 * that null_oid is the OID of an
-				 * actual object that we consider its
-				 * appearance in a loose reference
-				 * file to be repo corruption
-				 * (probably due to a software bug).
-				 */
-				flag |= REF_ISBROKEN;
-			}
-
-			if (check_refname_format(refname.buf,
-						 REFNAME_ALLOW_ONELEVEL)) {
-				if (!refname_is_safe(refname.buf))
-					die("loose refname is dangerous: %s", refname.buf);
-				oidclr(&oid);
-				flag |= REF_BAD_NAME | REF_ISBROKEN;
-			}
-			add_entry_to_dir(dir,
-					 create_ref_entry(refname.buf, &oid, flag));
-		}
-		strbuf_setlen(&refname, dirnamelen);
-		strbuf_setlen(&path, path_baselen);
-	}
-	strbuf_release(&refname);
-	strbuf_release(&path);
-	closedir(d);
-
-	add_per_worktree_entries_to_dir(dir, dirname);
-}
-
-static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
-{
-	if (!refs->loose) {
-		/*
-		 * Mark the top-level directory complete because we
-		 * are about to read the only subdirectory that can
-		 * hold references:
-		 */
-		refs->loose = create_ref_cache(&refs->base, loose_fill_ref_dir);
-
-		/* We're going to fill the top level ourselves: */
-		refs->loose->root->flag &= ~REF_INCOMPLETE;
-
-		/*
-		 * Add an incomplete entry for "refs/" (to be filled
-		 * lazily):
-		 */
-		add_entry_to_dir(get_ref_dir(refs->loose->root),
-				 create_dir_entry(refs->loose, "refs/", 5, 1));
-	}
-	return refs->loose;
-}
-
-static int files_read_raw_ref(struct ref_store *ref_store,
-			      const char *refname, struct object_id *oid,
-			      struct strbuf *referent, unsigned int *type)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
-	struct strbuf sb_contents = STRBUF_INIT;
-	struct strbuf sb_path = STRBUF_INIT;
-	const char *path;
-	const char *buf;
-	struct stat st;
-	int fd;
-	int ret = -1;
-	int save_errno;
-	int remaining_retries = 3;
-
-	*type = 0;
-	strbuf_reset(&sb_path);
-
-	files_ref_path(refs, &sb_path, refname);
-
-	path = sb_path.buf;
-
-stat_ref:
-	/*
-	 * We might have to loop back here to avoid a race
-	 * condition: first we lstat() the file, then we try
-	 * to read it as a link or as a file.  But if somebody
-	 * changes the type of the file (file <-> directory
-	 * <-> symlink) between the lstat() and reading, then
-	 * we don't want to report that as an error but rather
-	 * try again starting with the lstat().
-	 *
-	 * We'll keep a count of the retries, though, just to avoid
-	 * any confusing situation sending us into an infinite loop.
-	 */
-
-	if (remaining_retries-- <= 0)
-		goto out;
-
-	if (lstat(path, &st) < 0) {
-		if (errno != ENOENT)
-			goto out;
-		if (refs_read_raw_ref(refs->packed_ref_store, refname,
-				      oid, referent, type)) {
-			errno = ENOENT;
-			goto out;
-		}
-		ret = 0;
-		goto out;
-	}
-
-	/* Follow "normalized" - ie "refs/.." symlinks by hand */
-	if (S_ISLNK(st.st_mode)) {
-		strbuf_reset(&sb_contents);
-		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
-			if (errno == ENOENT || errno == EINVAL)
-				/* inconsistent with lstat; retry */
-				goto stat_ref;
-			else
-				goto out;
-		}
-		if (starts_with(sb_contents.buf, "refs/") &&
-		    !check_refname_format(sb_contents.buf, 0)) {
-			strbuf_swap(&sb_contents, referent);
-			*type |= REF_ISSYMREF;
-			ret = 0;
-			goto out;
-		}
-		/*
-		 * It doesn't look like a refname; fall through to just
-		 * treating it like a non-symlink, and reading whatever it
-		 * points to.
-		 */
-	}
-
-	/* Is it a directory? */
-	if (S_ISDIR(st.st_mode)) {
-		/*
-		 * Even though there is a directory where the loose
-		 * ref is supposed to be, there could still be a
-		 * packed ref:
-		 */
-		if (refs_read_raw_ref(refs->packed_ref_store, refname,
-				      oid, referent, type)) {
-			errno = EISDIR;
-			goto out;
-		}
-		ret = 0;
-		goto out;
-	}
-
-	/*
-	 * Anything else, just open it and try to use it as
-	 * a ref
-	 */
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
-		if (errno == ENOENT && !S_ISLNK(st.st_mode))
-			/* inconsistent with lstat; retry */
-			goto stat_ref;
-		else
-			goto out;
-	}
-	strbuf_reset(&sb_contents);
-	if (strbuf_read(&sb_contents, fd, 256) < 0) {
-		int save_errno = errno;
-		close(fd);
-		errno = save_errno;
-		goto out;
-	}
-	close(fd);
-	strbuf_rtrim(&sb_contents);
-	buf = sb_contents.buf;
-
-	ret = parse_loose_ref_contents(buf, oid, referent, type);
-
-out:
-	save_errno = errno;
-	strbuf_release(&sb_path);
-	strbuf_release(&sb_contents);
-	errno = save_errno;
-	return ret;
-}
-
-int parse_loose_ref_contents(const char *buf, struct object_id *oid,
-			     struct strbuf *referent, unsigned int *type)
-{
-	const char *p;
-	if (skip_prefix(buf, "ref:", &buf)) {
-		while (isspace(*buf))
-			buf++;
-
-		strbuf_reset(referent);
-		strbuf_addstr(referent, buf);
-		*type |= REF_ISSYMREF;
-		return 0;
-	}
-
-	/*
-	 * FETCH_HEAD has additional data after the sha.
-	 */
-	if (parse_oid_hex(buf, oid, &p) ||
-	    (*p != '\0' && !isspace(*p))) {
-		*type |= REF_ISBROKEN;
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
-}
-
-static void unlock_ref(struct ref_lock *lock)
-{
-	rollback_lock_file(&lock->lk);
-	free(lock->ref_name);
-	free(lock);
-}
-
-/*
- * Lock refname, without following symrefs, and set *lock_p to point
- * at a newly-allocated lock object. Fill in lock->old_oid, referent,
- * and type similarly to read_raw_ref().
- *
- * The caller must verify that refname is a "safe" reference name (in
- * the sense of refname_is_safe()) before calling this function.
- *
- * If the reference doesn't already exist, verify that refname doesn't
- * have a D/F conflict with any existing references. extras and skip
- * are passed to refs_verify_refname_available() for this check.
- *
- * If mustexist is not set and the reference is not found or is
- * broken, lock the reference anyway but clear old_oid.
- *
- * Return 0 on success. On failure, write an error message to err and
- * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR.
- *
- * Implementation note: This function is basically
- *
- *     lock reference
- *     read_raw_ref()
- *
- * but it includes a lot more code to
- * - Deal with possible races with other processes
- * - Avoid calling refs_verify_refname_available() when it can be
- *   avoided, namely if we were successfully able to read the ref
- * - Generate informative error messages in the case of failure
- */
-static int lock_raw_ref(struct files_ref_store *refs,
-			const char *refname, int mustexist,
-			const struct string_list *extras,
-			const struct string_list *skip,
-			struct ref_lock **lock_p,
-			struct strbuf *referent,
-			unsigned int *type,
-			struct strbuf *err)
-{
-	struct ref_lock *lock;
-	struct strbuf ref_file = STRBUF_INIT;
-	int attempts_remaining = 3;
-	int ret = TRANSACTION_GENERIC_ERROR;
-
-	assert(err);
-	files_assert_main_repository(refs, "lock_raw_ref");
-
-	*type = 0;
-
-	/* First lock the file so it can't change out from under us. */
-
-	*lock_p = lock = xcalloc(1, sizeof(*lock));
-
-	lock->ref_name = xstrdup(refname);
-	files_ref_path(refs, &ref_file, refname);
-
-retry:
-	switch (safe_create_leading_directories(ref_file.buf)) {
-	case SCLD_OK:
-		break; /* success */
-	case SCLD_EXISTS:
-		/*
-		 * Suppose refname is "refs/foo/bar". We just failed
-		 * to create the containing directory, "refs/foo",
-		 * because there was a non-directory in the way. This
-		 * indicates a D/F conflict, probably because of
-		 * another reference such as "refs/foo". There is no
-		 * reason to expect this error to be transitory.
-		 */
-		if (refs_verify_refname_available(&refs->base, refname,
-						  extras, skip, err)) {
-			if (mustexist) {
-				/*
-				 * To the user the relevant error is
-				 * that the "mustexist" reference is
-				 * missing:
-				 */
-				strbuf_reset(err);
-				strbuf_addf(err, "unable to resolve reference '%s'",
-					    refname);
-			} else {
-				/*
-				 * The error message set by
-				 * refs_verify_refname_available() is
-				 * OK.
-				 */
-				ret = TRANSACTION_NAME_CONFLICT;
-			}
-		} else {
-			/*
-			 * The file that is in the way isn't a loose
-			 * reference. Report it as a low-level
-			 * failure.
-			 */
-			strbuf_addf(err, "unable to create lock file %s.lock; "
-				    "non-directory in the way",
-				    ref_file.buf);
-		}
-		goto error_return;
-	case SCLD_VANISHED:
-		/* Maybe another process was tidying up. Try again. */
-		if (--attempts_remaining > 0)
-			goto retry;
-		/* fall through */
-	default:
-		strbuf_addf(err, "unable to create directory for %s",
-			    ref_file.buf);
-		goto error_return;
-	}
-
-	if (hold_lock_file_for_update_timeout(
-			    &lock->lk, ref_file.buf, LOCK_NO_DEREF,
-			    get_files_ref_lock_timeout_ms()) < 0) {
-		if (errno == ENOENT && --attempts_remaining > 0) {
-			/*
-			 * Maybe somebody just deleted one of the
-			 * directories leading to ref_file.  Try
-			 * again:
-			 */
-			goto retry;
-		} else {
-			unable_to_lock_message(ref_file.buf, errno, err);
-			goto error_return;
-		}
-	}
-
-	/*
-	 * Now we hold the lock and can read the reference without
-	 * fear that its value will change.
-	 */
-
-	if (files_read_raw_ref(&refs->base, refname,
-			       &lock->old_oid, referent, type)) {
-		if (errno == ENOENT) {
-			if (mustexist) {
-				/* Garden variety missing reference. */
-				strbuf_addf(err, "unable to resolve reference '%s'",
-					    refname);
-				goto error_return;
-			} else {
-				/*
-				 * Reference is missing, but that's OK. We
-				 * know that there is not a conflict with
-				 * another loose reference because
-				 * (supposing that we are trying to lock
-				 * reference "refs/foo/bar"):
-				 *
-				 * - We were successfully able to create
-				 *   the lockfile refs/foo/bar.lock, so we
-				 *   know there cannot be a loose reference
-				 *   named "refs/foo".
-				 *
-				 * - We got ENOENT and not EISDIR, so we
-				 *   know that there cannot be a loose
-				 *   reference named "refs/foo/bar/baz".
-				 */
-			}
-		} else if (errno == EISDIR) {
-			/*
-			 * There is a directory in the way. It might have
-			 * contained references that have been deleted. If
-			 * we don't require that the reference already
-			 * exists, try to remove the directory so that it
-			 * doesn't cause trouble when we want to rename the
-			 * lockfile into place later.
-			 */
-			if (mustexist) {
-				/* Garden variety missing reference. */
-				strbuf_addf(err, "unable to resolve reference '%s'",
-					    refname);
-				goto error_return;
-			} else if (remove_dir_recursively(&ref_file,
-							  REMOVE_DIR_EMPTY_ONLY)) {
-				if (refs_verify_refname_available(
-						    &refs->base, refname,
-						    extras, skip, err)) {
-					/*
-					 * The error message set by
-					 * verify_refname_available() is OK.
-					 */
-					ret = TRANSACTION_NAME_CONFLICT;
-					goto error_return;
-				} else {
-					/*
-					 * We can't delete the directory,
-					 * but we also don't know of any
-					 * references that it should
-					 * contain.
-					 */
-					strbuf_addf(err, "there is a non-empty directory '%s' "
-						    "blocking reference '%s'",
-						    ref_file.buf, refname);
-					goto error_return;
-				}
-			}
-		} else if (errno == EINVAL && (*type & REF_ISBROKEN)) {
-			strbuf_addf(err, "unable to resolve reference '%s': "
-				    "reference broken", refname);
-			goto error_return;
-		} else {
-			strbuf_addf(err, "unable to resolve reference '%s': %s",
-				    refname, strerror(errno));
-			goto error_return;
-		}
-
-		/*
-		 * If the ref did not exist and we are creating it,
-		 * make sure there is no existing packed ref that
-		 * conflicts with refname:
-		 */
-		if (refs_verify_refname_available(
-				    refs->packed_ref_store, refname,
-				    extras, skip, err))
-			goto error_return;
-	}
-
-	ret = 0;
-	goto out;
-
-error_return:
-	unlock_ref(lock);
-	*lock_p = NULL;
-
-out:
-	strbuf_release(&ref_file);
-	return ret;
-}
-
-struct files_ref_iterator {
-	struct ref_iterator base;
-
-	struct ref_iterator *iter0;
-	unsigned int flags;
-};
-
-static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct files_ref_iterator *iter =
-		(struct files_ref_iterator *)ref_iterator;
-	int ok;
-
-	while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
-		if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
-		    ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
-			continue;
-
-		if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
-		    !ref_resolves_to_object(iter->iter0->refname,
-					    iter->iter0->oid,
-					    iter->iter0->flags))
-			continue;
-
-		iter->base.refname = iter->iter0->refname;
-		iter->base.oid = iter->iter0->oid;
-		iter->base.flags = iter->iter0->flags;
-		return ITER_OK;
-	}
-
-	iter->iter0 = NULL;
-	if (ref_iterator_abort(ref_iterator) != ITER_DONE)
-		ok = ITER_ERROR;
-
-	return ok;
-}
-
-static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct files_ref_iterator *iter =
-		(struct files_ref_iterator *)ref_iterator;
-
-	return ref_iterator_peel(iter->iter0, peeled);
-}
-
-static int files_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct files_ref_iterator *iter =
-		(struct files_ref_iterator *)ref_iterator;
-	int ok = ITER_DONE;
-
-	if (iter->iter0)
-		ok = ref_iterator_abort(iter->iter0);
-
-	base_ref_iterator_free(ref_iterator);
-	return ok;
-}
-
-static struct ref_iterator_vtable files_ref_iterator_vtable = {
-	files_ref_iterator_advance,
-	files_ref_iterator_peel,
-	files_ref_iterator_abort
-};
-
-static struct ref_iterator *files_ref_iterator_begin(
-		struct ref_store *ref_store,
-		const char *prefix, unsigned int flags)
-{
-	struct files_ref_store *refs;
-	struct ref_iterator *loose_iter, *packed_iter, *overlay_iter;
-	struct files_ref_iterator *iter;
-	struct ref_iterator *ref_iterator;
-	unsigned int required_flags = REF_STORE_READ;
-
-	if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
-		required_flags |= REF_STORE_ODB;
-
-	refs = files_downcast(ref_store, required_flags, "ref_iterator_begin");
-
-	/*
-	 * We must make sure that all loose refs are read before
-	 * accessing the packed-refs file; this avoids a race
-	 * condition if loose refs are migrated to the packed-refs
-	 * file by a simultaneous process, but our in-memory view is
-	 * from before the migration. We ensure this as follows:
-	 * First, we call start the loose refs iteration with its
-	 * `prime_ref` argument set to true. This causes the loose
-	 * references in the subtree to be pre-read into the cache.
-	 * (If they've already been read, that's OK; we only need to
-	 * guarantee that they're read before the packed refs, not
-	 * *how much* before.) After that, we call
-	 * packed_ref_iterator_begin(), which internally checks
-	 * whether the packed-ref cache is up to date with what is on
-	 * disk, and re-reads it if not.
-	 */
-
-	loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs),
-					      prefix, 1);
-
-	/*
-	 * The packed-refs file might contain broken references, for
-	 * example an old version of a reference that points at an
-	 * object that has since been garbage-collected. This is OK as
-	 * long as there is a corresponding loose reference that
-	 * overrides it, and we don't want to emit an error message in
-	 * this case. So ask the packed_ref_store for all of its
-	 * references, and (if needed) do our own check for broken
-	 * ones in files_ref_iterator_advance(), after we have merged
-	 * the packed and loose references.
-	 */
-	packed_iter = refs_ref_iterator_begin(
-			refs->packed_ref_store, prefix, 0,
-			DO_FOR_EACH_INCLUDE_BROKEN);
-
-	overlay_iter = overlay_ref_iterator_begin(loose_iter, packed_iter);
-
-	iter = xcalloc(1, sizeof(*iter));
-	ref_iterator = &iter->base;
-	base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable,
-			       overlay_iter->ordered);
-	iter->iter0 = overlay_iter;
-	iter->flags = flags;
-
-	return ref_iterator;
-}
-
-/*
- * Verify that the reference locked by lock has the value old_oid
- * (unless it is NULL).  Fail if the reference doesn't exist and
- * mustexist is set. Return 0 on success. On error, write an error
- * message to err, set errno, and return a negative value.
- */
-static int verify_lock(struct ref_store *ref_store, struct ref_lock *lock,
-		       const struct object_id *old_oid, int mustexist,
-		       struct strbuf *err)
-{
-	assert(err);
-
-	if (refs_read_ref_full(ref_store, lock->ref_name,
-			       mustexist ? RESOLVE_REF_READING : 0,
-			       &lock->old_oid, NULL)) {
-		if (old_oid) {
-			int save_errno = errno;
-			strbuf_addf(err, "can't verify ref '%s'", lock->ref_name);
-			errno = save_errno;
-			return -1;
-		} else {
-			oidclr(&lock->old_oid);
-			return 0;
-		}
-	}
-	if (old_oid && !oideq(&lock->old_oid, old_oid)) {
-		strbuf_addf(err, "ref '%s' is at %s but expected %s",
-			    lock->ref_name,
-			    oid_to_hex(&lock->old_oid),
-			    oid_to_hex(old_oid));
-		errno = EBUSY;
-		return -1;
-	}
-	return 0;
-}
-
-static int remove_empty_directories(struct strbuf *path)
-{
-	/*
-	 * we want to create a file but there is a directory there;
-	 * if that is an empty directory (or a directory that contains
-	 * only empty directories), remove them.
-	 */
-	return remove_dir_recursively(path, REMOVE_DIR_EMPTY_ONLY);
-}
-
-static int create_reflock(const char *path, void *cb)
-{
-	struct lock_file *lk = cb;
-
-	return hold_lock_file_for_update_timeout(
-			lk, path, LOCK_NO_DEREF,
-			get_files_ref_lock_timeout_ms()) < 0 ? -1 : 0;
-}
-
-/*
- * Locks a ref returning the lock on success and NULL on failure.
- * On failure errno is set to something meaningful.
- */
-static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
-					   const char *refname,
-					   const struct object_id *old_oid,
-					   const struct string_list *extras,
-					   const struct string_list *skip,
-					   unsigned int flags, int *type,
-					   struct strbuf *err)
-{
-	struct strbuf ref_file = STRBUF_INIT;
-	struct ref_lock *lock;
-	int last_errno = 0;
-	int mustexist = (old_oid && !is_null_oid(old_oid));
-	int resolve_flags = RESOLVE_REF_NO_RECURSE;
-	int resolved;
-
-	files_assert_main_repository(refs, "lock_ref_oid_basic");
-	assert(err);
-
-	lock = xcalloc(1, sizeof(struct ref_lock));
-
-	if (mustexist)
-		resolve_flags |= RESOLVE_REF_READING;
-	if (flags & REF_DELETING)
-		resolve_flags |= RESOLVE_REF_ALLOW_BAD_NAME;
-
-	files_ref_path(refs, &ref_file, refname);
-	resolved = !!refs_resolve_ref_unsafe(&refs->base,
-					     refname, resolve_flags,
-					     &lock->old_oid, type);
-	if (!resolved && errno == EISDIR) {
-		/*
-		 * we are trying to lock foo but we used to
-		 * have foo/bar which now does not exist;
-		 * it is normal for the empty directory 'foo'
-		 * to remain.
-		 */
-		if (remove_empty_directories(&ref_file)) {
-			last_errno = errno;
-			if (!refs_verify_refname_available(
-					    &refs->base,
-					    refname, extras, skip, err))
-				strbuf_addf(err, "there are still refs under '%s'",
-					    refname);
-			goto error_return;
-		}
-		resolved = !!refs_resolve_ref_unsafe(&refs->base,
-						     refname, resolve_flags,
-						     &lock->old_oid, type);
-	}
-	if (!resolved) {
-		last_errno = errno;
-		if (last_errno != ENOTDIR ||
-		    !refs_verify_refname_available(&refs->base, refname,
-						   extras, skip, err))
-			strbuf_addf(err, "unable to resolve reference '%s': %s",
-				    refname, strerror(last_errno));
-
-		goto error_return;
-	}
-
-	/*
-	 * If the ref did not exist and we are creating it, make sure
-	 * there is no existing packed ref whose name begins with our
-	 * refname, nor a packed ref whose name is a proper prefix of
-	 * our refname.
-	 */
-	if (is_null_oid(&lock->old_oid) &&
-	    refs_verify_refname_available(refs->packed_ref_store, refname,
-					  extras, skip, err)) {
-		last_errno = ENOTDIR;
-		goto error_return;
-	}
-
-	lock->ref_name = xstrdup(refname);
-
-	if (raceproof_create_file(ref_file.buf, create_reflock, &lock->lk)) {
-		last_errno = errno;
-		unable_to_lock_message(ref_file.buf, errno, err);
-		goto error_return;
-	}
-
-	if (verify_lock(&refs->base, lock, old_oid, mustexist, err)) {
-		last_errno = errno;
-		goto error_return;
-	}
-	goto out;
-
- error_return:
-	unlock_ref(lock);
-	lock = NULL;
-
- out:
-	strbuf_release(&ref_file);
-	errno = last_errno;
-	return lock;
-}
-
-struct ref_to_prune {
-	struct ref_to_prune *next;
-	struct object_id oid;
-	char name[FLEX_ARRAY];
-};
-
-enum {
-	REMOVE_EMPTY_PARENTS_REF = 0x01,
-	REMOVE_EMPTY_PARENTS_REFLOG = 0x02
-};
-
-/*
- * Remove empty parent directories associated with the specified
- * reference and/or its reflog, but spare [logs/]refs/ and immediate
- * subdirs. flags is a combination of REMOVE_EMPTY_PARENTS_REF and/or
- * REMOVE_EMPTY_PARENTS_REFLOG.
- */
-static void try_remove_empty_parents(struct files_ref_store *refs,
-				     const char *refname,
-				     unsigned int flags)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf sb = STRBUF_INIT;
-	char *p, *q;
-	int i;
-
-	strbuf_addstr(&buf, refname);
-	p = buf.buf;
-	for (i = 0; i < 2; i++) { /* refs/{heads,tags,...}/ */
-		while (*p && *p != '/')
-			p++;
-		/* tolerate duplicate slashes; see check_refname_format() */
-		while (*p == '/')
-			p++;
-	}
-	q = buf.buf + buf.len;
-	while (flags & (REMOVE_EMPTY_PARENTS_REF | REMOVE_EMPTY_PARENTS_REFLOG)) {
-		while (q > p && *q != '/')
-			q--;
-		while (q > p && *(q-1) == '/')
-			q--;
-		if (q == p)
-			break;
-		strbuf_setlen(&buf, q - buf.buf);
-
-		strbuf_reset(&sb);
-		files_ref_path(refs, &sb, buf.buf);
-		if ((flags & REMOVE_EMPTY_PARENTS_REF) && rmdir(sb.buf))
-			flags &= ~REMOVE_EMPTY_PARENTS_REF;
-
-		strbuf_reset(&sb);
-		files_reflog_path(refs, &sb, buf.buf);
-		if ((flags & REMOVE_EMPTY_PARENTS_REFLOG) && rmdir(sb.buf))
-			flags &= ~REMOVE_EMPTY_PARENTS_REFLOG;
-	}
-	strbuf_release(&buf);
-	strbuf_release(&sb);
-}
-
-/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
-{
-	struct ref_transaction *transaction;
-	struct strbuf err = STRBUF_INIT;
-	int ret = -1;
-
-	if (check_refname_format(r->name, 0))
-		return;
-
-	transaction = ref_store_transaction_begin(&refs->base, &err);
-	if (!transaction)
-		goto cleanup;
-	ref_transaction_add_update(
-			transaction, r->name,
-			REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,
-			&null_oid, &r->oid, NULL);
-	if (ref_transaction_commit(transaction, &err))
-		goto cleanup;
-
-	ret = 0;
-
-cleanup:
-	if (ret)
-		error("%s", err.buf);
-	strbuf_release(&err);
-	ref_transaction_free(transaction);
-	return;
-}
-
-/*
- * Prune the loose versions of the references in the linked list
- * `*refs_to_prune`, freeing the entries in the list as we go.
- */
-static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_to_prune)
-{
-	while (*refs_to_prune) {
-		struct ref_to_prune *r = *refs_to_prune;
-		*refs_to_prune = r->next;
-		prune_ref(refs, r);
-		free(r);
-	}
-}
-
-/*
- * Return true if the specified reference should be packed.
- */
-static int should_pack_ref(const char *refname,
-			   const struct object_id *oid, unsigned int ref_flags,
-			   unsigned int pack_flags)
-{
-	/* Do not pack per-worktree refs: */
-	if (ref_type(refname) != REF_TYPE_NORMAL)
-		return 0;
-
-	/* Do not pack non-tags unless PACK_REFS_ALL is set: */
-	if (!(pack_flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
-		return 0;
-
-	/* Do not pack symbolic refs: */
-	if (ref_flags & REF_ISSYMREF)
-		return 0;
-
-	/* Do not pack broken refs: */
-	if (!ref_resolves_to_object(refname, oid, ref_flags))
-		return 0;
-
-	return 1;
-}
-
-static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
-			       "pack_refs");
-	struct ref_iterator *iter;
-	int ok;
-	struct ref_to_prune *refs_to_prune = NULL;
-	struct strbuf err = STRBUF_INIT;
-	struct ref_transaction *transaction;
-
-	transaction = ref_store_transaction_begin(refs->packed_ref_store, &err);
-	if (!transaction)
-		return -1;
-
-	packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err);
-
-	iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL, 0);
-	while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
-		/*
-		 * If the loose reference can be packed, add an entry
-		 * in the packed ref cache. If the reference should be
-		 * pruned, also add it to refs_to_prune.
-		 */
-		if (!should_pack_ref(iter->refname, iter->oid, iter->flags,
-				     flags))
-			continue;
-
-		/*
-		 * Add a reference creation for this reference to the
-		 * packed-refs transaction:
-		 */
-		if (ref_transaction_update(transaction, iter->refname,
-					   iter->oid, NULL,
-					   REF_NO_DEREF, NULL, &err))
-			die("failure preparing to create packed reference %s: %s",
-			    iter->refname, err.buf);
-
-		/* Schedule the loose reference for pruning if requested. */
-		if ((flags & PACK_REFS_PRUNE)) {
-			struct ref_to_prune *n;
-			FLEX_ALLOC_STR(n, name, iter->refname);
-			oidcpy(&n->oid, iter->oid);
-			n->next = refs_to_prune;
-			refs_to_prune = n;
-		}
-	}
-	if (ok != ITER_DONE)
-		die("error while iterating over references");
-
-	if (ref_transaction_commit(transaction, &err))
-		die("unable to write new packed-refs: %s", err.buf);
-
-	ref_transaction_free(transaction);
-
-	packed_refs_unlock(refs->packed_ref_store);
-
-	prune_refs(refs, &refs_to_prune);
-	strbuf_release(&err);
-	return 0;
-}
-
-static int files_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
-	struct strbuf err = STRBUF_INIT;
-	int i, result = 0;
-
-	if (!refnames->nr)
-		return 0;
-
-	if (packed_refs_lock(refs->packed_ref_store, 0, &err))
-		goto error;
-
-	if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) {
-		packed_refs_unlock(refs->packed_ref_store);
-		goto error;
-	}
-
-	packed_refs_unlock(refs->packed_ref_store);
-
-	for (i = 0; i < refnames->nr; i++) {
-		const char *refname = refnames->items[i].string;
-
-		if (refs_delete_ref(&refs->base, msg, refname, NULL, flags))
-			result |= error(_("could not remove reference %s"), refname);
-	}
-
-	strbuf_release(&err);
-	return result;
-
-error:
-	/*
-	 * If we failed to rewrite the packed-refs file, then it is
-	 * unsafe to try to remove loose refs, because doing so might
-	 * expose an obsolete packed value for a reference that might
-	 * even point at an object that has been garbage collected.
-	 */
-	if (refnames->nr == 1)
-		error(_("could not delete reference %s: %s"),
-		      refnames->items[0].string, err.buf);
-	else
-		error(_("could not delete references: %s"), err.buf);
-
-	strbuf_release(&err);
-	return -1;
-}
-
-/*
- * People using contrib's git-new-workdir have .git/logs/refs ->
- * /some/other/path/.git/logs/refs, and that may live on another device.
- *
- * IOW, to avoid cross device rename errors, the temporary renamed log must
- * live into logs/refs.
- */
-#define TMP_RENAMED_LOG  "refs/.tmp-renamed-log"
-
-struct rename_cb {
-	const char *tmp_renamed_log;
-	int true_errno;
-};
-
-static int rename_tmp_log_callback(const char *path, void *cb_data)
-{
-	struct rename_cb *cb = cb_data;
-
-	if (rename(cb->tmp_renamed_log, path)) {
-		/*
-		 * rename(a, b) when b is an existing directory ought
-		 * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
-		 * Sheesh. Record the true errno for error reporting,
-		 * but report EISDIR to raceproof_create_file() so
-		 * that it knows to retry.
-		 */
-		cb->true_errno = errno;
-		if (errno == ENOTDIR)
-			errno = EISDIR;
-		return -1;
-	} else {
-		return 0;
-	}
-}
-
-static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
-{
-	struct strbuf path = STRBUF_INIT;
-	struct strbuf tmp = STRBUF_INIT;
-	struct rename_cb cb;
-	int ret;
-
-	files_reflog_path(refs, &path, newrefname);
-	files_reflog_path(refs, &tmp, TMP_RENAMED_LOG);
-	cb.tmp_renamed_log = tmp.buf;
-	ret = raceproof_create_file(path.buf, rename_tmp_log_callback, &cb);
-	if (ret) {
-		if (errno == EISDIR)
-			error("directory not empty: %s", path.buf);
-		else
-			error("unable to move logfile %s to %s: %s",
-			      tmp.buf, path.buf,
-			      strerror(cb.true_errno));
-	}
-
-	strbuf_release(&path);
-	strbuf_release(&tmp);
-	return ret;
-}
-
-static int write_ref_to_lockfile(struct ref_lock *lock,
-				 const struct object_id *oid, struct strbuf *err);
-static int commit_ref_update(struct files_ref_store *refs,
-			     struct ref_lock *lock,
-			     const struct object_id *oid, const char *logmsg,
-			     struct strbuf *err);
-
-static int files_copy_or_rename_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg, int copy)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
-	struct object_id orig_oid;
-	int flag = 0, logmoved = 0;
-	struct ref_lock *lock;
-	struct stat loginfo;
-	struct strbuf sb_oldref = STRBUF_INIT;
-	struct strbuf sb_newref = STRBUF_INIT;
-	struct strbuf tmp_renamed_log = STRBUF_INIT;
-	int log, ret;
-	struct strbuf err = STRBUF_INIT;
-
-	files_reflog_path(refs, &sb_oldref, oldrefname);
-	files_reflog_path(refs, &sb_newref, newrefname);
-	files_reflog_path(refs, &tmp_renamed_log, TMP_RENAMED_LOG);
-
-	log = !lstat(sb_oldref.buf, &loginfo);
-	if (log && S_ISLNK(loginfo.st_mode)) {
-		ret = error("reflog for %s is a symlink", oldrefname);
-		goto out;
-	}
-
-	if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
-				     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				&orig_oid, &flag)) {
-		ret = error("refname %s not found", oldrefname);
-		goto out;
-	}
-
-	if (flag & REF_ISSYMREF) {
-		if (copy)
-			ret = error("refname %s is a symbolic ref, copying it is not supported",
-				    oldrefname);
-		else
-			ret = error("refname %s is a symbolic ref, renaming it is not supported",
-				    oldrefname);
-		goto out;
-	}
-	if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname)) {
-		ret = 1;
-		goto out;
-	}
-
-	if (!copy && log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
-		ret = error("unable to move logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
-			    oldrefname, strerror(errno));
-		goto out;
-	}
-
-	if (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {
-		ret = error("unable to copy logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
-			    oldrefname, strerror(errno));
-		goto out;
-	}
-
-	if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname,
-			    &orig_oid, REF_NO_DEREF)) {
-		error("unable to delete old %s", oldrefname);
-		goto rollback;
-	}
-
-	/*
-	 * Since we are doing a shallow lookup, oid is not the
-	 * correct value to pass to delete_ref as old_oid. But that
-	 * doesn't matter, because an old_oid check wouldn't add to
-	 * the safety anyway; we want to delete the reference whatever
-	 * its current value.
-	 */
-	if (!copy && !refs_read_ref_full(&refs->base, newrefname,
-				RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				NULL, NULL) &&
-	    refs_delete_ref(&refs->base, NULL, newrefname,
-			    NULL, REF_NO_DEREF)) {
-		if (errno == EISDIR) {
-			struct strbuf path = STRBUF_INIT;
-			int result;
-
-			files_ref_path(refs, &path, newrefname);
-			result = remove_empty_directories(&path);
-			strbuf_release(&path);
-
-			if (result) {
-				error("Directory not empty: %s", newrefname);
-				goto rollback;
-			}
-		} else {
-			error("unable to delete existing %s", newrefname);
-			goto rollback;
-		}
-	}
-
-	if (log && rename_tmp_log(refs, newrefname))
-		goto rollback;
-
-	logmoved = log;
-
-	lock = lock_ref_oid_basic(refs, newrefname, NULL, NULL, NULL,
-				  REF_NO_DEREF, NULL, &err);
-	if (!lock) {
-		if (copy)
-			error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
-		else
-			error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
-		strbuf_release(&err);
-		goto rollback;
-	}
-	oidcpy(&lock->old_oid, &orig_oid);
-
-	if (write_ref_to_lockfile(lock, &orig_oid, &err) ||
-	    commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {
-		error("unable to write current sha1 into %s: %s", newrefname, err.buf);
-		strbuf_release(&err);
-		goto rollback;
-	}
-
-	ret = 0;
-	goto out;
-
- rollback:
-	lock = lock_ref_oid_basic(refs, oldrefname, NULL, NULL, NULL,
-				  REF_NO_DEREF, NULL, &err);
-	if (!lock) {
-		error("unable to lock %s for rollback: %s", oldrefname, err.buf);
-		strbuf_release(&err);
-		goto rollbacklog;
-	}
-
-	flag = log_all_ref_updates;
-	log_all_ref_updates = LOG_REFS_NONE;
-	if (write_ref_to_lockfile(lock, &orig_oid, &err) ||
-	    commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {
-		error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
-		strbuf_release(&err);
-	}
-	log_all_ref_updates = flag;
-
- rollbacklog:
-	if (logmoved && rename(sb_newref.buf, sb_oldref.buf))
-		error("unable to restore logfile %s from %s: %s",
-			oldrefname, newrefname, strerror(errno));
-	if (!logmoved && log &&
-	    rename(tmp_renamed_log.buf, sb_oldref.buf))
-		error("unable to restore logfile %s from logs/"TMP_RENAMED_LOG": %s",
-			oldrefname, strerror(errno));
-	ret = 1;
- out:
-	strbuf_release(&sb_newref);
-	strbuf_release(&sb_oldref);
-	strbuf_release(&tmp_renamed_log);
-
-	return ret;
-}
-
-static int files_rename_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
-{
-	return files_copy_or_rename_ref(ref_store, oldrefname,
-				 newrefname, logmsg, 0);
-}
-
-static int files_copy_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
-{
-	return files_copy_or_rename_ref(ref_store, oldrefname,
-				 newrefname, logmsg, 1);
-}
-
-static int close_ref_gently(struct ref_lock *lock)
-{
-	if (close_lock_file_gently(&lock->lk))
-		return -1;
-	return 0;
-}
-
-static int commit_ref(struct ref_lock *lock)
-{
-	char *path = get_locked_file_path(&lock->lk);
-	struct stat st;
-
-	if (!lstat(path, &st) && S_ISDIR(st.st_mode)) {
-		/*
-		 * There is a directory at the path we want to rename
-		 * the lockfile to. Hopefully it is empty; try to
-		 * delete it.
-		 */
-		size_t len = strlen(path);
-		struct strbuf sb_path = STRBUF_INIT;
-
-		strbuf_attach(&sb_path, path, len, len);
-
-		/*
-		 * If this fails, commit_lock_file() will also fail
-		 * and will report the problem.
-		 */
-		remove_empty_directories(&sb_path);
-		strbuf_release(&sb_path);
-	} else {
-		free(path);
-	}
-
-	if (commit_lock_file(&lock->lk))
-		return -1;
-	return 0;
-}
-
-static int open_or_create_logfile(const char *path, void *cb)
-{
-	int *fd = cb;
-
-	*fd = open(path, O_APPEND | O_WRONLY | O_CREAT, 0666);
-	return (*fd < 0) ? -1 : 0;
-}
-
-/*
- * Create a reflog for a ref. If force_create = 0, only create the
- * reflog for certain refs (those for which should_autocreate_reflog
- * returns non-zero). Otherwise, create it regardless of the reference
- * name. If the logfile already existed or was created, return 0 and
- * set *logfd to the file descriptor opened for appending to the file.
- * If no logfile exists and we decided not to create one, return 0 and
- * set *logfd to -1. On failure, fill in *err, set *logfd to -1, and
- * return -1.
- */
-static int log_ref_setup(struct files_ref_store *refs,
-			 const char *refname, int force_create,
-			 int *logfd, struct strbuf *err)
-{
-	struct strbuf logfile_sb = STRBUF_INIT;
-	char *logfile;
-
-	files_reflog_path(refs, &logfile_sb, refname);
-	logfile = strbuf_detach(&logfile_sb, NULL);
-
-	if (force_create || should_autocreate_reflog(refname)) {
-		if (raceproof_create_file(logfile, open_or_create_logfile, logfd)) {
-			if (errno == ENOENT)
-				strbuf_addf(err, "unable to create directory for '%s': "
-					    "%s", logfile, strerror(errno));
-			else if (errno == EISDIR)
-				strbuf_addf(err, "there are still logs under '%s'",
-					    logfile);
-			else
-				strbuf_addf(err, "unable to append to '%s': %s",
-					    logfile, strerror(errno));
-
-			goto error;
-		}
-	} else {
-		*logfd = open(logfile, O_APPEND | O_WRONLY, 0666);
-		if (*logfd < 0) {
-			if (errno == ENOENT || errno == EISDIR) {
-				/*
-				 * The logfile doesn't already exist,
-				 * but that is not an error; it only
-				 * means that we won't write log
-				 * entries to it.
-				 */
-				;
-			} else {
-				strbuf_addf(err, "unable to append to '%s': %s",
-					    logfile, strerror(errno));
-				goto error;
-			}
-		}
-	}
-
-	if (*logfd >= 0)
-		adjust_shared_perm(logfile);
-
-	free(logfile);
-	return 0;
-
-error:
-	free(logfile);
-	return -1;
-}
-
-static int files_create_reflog(struct ref_store *ref_store,
-			       const char *refname, int force_create,
-			       struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "create_reflog");
-	int fd;
-
-	if (log_ref_setup(refs, refname, force_create, &fd, err))
-		return -1;
-
-	if (fd >= 0)
-		close(fd);
-
-	return 0;
-}
-
-static int log_ref_write_fd(int fd, const struct object_id *old_oid,
-			    const struct object_id *new_oid,
-			    const char *committer, const char *msg)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int ret = 0;
-
-	strbuf_addf(&sb, "%s %s %s", oid_to_hex(old_oid), oid_to_hex(new_oid), committer);
-	if (msg && *msg) {
-		strbuf_addch(&sb, '\t');
-		strbuf_addstr(&sb, msg);
-	}
-	strbuf_addch(&sb, '\n');
-	if (write_in_full(fd, sb.buf, sb.len) < 0)
-		ret = -1;
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int files_log_ref_write(struct files_ref_store *refs,
-			       const char *refname, const struct object_id *old_oid,
-			       const struct object_id *new_oid, const char *msg,
-			       int flags, struct strbuf *err)
-{
-	int logfd, result;
-
-	if (log_all_ref_updates == LOG_REFS_UNSET)
-		log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
-
-	result = log_ref_setup(refs, refname,
-			       flags & REF_FORCE_CREATE_REFLOG,
-			       &logfd, err);
-
-	if (result)
-		return result;
-
-	if (logfd < 0)
-		return 0;
-	result = log_ref_write_fd(logfd, old_oid, new_oid,
-				  git_committer_info(0), msg);
-	if (result) {
-		struct strbuf sb = STRBUF_INIT;
-		int save_errno = errno;
-
-		files_reflog_path(refs, &sb, refname);
-		strbuf_addf(err, "unable to append to '%s': %s",
-			    sb.buf, strerror(save_errno));
-		strbuf_release(&sb);
-		close(logfd);
-		return -1;
-	}
-	if (close(logfd)) {
-		struct strbuf sb = STRBUF_INIT;
-		int save_errno = errno;
-
-		files_reflog_path(refs, &sb, refname);
-		strbuf_addf(err, "unable to append to '%s': %s",
-			    sb.buf, strerror(save_errno));
-		strbuf_release(&sb);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * Write oid into the open lockfile, then close the lockfile. On
- * errors, rollback the lockfile, fill in *err and return -1.
- */
-static int write_ref_to_lockfile(struct ref_lock *lock,
-				 const struct object_id *oid, struct strbuf *err)
-{
-	static char term = '\n';
-	struct object *o;
-	int fd;
-
-	o = parse_object(the_repository, oid);
-	if (!o) {
-		strbuf_addf(err,
-			    "trying to write ref '%s' with nonexistent object %s",
-			    lock->ref_name, oid_to_hex(oid));
-		unlock_ref(lock);
-		return -1;
-	}
-	if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
-		strbuf_addf(err,
-			    "trying to write non-commit object %s to branch '%s'",
-			    oid_to_hex(oid), lock->ref_name);
-		unlock_ref(lock);
-		return -1;
-	}
-	fd = get_lock_file_fd(&lock->lk);
-	if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
-	    write_in_full(fd, &term, 1) < 0 ||
-	    close_ref_gently(lock) < 0) {
-		strbuf_addf(err,
-			    "couldn't write '%s'", get_lock_file_path(&lock->lk));
-		unlock_ref(lock);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * Commit a change to a loose reference that has already been written
- * to the loose reference lockfile. Also update the reflogs if
- * necessary, using the specified lockmsg (which can be NULL).
- */
-static int commit_ref_update(struct files_ref_store *refs,
-			     struct ref_lock *lock,
-			     const struct object_id *oid, const char *logmsg,
-			     struct strbuf *err)
-{
-	files_assert_main_repository(refs, "commit_ref_update");
-
-	clear_loose_ref_cache(refs);
-	if (files_log_ref_write(refs, lock->ref_name,
-				&lock->old_oid, oid,
-				logmsg, 0, err)) {
-		char *old_msg = strbuf_detach(err, NULL);
-		strbuf_addf(err, "cannot update the ref '%s': %s",
-			    lock->ref_name, old_msg);
-		free(old_msg);
-		unlock_ref(lock);
-		return -1;
-	}
-
-	if (strcmp(lock->ref_name, "HEAD") != 0) {
-		/*
-		 * Special hack: If a branch is updated directly and HEAD
-		 * points to it (may happen on the remote side of a push
-		 * for example) then logically the HEAD reflog should be
-		 * updated too.
-		 * A generic solution implies reverse symref information,
-		 * but finding all symrefs pointing to the given branch
-		 * would be rather costly for this rare event (the direct
-		 * update of a branch) to be worth it.  So let's cheat and
-		 * check with HEAD only which should cover 99% of all usage
-		 * scenarios (even 100% of the default ones).
-		 */
-		int head_flag;
-		const char *head_ref;
-
-		head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
-						   RESOLVE_REF_READING,
-						   NULL, &head_flag);
-		if (head_ref && (head_flag & REF_ISSYMREF) &&
-		    !strcmp(head_ref, lock->ref_name)) {
-			struct strbuf log_err = STRBUF_INIT;
-			if (files_log_ref_write(refs, "HEAD",
-						&lock->old_oid, oid,
-						logmsg, 0, &log_err)) {
-				error("%s", log_err.buf);
-				strbuf_release(&log_err);
-			}
-		}
-	}
-
-	if (commit_ref(lock)) {
-		strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
-		unlock_ref(lock);
-		return -1;
-	}
-
-	unlock_ref(lock);
-	return 0;
-}
-
-static int create_ref_symlink(struct ref_lock *lock, const char *target)
-{
-	int ret = -1;
-#ifndef NO_SYMLINK_HEAD
-	char *ref_path = get_locked_file_path(&lock->lk);
-	unlink(ref_path);
-	ret = symlink(target, ref_path);
-	free(ref_path);
-
-	if (ret)
-		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
-#endif
-	return ret;
-}
-
-static void update_symref_reflog(struct files_ref_store *refs,
-				 struct ref_lock *lock, const char *refname,
-				 const char *target, const char *logmsg)
-{
-	struct strbuf err = STRBUF_INIT;
-	struct object_id new_oid;
-	if (logmsg &&
-	    !refs_read_ref_full(&refs->base, target,
-				RESOLVE_REF_READING, &new_oid, NULL) &&
-	    files_log_ref_write(refs, refname, &lock->old_oid,
-				&new_oid, logmsg, 0, &err)) {
-		error("%s", err.buf);
-		strbuf_release(&err);
-	}
-}
-
-static int create_symref_locked(struct files_ref_store *refs,
-				struct ref_lock *lock, const char *refname,
-				const char *target, const char *logmsg)
-{
-	if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
-		update_symref_reflog(refs, lock, refname, target, logmsg);
-		return 0;
-	}
-
-	if (!fdopen_lock_file(&lock->lk, "w"))
-		return error("unable to fdopen %s: %s",
-			     lock->lk.tempfile->filename.buf, strerror(errno));
-
-	update_symref_reflog(refs, lock, refname, target, logmsg);
-
-	/* no error check; commit_ref will check ferror */
-	fprintf(lock->lk.tempfile->fp, "ref: %s\n", target);
-	if (commit_ref(lock) < 0)
-		return error("unable to write symref for %s: %s", refname,
-			     strerror(errno));
-	return 0;
-}
-
-static int files_create_symref(struct ref_store *ref_store,
-			       const char *refname, const char *target,
-			       const char *logmsg)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "create_symref");
-	struct strbuf err = STRBUF_INIT;
-	struct ref_lock *lock;
-	int ret;
-
-	lock = lock_ref_oid_basic(refs, refname, NULL,
-				  NULL, NULL, REF_NO_DEREF, NULL,
-				  &err);
-	if (!lock) {
-		error("%s", err.buf);
-		strbuf_release(&err);
-		return -1;
-	}
-
-	ret = create_symref_locked(refs, lock, refname, target, logmsg);
-	unlock_ref(lock);
-	return ret;
-}
-
-static int files_reflog_exists(struct ref_store *ref_store,
-			       const char *refname)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ, "reflog_exists");
-	struct strbuf sb = STRBUF_INIT;
-	struct stat st;
-	int ret;
-
-	files_reflog_path(refs, &sb, refname);
-	ret = !lstat(sb.buf, &st) && S_ISREG(st.st_mode);
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int files_delete_reflog(struct ref_store *ref_store,
-			       const char *refname)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "delete_reflog");
-	struct strbuf sb = STRBUF_INIT;
-	int ret;
-
-	files_reflog_path(refs, &sb, refname);
-	ret = remove_path(sb.buf);
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int show_one_reflog_ent(struct strbuf *sb, each_reflog_ent_fn fn, void *cb_data)
-{
-	struct object_id ooid, noid;
-	char *email_end, *message;
-	timestamp_t timestamp;
-	int tz;
-	const char *p = sb->buf;
-
-	/* old SP new SP name <email> SP time TAB msg LF */
-	if (!sb->len || sb->buf[sb->len - 1] != '\n' ||
-	    parse_oid_hex(p, &ooid, &p) || *p++ != ' ' ||
-	    parse_oid_hex(p, &noid, &p) || *p++ != ' ' ||
-	    !(email_end = strchr(p, '>')) ||
-	    email_end[1] != ' ' ||
-	    !(timestamp = parse_timestamp(email_end + 2, &message, 10)) ||
-	    !message || message[0] != ' ' ||
-	    (message[1] != '+' && message[1] != '-') ||
-	    !isdigit(message[2]) || !isdigit(message[3]) ||
-	    !isdigit(message[4]) || !isdigit(message[5]))
-		return 0; /* corrupt? */
-	email_end[1] = '\0';
-	tz = strtol(message + 1, NULL, 10);
-	if (message[6] != '\t')
-		message += 6;
-	else
-		message += 7;
-	return fn(&ooid, &noid, p, timestamp, tz, message, cb_data);
-}
-
-static char *find_beginning_of_line(char *bob, char *scan)
-{
-	while (bob < scan && *(--scan) != '\n')
-		; /* keep scanning backwards */
-	/*
-	 * Return either beginning of the buffer, or LF at the end of
-	 * the previous line.
-	 */
-	return scan;
-}
-
-static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
-					     const char *refname,
-					     each_reflog_ent_fn fn,
-					     void *cb_data)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ,
-			       "for_each_reflog_ent_reverse");
-	struct strbuf sb = STRBUF_INIT;
-	FILE *logfp;
-	long pos;
-	int ret = 0, at_tail = 1;
-
-	files_reflog_path(refs, &sb, refname);
-	logfp = fopen(sb.buf, "r");
-	strbuf_release(&sb);
-	if (!logfp)
-		return -1;
-
-	/* Jump to the end */
-	if (fseek(logfp, 0, SEEK_END) < 0)
-		ret = error("cannot seek back reflog for %s: %s",
-			    refname, strerror(errno));
-	pos = ftell(logfp);
-	while (!ret && 0 < pos) {
-		int cnt;
-		size_t nread;
-		char buf[BUFSIZ];
-		char *endp, *scanp;
-
-		/* Fill next block from the end */
-		cnt = (sizeof(buf) < pos) ? sizeof(buf) : pos;
-		if (fseek(logfp, pos - cnt, SEEK_SET)) {
-			ret = error("cannot seek back reflog for %s: %s",
-				    refname, strerror(errno));
-			break;
-		}
-		nread = fread(buf, cnt, 1, logfp);
-		if (nread != 1) {
-			ret = error("cannot read %d bytes from reflog for %s: %s",
-				    cnt, refname, strerror(errno));
-			break;
-		}
-		pos -= cnt;
-
-		scanp = endp = buf + cnt;
-		if (at_tail && scanp[-1] == '\n')
-			/* Looking at the final LF at the end of the file */
-			scanp--;
-		at_tail = 0;
-
-		while (buf < scanp) {
-			/*
-			 * terminating LF of the previous line, or the beginning
-			 * of the buffer.
-			 */
-			char *bp;
-
-			bp = find_beginning_of_line(buf, scanp);
-
-			if (*bp == '\n') {
-				/*
-				 * The newline is the end of the previous line,
-				 * so we know we have complete line starting
-				 * at (bp + 1). Prefix it onto any prior data
-				 * we collected for the line and process it.
-				 */
-				strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
-				scanp = bp;
-				endp = bp + 1;
-				ret = show_one_reflog_ent(&sb, fn, cb_data);
-				strbuf_reset(&sb);
-				if (ret)
-					break;
-			} else if (!pos) {
-				/*
-				 * We are at the start of the buffer, and the
-				 * start of the file; there is no previous
-				 * line, and we have everything for this one.
-				 * Process it, and we can end the loop.
-				 */
-				strbuf_splice(&sb, 0, 0, buf, endp - buf);
-				ret = show_one_reflog_ent(&sb, fn, cb_data);
-				strbuf_reset(&sb);
-				break;
-			}
-
-			if (bp == buf) {
-				/*
-				 * We are at the start of the buffer, and there
-				 * is more file to read backwards. Which means
-				 * we are in the middle of a line. Note that we
-				 * may get here even if *bp was a newline; that
-				 * just means we are at the exact end of the
-				 * previous line, rather than some spot in the
-				 * middle.
-				 *
-				 * Save away what we have to be combined with
-				 * the data from the next read.
-				 */
-				strbuf_splice(&sb, 0, 0, buf, endp - buf);
-				break;
-			}
-		}
-
-	}
-	if (!ret && sb.len)
-		BUG("reverse reflog parser had leftover data");
-
-	fclose(logfp);
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int files_for_each_reflog_ent(struct ref_store *ref_store,
-				     const char *refname,
-				     each_reflog_ent_fn fn, void *cb_data)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ,
-			       "for_each_reflog_ent");
-	FILE *logfp;
-	struct strbuf sb = STRBUF_INIT;
-	int ret = 0;
-
-	files_reflog_path(refs, &sb, refname);
-	logfp = fopen(sb.buf, "r");
-	strbuf_release(&sb);
-	if (!logfp)
-		return -1;
-
-	while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
-		ret = show_one_reflog_ent(&sb, fn, cb_data);
-	fclose(logfp);
-	strbuf_release(&sb);
-	return ret;
-}
-
-struct files_reflog_iterator {
-	struct ref_iterator base;
-
-	struct ref_store *ref_store;
-	struct dir_iterator *dir_iterator;
-	struct object_id oid;
-};
-
-static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct files_reflog_iterator *iter =
-		(struct files_reflog_iterator *)ref_iterator;
-	struct dir_iterator *diter = iter->dir_iterator;
-	int ok;
-
-	while ((ok = dir_iterator_advance(diter)) == ITER_OK) {
-		int flags;
-
-		if (!S_ISREG(diter->st.st_mode))
-			continue;
-		if (diter->basename[0] == '.')
-			continue;
-		if (ends_with(diter->basename, ".lock"))
-			continue;
-
-		if (refs_read_ref_full(iter->ref_store,
-				       diter->relative_path, 0,
-				       &iter->oid, &flags)) {
-			error("bad ref for %s", diter->path.buf);
-			continue;
-		}
-
-		iter->base.refname = diter->relative_path;
-		iter->base.oid = &iter->oid;
-		iter->base.flags = flags;
-		return ITER_OK;
-	}
-
-	iter->dir_iterator = NULL;
-	if (ref_iterator_abort(ref_iterator) == ITER_ERROR)
-		ok = ITER_ERROR;
-	return ok;
-}
-
-static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	BUG("ref_iterator_peel() called for reflog_iterator");
-}
-
-static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct files_reflog_iterator *iter =
-		(struct files_reflog_iterator *)ref_iterator;
-	int ok = ITER_DONE;
-
-	if (iter->dir_iterator)
-		ok = dir_iterator_abort(iter->dir_iterator);
-
-	base_ref_iterator_free(ref_iterator);
-	return ok;
-}
-
-static struct ref_iterator_vtable files_reflog_iterator_vtable = {
-	files_reflog_iterator_advance,
-	files_reflog_iterator_peel,
-	files_reflog_iterator_abort
-};
-
-static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
-						  const char *gitdir)
-{
-	struct dir_iterator *diter;
-	struct files_reflog_iterator *iter;
-	struct ref_iterator *ref_iterator;
-	struct strbuf sb = STRBUF_INIT;
-
-	strbuf_addf(&sb, "%s/logs", gitdir);
-
-	diter = dir_iterator_begin(sb.buf, 0);
-	if (!diter) {
-		strbuf_release(&sb);
-		return empty_ref_iterator_begin();
-	}
-
-	iter = xcalloc(1, sizeof(*iter));
-	ref_iterator = &iter->base;
-
-	base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0);
-	iter->dir_iterator = diter;
-	iter->ref_store = ref_store;
-	strbuf_release(&sb);
-
-	return ref_iterator;
-}
-
-static enum iterator_selection reflog_iterator_select(
-	struct ref_iterator *iter_worktree,
-	struct ref_iterator *iter_common,
-	void *cb_data)
-{
-	if (iter_worktree) {
-		/*
-		 * We're a bit loose here. We probably should ignore
-		 * common refs if they are accidentally added as
-		 * per-worktree refs.
-		 */
-		return ITER_SELECT_0;
-	} else if (iter_common) {
-		if (ref_type(iter_common->refname) == REF_TYPE_NORMAL)
-			return ITER_SELECT_1;
-
-		/*
-		 * The main ref store may contain main worktree's
-		 * per-worktree refs, which should be ignored
-		 */
-		return ITER_SKIP_1;
-	} else
-		return ITER_DONE;
-}
-
-static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_READ,
-			       "reflog_iterator_begin");
-
-	if (!strcmp(refs->base.gitdir, refs->gitcommondir)) {
-		return reflog_iterator_begin(ref_store, refs->gitcommondir);
-	} else {
-		return merge_ref_iterator_begin(
-			0, reflog_iterator_begin(ref_store, refs->base.gitdir),
-			reflog_iterator_begin(ref_store, refs->gitcommondir),
-			reflog_iterator_select, refs);
-	}
-}
-
-/*
- * If update is a direct update of head_ref (the reference pointed to
- * by HEAD), then add an extra REF_LOG_ONLY update for HEAD.
- */
-static int split_head_update(struct ref_update *update,
-			     struct ref_transaction *transaction,
-			     const char *head_ref,
-			     struct string_list *affected_refnames,
-			     struct strbuf *err)
-{
-	struct string_list_item *item;
-	struct ref_update *new_update;
-
-	if ((update->flags & REF_LOG_ONLY) ||
-	    (update->flags & REF_IS_PRUNING) ||
-	    (update->flags & REF_UPDATE_VIA_HEAD))
-		return 0;
-
-	if (strcmp(update->refname, head_ref))
-		return 0;
-
-	/*
-	 * First make sure that HEAD is not already in the
-	 * transaction. This check is O(lg N) in the transaction
-	 * size, but it happens at most once per transaction.
-	 */
-	if (string_list_has_string(affected_refnames, "HEAD")) {
-		/* An entry already existed */
-		strbuf_addf(err,
-			    "multiple updates for 'HEAD' (including one "
-			    "via its referent '%s') are not allowed",
-			    update->refname);
-		return TRANSACTION_NAME_CONFLICT;
-	}
-
-	new_update = ref_transaction_add_update(
-			transaction, "HEAD",
-			update->flags | REF_LOG_ONLY | REF_NO_DEREF,
-			&update->new_oid, &update->old_oid,
-			update->msg);
-
-	/*
-	 * Add "HEAD". This insertion is O(N) in the transaction
-	 * size, but it happens at most once per transaction.
-	 * Add new_update->refname instead of a literal "HEAD".
-	 */
-	if (strcmp(new_update->refname, "HEAD"))
-		BUG("%s unexpectedly not 'HEAD'", new_update->refname);
-	item = string_list_insert(affected_refnames, new_update->refname);
-	item->util = new_update;
-
-	return 0;
-}
-
-/*
- * update is for a symref that points at referent and doesn't have
- * REF_NO_DEREF set. Split it into two updates:
- * - The original update, but with REF_LOG_ONLY and REF_NO_DEREF set
- * - A new, separate update for the referent reference
- * Note that the new update will itself be subject to splitting when
- * the iteration gets to it.
- */
-static int split_symref_update(struct ref_update *update,
-			       const char *referent,
-			       struct ref_transaction *transaction,
-			       struct string_list *affected_refnames,
-			       struct strbuf *err)
-{
-	struct string_list_item *item;
-	struct ref_update *new_update;
-	unsigned int new_flags;
-
-	/*
-	 * First make sure that referent is not already in the
-	 * transaction. This check is O(lg N) in the transaction
-	 * size, but it happens at most once per symref in a
-	 * transaction.
-	 */
-	if (string_list_has_string(affected_refnames, referent)) {
-		/* An entry already exists */
-		strbuf_addf(err,
-			    "multiple updates for '%s' (including one "
-			    "via symref '%s') are not allowed",
-			    referent, update->refname);
-		return TRANSACTION_NAME_CONFLICT;
-	}
-
-	new_flags = update->flags;
-	if (!strcmp(update->refname, "HEAD")) {
-		/*
-		 * Record that the new update came via HEAD, so that
-		 * when we process it, split_head_update() doesn't try
-		 * to add another reflog update for HEAD. Note that
-		 * this bit will be propagated if the new_update
-		 * itself needs to be split.
-		 */
-		new_flags |= REF_UPDATE_VIA_HEAD;
-	}
-
-	new_update = ref_transaction_add_update(
-			transaction, referent, new_flags,
-			&update->new_oid, &update->old_oid,
-			update->msg);
-
-	new_update->parent_update = update;
-
-	/*
-	 * Change the symbolic ref update to log only. Also, it
-	 * doesn't need to check its old OID value, as that will be
-	 * done when new_update is processed.
-	 */
-	update->flags |= REF_LOG_ONLY | REF_NO_DEREF;
-	update->flags &= ~REF_HAVE_OLD;
-
-	/*
-	 * Add the referent. This insertion is O(N) in the transaction
-	 * size, but it happens at most once per symref in a
-	 * transaction. Make sure to add new_update->refname, which will
-	 * be valid as long as affected_refnames is in use, and NOT
-	 * referent, which might soon be freed by our caller.
-	 */
-	item = string_list_insert(affected_refnames, new_update->refname);
-	if (item->util)
-		BUG("%s unexpectedly found in affected_refnames",
-		    new_update->refname);
-	item->util = new_update;
-
-	return 0;
-}
-
-/*
- * Return the refname under which update was originally requested.
- */
-static const char *original_update_refname(struct ref_update *update)
-{
-	while (update->parent_update)
-		update = update->parent_update;
-
-	return update->refname;
-}
-
-/*
- * Check whether the REF_HAVE_OLD and old_oid values stored in update
- * are consistent with oid, which is the reference's current value. If
- * everything is OK, return 0; otherwise, write an error message to
- * err and return -1.
- */
-static int check_old_oid(struct ref_update *update, struct object_id *oid,
-			 struct strbuf *err)
-{
-	if (!(update->flags & REF_HAVE_OLD) ||
-		   oideq(oid, &update->old_oid))
-		return 0;
-
-	if (is_null_oid(&update->old_oid))
-		strbuf_addf(err, "cannot lock ref '%s': "
-			    "reference already exists",
-			    original_update_refname(update));
-	else if (is_null_oid(oid))
-		strbuf_addf(err, "cannot lock ref '%s': "
-			    "reference is missing but expected %s",
-			    original_update_refname(update),
-			    oid_to_hex(&update->old_oid));
-	else
-		strbuf_addf(err, "cannot lock ref '%s': "
-			    "is at %s but expected %s",
-			    original_update_refname(update),
-			    oid_to_hex(oid),
-			    oid_to_hex(&update->old_oid));
-
-	return -1;
-}
-
-/*
- * Prepare for carrying out update:
- * - Lock the reference referred to by update.
- * - Read the reference under lock.
- * - Check that its old OID value (if specified) is correct, and in
- *   any case record it in update->lock->old_oid for later use when
- *   writing the reflog.
- * - If it is a symref update without REF_NO_DEREF, split it up into a
- *   REF_LOG_ONLY update of the symref and add a separate update for
- *   the referent to transaction.
- * - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
- *   update of HEAD.
- */
-static int lock_ref_for_update(struct files_ref_store *refs,
-			       struct ref_update *update,
-			       struct ref_transaction *transaction,
-			       const char *head_ref,
-			       struct string_list *affected_refnames,
-			       struct strbuf *err)
-{
-	struct strbuf referent = STRBUF_INIT;
-	int mustexist = (update->flags & REF_HAVE_OLD) &&
-		!is_null_oid(&update->old_oid);
-	int ret = 0;
-	struct ref_lock *lock;
-
-	files_assert_main_repository(refs, "lock_ref_for_update");
-
-	if ((update->flags & REF_HAVE_NEW) && is_null_oid(&update->new_oid))
-		update->flags |= REF_DELETING;
-
-	if (head_ref) {
-		ret = split_head_update(update, transaction, head_ref,
-					affected_refnames, err);
-		if (ret)
-			goto out;
-	}
-
-	ret = lock_raw_ref(refs, update->refname, mustexist,
-			   affected_refnames, NULL,
-			   &lock, &referent,
-			   &update->type, err);
-	if (ret) {
-		char *reason;
-
-		reason = strbuf_detach(err, NULL);
-		strbuf_addf(err, "cannot lock ref '%s': %s",
-			    original_update_refname(update), reason);
-		free(reason);
-		goto out;
-	}
-
-	update->backend_data = lock;
-
-	if (update->type & REF_ISSYMREF) {
-		if (update->flags & REF_NO_DEREF) {
-			/*
-			 * We won't be reading the referent as part of
-			 * the transaction, so we have to read it here
-			 * to record and possibly check old_oid:
-			 */
-			if (refs_read_ref_full(&refs->base,
-					       referent.buf, 0,
-					       &lock->old_oid, NULL)) {
-				if (update->flags & REF_HAVE_OLD) {
-					strbuf_addf(err, "cannot lock ref '%s': "
-						    "error reading reference",
-						    original_update_refname(update));
-					ret = TRANSACTION_GENERIC_ERROR;
-					goto out;
-				}
-			} else if (check_old_oid(update, &lock->old_oid, err)) {
-				ret = TRANSACTION_GENERIC_ERROR;
-				goto out;
-			}
-		} else {
-			/*
-			 * Create a new update for the reference this
-			 * symref is pointing at. Also, we will record
-			 * and verify old_oid for this update as part
-			 * of processing the split-off update, so we
-			 * don't have to do it here.
-			 */
-			ret = split_symref_update(update,
-						  referent.buf, transaction,
-						  affected_refnames, err);
-			if (ret)
-				goto out;
-		}
-	} else {
-		struct ref_update *parent_update;
-
-		if (check_old_oid(update, &lock->old_oid, err)) {
-			ret = TRANSACTION_GENERIC_ERROR;
-			goto out;
-		}
-
-		/*
-		 * If this update is happening indirectly because of a
-		 * symref update, record the old OID in the parent
-		 * update:
-		 */
-		for (parent_update = update->parent_update;
-		     parent_update;
-		     parent_update = parent_update->parent_update) {
-			struct ref_lock *parent_lock = parent_update->backend_data;
-			oidcpy(&parent_lock->old_oid, &lock->old_oid);
-		}
-	}
-
-	if ((update->flags & REF_HAVE_NEW) &&
-	    !(update->flags & REF_DELETING) &&
-	    !(update->flags & REF_LOG_ONLY)) {
-		if (!(update->type & REF_ISSYMREF) &&
-		    oideq(&lock->old_oid, &update->new_oid)) {
-			/*
-			 * The reference already has the desired
-			 * value, so we don't need to write it.
-			 */
-		} else if (write_ref_to_lockfile(lock, &update->new_oid,
-						 err)) {
-			char *write_err = strbuf_detach(err, NULL);
-
-			/*
-			 * The lock was freed upon failure of
-			 * write_ref_to_lockfile():
-			 */
-			update->backend_data = NULL;
-			strbuf_addf(err,
-				    "cannot update ref '%s': %s",
-				    update->refname, write_err);
-			free(write_err);
-			ret = TRANSACTION_GENERIC_ERROR;
-			goto out;
-		} else {
-			update->flags |= REF_NEEDS_COMMIT;
-		}
-	}
-	if (!(update->flags & REF_NEEDS_COMMIT)) {
-		/*
-		 * We didn't call write_ref_to_lockfile(), so
-		 * the lockfile is still open. Close it to
-		 * free up the file descriptor:
-		 */
-		if (close_ref_gently(lock)) {
-			strbuf_addf(err, "couldn't close '%s.lock'",
-				    update->refname);
-			ret = TRANSACTION_GENERIC_ERROR;
-			goto out;
-		}
-	}
-
-out:
-	strbuf_release(&referent);
-	return ret;
-}
-
-struct files_transaction_backend_data {
-	struct ref_transaction *packed_transaction;
-	int packed_refs_locked;
-};
-
-/*
- * Unlock any references in `transaction` that are still locked, and
- * mark the transaction closed.
- */
-static void files_transaction_cleanup(struct files_ref_store *refs,
-				      struct ref_transaction *transaction)
-{
-	size_t i;
-	struct files_transaction_backend_data *backend_data =
-		transaction->backend_data;
-	struct strbuf err = STRBUF_INIT;
-
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		struct ref_lock *lock = update->backend_data;
-
-		if (lock) {
-			unlock_ref(lock);
-			update->backend_data = NULL;
-		}
-	}
-
-	if (backend_data) {
-		if (backend_data->packed_transaction &&
-		    ref_transaction_abort(backend_data->packed_transaction, &err)) {
-			error("error aborting transaction: %s", err.buf);
-			strbuf_release(&err);
-		}
-
-		if (backend_data->packed_refs_locked)
-			packed_refs_unlock(refs->packed_ref_store);
-
-		free(backend_data);
-	}
-
-	transaction->state = REF_TRANSACTION_CLOSED;
-}
-
-static int files_transaction_prepare(struct ref_store *ref_store,
-				     struct ref_transaction *transaction,
-				     struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE,
-			       "ref_transaction_prepare");
-	size_t i;
-	int ret = 0;
-	struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
-	char *head_ref = NULL;
-	int head_type;
-	struct files_transaction_backend_data *backend_data;
-	struct ref_transaction *packed_transaction = NULL;
-
-	assert(err);
-
-	if (!transaction->nr)
-		goto cleanup;
-
-	backend_data = xcalloc(1, sizeof(*backend_data));
-	transaction->backend_data = backend_data;
-
-	/*
-	 * Fail if a refname appears more than once in the
-	 * transaction. (If we end up splitting up any updates using
-	 * split_symref_update() or split_head_update(), those
-	 * functions will check that the new updates don't have the
-	 * same refname as any existing ones.) Also fail if any of the
-	 * updates use REF_IS_PRUNING without REF_NO_DEREF.
-	 */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		struct string_list_item *item =
-			string_list_append(&affected_refnames, update->refname);
-
-		if ((update->flags & REF_IS_PRUNING) &&
-		    !(update->flags & REF_NO_DEREF))
-			BUG("REF_IS_PRUNING set without REF_NO_DEREF");
-
-		/*
-		 * We store a pointer to update in item->util, but at
-		 * the moment we never use the value of this field
-		 * except to check whether it is non-NULL.
-		 */
-		item->util = update;
-	}
-	string_list_sort(&affected_refnames);
-	if (ref_update_reject_duplicates(&affected_refnames, err)) {
-		ret = TRANSACTION_GENERIC_ERROR;
-		goto cleanup;
-	}
-
-	/*
-	 * Special hack: If a branch is updated directly and HEAD
-	 * points to it (may happen on the remote side of a push
-	 * for example) then logically the HEAD reflog should be
-	 * updated too.
-	 *
-	 * A generic solution would require reverse symref lookups,
-	 * but finding all symrefs pointing to a given branch would be
-	 * rather costly for this rare event (the direct update of a
-	 * branch) to be worth it. So let's cheat and check with HEAD
-	 * only, which should cover 99% of all usage scenarios (even
-	 * 100% of the default ones).
-	 *
-	 * So if HEAD is a symbolic reference, then record the name of
-	 * the reference that it points to. If we see an update of
-	 * head_ref within the transaction, then split_head_update()
-	 * arranges for the reflog of HEAD to be updated, too.
-	 */
-	head_ref = refs_resolve_refdup(ref_store, "HEAD",
-				       RESOLVE_REF_NO_RECURSE,
-				       NULL, &head_type);
-
-	if (head_ref && !(head_type & REF_ISSYMREF)) {
-		FREE_AND_NULL(head_ref);
-	}
-
-	/*
-	 * Acquire all locks, verify old values if provided, check
-	 * that new values are valid, and write new values to the
-	 * lockfiles, ready to be activated. Only keep one lockfile
-	 * open at a time to avoid running out of file descriptors.
-	 * Note that lock_ref_for_update() might append more updates
-	 * to the transaction.
-	 */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-
-		ret = lock_ref_for_update(refs, update, transaction,
-					  head_ref, &affected_refnames, err);
-		if (ret)
-			goto cleanup;
-
-		if (update->flags & REF_DELETING &&
-		    !(update->flags & REF_LOG_ONLY) &&
-		    !(update->flags & REF_IS_PRUNING)) {
-			/*
-			 * This reference has to be deleted from
-			 * packed-refs if it exists there.
-			 */
-			if (!packed_transaction) {
-				packed_transaction = ref_store_transaction_begin(
-						refs->packed_ref_store, err);
-				if (!packed_transaction) {
-					ret = TRANSACTION_GENERIC_ERROR;
-					goto cleanup;
-				}
-
-				backend_data->packed_transaction =
-					packed_transaction;
-			}
-
-			ref_transaction_add_update(
-					packed_transaction, update->refname,
-					REF_HAVE_NEW | REF_NO_DEREF,
-					&update->new_oid, NULL,
-					NULL);
-		}
-	}
-
-	if (packed_transaction) {
-		if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
-			ret = TRANSACTION_GENERIC_ERROR;
-			goto cleanup;
-		}
-		backend_data->packed_refs_locked = 1;
-
-		if (is_packed_transaction_needed(refs->packed_ref_store,
-						 packed_transaction)) {
-			ret = ref_transaction_prepare(packed_transaction, err);
-			/*
-			 * A failure during the prepare step will abort
-			 * itself, but not free. Do that now, and disconnect
-			 * from the files_transaction so it does not try to
-			 * abort us when we hit the cleanup code below.
-			 */
-			if (ret) {
-				ref_transaction_free(packed_transaction);
-				backend_data->packed_transaction = NULL;
-			}
-		} else {
-			/*
-			 * We can skip rewriting the `packed-refs`
-			 * file. But we do need to leave it locked, so
-			 * that somebody else doesn't pack a reference
-			 * that we are trying to delete.
-			 *
-			 * We need to disconnect our transaction from
-			 * backend_data, since the abort (whether successful or
-			 * not) will free it.
-			 */
-			backend_data->packed_transaction = NULL;
-			if (ref_transaction_abort(packed_transaction, err)) {
-				ret = TRANSACTION_GENERIC_ERROR;
-				goto cleanup;
-			}
-		}
-	}
-
-cleanup:
-	free(head_ref);
-	string_list_clear(&affected_refnames, 0);
-
-	if (ret)
-		files_transaction_cleanup(refs, transaction);
-	else
-		transaction->state = REF_TRANSACTION_PREPARED;
-
-	return ret;
-}
-
-static int files_transaction_finish(struct ref_store *ref_store,
-				    struct ref_transaction *transaction,
-				    struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, 0, "ref_transaction_finish");
-	size_t i;
-	int ret = 0;
-	struct strbuf sb = STRBUF_INIT;
-	struct files_transaction_backend_data *backend_data;
-	struct ref_transaction *packed_transaction;
-
-
-	assert(err);
-
-	if (!transaction->nr) {
-		transaction->state = REF_TRANSACTION_CLOSED;
-		return 0;
-	}
-
-	backend_data = transaction->backend_data;
-	packed_transaction = backend_data->packed_transaction;
-
-	/* Perform updates first so live commits remain referenced */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		struct ref_lock *lock = update->backend_data;
-
-		if (update->flags & REF_NEEDS_COMMIT ||
-		    update->flags & REF_LOG_ONLY) {
-			if (files_log_ref_write(refs,
-						lock->ref_name,
-						&lock->old_oid,
-						&update->new_oid,
-						update->msg, update->flags,
-						err)) {
-				char *old_msg = strbuf_detach(err, NULL);
-
-				strbuf_addf(err, "cannot update the ref '%s': %s",
-					    lock->ref_name, old_msg);
-				free(old_msg);
-				unlock_ref(lock);
-				update->backend_data = NULL;
-				ret = TRANSACTION_GENERIC_ERROR;
-				goto cleanup;
-			}
-		}
-		if (update->flags & REF_NEEDS_COMMIT) {
-			clear_loose_ref_cache(refs);
-			if (commit_ref(lock)) {
-				strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
-				unlock_ref(lock);
-				update->backend_data = NULL;
-				ret = TRANSACTION_GENERIC_ERROR;
-				goto cleanup;
-			}
-		}
-	}
-
-	/*
-	 * Now that updates are safely completed, we can perform
-	 * deletes. First delete the reflogs of any references that
-	 * will be deleted, since (in the unexpected event of an
-	 * error) leaving a reference without a reflog is less bad
-	 * than leaving a reflog without a reference (the latter is a
-	 * mildly invalid repository state):
-	 */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		if (update->flags & REF_DELETING &&
-		    !(update->flags & REF_LOG_ONLY) &&
-		    !(update->flags & REF_IS_PRUNING)) {
-			strbuf_reset(&sb);
-			files_reflog_path(refs, &sb, update->refname);
-			if (!unlink_or_warn(sb.buf))
-				try_remove_empty_parents(refs, update->refname,
-							 REMOVE_EMPTY_PARENTS_REFLOG);
-		}
-	}
-
-	/*
-	 * Perform deletes now that updates are safely completed.
-	 *
-	 * First delete any packed versions of the references, while
-	 * retaining the packed-refs lock:
-	 */
-	if (packed_transaction) {
-		ret = ref_transaction_commit(packed_transaction, err);
-		ref_transaction_free(packed_transaction);
-		packed_transaction = NULL;
-		backend_data->packed_transaction = NULL;
-		if (ret)
-			goto cleanup;
-	}
-
-	/* Now delete the loose versions of the references: */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		struct ref_lock *lock = update->backend_data;
-
-		if (update->flags & REF_DELETING &&
-		    !(update->flags & REF_LOG_ONLY)) {
-			if (!(update->type & REF_ISPACKED) ||
-			    update->type & REF_ISSYMREF) {
-				/* It is a loose reference. */
-				strbuf_reset(&sb);
-				files_ref_path(refs, &sb, lock->ref_name);
-				if (unlink_or_msg(sb.buf, err)) {
-					ret = TRANSACTION_GENERIC_ERROR;
-					goto cleanup;
-				}
-				update->flags |= REF_DELETED_LOOSE;
-			}
-		}
-	}
-
-	clear_loose_ref_cache(refs);
-
-cleanup:
-	files_transaction_cleanup(refs, transaction);
-
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-
-		if (update->flags & REF_DELETED_LOOSE) {
-			/*
-			 * The loose reference was deleted. Delete any
-			 * empty parent directories. (Note that this
-			 * can only work because we have already
-			 * removed the lockfile.)
-			 */
-			try_remove_empty_parents(refs, update->refname,
-						 REMOVE_EMPTY_PARENTS_REF);
-		}
-	}
-
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int files_transaction_abort(struct ref_store *ref_store,
-				   struct ref_transaction *transaction,
-				   struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, 0, "ref_transaction_abort");
-
-	files_transaction_cleanup(refs, transaction);
-	return 0;
-}
-
-static int ref_present(const char *refname,
-		       const struct object_id *oid, int flags, void *cb_data)
-{
-	struct string_list *affected_refnames = cb_data;
-
-	return string_list_has_string(affected_refnames, refname);
-}
-
-static int files_initial_transaction_commit(struct ref_store *ref_store,
-					    struct ref_transaction *transaction,
-					    struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE,
-			       "initial_ref_transaction_commit");
-	size_t i;
-	int ret = 0;
-	struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
-	struct ref_transaction *packed_transaction = NULL;
-
-	assert(err);
-
-	if (transaction->state != REF_TRANSACTION_OPEN)
-		BUG("commit called for transaction that is not open");
-
-	/* Fail if a refname appears more than once in the transaction: */
-	for (i = 0; i < transaction->nr; i++)
-		string_list_append(&affected_refnames,
-				   transaction->updates[i]->refname);
-	string_list_sort(&affected_refnames);
-	if (ref_update_reject_duplicates(&affected_refnames, err)) {
-		ret = TRANSACTION_GENERIC_ERROR;
-		goto cleanup;
-	}
-
-	/*
-	 * It's really undefined to call this function in an active
-	 * repository or when there are existing references: we are
-	 * only locking and changing packed-refs, so (1) any
-	 * simultaneous processes might try to change a reference at
-	 * the same time we do, and (2) any existing loose versions of
-	 * the references that we are setting would have precedence
-	 * over our values. But some remote helpers create the remote
-	 * "HEAD" and "master" branches before calling this function,
-	 * so here we really only check that none of the references
-	 * that we are creating already exists.
-	 */
-	if (refs_for_each_rawref(&refs->base, ref_present,
-				 &affected_refnames))
-		BUG("initial ref transaction called with existing refs");
-
-	packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, err);
-	if (!packed_transaction) {
-		ret = TRANSACTION_GENERIC_ERROR;
-		goto cleanup;
-	}
-
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-
-		if ((update->flags & REF_HAVE_OLD) &&
-		    !is_null_oid(&update->old_oid))
-			BUG("initial ref transaction with old_sha1 set");
-		if (refs_verify_refname_available(&refs->base, update->refname,
-						  &affected_refnames, NULL,
-						  err)) {
-			ret = TRANSACTION_NAME_CONFLICT;
-			goto cleanup;
-		}
-
-		/*
-		 * Add a reference creation for this reference to the
-		 * packed-refs transaction:
-		 */
-		ref_transaction_add_update(packed_transaction, update->refname,
-					   update->flags & ~REF_HAVE_OLD,
-					   &update->new_oid, &update->old_oid,
-					   NULL);
-	}
-
-	if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
-		ret = TRANSACTION_GENERIC_ERROR;
-		goto cleanup;
-	}
-
-	if (initial_ref_transaction_commit(packed_transaction, err)) {
-		ret = TRANSACTION_GENERIC_ERROR;
-	}
-
-	packed_refs_unlock(refs->packed_ref_store);
-cleanup:
-	if (packed_transaction)
-		ref_transaction_free(packed_transaction);
-	transaction->state = REF_TRANSACTION_CLOSED;
-	string_list_clear(&affected_refnames, 0);
-	return ret;
-}
-
-struct expire_reflog_cb {
-	unsigned int flags;
-	reflog_expiry_should_prune_fn *should_prune_fn;
-	void *policy_cb;
-	FILE *newlog;
-	struct object_id last_kept_oid;
-};
-
-static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
-			     const char *email, timestamp_t timestamp, int tz,
-			     const char *message, void *cb_data)
-{
-	struct expire_reflog_cb *cb = cb_data;
-	struct expire_reflog_policy_cb *policy_cb = cb->policy_cb;
-
-	if (cb->flags & EXPIRE_REFLOGS_REWRITE)
-		ooid = &cb->last_kept_oid;
-
-	if ((*cb->should_prune_fn)(ooid, noid, email, timestamp, tz,
-				   message, policy_cb)) {
-		if (!cb->newlog)
-			printf("would prune %s", message);
-		else if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
-			printf("prune %s", message);
-	} else {
-		if (cb->newlog) {
-			fprintf(cb->newlog, "%s %s %s %"PRItime" %+05d\t%s",
-				oid_to_hex(ooid), oid_to_hex(noid),
-				email, timestamp, tz, message);
-			oidcpy(&cb->last_kept_oid, noid);
-		}
-		if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
-			printf("keep %s", message);
-	}
-	return 0;
-}
-
-static int files_reflog_expire(struct ref_store *ref_store,
-			       const char *refname, const struct object_id *oid,
-			       unsigned int flags,
-			       reflog_expiry_prepare_fn prepare_fn,
-			       reflog_expiry_should_prune_fn should_prune_fn,
-			       reflog_expiry_cleanup_fn cleanup_fn,
-			       void *policy_cb_data)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
-	struct lock_file reflog_lock = LOCK_INIT;
-	struct expire_reflog_cb cb;
-	struct ref_lock *lock;
-	struct strbuf log_file_sb = STRBUF_INIT;
-	char *log_file;
-	int status = 0;
-	int type;
-	struct strbuf err = STRBUF_INIT;
-
-	memset(&cb, 0, sizeof(cb));
-	cb.flags = flags;
-	cb.policy_cb = policy_cb_data;
-	cb.should_prune_fn = should_prune_fn;
-
-	/*
-	 * The reflog file is locked by holding the lock on the
-	 * reference itself, plus we might need to update the
-	 * reference if --updateref was specified:
-	 */
-	lock = lock_ref_oid_basic(refs, refname, oid,
-				  NULL, NULL, REF_NO_DEREF,
-				  &type, &err);
-	if (!lock) {
-		error("cannot lock ref '%s': %s", refname, err.buf);
-		strbuf_release(&err);
-		return -1;
-	}
-	if (!refs_reflog_exists(ref_store, refname)) {
-		unlock_ref(lock);
-		return 0;
-	}
-
-	files_reflog_path(refs, &log_file_sb, refname);
-	log_file = strbuf_detach(&log_file_sb, NULL);
-	if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
-		/*
-		 * Even though holding $GIT_DIR/logs/$reflog.lock has
-		 * no locking implications, we use the lock_file
-		 * machinery here anyway because it does a lot of the
-		 * work we need, including cleaning up if the program
-		 * exits unexpectedly.
-		 */
-		if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0) {
-			struct strbuf err = STRBUF_INIT;
-			unable_to_lock_message(log_file, errno, &err);
-			error("%s", err.buf);
-			strbuf_release(&err);
-			goto failure;
-		}
-		cb.newlog = fdopen_lock_file(&reflog_lock, "w");
-		if (!cb.newlog) {
-			error("cannot fdopen %s (%s)",
-			      get_lock_file_path(&reflog_lock), strerror(errno));
-			goto failure;
-		}
-	}
-
-	(*prepare_fn)(refname, oid, cb.policy_cb);
-	refs_for_each_reflog_ent(ref_store, refname, expire_reflog_ent, &cb);
-	(*cleanup_fn)(cb.policy_cb);
-
-	if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
-		/*
-		 * It doesn't make sense to adjust a reference pointed
-		 * to by a symbolic ref based on expiring entries in
-		 * the symbolic reference's reflog. Nor can we update
-		 * a reference if there are no remaining reflog
-		 * entries.
-		 */
-		int update = (flags & EXPIRE_REFLOGS_UPDATE_REF) &&
-			!(type & REF_ISSYMREF) &&
-			!is_null_oid(&cb.last_kept_oid);
-
-		if (close_lock_file_gently(&reflog_lock)) {
-			status |= error("couldn't write %s: %s", log_file,
-					strerror(errno));
-			rollback_lock_file(&reflog_lock);
-		} else if (update &&
-			   (write_in_full(get_lock_file_fd(&lock->lk),
-				oid_to_hex(&cb.last_kept_oid), the_hash_algo->hexsz) < 0 ||
-			    write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 0 ||
-			    close_ref_gently(lock) < 0)) {
-			status |= error("couldn't write %s",
-					get_lock_file_path(&lock->lk));
-			rollback_lock_file(&reflog_lock);
-		} else if (commit_lock_file(&reflog_lock)) {
-			status |= error("unable to write reflog '%s' (%s)",
-					log_file, strerror(errno));
-		} else if (update && commit_ref(lock)) {
-			status |= error("couldn't set %s", lock->ref_name);
-		}
-	}
-	free(log_file);
-	unlock_ref(lock);
-	return status;
-
- failure:
-	rollback_lock_file(&reflog_lock);
-	free(log_file);
-	unlock_ref(lock);
-	return -1;
-}
-
-static int files_init_db(struct ref_store *ref_store, struct strbuf *err)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "init_db");
-	struct strbuf sb = STRBUF_INIT;
-
-	/*
-	 * Create .git/refs/{heads,tags}
-	 */
-	files_ref_path(refs, &sb, "refs/heads");
-	safe_create_dir(sb.buf, 1);
-
-	strbuf_reset(&sb);
-	files_ref_path(refs, &sb, "refs/tags");
-	safe_create_dir(sb.buf, 1);
-
-	strbuf_release(&sb);
-	return 0;
-}
-
-struct ref_storage_be refs_be_files = {
-	NULL,
-	"files",
-	files_ref_store_create,
-	files_init_db,
-	files_transaction_prepare,
-	files_transaction_finish,
-	files_transaction_abort,
-	files_initial_transaction_commit,
-
-	files_pack_refs,
-	files_create_symref,
-	files_delete_refs,
-	files_rename_ref,
-	files_copy_ref,
-
-	files_ref_iterator_begin,
-	files_read_raw_ref,
-
-	files_reflog_iterator_begin,
-	files_for_each_reflog_ent,
-	files_for_each_reflog_ent_reverse,
-	files_reflog_exists,
-	files_create_reflog,
-	files_delete_reflog,
-	files_reflog_expire
-};
diff --git a/third_party/git/refs/iterator.c b/third_party/git/refs/iterator.c
deleted file mode 100644
index 629e00a122a7..000000000000
--- a/third_party/git/refs/iterator.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Generic reference iterator infrastructure. See refs-internal.h for
- * documentation about the design and use of reference iterators.
- */
-
-#include "cache.h"
-#include "refs.h"
-#include "refs/refs-internal.h"
-#include "iterator.h"
-
-int ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	return ref_iterator->vtable->advance(ref_iterator);
-}
-
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
-		      struct object_id *peeled)
-{
-	return ref_iterator->vtable->peel(ref_iterator, peeled);
-}
-
-int ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	return ref_iterator->vtable->abort(ref_iterator);
-}
-
-void base_ref_iterator_init(struct ref_iterator *iter,
-			    struct ref_iterator_vtable *vtable,
-			    int ordered)
-{
-	iter->vtable = vtable;
-	iter->ordered = !!ordered;
-	iter->refname = NULL;
-	iter->oid = NULL;
-	iter->flags = 0;
-}
-
-void base_ref_iterator_free(struct ref_iterator *iter)
-{
-	/* Help make use-after-free bugs fail quickly: */
-	iter->vtable = NULL;
-	free(iter);
-}
-
-struct empty_ref_iterator {
-	struct ref_iterator base;
-};
-
-static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	return ref_iterator_abort(ref_iterator);
-}
-
-static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	BUG("peel called for empty iterator");
-}
-
-static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	base_ref_iterator_free(ref_iterator);
-	return ITER_DONE;
-}
-
-static struct ref_iterator_vtable empty_ref_iterator_vtable = {
-	empty_ref_iterator_advance,
-	empty_ref_iterator_peel,
-	empty_ref_iterator_abort
-};
-
-struct ref_iterator *empty_ref_iterator_begin(void)
-{
-	struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter));
-	struct ref_iterator *ref_iterator = &iter->base;
-
-	base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable, 1);
-	return ref_iterator;
-}
-
-int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
-{
-	return ref_iterator->vtable == &empty_ref_iterator_vtable;
-}
-
-struct merge_ref_iterator {
-	struct ref_iterator base;
-
-	struct ref_iterator *iter0, *iter1;
-
-	ref_iterator_select_fn *select;
-	void *cb_data;
-
-	/*
-	 * A pointer to iter0 or iter1 (whichever is supplying the
-	 * current value), or NULL if advance has not yet been called.
-	 */
-	struct ref_iterator **current;
-};
-
-static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct merge_ref_iterator *iter =
-		(struct merge_ref_iterator *)ref_iterator;
-	int ok;
-
-	if (!iter->current) {
-		/* Initialize: advance both iterators to their first entries */
-		if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) {
-			iter->iter0 = NULL;
-			if (ok == ITER_ERROR)
-				goto error;
-		}
-		if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) {
-			iter->iter1 = NULL;
-			if (ok == ITER_ERROR)
-				goto error;
-		}
-	} else {
-		/*
-		 * Advance the current iterator past the just-used
-		 * entry:
-		 */
-		if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) {
-			*iter->current = NULL;
-			if (ok == ITER_ERROR)
-				goto error;
-		}
-	}
-
-	/* Loop until we find an entry that we can yield. */
-	while (1) {
-		struct ref_iterator **secondary;
-		enum iterator_selection selection =
-			iter->select(iter->iter0, iter->iter1, iter->cb_data);
-
-		if (selection == ITER_SELECT_DONE) {
-			return ref_iterator_abort(ref_iterator);
-		} else if (selection == ITER_SELECT_ERROR) {
-			ref_iterator_abort(ref_iterator);
-			return ITER_ERROR;
-		}
-
-		if ((selection & ITER_CURRENT_SELECTION_MASK) == 0) {
-			iter->current = &iter->iter0;
-			secondary = &iter->iter1;
-		} else {
-			iter->current = &iter->iter1;
-			secondary = &iter->iter0;
-		}
-
-		if (selection & ITER_SKIP_SECONDARY) {
-			if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) {
-				*secondary = NULL;
-				if (ok == ITER_ERROR)
-					goto error;
-			}
-		}
-
-		if (selection & ITER_YIELD_CURRENT) {
-			iter->base.refname = (*iter->current)->refname;
-			iter->base.oid = (*iter->current)->oid;
-			iter->base.flags = (*iter->current)->flags;
-			return ITER_OK;
-		}
-	}
-
-error:
-	ref_iterator_abort(ref_iterator);
-	return ITER_ERROR;
-}
-
-static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct merge_ref_iterator *iter =
-		(struct merge_ref_iterator *)ref_iterator;
-
-	if (!iter->current) {
-		BUG("peel called before advance for merge iterator");
-	}
-	return ref_iterator_peel(*iter->current, peeled);
-}
-
-static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct merge_ref_iterator *iter =
-		(struct merge_ref_iterator *)ref_iterator;
-	int ok = ITER_DONE;
-
-	if (iter->iter0) {
-		if (ref_iterator_abort(iter->iter0) != ITER_DONE)
-			ok = ITER_ERROR;
-	}
-	if (iter->iter1) {
-		if (ref_iterator_abort(iter->iter1) != ITER_DONE)
-			ok = ITER_ERROR;
-	}
-	base_ref_iterator_free(ref_iterator);
-	return ok;
-}
-
-static struct ref_iterator_vtable merge_ref_iterator_vtable = {
-	merge_ref_iterator_advance,
-	merge_ref_iterator_peel,
-	merge_ref_iterator_abort
-};
-
-struct ref_iterator *merge_ref_iterator_begin(
-		int ordered,
-		struct ref_iterator *iter0, struct ref_iterator *iter1,
-		ref_iterator_select_fn *select, void *cb_data)
-{
-	struct merge_ref_iterator *iter = xcalloc(1, sizeof(*iter));
-	struct ref_iterator *ref_iterator = &iter->base;
-
-	/*
-	 * We can't do the same kind of is_empty_ref_iterator()-style
-	 * optimization here as overlay_ref_iterator_begin() does,
-	 * because we don't know the semantics of the select function.
-	 * It might, for example, implement "intersect" by passing
-	 * references through only if they exist in both iterators.
-	 */
-
-	base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable, ordered);
-	iter->iter0 = iter0;
-	iter->iter1 = iter1;
-	iter->select = select;
-	iter->cb_data = cb_data;
-	iter->current = NULL;
-	return ref_iterator;
-}
-
-/*
- * A ref_iterator_select_fn that overlays the items from front on top
- * of those from back (like loose refs over packed refs). See
- * overlay_ref_iterator_begin().
- */
-static enum iterator_selection overlay_iterator_select(
-		struct ref_iterator *front, struct ref_iterator *back,
-		void *cb_data)
-{
-	int cmp;
-
-	if (!back)
-		return front ? ITER_SELECT_0 : ITER_SELECT_DONE;
-	else if (!front)
-		return ITER_SELECT_1;
-
-	cmp = strcmp(front->refname, back->refname);
-
-	if (cmp < 0)
-		return ITER_SELECT_0;
-	else if (cmp > 0)
-		return ITER_SELECT_1;
-	else
-		return ITER_SELECT_0_SKIP_1;
-}
-
-struct ref_iterator *overlay_ref_iterator_begin(
-		struct ref_iterator *front, struct ref_iterator *back)
-{
-	/*
-	 * Optimization: if one of the iterators is empty, return the
-	 * other one rather than incurring the overhead of wrapping
-	 * them.
-	 */
-	if (is_empty_ref_iterator(front)) {
-		ref_iterator_abort(front);
-		return back;
-	} else if (is_empty_ref_iterator(back)) {
-		ref_iterator_abort(back);
-		return front;
-	} else if (!front->ordered || !back->ordered) {
-		BUG("overlay_ref_iterator requires ordered inputs");
-	}
-
-	return merge_ref_iterator_begin(1, front, back,
-					overlay_iterator_select, NULL);
-}
-
-struct prefix_ref_iterator {
-	struct ref_iterator base;
-
-	struct ref_iterator *iter0;
-	char *prefix;
-	int trim;
-};
-
-/* Return -1, 0, 1 if refname is before, inside, or after the prefix. */
-static int compare_prefix(const char *refname, const char *prefix)
-{
-	while (*prefix) {
-		if (*refname != *prefix)
-			return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1;
-
-		refname++;
-		prefix++;
-	}
-
-	return 0;
-}
-
-static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct prefix_ref_iterator *iter =
-		(struct prefix_ref_iterator *)ref_iterator;
-	int ok;
-
-	while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
-		int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
-
-		if (cmp < 0)
-			continue;
-
-		if (cmp > 0) {
-			/*
-			 * If the source iterator is ordered, then we
-			 * can stop the iteration as soon as we see a
-			 * refname that comes after the prefix:
-			 */
-			if (iter->iter0->ordered) {
-				ok = ref_iterator_abort(iter->iter0);
-				break;
-			} else {
-				continue;
-			}
-		}
-
-		if (iter->trim) {
-			/*
-			 * It is nonsense to trim off characters that
-			 * you haven't already checked for via a
-			 * prefix check, whether via this
-			 * `prefix_ref_iterator` or upstream in
-			 * `iter0`). So if there wouldn't be at least
-			 * one character left in the refname after
-			 * trimming, report it as a bug:
-			 */
-			if (strlen(iter->iter0->refname) <= iter->trim)
-				BUG("attempt to trim too many characters");
-			iter->base.refname = iter->iter0->refname + iter->trim;
-		} else {
-			iter->base.refname = iter->iter0->refname;
-		}
-
-		iter->base.oid = iter->iter0->oid;
-		iter->base.flags = iter->iter0->flags;
-		return ITER_OK;
-	}
-
-	iter->iter0 = NULL;
-	if (ref_iterator_abort(ref_iterator) != ITER_DONE)
-		return ITER_ERROR;
-	return ok;
-}
-
-static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				    struct object_id *peeled)
-{
-	struct prefix_ref_iterator *iter =
-		(struct prefix_ref_iterator *)ref_iterator;
-
-	return ref_iterator_peel(iter->iter0, peeled);
-}
-
-static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct prefix_ref_iterator *iter =
-		(struct prefix_ref_iterator *)ref_iterator;
-	int ok = ITER_DONE;
-
-	if (iter->iter0)
-		ok = ref_iterator_abort(iter->iter0);
-	free(iter->prefix);
-	base_ref_iterator_free(ref_iterator);
-	return ok;
-}
-
-static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
-	prefix_ref_iterator_advance,
-	prefix_ref_iterator_peel,
-	prefix_ref_iterator_abort
-};
-
-struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
-					       const char *prefix,
-					       int trim)
-{
-	struct prefix_ref_iterator *iter;
-	struct ref_iterator *ref_iterator;
-
-	if (!*prefix && !trim)
-		return iter0; /* optimization: no need to wrap iterator */
-
-	iter = xcalloc(1, sizeof(*iter));
-	ref_iterator = &iter->base;
-
-	base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable, iter0->ordered);
-
-	iter->iter0 = iter0;
-	iter->prefix = xstrdup(prefix);
-	iter->trim = trim;
-
-	return ref_iterator;
-}
-
-struct ref_iterator *current_ref_iter = NULL;
-
-int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter,
-				  each_repo_ref_fn fn, void *cb_data)
-{
-	int retval = 0, ok;
-	struct ref_iterator *old_ref_iter = current_ref_iter;
-
-	current_ref_iter = iter;
-	while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
-		retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data);
-		if (retval) {
-			/*
-			 * If ref_iterator_abort() returns ITER_ERROR,
-			 * we ignore that error in deference to the
-			 * callback function's return value.
-			 */
-			ref_iterator_abort(iter);
-			goto out;
-		}
-	}
-
-out:
-	current_ref_iter = old_ref_iter;
-	if (ok == ITER_ERROR)
-		return -1;
-	return retval;
-}
diff --git a/third_party/git/refs/packed-backend.c b/third_party/git/refs/packed-backend.c
deleted file mode 100644
index b912f2505fee..000000000000
--- a/third_party/git/refs/packed-backend.c
+++ /dev/null
@@ -1,1670 +0,0 @@
-#include "../cache.h"
-#include "../config.h"
-#include "../refs.h"
-#include "refs-internal.h"
-#include "packed-backend.h"
-#include "../iterator.h"
-#include "../lockfile.h"
-#include "../chdir-notify.h"
-
-enum mmap_strategy {
-	/*
-	 * Don't use mmap() at all for reading `packed-refs`.
-	 */
-	MMAP_NONE,
-
-	/*
-	 * Can use mmap() for reading `packed-refs`, but the file must
-	 * not remain mmapped. This is the usual option on Windows,
-	 * where you cannot rename a new version of a file onto a file
-	 * that is currently mmapped.
-	 */
-	MMAP_TEMPORARY,
-
-	/*
-	 * It is OK to leave the `packed-refs` file mmapped while
-	 * arbitrary other code is running.
-	 */
-	MMAP_OK
-};
-
-#if defined(NO_MMAP)
-static enum mmap_strategy mmap_strategy = MMAP_NONE;
-#elif defined(MMAP_PREVENTS_DELETE)
-static enum mmap_strategy mmap_strategy = MMAP_TEMPORARY;
-#else
-static enum mmap_strategy mmap_strategy = MMAP_OK;
-#endif
-
-struct packed_ref_store;
-
-/*
- * A `snapshot` represents one snapshot of a `packed-refs` file.
- *
- * Normally, this will be a mmapped view of the contents of the
- * `packed-refs` file at the time the snapshot was created. However,
- * if the `packed-refs` file was not sorted, this might point at heap
- * memory holding the contents of the `packed-refs` file with its
- * records sorted by refname.
- *
- * `snapshot` instances are reference counted (via
- * `acquire_snapshot()` and `release_snapshot()`). This is to prevent
- * an instance from disappearing while an iterator is still iterating
- * over it. Instances are garbage collected when their `referrers`
- * count goes to zero.
- *
- * The most recent `snapshot`, if available, is referenced by the
- * `packed_ref_store`. Its freshness is checked whenever
- * `get_snapshot()` is called; if the existing snapshot is obsolete, a
- * new snapshot is taken.
- */
-struct snapshot {
-	/*
-	 * A back-pointer to the packed_ref_store with which this
-	 * snapshot is associated:
-	 */
-	struct packed_ref_store *refs;
-
-	/* Is the `packed-refs` file currently mmapped? */
-	int mmapped;
-
-	/*
-	 * The contents of the `packed-refs` file:
-	 *
-	 * - buf -- a pointer to the start of the memory
-	 * - start -- a pointer to the first byte of actual references
-	 *   (i.e., after the header line, if one is present)
-	 * - eof -- a pointer just past the end of the reference
-	 *   contents
-	 *
-	 * If the `packed-refs` file was already sorted, `buf` points
-	 * at the mmapped contents of the file. If not, it points at
-	 * heap-allocated memory containing the contents, sorted. If
-	 * there were no contents (e.g., because the file didn't
-	 * exist), `buf`, `start`, and `eof` are all NULL.
-	 */
-	char *buf, *start, *eof;
-
-	/*
-	 * What is the peeled state of the `packed-refs` file that
-	 * this snapshot represents? (This is usually determined from
-	 * the file's header.)
-	 */
-	enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled;
-
-	/*
-	 * Count of references to this instance, including the pointer
-	 * from `packed_ref_store::snapshot`, if any. The instance
-	 * will not be freed as long as the reference count is
-	 * nonzero.
-	 */
-	unsigned int referrers;
-
-	/*
-	 * The metadata of the `packed-refs` file from which this
-	 * snapshot was created, used to tell if the file has been
-	 * replaced since we read it.
-	 */
-	struct stat_validity validity;
-};
-
-/*
- * A `ref_store` representing references stored in a `packed-refs`
- * file. It implements the `ref_store` interface, though it has some
- * limitations:
- *
- * - It cannot store symbolic references.
- *
- * - It cannot store reflogs.
- *
- * - It does not support reference renaming (though it could).
- *
- * On the other hand, it can be locked outside of a reference
- * transaction. In that case, it remains locked even after the
- * transaction is done and the new `packed-refs` file is activated.
- */
-struct packed_ref_store {
-	struct ref_store base;
-
-	unsigned int store_flags;
-
-	/* The path of the "packed-refs" file: */
-	char *path;
-
-	/*
-	 * A snapshot of the values read from the `packed-refs` file,
-	 * if it might still be current; otherwise, NULL.
-	 */
-	struct snapshot *snapshot;
-
-	/*
-	 * Lock used for the "packed-refs" file. Note that this (and
-	 * thus the enclosing `packed_ref_store`) must not be freed.
-	 */
-	struct lock_file lock;
-
-	/*
-	 * Temporary file used when rewriting new contents to the
-	 * "packed-refs" file. Note that this (and thus the enclosing
-	 * `packed_ref_store`) must not be freed.
-	 */
-	struct tempfile *tempfile;
-};
-
-/*
- * Increment the reference count of `*snapshot`.
- */
-static void acquire_snapshot(struct snapshot *snapshot)
-{
-	snapshot->referrers++;
-}
-
-/*
- * If the buffer in `snapshot` is active, then either munmap the
- * memory and close the file, or free the memory. Then set the buffer
- * pointers to NULL.
- */
-static void clear_snapshot_buffer(struct snapshot *snapshot)
-{
-	if (snapshot->mmapped) {
-		if (munmap(snapshot->buf, snapshot->eof - snapshot->buf))
-			die_errno("error ummapping packed-refs file %s",
-				  snapshot->refs->path);
-		snapshot->mmapped = 0;
-	} else {
-		free(snapshot->buf);
-	}
-	snapshot->buf = snapshot->start = snapshot->eof = NULL;
-}
-
-/*
- * Decrease the reference count of `*snapshot`. If it goes to zero,
- * free `*snapshot` and return true; otherwise return false.
- */
-static int release_snapshot(struct snapshot *snapshot)
-{
-	if (!--snapshot->referrers) {
-		stat_validity_clear(&snapshot->validity);
-		clear_snapshot_buffer(snapshot);
-		free(snapshot);
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-struct ref_store *packed_ref_store_create(const char *path,
-					  unsigned int store_flags)
-{
-	struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
-	struct ref_store *ref_store = (struct ref_store *)refs;
-
-	base_ref_store_init(ref_store, &refs_be_packed);
-	ref_store->gitdir = xstrdup(path);
-	refs->store_flags = store_flags;
-
-	refs->path = xstrdup(path);
-	chdir_notify_reparent("packed-refs", &refs->path);
-
-	return ref_store;
-}
-
-/*
- * Downcast `ref_store` to `packed_ref_store`. Die if `ref_store` is
- * not a `packed_ref_store`. Also die if `packed_ref_store` doesn't
- * support at least the flags specified in `required_flags`. `caller`
- * is used in any necessary error messages.
- */
-static struct packed_ref_store *packed_downcast(struct ref_store *ref_store,
-						unsigned int required_flags,
-						const char *caller)
-{
-	struct packed_ref_store *refs;
-
-	if (ref_store->be != &refs_be_packed)
-		BUG("ref_store is type \"%s\" not \"packed\" in %s",
-		    ref_store->be->name, caller);
-
-	refs = (struct packed_ref_store *)ref_store;
-
-	if ((refs->store_flags & required_flags) != required_flags)
-		BUG("unallowed operation (%s), requires %x, has %x\n",
-		    caller, required_flags, refs->store_flags);
-
-	return refs;
-}
-
-static void clear_snapshot(struct packed_ref_store *refs)
-{
-	if (refs->snapshot) {
-		struct snapshot *snapshot = refs->snapshot;
-
-		refs->snapshot = NULL;
-		release_snapshot(snapshot);
-	}
-}
-
-static NORETURN void die_unterminated_line(const char *path,
-					   const char *p, size_t len)
-{
-	if (len < 80)
-		die("unterminated line in %s: %.*s", path, (int)len, p);
-	else
-		die("unterminated line in %s: %.75s...", path, p);
-}
-
-static NORETURN void die_invalid_line(const char *path,
-				      const char *p, size_t len)
-{
-	const char *eol = memchr(p, '\n', len);
-
-	if (!eol)
-		die_unterminated_line(path, p, len);
-	else if (eol - p < 80)
-		die("unexpected line in %s: %.*s", path, (int)(eol - p), p);
-	else
-		die("unexpected line in %s: %.75s...", path, p);
-
-}
-
-struct snapshot_record {
-	const char *start;
-	size_t len;
-};
-
-static int cmp_packed_ref_records(const void *v1, const void *v2)
-{
-	const struct snapshot_record *e1 = v1, *e2 = v2;
-	const char *r1 = e1->start + the_hash_algo->hexsz + 1;
-	const char *r2 = e2->start + the_hash_algo->hexsz + 1;
-
-	while (1) {
-		if (*r1 == '\n')
-			return *r2 == '\n' ? 0 : -1;
-		if (*r1 != *r2) {
-			if (*r2 == '\n')
-				return 1;
-			else
-				return (unsigned char)*r1 < (unsigned char)*r2 ? -1 : +1;
-		}
-		r1++;
-		r2++;
-	}
-}
-
-/*
- * Compare a snapshot record at `rec` to the specified NUL-terminated
- * refname.
- */
-static int cmp_record_to_refname(const char *rec, const char *refname)
-{
-	const char *r1 = rec + the_hash_algo->hexsz + 1;
-	const char *r2 = refname;
-
-	while (1) {
-		if (*r1 == '\n')
-			return *r2 ? -1 : 0;
-		if (!*r2)
-			return 1;
-		if (*r1 != *r2)
-			return (unsigned char)*r1 < (unsigned char)*r2 ? -1 : +1;
-		r1++;
-		r2++;
-	}
-}
-
-/*
- * `snapshot->buf` is not known to be sorted. Check whether it is, and
- * if not, sort it into new memory and munmap/free the old storage.
- */
-static void sort_snapshot(struct snapshot *snapshot)
-{
-	struct snapshot_record *records = NULL;
-	size_t alloc = 0, nr = 0;
-	int sorted = 1;
-	const char *pos, *eof, *eol;
-	size_t len, i;
-	char *new_buffer, *dst;
-
-	pos = snapshot->start;
-	eof = snapshot->eof;
-
-	if (pos == eof)
-		return;
-
-	len = eof - pos;
-
-	/*
-	 * Initialize records based on a crude estimate of the number
-	 * of references in the file (we'll grow it below if needed):
-	 */
-	ALLOC_GROW(records, len / 80 + 20, alloc);
-
-	while (pos < eof) {
-		eol = memchr(pos, '\n', eof - pos);
-		if (!eol)
-			/* The safety check should prevent this. */
-			BUG("unterminated line found in packed-refs");
-		if (eol - pos < the_hash_algo->hexsz + 2)
-			die_invalid_line(snapshot->refs->path,
-					 pos, eof - pos);
-		eol++;
-		if (eol < eof && *eol == '^') {
-			/*
-			 * Keep any peeled line together with its
-			 * reference:
-			 */
-			const char *peeled_start = eol;
-
-			eol = memchr(peeled_start, '\n', eof - peeled_start);
-			if (!eol)
-				/* The safety check should prevent this. */
-				BUG("unterminated peeled line found in packed-refs");
-			eol++;
-		}
-
-		ALLOC_GROW(records, nr + 1, alloc);
-		records[nr].start = pos;
-		records[nr].len = eol - pos;
-		nr++;
-
-		if (sorted &&
-		    nr > 1 &&
-		    cmp_packed_ref_records(&records[nr - 2],
-					   &records[nr - 1]) >= 0)
-			sorted = 0;
-
-		pos = eol;
-	}
-
-	if (sorted)
-		goto cleanup;
-
-	/* We need to sort the memory. First we sort the records array: */
-	QSORT(records, nr, cmp_packed_ref_records);
-
-	/*
-	 * Allocate a new chunk of memory, and copy the old memory to
-	 * the new in the order indicated by `records` (not bothering
-	 * with the header line):
-	 */
-	new_buffer = xmalloc(len);
-	for (dst = new_buffer, i = 0; i < nr; i++) {
-		memcpy(dst, records[i].start, records[i].len);
-		dst += records[i].len;
-	}
-
-	/*
-	 * Now munmap the old buffer and use the sorted buffer in its
-	 * place:
-	 */
-	clear_snapshot_buffer(snapshot);
-	snapshot->buf = snapshot->start = new_buffer;
-	snapshot->eof = new_buffer + len;
-
-cleanup:
-	free(records);
-}
-
-/*
- * Return a pointer to the start of the record that contains the
- * character `*p` (which must be within the buffer). If no other
- * record start is found, return `buf`.
- */
-static const char *find_start_of_record(const char *buf, const char *p)
-{
-	while (p > buf && (p[-1] != '\n' || p[0] == '^'))
-		p--;
-	return p;
-}
-
-/*
- * Return a pointer to the start of the record following the record
- * that contains `*p`. If none is found before `end`, return `end`.
- */
-static const char *find_end_of_record(const char *p, const char *end)
-{
-	while (++p < end && (p[-1] != '\n' || p[0] == '^'))
-		;
-	return p;
-}
-
-/*
- * We want to be able to compare mmapped reference records quickly,
- * without totally parsing them. We can do so because the records are
- * LF-terminated, and the refname should start exactly (GIT_SHA1_HEXSZ
- * + 1) bytes past the beginning of the record.
- *
- * But what if the `packed-refs` file contains garbage? We're willing
- * to tolerate not detecting the problem, as long as we don't produce
- * totally garbled output (we can't afford to check the integrity of
- * the whole file during every Git invocation). But we do want to be
- * sure that we never read past the end of the buffer in memory and
- * perform an illegal memory access.
- *
- * Guarantee that minimum level of safety by verifying that the last
- * record in the file is LF-terminated, and that it has at least
- * (GIT_SHA1_HEXSZ + 1) characters before the LF. Die if either of
- * these checks fails.
- */
-static void verify_buffer_safe(struct snapshot *snapshot)
-{
-	const char *start = snapshot->start;
-	const char *eof = snapshot->eof;
-	const char *last_line;
-
-	if (start == eof)
-		return;
-
-	last_line = find_start_of_record(start, eof - 1);
-	if (*(eof - 1) != '\n' || eof - last_line < the_hash_algo->hexsz + 2)
-		die_invalid_line(snapshot->refs->path,
-				 last_line, eof - last_line);
-}
-
-#define SMALL_FILE_SIZE (32*1024)
-
-/*
- * Depending on `mmap_strategy`, either mmap or read the contents of
- * the `packed-refs` file into the snapshot. Return 1 if the file
- * existed and was read, or 0 if the file was absent or empty. Die on
- * errors.
- */
-static int load_contents(struct snapshot *snapshot)
-{
-	int fd;
-	struct stat st;
-	size_t size;
-	ssize_t bytes_read;
-
-	fd = open(snapshot->refs->path, O_RDONLY);
-	if (fd < 0) {
-		if (errno == ENOENT) {
-			/*
-			 * This is OK; it just means that no
-			 * "packed-refs" file has been written yet,
-			 * which is equivalent to it being empty,
-			 * which is its state when initialized with
-			 * zeros.
-			 */
-			return 0;
-		} else {
-			die_errno("couldn't read %s", snapshot->refs->path);
-		}
-	}
-
-	stat_validity_update(&snapshot->validity, fd);
-
-	if (fstat(fd, &st) < 0)
-		die_errno("couldn't stat %s", snapshot->refs->path);
-	size = xsize_t(st.st_size);
-
-	if (!size) {
-		close(fd);
-		return 0;
-	} else if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE) {
-		snapshot->buf = xmalloc(size);
-		bytes_read = read_in_full(fd, snapshot->buf, size);
-		if (bytes_read < 0 || bytes_read != size)
-			die_errno("couldn't read %s", snapshot->refs->path);
-		snapshot->mmapped = 0;
-	} else {
-		snapshot->buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-		snapshot->mmapped = 1;
-	}
-	close(fd);
-
-	snapshot->start = snapshot->buf;
-	snapshot->eof = snapshot->buf + size;
-
-	return 1;
-}
-
-/*
- * Find the place in `snapshot->buf` where the start of the record for
- * `refname` starts. If `mustexist` is true and the reference doesn't
- * exist, then return NULL. If `mustexist` is false and the reference
- * doesn't exist, then return the point where that reference would be
- * inserted, or `snapshot->eof` (which might be NULL) if it would be
- * inserted at the end of the file. In the latter mode, `refname`
- * doesn't have to be a proper reference name; for example, one could
- * search for "refs/replace/" to find the start of any replace
- * references.
- *
- * The record is sought using a binary search, so `snapshot->buf` must
- * be sorted.
- */
-static const char *find_reference_location(struct snapshot *snapshot,
-					   const char *refname, int mustexist)
-{
-	/*
-	 * This is not *quite* a garden-variety binary search, because
-	 * the data we're searching is made up of records, and we
-	 * always need to find the beginning of a record to do a
-	 * comparison. A "record" here is one line for the reference
-	 * itself and zero or one peel lines that start with '^'. Our
-	 * loop invariant is described in the next two comments.
-	 */
-
-	/*
-	 * A pointer to the character at the start of a record whose
-	 * preceding records all have reference names that come
-	 * *before* `refname`.
-	 */
-	const char *lo = snapshot->start;
-
-	/*
-	 * A pointer to a the first character of a record whose
-	 * reference name comes *after* `refname`.
-	 */
-	const char *hi = snapshot->eof;
-
-	while (lo != hi) {
-		const char *mid, *rec;
-		int cmp;
-
-		mid = lo + (hi - lo) / 2;
-		rec = find_start_of_record(lo, mid);
-		cmp = cmp_record_to_refname(rec, refname);
-		if (cmp < 0) {
-			lo = find_end_of_record(mid, hi);
-		} else if (cmp > 0) {
-			hi = rec;
-		} else {
-			return rec;
-		}
-	}
-
-	if (mustexist)
-		return NULL;
-	else
-		return lo;
-}
-
-/*
- * Create a newly-allocated `snapshot` of the `packed-refs` file in
- * its current state and return it. The return value will already have
- * its reference count incremented.
- *
- * A comment line of the form "# pack-refs with: " may contain zero or
- * more traits. We interpret the traits as follows:
- *
- *   Neither `peeled` nor `fully-peeled`:
- *
- *      Probably no references are peeled. But if the file contains a
- *      peeled value for a reference, we will use it.
- *
- *   `peeled`:
- *
- *      References under "refs/tags/", if they *can* be peeled, *are*
- *      peeled in this file. References outside of "refs/tags/" are
- *      probably not peeled even if they could have been, but if we find
- *      a peeled value for such a reference we will use it.
- *
- *   `fully-peeled`:
- *
- *      All references in the file that can be peeled are peeled.
- *      Inversely (and this is more important), any references in the
- *      file for which no peeled value is recorded is not peelable. This
- *      trait should typically be written alongside "peeled" for
- *      compatibility with older clients, but we do not require it
- *      (i.e., "peeled" is a no-op if "fully-peeled" is set).
- *
- *   `sorted`:
- *
- *      The references in this file are known to be sorted by refname.
- */
-static struct snapshot *create_snapshot(struct packed_ref_store *refs)
-{
-	struct snapshot *snapshot = xcalloc(1, sizeof(*snapshot));
-	int sorted = 0;
-
-	snapshot->refs = refs;
-	acquire_snapshot(snapshot);
-	snapshot->peeled = PEELED_NONE;
-
-	if (!load_contents(snapshot))
-		return snapshot;
-
-	/* If the file has a header line, process it: */
-	if (snapshot->buf < snapshot->eof && *snapshot->buf == '#') {
-		char *tmp, *p, *eol;
-		struct string_list traits = STRING_LIST_INIT_NODUP;
-
-		eol = memchr(snapshot->buf, '\n',
-			     snapshot->eof - snapshot->buf);
-		if (!eol)
-			die_unterminated_line(refs->path,
-					      snapshot->buf,
-					      snapshot->eof - snapshot->buf);
-
-		tmp = xmemdupz(snapshot->buf, eol - snapshot->buf);
-
-		if (!skip_prefix(tmp, "# pack-refs with:", (const char **)&p))
-			die_invalid_line(refs->path,
-					 snapshot->buf,
-					 snapshot->eof - snapshot->buf);
-
-		string_list_split_in_place(&traits, p, ' ', -1);
-
-		if (unsorted_string_list_has_string(&traits, "fully-peeled"))
-			snapshot->peeled = PEELED_FULLY;
-		else if (unsorted_string_list_has_string(&traits, "peeled"))
-			snapshot->peeled = PEELED_TAGS;
-
-		sorted = unsorted_string_list_has_string(&traits, "sorted");
-
-		/* perhaps other traits later as well */
-
-		/* The "+ 1" is for the LF character. */
-		snapshot->start = eol + 1;
-
-		string_list_clear(&traits, 0);
-		free(tmp);
-	}
-
-	verify_buffer_safe(snapshot);
-
-	if (!sorted) {
-		sort_snapshot(snapshot);
-
-		/*
-		 * Reordering the records might have moved a short one
-		 * to the end of the buffer, so verify the buffer's
-		 * safety again:
-		 */
-		verify_buffer_safe(snapshot);
-	}
-
-	if (mmap_strategy != MMAP_OK && snapshot->mmapped) {
-		/*
-		 * We don't want to leave the file mmapped, so we are
-		 * forced to make a copy now:
-		 */
-		size_t size = snapshot->eof - snapshot->start;
-		char *buf_copy = xmalloc(size);
-
-		memcpy(buf_copy, snapshot->start, size);
-		clear_snapshot_buffer(snapshot);
-		snapshot->buf = snapshot->start = buf_copy;
-		snapshot->eof = buf_copy + size;
-	}
-
-	return snapshot;
-}
-
-/*
- * Check that `refs->snapshot` (if present) still reflects the
- * contents of the `packed-refs` file. If not, clear the snapshot.
- */
-static void validate_snapshot(struct packed_ref_store *refs)
-{
-	if (refs->snapshot &&
-	    !stat_validity_check(&refs->snapshot->validity, refs->path))
-		clear_snapshot(refs);
-}
-
-/*
- * Get the `snapshot` for the specified packed_ref_store, creating and
- * populating it if it hasn't been read before or if the file has been
- * changed (according to its `validity` field) since it was last read.
- * On the other hand, if we hold the lock, then assume that the file
- * hasn't been changed out from under us, so skip the extra `stat()`
- * call in `stat_validity_check()`. This function does *not* increase
- * the snapshot's reference count on behalf of the caller.
- */
-static struct snapshot *get_snapshot(struct packed_ref_store *refs)
-{
-	if (!is_lock_file_locked(&refs->lock))
-		validate_snapshot(refs);
-
-	if (!refs->snapshot)
-		refs->snapshot = create_snapshot(refs);
-
-	return refs->snapshot;
-}
-
-static int packed_read_raw_ref(struct ref_store *ref_store,
-			       const char *refname, struct object_id *oid,
-			       struct strbuf *referent, unsigned int *type)
-{
-	struct packed_ref_store *refs =
-		packed_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
-	struct snapshot *snapshot = get_snapshot(refs);
-	const char *rec;
-
-	*type = 0;
-
-	rec = find_reference_location(snapshot, refname, 1);
-
-	if (!rec) {
-		/* refname is not a packed reference. */
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (get_oid_hex(rec, oid))
-		die_invalid_line(refs->path, rec, snapshot->eof - rec);
-
-	*type = REF_ISPACKED;
-	return 0;
-}
-
-/*
- * This value is set in `base.flags` if the peeled value of the
- * current reference is known. In that case, `peeled` contains the
- * correct peeled value for the reference, which might be `null_oid`
- * if the reference is not a tag or if it is broken.
- */
-#define REF_KNOWS_PEELED 0x40
-
-/*
- * An iterator over a snapshot of a `packed-refs` file.
- */
-struct packed_ref_iterator {
-	struct ref_iterator base;
-
-	struct snapshot *snapshot;
-
-	/* The current position in the snapshot's buffer: */
-	const char *pos;
-
-	/* The end of the part of the buffer that will be iterated over: */
-	const char *eof;
-
-	/* Scratch space for current values: */
-	struct object_id oid, peeled;
-	struct strbuf refname_buf;
-
-	unsigned int flags;
-};
-
-/*
- * Move the iterator to the next record in the snapshot, without
- * respect for whether the record is actually required by the current
- * iteration. Adjust the fields in `iter` and return `ITER_OK` or
- * `ITER_DONE`. This function does not free the iterator in the case
- * of `ITER_DONE`.
- */
-static int next_record(struct packed_ref_iterator *iter)
-{
-	const char *p = iter->pos, *eol;
-
-	strbuf_reset(&iter->refname_buf);
-
-	if (iter->pos == iter->eof)
-		return ITER_DONE;
-
-	iter->base.flags = REF_ISPACKED;
-
-	if (iter->eof - p < the_hash_algo->hexsz + 2 ||
-	    parse_oid_hex(p, &iter->oid, &p) ||
-	    !isspace(*p++))
-		die_invalid_line(iter->snapshot->refs->path,
-				 iter->pos, iter->eof - iter->pos);
-
-	eol = memchr(p, '\n', iter->eof - p);
-	if (!eol)
-		die_unterminated_line(iter->snapshot->refs->path,
-				      iter->pos, iter->eof - iter->pos);
-
-	strbuf_add(&iter->refname_buf, p, eol - p);
-	iter->base.refname = iter->refname_buf.buf;
-
-	if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
-		if (!refname_is_safe(iter->base.refname))
-			die("packed refname is dangerous: %s",
-			    iter->base.refname);
-		oidclr(&iter->oid);
-		iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
-	}
-	if (iter->snapshot->peeled == PEELED_FULLY ||
-	    (iter->snapshot->peeled == PEELED_TAGS &&
-	     starts_with(iter->base.refname, "refs/tags/")))
-		iter->base.flags |= REF_KNOWS_PEELED;
-
-	iter->pos = eol + 1;
-
-	if (iter->pos < iter->eof && *iter->pos == '^') {
-		p = iter->pos + 1;
-		if (iter->eof - p < the_hash_algo->hexsz + 1 ||
-		    parse_oid_hex(p, &iter->peeled, &p) ||
-		    *p++ != '\n')
-			die_invalid_line(iter->snapshot->refs->path,
-					 iter->pos, iter->eof - iter->pos);
-		iter->pos = p;
-
-		/*
-		 * Regardless of what the file header said, we
-		 * definitely know the value of *this* reference. But
-		 * we suppress it if the reference is broken:
-		 */
-		if ((iter->base.flags & REF_ISBROKEN)) {
-			oidclr(&iter->peeled);
-			iter->base.flags &= ~REF_KNOWS_PEELED;
-		} else {
-			iter->base.flags |= REF_KNOWS_PEELED;
-		}
-	} else {
-		oidclr(&iter->peeled);
-	}
-
-	return ITER_OK;
-}
-
-static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct packed_ref_iterator *iter =
-		(struct packed_ref_iterator *)ref_iterator;
-	int ok;
-
-	while ((ok = next_record(iter)) == ITER_OK) {
-		if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
-		    ref_type(iter->base.refname) != REF_TYPE_PER_WORKTREE)
-			continue;
-
-		if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
-		    !ref_resolves_to_object(iter->base.refname, &iter->oid,
-					    iter->flags))
-			continue;
-
-		return ITER_OK;
-	}
-
-	if (ref_iterator_abort(ref_iterator) != ITER_DONE)
-		ok = ITER_ERROR;
-
-	return ok;
-}
-
-static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct packed_ref_iterator *iter =
-		(struct packed_ref_iterator *)ref_iterator;
-
-	if ((iter->base.flags & REF_KNOWS_PEELED)) {
-		oidcpy(peeled, &iter->peeled);
-		return is_null_oid(&iter->peeled) ? -1 : 0;
-	} else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
-		return -1;
-	} else {
-		return !!peel_object(&iter->oid, peeled);
-	}
-}
-
-static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct packed_ref_iterator *iter =
-		(struct packed_ref_iterator *)ref_iterator;
-	int ok = ITER_DONE;
-
-	strbuf_release(&iter->refname_buf);
-	release_snapshot(iter->snapshot);
-	base_ref_iterator_free(ref_iterator);
-	return ok;
-}
-
-static struct ref_iterator_vtable packed_ref_iterator_vtable = {
-	packed_ref_iterator_advance,
-	packed_ref_iterator_peel,
-	packed_ref_iterator_abort
-};
-
-static struct ref_iterator *packed_ref_iterator_begin(
-		struct ref_store *ref_store,
-		const char *prefix, unsigned int flags)
-{
-	struct packed_ref_store *refs;
-	struct snapshot *snapshot;
-	const char *start;
-	struct packed_ref_iterator *iter;
-	struct ref_iterator *ref_iterator;
-	unsigned int required_flags = REF_STORE_READ;
-
-	if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
-		required_flags |= REF_STORE_ODB;
-	refs = packed_downcast(ref_store, required_flags, "ref_iterator_begin");
-
-	/*
-	 * Note that `get_snapshot()` internally checks whether the
-	 * snapshot is up to date with what is on disk, and re-reads
-	 * it if not.
-	 */
-	snapshot = get_snapshot(refs);
-
-	if (prefix && *prefix)
-		start = find_reference_location(snapshot, prefix, 0);
-	else
-		start = snapshot->start;
-
-	if (start == snapshot->eof)
-		return empty_ref_iterator_begin();
-
-	iter = xcalloc(1, sizeof(*iter));
-	ref_iterator = &iter->base;
-	base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable, 1);
-
-	iter->snapshot = snapshot;
-	acquire_snapshot(snapshot);
-
-	iter->pos = start;
-	iter->eof = snapshot->eof;
-	strbuf_init(&iter->refname_buf, 0);
-
-	iter->base.oid = &iter->oid;
-
-	iter->flags = flags;
-
-	if (prefix && *prefix)
-		/* Stop iteration after we've gone *past* prefix: */
-		ref_iterator = prefix_ref_iterator_begin(ref_iterator, prefix, 0);
-
-	return ref_iterator;
-}
-
-/*
- * Write an entry to the packed-refs file for the specified refname.
- * If peeled is non-NULL, write it as the entry's peeled value. On
- * error, return a nonzero value and leave errno set at the value left
- * by the failing call to `fprintf()`.
- */
-static int write_packed_entry(FILE *fh, const char *refname,
-			      const struct object_id *oid,
-			      const struct object_id *peeled)
-{
-	if (fprintf(fh, "%s %s\n", oid_to_hex(oid), refname) < 0 ||
-	    (peeled && fprintf(fh, "^%s\n", oid_to_hex(peeled)) < 0))
-		return -1;
-
-	return 0;
-}
-
-int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err)
-{
-	struct packed_ref_store *refs =
-		packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN,
-				"packed_refs_lock");
-	static int timeout_configured = 0;
-	static int timeout_value = 1000;
-
-	if (!timeout_configured) {
-		git_config_get_int("core.packedrefstimeout", &timeout_value);
-		timeout_configured = 1;
-	}
-
-	/*
-	 * Note that we close the lockfile immediately because we
-	 * don't write new content to it, but rather to a separate
-	 * tempfile.
-	 */
-	if (hold_lock_file_for_update_timeout(
-			    &refs->lock,
-			    refs->path,
-			    flags, timeout_value) < 0) {
-		unable_to_lock_message(refs->path, errno, err);
-		return -1;
-	}
-
-	if (close_lock_file_gently(&refs->lock)) {
-		strbuf_addf(err, "unable to close %s: %s", refs->path, strerror(errno));
-		rollback_lock_file(&refs->lock);
-		return -1;
-	}
-
-	/*
-	 * There is a stat-validity problem might cause `update-ref -d`
-	 * lost the newly commit of a ref, because a new `packed-refs`
-	 * file might has the same on-disk file attributes such as
-	 * timestamp, file size and inode value, but has a changed
-	 * ref value.
-	 *
-	 * This could happen with a very small chance when
-	 * `update-ref -d` is called and at the same time another
-	 * `pack-refs --all` process is running.
-	 *
-	 * Now that we hold the `packed-refs` lock, it is important
-	 * to make sure we could read the latest version of
-	 * `packed-refs` file no matter we have just mmap it or not.
-	 * So what need to do is clear the snapshot if we hold it
-	 * already.
-	 */
-	clear_snapshot(refs);
-
-	/*
-	 * Now make sure that the packed-refs file as it exists in the
-	 * locked state is loaded into the snapshot:
-	 */
-	get_snapshot(refs);
-	return 0;
-}
-
-void packed_refs_unlock(struct ref_store *ref_store)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ | REF_STORE_WRITE,
-			"packed_refs_unlock");
-
-	if (!is_lock_file_locked(&refs->lock))
-		BUG("packed_refs_unlock() called when not locked");
-	rollback_lock_file(&refs->lock);
-}
-
-int packed_refs_is_locked(struct ref_store *ref_store)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ | REF_STORE_WRITE,
-			"packed_refs_is_locked");
-
-	return is_lock_file_locked(&refs->lock);
-}
-
-/*
- * The packed-refs header line that we write out. Perhaps other traits
- * will be added later.
- *
- * Note that earlier versions of Git used to parse these traits by
- * looking for " trait " in the line. For this reason, the space after
- * the colon and the trailing space are required.
- */
-static const char PACKED_REFS_HEADER[] =
-	"# pack-refs with: peeled fully-peeled sorted \n";
-
-static int packed_init_db(struct ref_store *ref_store, struct strbuf *err)
-{
-	/* Nothing to do. */
-	return 0;
-}
-
-/*
- * Write the packed refs from the current snapshot to the packed-refs
- * tempfile, incorporating any changes from `updates`. `updates` must
- * be a sorted string list whose keys are the refnames and whose util
- * values are `struct ref_update *`. On error, rollback the tempfile,
- * write an error message to `err`, and return a nonzero value.
- *
- * The packfile must be locked before calling this function and will
- * remain locked when it is done.
- */
-static int write_with_updates(struct packed_ref_store *refs,
-			      struct string_list *updates,
-			      struct strbuf *err)
-{
-	struct ref_iterator *iter = NULL;
-	size_t i;
-	int ok;
-	FILE *out;
-	struct strbuf sb = STRBUF_INIT;
-	char *packed_refs_path;
-
-	if (!is_lock_file_locked(&refs->lock))
-		BUG("write_with_updates() called while unlocked");
-
-	/*
-	 * If packed-refs is a symlink, we want to overwrite the
-	 * symlinked-to file, not the symlink itself. Also, put the
-	 * staging file next to it:
-	 */
-	packed_refs_path = get_locked_file_path(&refs->lock);
-	strbuf_addf(&sb, "%s.new", packed_refs_path);
-	free(packed_refs_path);
-	refs->tempfile = create_tempfile(sb.buf);
-	if (!refs->tempfile) {
-		strbuf_addf(err, "unable to create file %s: %s",
-			    sb.buf, strerror(errno));
-		strbuf_release(&sb);
-		return -1;
-	}
-	strbuf_release(&sb);
-
-	out = fdopen_tempfile(refs->tempfile, "w");
-	if (!out) {
-		strbuf_addf(err, "unable to fdopen packed-refs tempfile: %s",
-			    strerror(errno));
-		goto error;
-	}
-
-	if (fprintf(out, "%s", PACKED_REFS_HEADER) < 0)
-		goto write_error;
-
-	/*
-	 * We iterate in parallel through the current list of refs and
-	 * the list of updates, processing an entry from at least one
-	 * of the lists each time through the loop. When the current
-	 * list of refs is exhausted, set iter to NULL. When the list
-	 * of updates is exhausted, leave i set to updates->nr.
-	 */
-	iter = packed_ref_iterator_begin(&refs->base, "",
-					 DO_FOR_EACH_INCLUDE_BROKEN);
-	if ((ok = ref_iterator_advance(iter)) != ITER_OK)
-		iter = NULL;
-
-	i = 0;
-
-	while (iter || i < updates->nr) {
-		struct ref_update *update = NULL;
-		int cmp;
-
-		if (i >= updates->nr) {
-			cmp = -1;
-		} else {
-			update = updates->items[i].util;
-
-			if (!iter)
-				cmp = +1;
-			else
-				cmp = strcmp(iter->refname, update->refname);
-		}
-
-		if (!cmp) {
-			/*
-			 * There is both an old value and an update
-			 * for this reference. Check the old value if
-			 * necessary:
-			 */
-			if ((update->flags & REF_HAVE_OLD)) {
-				if (is_null_oid(&update->old_oid)) {
-					strbuf_addf(err, "cannot update ref '%s': "
-						    "reference already exists",
-						    update->refname);
-					goto error;
-				} else if (!oideq(&update->old_oid, iter->oid)) {
-					strbuf_addf(err, "cannot update ref '%s': "
-						    "is at %s but expected %s",
-						    update->refname,
-						    oid_to_hex(iter->oid),
-						    oid_to_hex(&update->old_oid));
-					goto error;
-				}
-			}
-
-			/* Now figure out what to use for the new value: */
-			if ((update->flags & REF_HAVE_NEW)) {
-				/*
-				 * The update takes precedence. Skip
-				 * the iterator over the unneeded
-				 * value.
-				 */
-				if ((ok = ref_iterator_advance(iter)) != ITER_OK)
-					iter = NULL;
-				cmp = +1;
-			} else {
-				/*
-				 * The update doesn't actually want to
-				 * change anything. We're done with it.
-				 */
-				i++;
-				cmp = -1;
-			}
-		} else if (cmp > 0) {
-			/*
-			 * There is no old value but there is an
-			 * update for this reference. Make sure that
-			 * the update didn't expect an existing value:
-			 */
-			if ((update->flags & REF_HAVE_OLD) &&
-			    !is_null_oid(&update->old_oid)) {
-				strbuf_addf(err, "cannot update ref '%s': "
-					    "reference is missing but expected %s",
-					    update->refname,
-					    oid_to_hex(&update->old_oid));
-				goto error;
-			}
-		}
-
-		if (cmp < 0) {
-			/* Pass the old reference through. */
-
-			struct object_id peeled;
-			int peel_error = ref_iterator_peel(iter, &peeled);
-
-			if (write_packed_entry(out, iter->refname,
-					       iter->oid,
-					       peel_error ? NULL : &peeled))
-				goto write_error;
-
-			if ((ok = ref_iterator_advance(iter)) != ITER_OK)
-				iter = NULL;
-		} else if (is_null_oid(&update->new_oid)) {
-			/*
-			 * The update wants to delete the reference,
-			 * and the reference either didn't exist or we
-			 * have already skipped it. So we're done with
-			 * the update (and don't have to write
-			 * anything).
-			 */
-			i++;
-		} else {
-			struct object_id peeled;
-			int peel_error = peel_object(&update->new_oid,
-						     &peeled);
-
-			if (write_packed_entry(out, update->refname,
-					       &update->new_oid,
-					       peel_error ? NULL : &peeled))
-				goto write_error;
-
-			i++;
-		}
-	}
-
-	if (ok != ITER_DONE) {
-		strbuf_addstr(err, "unable to write packed-refs file: "
-			      "error iterating over old contents");
-		goto error;
-	}
-
-	if (close_tempfile_gently(refs->tempfile)) {
-		strbuf_addf(err, "error closing file %s: %s",
-			    get_tempfile_path(refs->tempfile),
-			    strerror(errno));
-		strbuf_release(&sb);
-		delete_tempfile(&refs->tempfile);
-		return -1;
-	}
-
-	return 0;
-
-write_error:
-	strbuf_addf(err, "error writing to %s: %s",
-		    get_tempfile_path(refs->tempfile), strerror(errno));
-
-error:
-	if (iter)
-		ref_iterator_abort(iter);
-
-	delete_tempfile(&refs->tempfile);
-	return -1;
-}
-
-int is_packed_transaction_needed(struct ref_store *ref_store,
-				 struct ref_transaction *transaction)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ,
-			"is_packed_transaction_needed");
-	struct strbuf referent = STRBUF_INIT;
-	size_t i;
-	int ret;
-
-	if (!is_lock_file_locked(&refs->lock))
-		BUG("is_packed_transaction_needed() called while unlocked");
-
-	/*
-	 * We're only going to bother returning false for the common,
-	 * trivial case that references are only being deleted, their
-	 * old values are not being checked, and the old `packed-refs`
-	 * file doesn't contain any of those reference(s). This gives
-	 * false positives for some other cases that could
-	 * theoretically be optimized away:
-	 *
-	 * 1. It could be that the old value is being verified without
-	 *    setting a new value. In this case, we could verify the
-	 *    old value here and skip the update if it agrees. If it
-	 *    disagrees, we could either let the update go through
-	 *    (the actual commit would re-detect and report the
-	 *    problem), or come up with a way of reporting such an
-	 *    error to *our* caller.
-	 *
-	 * 2. It could be that a new value is being set, but that it
-	 *    is identical to the current packed value of the
-	 *    reference.
-	 *
-	 * Neither of these cases will come up in the current code,
-	 * because the only caller of this function passes to it a
-	 * transaction that only includes `delete` updates with no
-	 * `old_id`. Even if that ever changes, false positives only
-	 * cause an optimization to be missed; they do not affect
-	 * correctness.
-	 */
-
-	/*
-	 * Start with the cheap checks that don't require old
-	 * reference values to be read:
-	 */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-
-		if (update->flags & REF_HAVE_OLD)
-			/* Have to check the old value -> needed. */
-			return 1;
-
-		if ((update->flags & REF_HAVE_NEW) && !is_null_oid(&update->new_oid))
-			/* Have to set a new value -> needed. */
-			return 1;
-	}
-
-	/*
-	 * The transaction isn't checking any old values nor is it
-	 * setting any nonzero new values, so it still might be able
-	 * to be skipped. Now do the more expensive check: the update
-	 * is needed if any of the updates is a delete, and the old
-	 * `packed-refs` file contains a value for that reference.
-	 */
-	ret = 0;
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		unsigned int type;
-		struct object_id oid;
-
-		if (!(update->flags & REF_HAVE_NEW))
-			/*
-			 * This reference isn't being deleted -> not
-			 * needed.
-			 */
-			continue;
-
-		if (!refs_read_raw_ref(ref_store, update->refname,
-				       &oid, &referent, &type) ||
-		    errno != ENOENT) {
-			/*
-			 * We have to actually delete that reference
-			 * -> this transaction is needed.
-			 */
-			ret = 1;
-			break;
-		}
-	}
-
-	strbuf_release(&referent);
-	return ret;
-}
-
-struct packed_transaction_backend_data {
-	/* True iff the transaction owns the packed-refs lock. */
-	int own_lock;
-
-	struct string_list updates;
-};
-
-static void packed_transaction_cleanup(struct packed_ref_store *refs,
-				       struct ref_transaction *transaction)
-{
-	struct packed_transaction_backend_data *data = transaction->backend_data;
-
-	if (data) {
-		string_list_clear(&data->updates, 0);
-
-		if (is_tempfile_active(refs->tempfile))
-			delete_tempfile(&refs->tempfile);
-
-		if (data->own_lock && is_lock_file_locked(&refs->lock)) {
-			packed_refs_unlock(&refs->base);
-			data->own_lock = 0;
-		}
-
-		free(data);
-		transaction->backend_data = NULL;
-	}
-
-	transaction->state = REF_TRANSACTION_CLOSED;
-}
-
-static int packed_transaction_prepare(struct ref_store *ref_store,
-				      struct ref_transaction *transaction,
-				      struct strbuf *err)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB,
-			"ref_transaction_prepare");
-	struct packed_transaction_backend_data *data;
-	size_t i;
-	int ret = TRANSACTION_GENERIC_ERROR;
-
-	/*
-	 * Note that we *don't* skip transactions with zero updates,
-	 * because such a transaction might be executed for the side
-	 * effect of ensuring that all of the references are peeled or
-	 * ensuring that the `packed-refs` file is sorted. If the
-	 * caller wants to optimize away empty transactions, it should
-	 * do so itself.
-	 */
-
-	data = xcalloc(1, sizeof(*data));
-	string_list_init(&data->updates, 0);
-
-	transaction->backend_data = data;
-
-	/*
-	 * Stick the updates in a string list by refname so that we
-	 * can sort them:
-	 */
-	for (i = 0; i < transaction->nr; i++) {
-		struct ref_update *update = transaction->updates[i];
-		struct string_list_item *item =
-			string_list_append(&data->updates, update->refname);
-
-		/* Store a pointer to update in item->util: */
-		item->util = update;
-	}
-	string_list_sort(&data->updates);
-
-	if (ref_update_reject_duplicates(&data->updates, err))
-		goto failure;
-
-	if (!is_lock_file_locked(&refs->lock)) {
-		if (packed_refs_lock(ref_store, 0, err))
-			goto failure;
-		data->own_lock = 1;
-	}
-
-	if (write_with_updates(refs, &data->updates, err))
-		goto failure;
-
-	transaction->state = REF_TRANSACTION_PREPARED;
-	return 0;
-
-failure:
-	packed_transaction_cleanup(refs, transaction);
-	return ret;
-}
-
-static int packed_transaction_abort(struct ref_store *ref_store,
-				    struct ref_transaction *transaction,
-				    struct strbuf *err)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB,
-			"ref_transaction_abort");
-
-	packed_transaction_cleanup(refs, transaction);
-	return 0;
-}
-
-static int packed_transaction_finish(struct ref_store *ref_store,
-				     struct ref_transaction *transaction,
-				     struct strbuf *err)
-{
-	struct packed_ref_store *refs = packed_downcast(
-			ref_store,
-			REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB,
-			"ref_transaction_finish");
-	int ret = TRANSACTION_GENERIC_ERROR;
-	char *packed_refs_path;
-
-	clear_snapshot(refs);
-
-	packed_refs_path = get_locked_file_path(&refs->lock);
-	if (rename_tempfile(&refs->tempfile, packed_refs_path)) {
-		strbuf_addf(err, "error replacing %s: %s",
-			    refs->path, strerror(errno));
-		goto cleanup;
-	}
-
-	ret = 0;
-
-cleanup:
-	free(packed_refs_path);
-	packed_transaction_cleanup(refs, transaction);
-	return ret;
-}
-
-static int packed_initial_transaction_commit(struct ref_store *ref_store,
-					    struct ref_transaction *transaction,
-					    struct strbuf *err)
-{
-	return ref_transaction_commit(transaction, err);
-}
-
-static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	struct packed_ref_store *refs =
-		packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
-	struct strbuf err = STRBUF_INIT;
-	struct ref_transaction *transaction;
-	struct string_list_item *item;
-	int ret;
-
-	(void)refs; /* We need the check above, but don't use the variable */
-
-	if (!refnames->nr)
-		return 0;
-
-	/*
-	 * Since we don't check the references' old_oids, the
-	 * individual updates can't fail, so we can pack all of the
-	 * updates into a single transaction.
-	 */
-
-	transaction = ref_store_transaction_begin(ref_store, &err);
-	if (!transaction)
-		return -1;
-
-	for_each_string_list_item(item, refnames) {
-		if (ref_transaction_delete(transaction, item->string, NULL,
-					   flags, msg, &err)) {
-			warning(_("could not delete reference %s: %s"),
-				item->string, err.buf);
-			strbuf_reset(&err);
-		}
-	}
-
-	ret = ref_transaction_commit(transaction, &err);
-
-	if (ret) {
-		if (refnames->nr == 1)
-			error(_("could not delete reference %s: %s"),
-			      refnames->items[0].string, err.buf);
-		else
-			error(_("could not delete references: %s"), err.buf);
-	}
-
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-	return ret;
-}
-
-static int packed_pack_refs(struct ref_store *ref_store, unsigned int flags)
-{
-	/*
-	 * Packed refs are already packed. It might be that loose refs
-	 * are packed *into* a packed refs store, but that is done by
-	 * updating the packed references via a transaction.
-	 */
-	return 0;
-}
-
-static int packed_create_symref(struct ref_store *ref_store,
-			       const char *refname, const char *target,
-			       const char *logmsg)
-{
-	BUG("packed reference store does not support symrefs");
-}
-
-static int packed_rename_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
-{
-	BUG("packed reference store does not support renaming references");
-}
-
-static int packed_copy_ref(struct ref_store *ref_store,
-			   const char *oldrefname, const char *newrefname,
-			   const char *logmsg)
-{
-	BUG("packed reference store does not support copying references");
-}
-
-static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)
-{
-	return empty_ref_iterator_begin();
-}
-
-static int packed_for_each_reflog_ent(struct ref_store *ref_store,
-				      const char *refname,
-				      each_reflog_ent_fn fn, void *cb_data)
-{
-	return 0;
-}
-
-static int packed_for_each_reflog_ent_reverse(struct ref_store *ref_store,
-					      const char *refname,
-					      each_reflog_ent_fn fn,
-					      void *cb_data)
-{
-	return 0;
-}
-
-static int packed_reflog_exists(struct ref_store *ref_store,
-			       const char *refname)
-{
-	return 0;
-}
-
-static int packed_create_reflog(struct ref_store *ref_store,
-			       const char *refname, int force_create,
-			       struct strbuf *err)
-{
-	BUG("packed reference store does not support reflogs");
-}
-
-static int packed_delete_reflog(struct ref_store *ref_store,
-			       const char *refname)
-{
-	return 0;
-}
-
-static int packed_reflog_expire(struct ref_store *ref_store,
-				const char *refname, const struct object_id *oid,
-				unsigned int flags,
-				reflog_expiry_prepare_fn prepare_fn,
-				reflog_expiry_should_prune_fn should_prune_fn,
-				reflog_expiry_cleanup_fn cleanup_fn,
-				void *policy_cb_data)
-{
-	return 0;
-}
-
-struct ref_storage_be refs_be_packed = {
-	NULL,
-	"packed",
-	packed_ref_store_create,
-	packed_init_db,
-	packed_transaction_prepare,
-	packed_transaction_finish,
-	packed_transaction_abort,
-	packed_initial_transaction_commit,
-
-	packed_pack_refs,
-	packed_create_symref,
-	packed_delete_refs,
-	packed_rename_ref,
-	packed_copy_ref,
-
-	packed_ref_iterator_begin,
-	packed_read_raw_ref,
-
-	packed_reflog_iterator_begin,
-	packed_for_each_reflog_ent,
-	packed_for_each_reflog_ent_reverse,
-	packed_reflog_exists,
-	packed_create_reflog,
-	packed_delete_reflog,
-	packed_reflog_expire
-};
diff --git a/third_party/git/refs/packed-backend.h b/third_party/git/refs/packed-backend.h
deleted file mode 100644
index a01a0aff9c77..000000000000
--- a/third_party/git/refs/packed-backend.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef REFS_PACKED_BACKEND_H
-#define REFS_PACKED_BACKEND_H
-
-struct ref_transaction;
-
-/*
- * Support for storing references in a `packed-refs` file.
- *
- * Note that this backend doesn't check for D/F conflicts, because it
- * doesn't care about them. But usually it should be wrapped in a
- * `files_ref_store` that prevents D/F conflicts from being created,
- * even among packed refs.
- */
-
-struct ref_store *packed_ref_store_create(const char *path,
-					  unsigned int store_flags);
-
-/*
- * Lock the packed-refs file for writing. Flags is passed to
- * hold_lock_file_for_update(). Return 0 on success. On errors, write
- * an error message to `err` and return a nonzero value.
- */
-int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err);
-
-void packed_refs_unlock(struct ref_store *ref_store);
-int packed_refs_is_locked(struct ref_store *ref_store);
-
-/*
- * Return true if `transaction` really needs to be carried out against
- * the specified packed_ref_store, or false if it can be skipped
- * (i.e., because it is an obvious NOOP). `ref_store` must be locked
- * before calling this function.
- */
-int is_packed_transaction_needed(struct ref_store *ref_store,
-				 struct ref_transaction *transaction);
-
-#endif /* REFS_PACKED_BACKEND_H */
diff --git a/third_party/git/refs/ref-cache.c b/third_party/git/refs/ref-cache.c
deleted file mode 100644
index b7052f72e2f4..000000000000
--- a/third_party/git/refs/ref-cache.c
+++ /dev/null
@@ -1,551 +0,0 @@
-#include "../cache.h"
-#include "../refs.h"
-#include "refs-internal.h"
-#include "ref-cache.h"
-#include "../iterator.h"
-
-void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
-{
-	ALLOC_GROW(dir->entries, dir->nr + 1, dir->alloc);
-	dir->entries[dir->nr++] = entry;
-	/* optimize for the case that entries are added in order */
-	if (dir->nr == 1 ||
-	    (dir->nr == dir->sorted + 1 &&
-	     strcmp(dir->entries[dir->nr - 2]->name,
-		    dir->entries[dir->nr - 1]->name) < 0))
-		dir->sorted = dir->nr;
-}
-
-struct ref_dir *get_ref_dir(struct ref_entry *entry)
-{
-	struct ref_dir *dir;
-	assert(entry->flag & REF_DIR);
-	dir = &entry->u.subdir;
-	if (entry->flag & REF_INCOMPLETE) {
-		if (!dir->cache->fill_ref_dir)
-			BUG("incomplete ref_store without fill_ref_dir function");
-
-		dir->cache->fill_ref_dir(dir->cache->ref_store, dir, entry->name);
-		entry->flag &= ~REF_INCOMPLETE;
-	}
-	return dir;
-}
-
-struct ref_entry *create_ref_entry(const char *refname,
-				   const struct object_id *oid, int flag)
-{
-	struct ref_entry *ref;
-
-	FLEX_ALLOC_STR(ref, name, refname);
-	oidcpy(&ref->u.value.oid, oid);
-	ref->flag = flag;
-	return ref;
-}
-
-struct ref_cache *create_ref_cache(struct ref_store *refs,
-				   fill_ref_dir_fn *fill_ref_dir)
-{
-	struct ref_cache *ret = xcalloc(1, sizeof(*ret));
-
-	ret->ref_store = refs;
-	ret->fill_ref_dir = fill_ref_dir;
-	ret->root = create_dir_entry(ret, "", 0, 1);
-	return ret;
-}
-
-static void clear_ref_dir(struct ref_dir *dir);
-
-static void free_ref_entry(struct ref_entry *entry)
-{
-	if (entry->flag & REF_DIR) {
-		/*
-		 * Do not use get_ref_dir() here, as that might
-		 * trigger the reading of loose refs.
-		 */
-		clear_ref_dir(&entry->u.subdir);
-	}
-	free(entry);
-}
-
-void free_ref_cache(struct ref_cache *cache)
-{
-	free_ref_entry(cache->root);
-	free(cache);
-}
-
-/*
- * Clear and free all entries in dir, recursively.
- */
-static void clear_ref_dir(struct ref_dir *dir)
-{
-	int i;
-	for (i = 0; i < dir->nr; i++)
-		free_ref_entry(dir->entries[i]);
-	FREE_AND_NULL(dir->entries);
-	dir->sorted = dir->nr = dir->alloc = 0;
-}
-
-struct ref_entry *create_dir_entry(struct ref_cache *cache,
-				   const char *dirname, size_t len,
-				   int incomplete)
-{
-	struct ref_entry *direntry;
-
-	FLEX_ALLOC_MEM(direntry, name, dirname, len);
-	direntry->u.subdir.cache = cache;
-	direntry->flag = REF_DIR | (incomplete ? REF_INCOMPLETE : 0);
-	return direntry;
-}
-
-static int ref_entry_cmp(const void *a, const void *b)
-{
-	struct ref_entry *one = *(struct ref_entry **)a;
-	struct ref_entry *two = *(struct ref_entry **)b;
-	return strcmp(one->name, two->name);
-}
-
-static void sort_ref_dir(struct ref_dir *dir);
-
-struct string_slice {
-	size_t len;
-	const char *str;
-};
-
-static int ref_entry_cmp_sslice(const void *key_, const void *ent_)
-{
-	const struct string_slice *key = key_;
-	const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;
-	int cmp = strncmp(key->str, ent->name, key->len);
-	if (cmp)
-		return cmp;
-	return '\0' - (unsigned char)ent->name[key->len];
-}
-
-int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len)
-{
-	struct ref_entry **r;
-	struct string_slice key;
-
-	if (refname == NULL || !dir->nr)
-		return -1;
-
-	sort_ref_dir(dir);
-	key.len = len;
-	key.str = refname;
-	r = bsearch(&key, dir->entries, dir->nr, sizeof(*dir->entries),
-		    ref_entry_cmp_sslice);
-
-	if (r == NULL)
-		return -1;
-
-	return r - dir->entries;
-}
-
-/*
- * Search for a directory entry directly within dir (without
- * recursing).  Sort dir if necessary.  subdirname must be a directory
- * name (i.e., end in '/').  If mkdir is set, then create the
- * directory if it is missing; otherwise, return NULL if the desired
- * directory cannot be found.  dir must already be complete.
- */
-static struct ref_dir *search_for_subdir(struct ref_dir *dir,
-					 const char *subdirname, size_t len,
-					 int mkdir)
-{
-	int entry_index = search_ref_dir(dir, subdirname, len);
-	struct ref_entry *entry;
-	if (entry_index == -1) {
-		if (!mkdir)
-			return NULL;
-		/*
-		 * Since dir is complete, the absence of a subdir
-		 * means that the subdir really doesn't exist;
-		 * therefore, create an empty record for it but mark
-		 * the record complete.
-		 */
-		entry = create_dir_entry(dir->cache, subdirname, len, 0);
-		add_entry_to_dir(dir, entry);
-	} else {
-		entry = dir->entries[entry_index];
-	}
-	return get_ref_dir(entry);
-}
-
-/*
- * If refname is a reference name, find the ref_dir within the dir
- * tree that should hold refname. If refname is a directory name
- * (i.e., it ends in '/'), then return that ref_dir itself. dir must
- * represent the top-level directory and must already be complete.
- * Sort ref_dirs and recurse into subdirectories as necessary. If
- * mkdir is set, then create any missing directories; otherwise,
- * return NULL if the desired directory cannot be found.
- */
-static struct ref_dir *find_containing_dir(struct ref_dir *dir,
-					   const char *refname, int mkdir)
-{
-	const char *slash;
-	for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
-		size_t dirnamelen = slash - refname + 1;
-		struct ref_dir *subdir;
-		subdir = search_for_subdir(dir, refname, dirnamelen, mkdir);
-		if (!subdir) {
-			dir = NULL;
-			break;
-		}
-		dir = subdir;
-	}
-
-	return dir;
-}
-
-struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname)
-{
-	int entry_index;
-	struct ref_entry *entry;
-	dir = find_containing_dir(dir, refname, 0);
-	if (!dir)
-		return NULL;
-	entry_index = search_ref_dir(dir, refname, strlen(refname));
-	if (entry_index == -1)
-		return NULL;
-	entry = dir->entries[entry_index];
-	return (entry->flag & REF_DIR) ? NULL : entry;
-}
-
-int remove_entry_from_dir(struct ref_dir *dir, const char *refname)
-{
-	int refname_len = strlen(refname);
-	int entry_index;
-	struct ref_entry *entry;
-	int is_dir = refname[refname_len - 1] == '/';
-	if (is_dir) {
-		/*
-		 * refname represents a reference directory.  Remove
-		 * the trailing slash; otherwise we will get the
-		 * directory *representing* refname rather than the
-		 * one *containing* it.
-		 */
-		char *dirname = xmemdupz(refname, refname_len - 1);
-		dir = find_containing_dir(dir, dirname, 0);
-		free(dirname);
-	} else {
-		dir = find_containing_dir(dir, refname, 0);
-	}
-	if (!dir)
-		return -1;
-	entry_index = search_ref_dir(dir, refname, refname_len);
-	if (entry_index == -1)
-		return -1;
-	entry = dir->entries[entry_index];
-
-	MOVE_ARRAY(&dir->entries[entry_index],
-		   &dir->entries[entry_index + 1], dir->nr - entry_index - 1);
-	dir->nr--;
-	if (dir->sorted > entry_index)
-		dir->sorted--;
-	free_ref_entry(entry);
-	return dir->nr;
-}
-
-int add_ref_entry(struct ref_dir *dir, struct ref_entry *ref)
-{
-	dir = find_containing_dir(dir, ref->name, 1);
-	if (!dir)
-		return -1;
-	add_entry_to_dir(dir, ref);
-	return 0;
-}
-
-/*
- * Emit a warning and return true iff ref1 and ref2 have the same name
- * and the same oid. Die if they have the same name but different
- * oids.
- */
-static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
-{
-	if (strcmp(ref1->name, ref2->name))
-		return 0;
-
-	/* Duplicate name; make sure that they don't conflict: */
-
-	if ((ref1->flag & REF_DIR) || (ref2->flag & REF_DIR))
-		/* This is impossible by construction */
-		die("Reference directory conflict: %s", ref1->name);
-
-	if (!oideq(&ref1->u.value.oid, &ref2->u.value.oid))
-		die("Duplicated ref, and SHA1s don't match: %s", ref1->name);
-
-	warning("Duplicated ref: %s", ref1->name);
-	return 1;
-}
-
-/*
- * Sort the entries in dir non-recursively (if they are not already
- * sorted) and remove any duplicate entries.
- */
-static void sort_ref_dir(struct ref_dir *dir)
-{
-	int i, j;
-	struct ref_entry *last = NULL;
-
-	/*
-	 * This check also prevents passing a zero-length array to qsort(),
-	 * which is a problem on some platforms.
-	 */
-	if (dir->sorted == dir->nr)
-		return;
-
-	QSORT(dir->entries, dir->nr, ref_entry_cmp);
-
-	/* Remove any duplicates: */
-	for (i = 0, j = 0; j < dir->nr; j++) {
-		struct ref_entry *entry = dir->entries[j];
-		if (last && is_dup_ref(last, entry))
-			free_ref_entry(entry);
-		else
-			last = dir->entries[i++] = entry;
-	}
-	dir->sorted = dir->nr = i;
-}
-
-enum prefix_state {
-	/* All refs within the directory would match prefix: */
-	PREFIX_CONTAINS_DIR,
-
-	/* Some, but not all, refs within the directory might match prefix: */
-	PREFIX_WITHIN_DIR,
-
-	/* No refs within the directory could possibly match prefix: */
-	PREFIX_EXCLUDES_DIR
-};
-
-/*
- * Return a `prefix_state` constant describing the relationship
- * between the directory with the specified `dirname` and `prefix`.
- */
-static enum prefix_state overlaps_prefix(const char *dirname,
-					 const char *prefix)
-{
-	while (*prefix && *dirname == *prefix) {
-		dirname++;
-		prefix++;
-	}
-	if (!*prefix)
-		return PREFIX_CONTAINS_DIR;
-	else if (!*dirname)
-		return PREFIX_WITHIN_DIR;
-	else
-		return PREFIX_EXCLUDES_DIR;
-}
-
-/*
- * Load all of the refs from `dir` (recursively) that could possibly
- * contain references matching `prefix` into our in-memory cache. If
- * `prefix` is NULL, prime unconditionally.
- */
-static void prime_ref_dir(struct ref_dir *dir, const char *prefix)
-{
-	/*
-	 * The hard work of loading loose refs is done by get_ref_dir(), so we
-	 * just need to recurse through all of the sub-directories. We do not
-	 * even need to care about sorting, as traversal order does not matter
-	 * to us.
-	 */
-	int i;
-	for (i = 0; i < dir->nr; i++) {
-		struct ref_entry *entry = dir->entries[i];
-		if (!(entry->flag & REF_DIR)) {
-			/* Not a directory; no need to recurse. */
-		} else if (!prefix) {
-			/* Recurse in any case: */
-			prime_ref_dir(get_ref_dir(entry), NULL);
-		} else {
-			switch (overlaps_prefix(entry->name, prefix)) {
-			case PREFIX_CONTAINS_DIR:
-				/*
-				 * Recurse, and from here down we
-				 * don't have to check the prefix
-				 * anymore:
-				 */
-				prime_ref_dir(get_ref_dir(entry), NULL);
-				break;
-			case PREFIX_WITHIN_DIR:
-				prime_ref_dir(get_ref_dir(entry), prefix);
-				break;
-			case PREFIX_EXCLUDES_DIR:
-				/* No need to prime this directory. */
-				break;
-			}
-		}
-	}
-}
-
-/*
- * A level in the reference hierarchy that is currently being iterated
- * through.
- */
-struct cache_ref_iterator_level {
-	/*
-	 * The ref_dir being iterated over at this level. The ref_dir
-	 * is sorted before being stored here.
-	 */
-	struct ref_dir *dir;
-
-	enum prefix_state prefix_state;
-
-	/*
-	 * The index of the current entry within dir (which might
-	 * itself be a directory). If index == -1, then the iteration
-	 * hasn't yet begun. If index == dir->nr, then the iteration
-	 * through this level is over.
-	 */
-	int index;
-};
-
-/*
- * Represent an iteration through a ref_dir in the memory cache. The
- * iteration recurses through subdirectories.
- */
-struct cache_ref_iterator {
-	struct ref_iterator base;
-
-	/*
-	 * The number of levels currently on the stack. This is always
-	 * at least 1, because when it becomes zero the iteration is
-	 * ended and this struct is freed.
-	 */
-	size_t levels_nr;
-
-	/* The number of levels that have been allocated on the stack */
-	size_t levels_alloc;
-
-	/*
-	 * Only include references with this prefix in the iteration.
-	 * The prefix is matched textually, without regard for path
-	 * component boundaries.
-	 */
-	const char *prefix;
-
-	/*
-	 * A stack of levels. levels[0] is the uppermost level that is
-	 * being iterated over in this iteration. (This is not
-	 * necessary the top level in the references hierarchy. If we
-	 * are iterating through a subtree, then levels[0] will hold
-	 * the ref_dir for that subtree, and subsequent levels will go
-	 * on from there.)
-	 */
-	struct cache_ref_iterator_level *levels;
-};
-
-static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
-{
-	struct cache_ref_iterator *iter =
-		(struct cache_ref_iterator *)ref_iterator;
-
-	while (1) {
-		struct cache_ref_iterator_level *level =
-			&iter->levels[iter->levels_nr - 1];
-		struct ref_dir *dir = level->dir;
-		struct ref_entry *entry;
-		enum prefix_state entry_prefix_state;
-
-		if (level->index == -1)
-			sort_ref_dir(dir);
-
-		if (++level->index == level->dir->nr) {
-			/* This level is exhausted; pop up a level */
-			if (--iter->levels_nr == 0)
-				return ref_iterator_abort(ref_iterator);
-
-			continue;
-		}
-
-		entry = dir->entries[level->index];
-
-		if (level->prefix_state == PREFIX_WITHIN_DIR) {
-			entry_prefix_state = overlaps_prefix(entry->name, iter->prefix);
-			if (entry_prefix_state == PREFIX_EXCLUDES_DIR)
-				continue;
-		} else {
-			entry_prefix_state = level->prefix_state;
-		}
-
-		if (entry->flag & REF_DIR) {
-			/* push down a level */
-			ALLOC_GROW(iter->levels, iter->levels_nr + 1,
-				   iter->levels_alloc);
-
-			level = &iter->levels[iter->levels_nr++];
-			level->dir = get_ref_dir(entry);
-			level->prefix_state = entry_prefix_state;
-			level->index = -1;
-		} else {
-			iter->base.refname = entry->name;
-			iter->base.oid = &entry->u.value.oid;
-			iter->base.flags = entry->flag;
-			return ITER_OK;
-		}
-	}
-}
-
-static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	return peel_object(ref_iterator->oid, peeled);
-}
-
-static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator)
-{
-	struct cache_ref_iterator *iter =
-		(struct cache_ref_iterator *)ref_iterator;
-
-	free((char *)iter->prefix);
-	free(iter->levels);
-	base_ref_iterator_free(ref_iterator);
-	return ITER_DONE;
-}
-
-static struct ref_iterator_vtable cache_ref_iterator_vtable = {
-	cache_ref_iterator_advance,
-	cache_ref_iterator_peel,
-	cache_ref_iterator_abort
-};
-
-struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
-					      const char *prefix,
-					      int prime_dir)
-{
-	struct ref_dir *dir;
-	struct cache_ref_iterator *iter;
-	struct ref_iterator *ref_iterator;
-	struct cache_ref_iterator_level *level;
-
-	dir = get_ref_dir(cache->root);
-	if (prefix && *prefix)
-		dir = find_containing_dir(dir, prefix, 0);
-	if (!dir)
-		/* There's nothing to iterate over. */
-		return empty_ref_iterator_begin();
-
-	if (prime_dir)
-		prime_ref_dir(dir, prefix);
-
-	iter = xcalloc(1, sizeof(*iter));
-	ref_iterator = &iter->base;
-	base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable, 1);
-	ALLOC_GROW(iter->levels, 10, iter->levels_alloc);
-
-	iter->levels_nr = 1;
-	level = &iter->levels[0];
-	level->index = -1;
-	level->dir = dir;
-
-	if (prefix && *prefix) {
-		iter->prefix = xstrdup(prefix);
-		level->prefix_state = PREFIX_WITHIN_DIR;
-	} else {
-		level->prefix_state = PREFIX_CONTAINS_DIR;
-	}
-
-	return ref_iterator;
-}
diff --git a/third_party/git/refs/ref-cache.h b/third_party/git/refs/ref-cache.h
deleted file mode 100644
index 3bfb89d2b343..000000000000
--- a/third_party/git/refs/ref-cache.h
+++ /dev/null
@@ -1,243 +0,0 @@
-#ifndef REFS_REF_CACHE_H
-#define REFS_REF_CACHE_H
-
-#include "cache.h"
-
-struct ref_dir;
-struct ref_store;
-
-/*
- * If this ref_cache is filled lazily, this function is used to load
- * information into the specified ref_dir (shallow or deep, at the
- * option of the ref_store). dirname includes a trailing slash.
- */
-typedef void fill_ref_dir_fn(struct ref_store *ref_store,
-			     struct ref_dir *dir, const char *dirname);
-
-struct ref_cache {
-	struct ref_entry *root;
-
-	/* A pointer to the ref_store whose cache this is: */
-	struct ref_store *ref_store;
-
-	/*
-	 * Function used (if necessary) to lazily-fill cache. May be
-	 * NULL.
-	 */
-	fill_ref_dir_fn *fill_ref_dir;
-};
-
-/*
- * Information used (along with the information in ref_entry) to
- * describe a single cached reference.  This data structure only
- * occurs embedded in a union in struct ref_entry, and only when
- * (ref_entry->flag & REF_DIR) is zero.
- */
-struct ref_value {
-	/*
-	 * The name of the object to which this reference resolves
-	 * (which may be a tag object).  If REF_ISBROKEN, this is
-	 * null.  If REF_ISSYMREF, then this is the name of the object
-	 * referred to by the last reference in the symlink chain.
-	 */
-	struct object_id oid;
-};
-
-/*
- * Information used (along with the information in ref_entry) to
- * describe a level in the hierarchy of references.  This data
- * structure only occurs embedded in a union in struct ref_entry, and
- * only when (ref_entry.flag & REF_DIR) is set.  In that case,
- * (ref_entry.flag & REF_INCOMPLETE) determines whether the references
- * in the directory have already been read:
- *
- *     (ref_entry.flag & REF_INCOMPLETE) unset -- a directory of loose
- *         or packed references, already read.
- *
- *     (ref_entry.flag & REF_INCOMPLETE) set -- a directory of loose
- *         references that hasn't been read yet (nor has any of its
- *         subdirectories).
- *
- * Entries within a directory are stored within a growable array of
- * pointers to ref_entries (entries, nr, alloc).  Entries 0 <= i <
- * sorted are sorted by their component name in strcmp() order and the
- * remaining entries are unsorted.
- *
- * Loose references are read lazily, one directory at a time.  When a
- * directory of loose references is read, then all of the references
- * in that directory are stored, and REF_INCOMPLETE stubs are created
- * for any subdirectories, but the subdirectories themselves are not
- * read.  The reading is triggered by get_ref_dir().
- */
-struct ref_dir {
-	int nr, alloc;
-
-	/*
-	 * Entries with index 0 <= i < sorted are sorted by name.  New
-	 * entries are appended to the list unsorted, and are sorted
-	 * only when required; thus we avoid the need to sort the list
-	 * after the addition of every reference.
-	 */
-	int sorted;
-
-	/* The ref_cache containing this entry: */
-	struct ref_cache *cache;
-
-	struct ref_entry **entries;
-};
-
-/*
- * Bit values for ref_entry::flag.  REF_ISSYMREF=0x01,
- * REF_ISPACKED=0x02, REF_ISBROKEN=0x04 and REF_BAD_NAME=0x08 are
- * public values; see refs.h.
- */
-
-/* ref_entry represents a directory of references */
-#define REF_DIR 0x10
-
-/*
- * Entry has not yet been read from disk (used only for REF_DIR
- * entries representing loose references)
- */
-#define REF_INCOMPLETE 0x20
-
-/*
- * A ref_entry represents either a reference or a "subdirectory" of
- * references.
- *
- * Each directory in the reference namespace is represented by a
- * ref_entry with (flags & REF_DIR) set and containing a subdir member
- * that holds the entries in that directory that have been read so
- * far.  If (flags & REF_INCOMPLETE) is set, then the directory and
- * its subdirectories haven't been read yet.  REF_INCOMPLETE is only
- * used for loose reference directories.
- *
- * References are represented by a ref_entry with (flags & REF_DIR)
- * unset and a value member that describes the reference's value.  The
- * flag member is at the ref_entry level, but it is also needed to
- * interpret the contents of the value field (in other words, a
- * ref_value object is not very much use without the enclosing
- * ref_entry).
- *
- * Reference names cannot end with slash and directories' names are
- * always stored with a trailing slash (except for the top-level
- * directory, which is always denoted by "").  This has two nice
- * consequences: (1) when the entries in each subdir are sorted
- * lexicographically by name (as they usually are), the references in
- * a whole tree can be generated in lexicographic order by traversing
- * the tree in left-to-right, depth-first order; (2) the names of
- * references and subdirectories cannot conflict, and therefore the
- * presence of an empty subdirectory does not block the creation of a
- * similarly-named reference.  (The fact that reference names with the
- * same leading components can conflict *with each other* is a
- * separate issue that is regulated by refs_verify_refname_available().)
- *
- * Please note that the name field contains the fully-qualified
- * reference (or subdirectory) name.  Space could be saved by only
- * storing the relative names.  But that would require the full names
- * to be generated on the fly when iterating in do_for_each_ref(), and
- * would break callback functions, who have always been able to assume
- * that the name strings that they are passed will not be freed during
- * the iteration.
- */
-struct ref_entry {
-	unsigned char flag; /* ISSYMREF? ISPACKED? */
-	union {
-		struct ref_value value; /* if not (flags&REF_DIR) */
-		struct ref_dir subdir; /* if (flags&REF_DIR) */
-	} u;
-	/*
-	 * The full name of the reference (e.g., "refs/heads/master")
-	 * or the full name of the directory with a trailing slash
-	 * (e.g., "refs/heads/"):
-	 */
-	char name[FLEX_ARRAY];
-};
-
-/*
- * Return the index of the entry with the given refname from the
- * ref_dir (non-recursively), sorting dir if necessary.  Return -1 if
- * no such entry is found.  dir must already be complete.
- */
-int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len);
-
-struct ref_dir *get_ref_dir(struct ref_entry *entry);
-
-/*
- * Create a struct ref_entry object for the specified dirname.
- * dirname is the name of the directory with a trailing slash (e.g.,
- * "refs/heads/") or "" for the top-level directory.
- */
-struct ref_entry *create_dir_entry(struct ref_cache *cache,
-				   const char *dirname, size_t len,
-				   int incomplete);
-
-struct ref_entry *create_ref_entry(const char *refname,
-				   const struct object_id *oid, int flag);
-
-/*
- * Return a pointer to a new `ref_cache`. Its top-level starts out
- * marked incomplete. If `fill_ref_dir` is non-NULL, it is the
- * function called to fill in incomplete directories in the
- * `ref_cache` when they are accessed. If it is NULL, then the whole
- * `ref_cache` must be filled (including clearing its directories'
- * `REF_INCOMPLETE` bits) before it is used, and `refs` can be NULL,
- * too.
- */
-struct ref_cache *create_ref_cache(struct ref_store *refs,
-				   fill_ref_dir_fn *fill_ref_dir);
-
-/*
- * Free the `ref_cache` and all of its associated data.
- */
-void free_ref_cache(struct ref_cache *cache);
-
-/*
- * Add a ref_entry to the end of dir (unsorted).  Entry is always
- * stored directly in dir; no recursion into subdirectories is
- * done.
- */
-void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry);
-
-/*
- * Remove the entry with the given name from dir, recursing into
- * subdirectories as necessary.  If refname is the name of a directory
- * (i.e., ends with '/'), then remove the directory and its contents.
- * If the removal was successful, return the number of entries
- * remaining in the directory entry that contained the deleted entry.
- * If the name was not found, return -1.  Please note that this
- * function only deletes the entry from the cache; it does not delete
- * it from the filesystem or ensure that other cache entries (which
- * might be symbolic references to the removed entry) are updated.
- * Nor does it remove any containing dir entries that might be made
- * empty by the removal.  dir must represent the top-level directory
- * and must already be complete.
- */
-int remove_entry_from_dir(struct ref_dir *dir, const char *refname);
-
-/*
- * Add a ref_entry to the ref_dir (unsorted), recursing into
- * subdirectories as necessary.  dir must represent the top-level
- * directory.  Return 0 on success.
- */
-int add_ref_entry(struct ref_dir *dir, struct ref_entry *ref);
-
-/*
- * Find the value entry with the given name in dir, sorting ref_dirs
- * and recursing into subdirectories as necessary.  If the name is not
- * found or it corresponds to a directory entry, return NULL.
- */
-struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname);
-
-/*
- * Start iterating over references in `cache`. If `prefix` is
- * specified, only include references whose names start with that
- * prefix. If `prime_dir` is true, then fill any incomplete
- * directories before beginning the iteration. The output is ordered
- * by refname.
- */
-struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
-					      const char *prefix,
-					      int prime_dir);
-
-#endif /* REFS_REF_CACHE_H */
diff --git a/third_party/git/refs/refs-internal.h b/third_party/git/refs/refs-internal.h
deleted file mode 100644
index 467f4b3c936d..000000000000
--- a/third_party/git/refs/refs-internal.h
+++ /dev/null
@@ -1,705 +0,0 @@
-#ifndef REFS_REFS_INTERNAL_H
-#define REFS_REFS_INTERNAL_H
-
-#include "cache.h"
-#include "refs.h"
-#include "iterator.h"
-
-struct ref_transaction;
-
-/*
- * Data structures and functions for the internal use of the refs
- * module. Code outside of the refs module should use only the public
- * functions defined in "refs.h", and should *not* include this file.
- */
-
-/*
- * The following flags can appear in `ref_update::flags`. Their
- * numerical values must not conflict with those of REF_NO_DEREF and
- * REF_FORCE_CREATE_REFLOG, which are also stored in
- * `ref_update::flags`.
- */
-
-/*
- * The reference should be updated to new_oid.
- */
-#define REF_HAVE_NEW (1 << 2)
-
-/*
- * The current reference's value should be checked to make sure that
- * it agrees with old_oid.
- */
-#define REF_HAVE_OLD (1 << 3)
-
-/*
- * Used as a flag in ref_update::flags when we want to log a ref
- * update but not actually perform it.  This is used when a symbolic
- * ref update is split up.
- */
-#define REF_LOG_ONLY (1 << 7)
-
-/*
- * Return the length of time to retry acquiring a loose reference lock
- * before giving up, in milliseconds:
- */
-long get_files_ref_lock_timeout_ms(void);
-
-/*
- * Return true iff refname is minimally safe. "Safe" here means that
- * deleting a loose reference by this name will not do any damage, for
- * example by causing a file that is not a reference to be deleted.
- * This function does not check that the reference name is legal; for
- * that, use check_refname_format().
- *
- * A refname that starts with "refs/" is considered safe iff it
- * doesn't contain any "." or ".." components or consecutive '/'
- * characters, end with '/', or (on Windows) contain any '\'
- * characters. Names that do not start with "refs/" are considered
- * safe iff they consist entirely of upper case characters and '_'
- * (like "HEAD" and "MERGE_HEAD" but not "config" or "FOO/BAR").
- */
-int refname_is_safe(const char *refname);
-
-/*
- * Helper function: return true if refname, which has the specified
- * oid and flags, can be resolved to an object in the database. If the
- * referred-to object does not exist, emit a warning and return false.
- */
-int ref_resolves_to_object(const char *refname,
-			   const struct object_id *oid,
-			   unsigned int flags);
-
-enum peel_status {
-	/* object was peeled successfully: */
-	PEEL_PEELED = 0,
-
-	/*
-	 * object cannot be peeled because the named object (or an
-	 * object referred to by a tag in the peel chain), does not
-	 * exist.
-	 */
-	PEEL_INVALID = -1,
-
-	/* object cannot be peeled because it is not a tag: */
-	PEEL_NON_TAG = -2,
-
-	/* ref_entry contains no peeled value because it is a symref: */
-	PEEL_IS_SYMREF = -3,
-
-	/*
-	 * ref_entry cannot be peeled because it is broken (i.e., the
-	 * symbolic reference cannot even be resolved to an object
-	 * name):
-	 */
-	PEEL_BROKEN = -4
-};
-
-/*
- * Peel the named object; i.e., if the object is a tag, resolve the
- * tag recursively until a non-tag is found.  If successful, store the
- * result to oid and return PEEL_PEELED.  If the object is not a tag
- * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
- * and leave oid unchanged.
- */
-enum peel_status peel_object(const struct object_id *name, struct object_id *oid);
-
-/**
- * Information needed for a single ref update. Set new_oid to the new
- * value or to null_oid to delete the ref. To check the old value
- * while the ref is locked, set (flags & REF_HAVE_OLD) and set old_oid
- * to the old value, or to null_oid to ensure the ref does not exist
- * before update.
- */
-struct ref_update {
-	/*
-	 * If (flags & REF_HAVE_NEW), set the reference to this value
-	 * (or delete it, if `new_oid` is `null_oid`).
-	 */
-	struct object_id new_oid;
-
-	/*
-	 * If (flags & REF_HAVE_OLD), check that the reference
-	 * previously had this value (or didn't previously exist, if
-	 * `old_oid` is `null_oid`).
-	 */
-	struct object_id old_oid;
-
-	/*
-	 * One or more of REF_NO_DEREF, REF_FORCE_CREATE_REFLOG,
-	 * REF_HAVE_NEW, REF_HAVE_OLD, or backend-specific flags.
-	 */
-	unsigned int flags;
-
-	void *backend_data;
-	unsigned int type;
-	char *msg;
-
-	/*
-	 * If this ref_update was split off of a symref update via
-	 * split_symref_update(), then this member points at that
-	 * update. This is used for two purposes:
-	 * 1. When reporting errors, we report the refname under which
-	 *    the update was originally requested.
-	 * 2. When we read the old value of this reference, we
-	 *    propagate it back to its parent update for recording in
-	 *    the latter's reflog.
-	 */
-	struct ref_update *parent_update;
-
-	const char refname[FLEX_ARRAY];
-};
-
-int refs_read_raw_ref(struct ref_store *ref_store,
-		      const char *refname, struct object_id *oid,
-		      struct strbuf *referent, unsigned int *type);
-
-/*
- * Write an error to `err` and return a nonzero value iff the same
- * refname appears multiple times in `refnames`. `refnames` must be
- * sorted on entry to this function.
- */
-int ref_update_reject_duplicates(struct string_list *refnames,
-				 struct strbuf *err);
-
-/*
- * Add a ref_update with the specified properties to transaction, and
- * return a pointer to the new object. This function does not verify
- * that refname is well-formed. new_oid and old_oid are only
- * dereferenced if the REF_HAVE_NEW and REF_HAVE_OLD bits,
- * respectively, are set in flags.
- */
-struct ref_update *ref_transaction_add_update(
-		struct ref_transaction *transaction,
-		const char *refname, unsigned int flags,
-		const struct object_id *new_oid,
-		const struct object_id *old_oid,
-		const char *msg);
-
-/*
- * Transaction states.
- *
- * OPEN:   The transaction is initialized and new updates can still be
- *         added to it. An OPEN transaction can be prepared,
- *         committed, freed, or aborted (freeing and aborting an open
- *         transaction are equivalent).
- *
- * PREPARED: ref_transaction_prepare(), which locks all of the
- *         references involved in the update and checks that the
- *         update has no errors, has been called successfully for the
- *         transaction. A PREPARED transaction can be committed or
- *         aborted.
- *
- * CLOSED: The transaction is no longer active. A transaction becomes
- *         CLOSED if there is a failure while building the transaction
- *         or if a transaction is committed or aborted. A CLOSED
- *         transaction can only be freed.
- */
-enum ref_transaction_state {
-	REF_TRANSACTION_OPEN     = 0,
-	REF_TRANSACTION_PREPARED = 1,
-	REF_TRANSACTION_CLOSED   = 2
-};
-
-/*
- * Data structure for holding a reference transaction, which can
- * consist of checks and updates to multiple references, carried out
- * as atomically as possible.  This structure is opaque to callers.
- */
-struct ref_transaction {
-	struct ref_store *ref_store;
-	struct ref_update **updates;
-	size_t alloc;
-	size_t nr;
-	enum ref_transaction_state state;
-	void *backend_data;
-};
-
-/*
- * Check for entries in extras that are within the specified
- * directory, where dirname is a reference directory name including
- * the trailing slash (e.g., "refs/heads/foo/"). Ignore any
- * conflicting references that are found in skip. If there is a
- * conflicting reference, return its name.
- *
- * extras and skip must be sorted lists of reference names. Either one
- * can be NULL, signifying the empty list.
- */
-const char *find_descendant_ref(const char *dirname,
-				const struct string_list *extras,
-				const struct string_list *skip);
-
-/*
- * 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).
- */
-int refs_rename_ref_available(struct ref_store *refs,
-			      const char *old_refname,
-			      const char *new_refname);
-
-/* We allow "recursive" symbolic refs. Only within reason, though */
-#define SYMREF_MAXDEPTH 5
-
-/* Include broken references in a do_for_each_ref*() iteration: */
-#define DO_FOR_EACH_INCLUDE_BROKEN 0x01
-
-/*
- * Reference iterators
- *
- * A reference iterator encapsulates the state of an in-progress
- * iteration over references. Create an instance of `struct
- * ref_iterator` via one of the functions in this module.
- *
- * A freshly-created ref_iterator doesn't yet point at a reference. To
- * advance the iterator, call ref_iterator_advance(). If successful,
- * this sets the iterator's refname, oid, and flags fields to describe
- * the next reference and returns ITER_OK. The data pointed at by
- * refname and oid belong to the iterator; if you want to retain them
- * after calling ref_iterator_advance() again or calling
- * ref_iterator_abort(), you must make a copy. When the iteration has
- * been exhausted, ref_iterator_advance() releases any resources
- * associated with the iteration, frees the ref_iterator object, and
- * returns ITER_DONE. If you want to abort the iteration early, call
- * ref_iterator_abort(), which also frees the ref_iterator object and
- * any associated resources. If there was an internal error advancing
- * to the next entry, ref_iterator_advance() aborts the iteration,
- * frees the ref_iterator, and returns ITER_ERROR.
- *
- * The reference currently being looked at can be peeled by calling
- * ref_iterator_peel(). This function is often faster than peel_ref(),
- * so it should be preferred when iterating over references.
- *
- * Putting it all together, a typical iteration looks like this:
- *
- *     int ok;
- *     struct ref_iterator *iter = ...;
- *
- *     while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- *             if (want_to_stop_iteration()) {
- *                     ok = ref_iterator_abort(iter);
- *                     break;
- *             }
- *
- *             // Access information about the current reference:
- *             if (!(iter->flags & REF_ISSYMREF))
- *                     printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid));
- *
- *             // If you need to peel the reference:
- *             ref_iterator_peel(iter, &oid);
- *     }
- *
- *     if (ok != ITER_DONE)
- *             handle_error();
- */
-struct ref_iterator {
-	struct ref_iterator_vtable *vtable;
-
-	/*
-	 * Does this `ref_iterator` iterate over references in order
-	 * by refname?
-	 */
-	unsigned int ordered : 1;
-
-	const char *refname;
-	const struct object_id *oid;
-	unsigned int flags;
-};
-
-/*
- * Advance the iterator to the first or next item and return ITER_OK.
- * If the iteration is exhausted, free the resources associated with
- * the ref_iterator and return ITER_DONE. On errors, free the iterator
- * resources and return ITER_ERROR. It is a bug to use ref_iterator or
- * call this function again after it has returned ITER_DONE or
- * ITER_ERROR.
- */
-int ref_iterator_advance(struct ref_iterator *ref_iterator);
-
-/*
- * If possible, peel the reference currently being viewed by the
- * iterator. Return 0 on success.
- */
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
-		      struct object_id *peeled);
-
-/*
- * End the iteration before it has been exhausted, freeing the
- * reference iterator and any associated resources and returning
- * ITER_DONE. If the abort itself failed, return ITER_ERROR.
- */
-int ref_iterator_abort(struct ref_iterator *ref_iterator);
-
-/*
- * An iterator over nothing (its first ref_iterator_advance() call
- * returns ITER_DONE).
- */
-struct ref_iterator *empty_ref_iterator_begin(void);
-
-/*
- * Return true iff ref_iterator is an empty_ref_iterator.
- */
-int is_empty_ref_iterator(struct ref_iterator *ref_iterator);
-
-/*
- * Return an iterator that goes over each reference in `refs` for
- * which the refname begins with prefix. If trim is non-zero, then
- * trim that many characters off the beginning of each refname.
- * The output is ordered by refname. The following flags are supported:
- *
- * DO_FOR_EACH_INCLUDE_BROKEN: include broken references in
- *         the iteration.
- *
- * DO_FOR_EACH_PER_WORKTREE_ONLY: only produce REF_TYPE_PER_WORKTREE refs.
- */
-struct ref_iterator *refs_ref_iterator_begin(
-		struct ref_store *refs,
-		const char *prefix, int trim, int flags);
-
-/*
- * A callback function used to instruct merge_ref_iterator how to
- * interleave the entries from iter0 and iter1. The function should
- * return one of the constants defined in enum iterator_selection. It
- * must not advance either of the iterators itself.
- *
- * The function must be prepared to handle the case that iter0 and/or
- * iter1 is NULL, which indicates that the corresponding sub-iterator
- * has been exhausted. Its return value must be consistent with the
- * current states of the iterators; e.g., it must not return
- * ITER_SKIP_1 if iter1 has already been exhausted.
- */
-typedef enum iterator_selection ref_iterator_select_fn(
-		struct ref_iterator *iter0, struct ref_iterator *iter1,
-		void *cb_data);
-
-/*
- * Iterate over the entries from iter0 and iter1, with the values
- * interleaved as directed by the select function. The iterator takes
- * ownership of iter0 and iter1 and frees them when the iteration is
- * over. A derived class should set `ordered` to 1 or 0 based on
- * whether it generates its output in order by reference name.
- */
-struct ref_iterator *merge_ref_iterator_begin(
-		int ordered,
-		struct ref_iterator *iter0, struct ref_iterator *iter1,
-		ref_iterator_select_fn *select, void *cb_data);
-
-/*
- * An iterator consisting of the union of the entries from front and
- * back. If there are entries common to the two sub-iterators, use the
- * one from front. Each iterator must iterate over its entries in
- * strcmp() order by refname for this to work.
- *
- * The new iterator takes ownership of its arguments and frees them
- * when the iteration is over. As a convenience to callers, if front
- * or back is an empty_ref_iterator, then abort that one immediately
- * and return the other iterator directly, without wrapping it.
- */
-struct ref_iterator *overlay_ref_iterator_begin(
-		struct ref_iterator *front, struct ref_iterator *back);
-
-/*
- * Wrap iter0, only letting through the references whose names start
- * with prefix. If trim is set, set iter->refname to the name of the
- * reference with that many characters trimmed off the front;
- * otherwise set it to the full refname. The new iterator takes over
- * ownership of iter0 and frees it when iteration is over. It makes
- * its own copy of prefix.
- *
- * As an convenience to callers, if prefix is the empty string and
- * trim is zero, this function returns iter0 directly, without
- * wrapping it.
- *
- * The resulting ref_iterator is ordered if iter0 is.
- */
-struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
-					       const char *prefix,
-					       int trim);
-
-/* Internal implementation of reference iteration: */
-
-/*
- * Base class constructor for ref_iterators. Initialize the
- * ref_iterator part of iter, setting its vtable pointer as specified.
- * `ordered` should be set to 1 if the iterator will iterate over
- * references in order by refname; otherwise it should be set to 0.
- * This is meant to be called only by the initializers of derived
- * classes.
- */
-void base_ref_iterator_init(struct ref_iterator *iter,
-			    struct ref_iterator_vtable *vtable,
-			    int ordered);
-
-/*
- * Base class destructor for ref_iterators. Destroy the ref_iterator
- * part of iter and shallow-free the object. This is meant to be
- * called only by the destructors of derived classes.
- */
-void base_ref_iterator_free(struct ref_iterator *iter);
-
-/* Virtual function declarations for ref_iterators: */
-
-/*
- * backend-specific implementation of ref_iterator_advance. For symrefs, the
- * function should set REF_ISSYMREF, and it should also dereference the symref
- * to provide the OID referent. If DO_FOR_EACH_INCLUDE_BROKEN is set, symrefs
- * with non-existent referents and refs pointing to non-existent object names
- * should also be returned. If DO_FOR_EACH_PER_WORKTREE_ONLY, only
- * REF_TYPE_PER_WORKTREE refs should be returned.
- */
-typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator);
-
-typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
-				 struct object_id *peeled);
-
-/*
- * Implementations of this function should free any resources specific
- * to the derived class, then call base_ref_iterator_free() to clean
- * up and free the ref_iterator object.
- */
-typedef int ref_iterator_abort_fn(struct ref_iterator *ref_iterator);
-
-struct ref_iterator_vtable {
-	ref_iterator_advance_fn *advance;
-	ref_iterator_peel_fn *peel;
-	ref_iterator_abort_fn *abort;
-};
-
-/*
- * current_ref_iter is a performance hack: when iterating over
- * references using the for_each_ref*() functions, current_ref_iter is
- * set to the reference iterator before calling the callback function.
- * If the callback function calls peel_ref(), then peel_ref() first
- * checks whether the reference to be peeled is the one referred to by
- * the iterator (it usually is) and if so, asks the iterator for the
- * peeled version of the reference if it is available. This avoids a
- * refname lookup in a common case. current_ref_iter is set to NULL
- * when the iteration is over.
- */
-extern struct ref_iterator *current_ref_iter;
-
-/*
- * The common backend for the for_each_*ref* functions. Call fn for
- * each reference in iter. If the iterator itself ever returns
- * ITER_ERROR, return -1. If fn ever returns a non-zero value, stop
- * the iteration and return that value. Otherwise, return 0. In any
- * case, free the iterator when done. This function is basically an
- * adapter between the callback style of reference iteration and the
- * iterator style.
- */
-int do_for_each_repo_ref_iterator(struct repository *r,
-				  struct ref_iterator *iter,
-				  each_repo_ref_fn fn, void *cb_data);
-
-/*
- * Only include per-worktree refs in a do_for_each_ref*() iteration.
- * Normally this will be used with a files ref_store, since that's
- * where all reference backends will presumably store their
- * per-worktree refs.
- */
-#define DO_FOR_EACH_PER_WORKTREE_ONLY 0x02
-
-struct ref_store;
-
-/* refs backends */
-
-/* ref_store_init flags */
-#define REF_STORE_READ		(1 << 0)
-#define REF_STORE_WRITE		(1 << 1) /* can perform update operations */
-#define REF_STORE_ODB		(1 << 2) /* has access to object database */
-#define REF_STORE_MAIN		(1 << 3)
-#define REF_STORE_ALL_CAPS	(REF_STORE_READ | \
-				 REF_STORE_WRITE | \
-				 REF_STORE_ODB | \
-				 REF_STORE_MAIN)
-
-/*
- * Initialize the ref_store for the specified gitdir. These functions
- * should call base_ref_store_init() to initialize the shared part of
- * the ref_store and to record the ref_store for later lookup.
- */
-typedef struct ref_store *ref_store_init_fn(const char *gitdir,
-					    unsigned int flags);
-
-typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
-
-typedef int ref_transaction_prepare_fn(struct ref_store *refs,
-				       struct ref_transaction *transaction,
-				       struct strbuf *err);
-
-typedef int ref_transaction_finish_fn(struct ref_store *refs,
-				      struct ref_transaction *transaction,
-				      struct strbuf *err);
-
-typedef int ref_transaction_abort_fn(struct ref_store *refs,
-				     struct ref_transaction *transaction,
-				     struct strbuf *err);
-
-typedef int ref_transaction_commit_fn(struct ref_store *refs,
-				      struct ref_transaction *transaction,
-				      struct strbuf *err);
-
-typedef int pack_refs_fn(struct ref_store *ref_store, unsigned int flags);
-typedef int create_symref_fn(struct ref_store *ref_store,
-			     const char *ref_target,
-			     const char *refs_heads_master,
-			     const char *logmsg);
-typedef int delete_refs_fn(struct ref_store *ref_store, const char *msg,
-			   struct string_list *refnames, unsigned int flags);
-typedef int rename_ref_fn(struct ref_store *ref_store,
-			  const char *oldref, const char *newref,
-			  const char *logmsg);
-typedef int copy_ref_fn(struct ref_store *ref_store,
-			  const char *oldref, const char *newref,
-			  const char *logmsg);
-
-/*
- * Iterate over the references in `ref_store` whose names start with
- * `prefix`. `prefix` is matched as a literal string, without regard
- * for path separators. If prefix is NULL or the empty string, iterate
- * over all references in `ref_store`. The output is ordered by
- * refname.
- */
-typedef struct ref_iterator *ref_iterator_begin_fn(
-		struct ref_store *ref_store,
-		const char *prefix, unsigned int flags);
-
-/* reflog functions */
-
-/*
- * Iterate over the references in the specified ref_store that have a
- * reflog. The refs are iterated over in arbitrary order.
- */
-typedef struct ref_iterator *reflog_iterator_begin_fn(
-		struct ref_store *ref_store);
-
-typedef int for_each_reflog_ent_fn(struct ref_store *ref_store,
-				   const char *refname,
-				   each_reflog_ent_fn fn,
-				   void *cb_data);
-typedef int for_each_reflog_ent_reverse_fn(struct ref_store *ref_store,
-					   const char *refname,
-					   each_reflog_ent_fn fn,
-					   void *cb_data);
-typedef int reflog_exists_fn(struct ref_store *ref_store, const char *refname);
-typedef int create_reflog_fn(struct ref_store *ref_store, const char *refname,
-			     int force_create, struct strbuf *err);
-typedef int delete_reflog_fn(struct ref_store *ref_store, const char *refname);
-typedef int reflog_expire_fn(struct ref_store *ref_store,
-			     const char *refname, const struct object_id *oid,
-			     unsigned int flags,
-			     reflog_expiry_prepare_fn prepare_fn,
-			     reflog_expiry_should_prune_fn should_prune_fn,
-			     reflog_expiry_cleanup_fn cleanup_fn,
-			     void *policy_cb_data);
-
-/*
- * Read a reference from the specified reference store, non-recursively.
- * Set type to describe the reference, and:
- *
- * - If refname is the name of a normal reference, fill in oid
- *   (leaving referent unchanged).
- *
- * - If refname is the name of a symbolic reference, write the full
- *   name of the reference to which it refers (e.g.
- *   "refs/heads/master") to referent and set the REF_ISSYMREF bit in
- *   type (leaving oid unchanged). The caller is responsible for
- *   validating that referent is a valid reference name.
- *
- * WARNING: refname might be used as part of a filename, so it is
- * important from a security standpoint that it be safe in the sense
- * of refname_is_safe(). Moreover, for symrefs this function sets
- * referent to whatever the repository says, which might not be a
- * properly-formatted or even safe reference name. NEITHER INPUT NOR
- * OUTPUT REFERENCE NAMES ARE VALIDATED WITHIN THIS FUNCTION.
- *
- * Return 0 on success. If the ref doesn't exist, set errno to ENOENT
- * and return -1. If the ref exists but is neither a symbolic ref nor
- * an object ID, it is broken; set REF_ISBROKEN in type, set errno to
- * EINVAL, and return -1. If there is another error reading the ref,
- * set errno appropriately and return -1.
- *
- * Backend-specific flags might be set in type as well, regardless of
- * outcome.
- *
- * It is OK for refname to point into referent. If so:
- *
- * - if the function succeeds with REF_ISSYMREF, referent will be
- *   overwritten and the memory formerly pointed to by it might be
- *   changed or even freed.
- *
- * - in all other cases, referent will be untouched, and therefore
- *   refname will still be valid and unchanged.
- */
-typedef int read_raw_ref_fn(struct ref_store *ref_store,
-			    const char *refname, struct object_id *oid,
-			    struct strbuf *referent, unsigned int *type);
-
-struct ref_storage_be {
-	struct ref_storage_be *next;
-	const char *name;
-	ref_store_init_fn *init;
-	ref_init_db_fn *init_db;
-
-	ref_transaction_prepare_fn *transaction_prepare;
-	ref_transaction_finish_fn *transaction_finish;
-	ref_transaction_abort_fn *transaction_abort;
-	ref_transaction_commit_fn *initial_transaction_commit;
-
-	pack_refs_fn *pack_refs;
-	create_symref_fn *create_symref;
-	delete_refs_fn *delete_refs;
-	rename_ref_fn *rename_ref;
-	copy_ref_fn *copy_ref;
-
-	ref_iterator_begin_fn *iterator_begin;
-	read_raw_ref_fn *read_raw_ref;
-
-	reflog_iterator_begin_fn *reflog_iterator_begin;
-	for_each_reflog_ent_fn *for_each_reflog_ent;
-	for_each_reflog_ent_reverse_fn *for_each_reflog_ent_reverse;
-	reflog_exists_fn *reflog_exists;
-	create_reflog_fn *create_reflog;
-	delete_reflog_fn *delete_reflog;
-	reflog_expire_fn *reflog_expire;
-};
-
-extern struct ref_storage_be refs_be_files;
-extern struct ref_storage_be refs_be_packed;
-
-/*
- * A representation of the reference store for the main repository or
- * a submodule. The ref_store instances for submodules are kept in a
- * hash map; see get_submodule_ref_store() for more info.
- */
-struct ref_store {
-	/* The backend describing this ref_store's storage scheme: */
-	const struct ref_storage_be *be;
-
-	/* The gitdir that this ref_store applies to: */
-	char *gitdir;
-};
-
-/*
- * Parse contents of a loose ref file.
- */
-int parse_loose_ref_contents(const char *buf, struct object_id *oid,
-			     struct strbuf *referent, unsigned int *type);
-
-/*
- * Fill in the generic part of refs and add it to our collection of
- * reference stores.
- */
-void base_ref_store_init(struct ref_store *refs,
-			 const struct ref_storage_be *be);
-
-/*
- * Support GIT_TRACE_REFS by optionally wrapping the given ref_store instance.
- */
-struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_store *store);
-
-#endif /* REFS_REFS_INTERNAL_H */