aboutsummaryrefslogtreecommitdiffstats
path: root/builtin/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/gc.c')
-rw-r--r--builtin/gc.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/builtin/gc.c b/builtin/gc.c
index 99431fd467..d5c75be252 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -33,6 +33,7 @@
#include "pack.h"
#include "pack-objects.h"
#include "path.h"
+#include "reflog.h"
#include "blob.h"
#include "tree.h"
#include "promisor-remote.h"
@@ -53,7 +54,6 @@ static const char * const builtin_gc_usage[] = {
static timestamp_t gc_log_expire_time;
-static struct strvec reflog = STRVEC_INIT;
static struct strvec repack = STRVEC_INIT;
static struct strvec prune = STRVEC_INIT;
static struct strvec prune_worktrees = STRVEC_INIT;
@@ -288,6 +288,58 @@ static int maintenance_task_pack_refs(struct maintenance_run_opts *opts,
return run_command(&cmd);
}
+struct count_reflog_entries_data {
+ struct expire_reflog_policy_cb policy;
+ size_t count;
+ size_t limit;
+};
+
+static int count_reflog_entries(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 count_reflog_entries_data *data = cb_data;
+ if (should_expire_reflog_ent(old_oid, new_oid, committer, timestamp, tz, msg, &data->policy))
+ data->count++;
+ return data->count >= data->limit;
+}
+
+static int reflog_expire_condition(struct gc_config *cfg UNUSED)
+{
+ timestamp_t now = time(NULL);
+ struct count_reflog_entries_data data = {
+ .policy = {
+ .opts = REFLOG_EXPIRE_OPTIONS_INIT(now),
+ },
+ };
+ int limit = 100;
+
+ git_config_get_int("maintenance.reflog-expire.auto", &limit);
+ if (!limit)
+ return 0;
+ if (limit < 0)
+ return 1;
+ data.limit = limit;
+
+ repo_config(the_repository, reflog_expire_config, &data.policy.opts);
+
+ reflog_expire_options_set_refname(&data.policy.opts, "HEAD");
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository), "HEAD",
+ count_reflog_entries, &data);
+
+ reflog_expiry_cleanup(&data.policy);
+ return data.count >= data.limit;
+}
+
+static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUSED,
+ struct gc_config *cfg UNUSED)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ cmd.git_cmd = 1;
+ strvec_pushl(&cmd.args, "reflog", "expire", "--all", NULL);
+ return run_command(&cmd);
+}
+
static int too_many_loose_objects(struct gc_config *cfg)
{
/*
@@ -667,15 +719,8 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg))
die(FAILED_RUN, "pack-refs");
-
- if (cfg->prune_reflogs) {
- struct child_process cmd = CHILD_PROCESS_INIT;
-
- cmd.git_cmd = 1;
- strvec_pushv(&cmd.args, reflog.v);
- if (run_command(&cmd))
- die(FAILED_RUN, reflog.v[0]);
- }
+ if (cfg->prune_reflogs && maintenance_task_reflog_expire(opts, cfg))
+ die(FAILED_RUN, "reflog");
}
int cmd_gc(int argc,
@@ -723,7 +768,6 @@ struct repository *repo UNUSED)
show_usage_with_options_if_asked(argc, argv,
builtin_gc_usage, builtin_gc_options);
- strvec_pushl(&reflog, "reflog", "expire", "--all", NULL);
strvec_pushl(&repack, "repack", "-d", "-l", NULL);
strvec_pushl(&prune, "prune", "--expire", NULL);
strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
@@ -1029,6 +1073,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
return !!run_command(&child);
}
@@ -1161,6 +1207,7 @@ static int write_loose_object_to_stdin(const struct object_id *oid,
fprintf(d->in, "%s\n", oid_to_hex(oid));
+ /* If batch_size is INT_MAX, then this will return 0 always. */
return ++(d->count) > d->batch_size;
}
@@ -1185,6 +1232,8 @@ static int pack_loose(struct maintenance_run_opts *opts)
strvec_push(&pack_proc.args, "pack-objects");
if (opts->quiet)
strvec_push(&pack_proc.args, "--quiet");
+ else
+ strvec_push(&pack_proc.args, "--no-quiet");
strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->odb->path);
pack_proc.in = -1;
@@ -1204,6 +1253,15 @@ static int pack_loose(struct maintenance_run_opts *opts)
data.count = 0;
data.batch_size = 50000;
+ repo_config_get_int(r, "maintenance.loose-objects.batchSize",
+ &data.batch_size);
+
+ /* If configured as 0, then remove limit. */
+ if (!data.batch_size)
+ data.batch_size = INT_MAX;
+ else if (data.batch_size > 0)
+ data.batch_size--; /* Decrease for equality on limit. */
+
for_each_loose_file_in_objdir(r->objects->odb->path,
write_loose_object_to_stdin,
NULL,
@@ -1263,6 +1321,8 @@ static int multi_pack_index_write(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
if (run_command(&child))
return error(_("failed to write multi-pack-index"));
@@ -1279,6 +1339,8 @@ static int multi_pack_index_expire(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
if (run_command(&child))
return error(_("'git multi-pack-index expire' failed"));
@@ -1335,6 +1397,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
strvec_pushf(&child.args, "--batch-size=%"PRIuMAX,
(uintmax_t)get_auto_pack_size());
@@ -1392,6 +1456,7 @@ enum maintenance_task_label {
TASK_GC,
TASK_COMMIT_GRAPH,
TASK_PACK_REFS,
+ TASK_REFLOG_EXPIRE,
/* Leave as final value */
TASK__COUNT
@@ -1428,6 +1493,11 @@ static struct maintenance_task tasks[] = {
maintenance_task_pack_refs,
pack_refs_condition,
},
+ [TASK_REFLOG_EXPIRE] = {
+ "reflog-expire",
+ maintenance_task_reflog_expire,
+ reflog_expire_condition,
+ },
};
static int compare_tasks_by_selection(const void *a_, const void *b_)