pack-refs: teach --exclude option to exclude refs from being packed

At GitLab, we have a system that creates ephemeral internal refs that
don't live long before getting deleted. Having an option to exclude
certain refs from a packed-refs file allows these internal references to
be deleted much more efficiently.

Add an --exclude option to the pack-refs builtin, and use the ref
exclusions API to exclude certain refs from being packed into the final
packed-refs file

Signed-off-by: John Cai <johncai86@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
John Cai
2023-05-12 21:34:41 +00:00
committed by Junio C Hamano
parent 283174b214
commit 826ae79fca
11 changed files with 69 additions and 20 deletions

View File

@ -19,6 +19,7 @@
#include "../worktree.h"
#include "../wrapper.h"
#include "../write-or-die.h"
#include "../revision.h"
/*
* This backend uses the following flags in `ref_update::flags` for
@ -1173,15 +1174,18 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
*/
static int should_pack_ref(const char *refname,
const struct object_id *oid, unsigned int ref_flags,
unsigned int pack_flags)
struct pack_refs_opts *opts)
{
/* Do not pack per-worktree refs: */
if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
REF_WORKTREE_SHARED)
return 0;
if (ref_excluded(opts->exclusions, refname))
return 0;
/* Do not pack non-tags unless PACK_REFS_ALL is set: */
if (!(pack_flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
if (!(opts->flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
return 0;
/* Do not pack symbolic refs: */
@ -1195,7 +1199,8 @@ static int should_pack_ref(const char *refname,
return 1;
}
static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
static int files_pack_refs(struct ref_store *ref_store,
struct pack_refs_opts *opts)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
@ -1220,8 +1225,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
* 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))
if (!should_pack_ref(iter->refname, iter->oid, iter->flags, opts))
continue;
/*
@ -1235,7 +1239,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
iter->refname, err.buf);
/* Schedule the loose reference for pruning if requested. */
if ((flags & PACK_REFS_PRUNE)) {
if ((opts->flags & PACK_REFS_PRUNE)) {
struct ref_to_prune *n;
FLEX_ALLOC_STR(n, name, iter->refname);
oidcpy(&n->oid, iter->oid);