builtin/reflog: make functions regarding `reflog_expire_options` public

Make functions that are required to manage `reflog_expire_options`
available elsewhere by moving them into "reflog.c" and exposing them in
the corresponding header. The functions will be used in a subsequent
commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Patrick Steinhardt 2025-04-08 08:22:15 +02:00 committed by Junio C Hamano
parent 964f364de9
commit d20fc193b6
3 changed files with 128 additions and 111 deletions

View File

@ -88,113 +88,6 @@ static int collect_reflog(const char *ref, void *cb_data)
return 0;
}

static struct reflog_expire_entry_option *find_cfg_ent(struct reflog_expire_options *opts,
const char *pattern, size_t len)
{
struct reflog_expire_entry_option *ent;

if (!opts->entries_tail)
opts->entries_tail = &opts->entries;

for (ent = opts->entries; ent; ent = ent->next)
if (!xstrncmpz(ent->pattern, pattern, len))
return ent;

FLEX_ALLOC_MEM(ent, pattern, pattern, len);
*opts->entries_tail = ent;
opts->entries_tail = &(ent->next);
return ent;
}

/* expiry timer slot */
#define EXPIRE_TOTAL 01
#define EXPIRE_UNREACH 02

static int reflog_expire_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct reflog_expire_options *opts = cb;
const char *pattern, *key;
size_t pattern_len;
timestamp_t expire;
int slot;
struct reflog_expire_entry_option *ent;

if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
return git_default_config(var, value, ctx, cb);

if (!strcmp(key, "reflogexpire")) {
slot = EXPIRE_TOTAL;
if (git_config_expiry_date(&expire, var, value))
return -1;
} else if (!strcmp(key, "reflogexpireunreachable")) {
slot = EXPIRE_UNREACH;
if (git_config_expiry_date(&expire, var, value))
return -1;
} else
return git_default_config(var, value, ctx, cb);

if (!pattern) {
switch (slot) {
case EXPIRE_TOTAL:
opts->default_expire_total = expire;
break;
case EXPIRE_UNREACH:
opts->default_expire_unreachable = expire;
break;
}
return 0;
}

ent = find_cfg_ent(opts, pattern, pattern_len);
if (!ent)
return -1;
switch (slot) {
case EXPIRE_TOTAL:
ent->expire_total = expire;
break;
case EXPIRE_UNREACH:
ent->expire_unreachable = expire;
break;
}
return 0;
}

static void set_reflog_expiry_param(struct reflog_expire_options *cb, const char *ref)
{
struct reflog_expire_entry_option *ent;

if (cb->explicit_expiry == (EXPIRE_TOTAL|EXPIRE_UNREACH))
return; /* both given explicitly -- nothing to tweak */

for (ent = cb->entries; ent; ent = ent->next) {
if (!wildmatch(ent->pattern, ref, 0)) {
if (!(cb->explicit_expiry & EXPIRE_TOTAL))
cb->expire_total = ent->expire_total;
if (!(cb->explicit_expiry & EXPIRE_UNREACH))
cb->expire_unreachable = ent->expire_unreachable;
return;
}
}

/*
* If unconfigured, make stash never expire
*/
if (!strcmp(ref, "refs/stash")) {
if (!(cb->explicit_expiry & EXPIRE_TOTAL))
cb->expire_total = 0;
if (!(cb->explicit_expiry & EXPIRE_UNREACH))
cb->expire_unreachable = 0;
return;
}

/* Nothing matched -- use the default value */
if (!(cb->explicit_expiry & EXPIRE_TOTAL))
cb->expire_total = cb->default_expire_total;
if (!(cb->explicit_expiry & EXPIRE_UNREACH))
cb->expire_unreachable = cb->default_expire_unreachable;
}

static int expire_unreachable_callback(const struct option *opt,
const char *arg,
int unset)
@ -207,7 +100,7 @@ static int expire_unreachable_callback(const struct option *opt,
die(_("invalid timestamp '%s' given to '--%s'"),
arg, opt->long_name);

opts->explicit_expiry |= EXPIRE_UNREACH;
opts->explicit_expiry |= REFLOG_EXPIRE_UNREACH;
return 0;
}

@ -223,7 +116,7 @@ static int expire_total_callback(const struct option *opt,
die(_("invalid timestamp '%s' given to '--%s'"),
arg, opt->long_name);

opts->explicit_expiry |= EXPIRE_TOTAL;
opts->explicit_expiry |= REFLOG_EXPIRE_TOTAL;
return 0;
}

@ -353,7 +246,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
.dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN),
};

set_reflog_expiry_param(&cb.opts, item->string);
reflog_expire_options_set_refname(&cb.opts, item->string);
status |= refs_reflog_expire(get_main_ref_store(the_repository),
item->string, flags,
reflog_expiry_prepare,
@ -372,7 +265,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
status |= error(_("%s points nowhere!"), argv[i]);
continue;
}
set_reflog_expiry_param(&cb.opts, ref);
reflog_expire_options_set_refname(&cb.opts, ref);
status |= refs_reflog_expire(get_main_ref_store(the_repository),
ref, flags,
reflog_expiry_prepare,

107
reflog.c
View File

@ -2,13 +2,120 @@
#define DISABLE_SIGN_COMPARE_WARNINGS

#include "git-compat-util.h"
#include "config.h"
#include "gettext.h"
#include "object-store-ll.h"
#include "parse-options.h"
#include "reflog.h"
#include "refs.h"
#include "revision.h"
#include "tree.h"
#include "tree-walk.h"
#include "wildmatch.h"

static struct reflog_expire_entry_option *find_cfg_ent(struct reflog_expire_options *opts,
const char *pattern, size_t len)
{
struct reflog_expire_entry_option *ent;

if (!opts->entries_tail)
opts->entries_tail = &opts->entries;

for (ent = opts->entries; ent; ent = ent->next)
if (!xstrncmpz(ent->pattern, pattern, len))
return ent;

FLEX_ALLOC_MEM(ent, pattern, pattern, len);
*opts->entries_tail = ent;
opts->entries_tail = &(ent->next);
return ent;
}

int reflog_expire_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct reflog_expire_options *opts = cb;
const char *pattern, *key;
size_t pattern_len;
timestamp_t expire;
int slot;
struct reflog_expire_entry_option *ent;

if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
return git_default_config(var, value, ctx, cb);

if (!strcmp(key, "reflogexpire")) {
slot = REFLOG_EXPIRE_TOTAL;
if (git_config_expiry_date(&expire, var, value))
return -1;
} else if (!strcmp(key, "reflogexpireunreachable")) {
slot = REFLOG_EXPIRE_UNREACH;
if (git_config_expiry_date(&expire, var, value))
return -1;
} else
return git_default_config(var, value, ctx, cb);

if (!pattern) {
switch (slot) {
case REFLOG_EXPIRE_TOTAL:
opts->default_expire_total = expire;
break;
case REFLOG_EXPIRE_UNREACH:
opts->default_expire_unreachable = expire;
break;
}
return 0;
}

ent = find_cfg_ent(opts, pattern, pattern_len);
if (!ent)
return -1;
switch (slot) {
case REFLOG_EXPIRE_TOTAL:
ent->expire_total = expire;
break;
case REFLOG_EXPIRE_UNREACH:
ent->expire_unreachable = expire;
break;
}
return 0;
}

void reflog_expire_options_set_refname(struct reflog_expire_options *cb,
const char *ref)
{
struct reflog_expire_entry_option *ent;

if (cb->explicit_expiry == (REFLOG_EXPIRE_TOTAL|REFLOG_EXPIRE_UNREACH))
return; /* both given explicitly -- nothing to tweak */

for (ent = cb->entries; ent; ent = ent->next) {
if (!wildmatch(ent->pattern, ref, 0)) {
if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL))
cb->expire_total = ent->expire_total;
if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH))
cb->expire_unreachable = ent->expire_unreachable;
return;
}
}

/*
* If unconfigured, make stash never expire
*/
if (!strcmp(ref, "refs/stash")) {
if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL))
cb->expire_total = 0;
if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH))
cb->expire_unreachable = 0;
return;
}

/* Nothing matched -- use the default value */
if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL))
cb->expire_total = cb->default_expire_total;
if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH))
cb->expire_unreachable = cb->default_expire_unreachable;
}

/* Remember to update object flag allocation in object.h */
#define INCOMPLETE (1u<<10)

View File

@ -2,6 +2,9 @@
#define REFLOG_H
#include "refs.h"

#define REFLOG_EXPIRE_TOTAL (1 << 0)
#define REFLOG_EXPIRE_UNREACH (1 << 1)

struct reflog_expire_entry_option {
struct reflog_expire_entry_option *next;
timestamp_t expire_total;
@ -24,6 +27,20 @@ struct reflog_expire_options {
.default_expire_unreachable = now - 90 * 24 * 3600, \
}

/*
* Parse the reflog expire configuration. This should be used with
* `repo_config()`.
*/
int reflog_expire_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);

/*
* Adapt the options so that they apply to the given refname. This applies any
* per-reference reflog expiry configuration that may exist to the options.
*/
void reflog_expire_options_set_refname(struct reflog_expire_options *cb,
const char *refname);

struct expire_reflog_policy_cb {
enum {
UE_NORMAL,