reflog expire: narrow scope of "cb" in cmd_reflog_expire()

As with the preceding change for "reflog delete", change the "cb_data" we pass to callbacks to be &cb.cmd itself, instead of passing &cb and having the callback lookup cb->cmd. This makes it clear that the "cb" itself is the same memzero'd structure on each iteration of the for-loops that use &cb, except for the "cmd" member. The "struct expire_reflog_policy_cb" we pass to reflog_expire() will have the members that aren't "cmd" modified by the callbacks, but before we invoke them everything except "cmd" is zero'd out. This included the "tip_commit", "mark_list" and "tips". It might have looked as though we were re-using those between iterations, but the first thing we did in reflog_expiry_prepare() was to either NULL them, or clobber them with another value. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Dec 22, 2021 at 05:06 UTC 46fbe418b283f174e2650c611181c005570e7b88
1 file changed +15 -16
builtin/reflog.c
+15 -16
@@ -357,7 +357,6 @@ static void reflog_expiry_prepare(const char *refname,
357 struct expire_reflog_policy_cb *cb = cb_data;
358
359 if (!cb->cmd.expire_unreachable || is_head(refname)) {
360 - cb->tip_commit = NULL;
360 cb->unreachable_expire_kind = UE_HEAD;
361 } else {
362 cb->tip_commit = lookup_commit_reference_gently(the_repository,
@@ -371,8 +370,6 @@ static void reflog_expiry_prepare(const char *refname,
370 if (cb->cmd.expire_unreachable <= cb->cmd.expire_total)
371 cb->unreachable_expire_kind = UE_ALWAYS;
372
374 - cb->mark_list = NULL;
375 - cb->tips = NULL;
373 if (cb->unreachable_expire_kind != UE_ALWAYS) {
374 if (cb->unreachable_expire_kind == UE_HEAD) {
375 struct commit_list *elem;
@@ -541,7 +538,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c
538
539 static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
540 {
544 - struct expire_reflog_policy_cb cb;
541 + struct cmd_reflog_expire_cb cmd = { 0 };
542 timestamp_t now = time(NULL);
543 int i, status, do_all, all_worktrees = 1;
544 int explicit_expiry = 0;
@@ -553,10 +550,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
550
551 save_commit_buffer = 0;
552 do_all = status = 0;
556 - memset(&cb, 0, sizeof(cb));
553
558 - cb.cmd.expire_total = default_reflog_expire;
559 - cb.cmd.expire_unreachable = default_reflog_expire_unreachable;
554 + cmd.expire_total = default_reflog_expire;
555 + cmd.expire_unreachable = default_reflog_expire_unreachable;
556
557 for (i = 1; i < argc; i++) {
558 const char *arg = argv[i];
@@ -564,17 +560,17 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
560 if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
561 flags |= EXPIRE_REFLOGS_DRY_RUN;
562 else if (skip_prefix(arg, "--expire=", &arg)) {
567 - if (parse_expiry_date(arg, &cb.cmd.expire_total))
563 + if (parse_expiry_date(arg, &cmd.expire_total))
564 die(_("'%s' is not a valid timestamp"), arg);
565 explicit_expiry |= EXPIRE_TOTAL;
566 }
567 else if (skip_prefix(arg, "--expire-unreachable=", &arg)) {
572 - if (parse_expiry_date(arg, &cb.cmd.expire_unreachable))
568 + if (parse_expiry_date(arg, &cmd.expire_unreachable))
569 die(_("'%s' is not a valid timestamp"), arg);
570 explicit_expiry |= EXPIRE_UNREACH;
571 }
572 else if (!strcmp(arg, "--stale-fix"))
577 - cb.cmd.stalefix = 1;
573 + cmd.stalefix = 1;
574 else if (!strcmp(arg, "--rewrite"))
575 flags |= EXPIRE_REFLOGS_REWRITE;
576 else if (!strcmp(arg, "--updateref"))
@@ -600,14 +596,14 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
596 * even in older repository. We cannot trust what's reachable
597 * from reflog if the repository was pruned with older git.
598 */
603 - if (cb.cmd.stalefix) {
604 - repo_init_revisions(the_repository, &cb.cmd.revs, prefix);
605 - cb.cmd.revs.do_not_die_on_missing_tree = 1;
606 - cb.cmd.revs.ignore_missing = 1;
607 - cb.cmd.revs.ignore_missing_links = 1;
599 + if (cmd.stalefix) {
600 + repo_init_revisions(the_repository, &cmd.revs, prefix);
601 + cmd.revs.do_not_die_on_missing_tree = 1;
602 + cmd.revs.ignore_missing = 1;
603 + cmd.revs.ignore_missing_links = 1;
604 if (flags & EXPIRE_REFLOGS_VERBOSE)
605 printf(_("Marking reachable objects..."));
610 - mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);
606 + mark_reachable_objects(&cmd.revs, 0, 0, NULL);
607 if (flags & EXPIRE_REFLOGS_VERBOSE)
608 putchar('\n');
609 }
@@ -629,6 +625,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
625 free_worktrees(worktrees);
626 for (i = 0; i < collected.nr; i++) {
627 struct collected_reflog *e = collected.e[i];
628 + struct expire_reflog_policy_cb cb = { .cmd = cmd };
629
630 set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog);
631 status |= reflog_expire(e->reflog, flags,
@@ -643,6 +640,8 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
640
641 for (; i < argc; i++) {
642 char *ref;
643 + struct expire_reflog_policy_cb cb = { .cmd = cmd };
644 +
645 if (!dwim_log(argv[i], strlen(argv[i]), NULL, &ref)) {
646 status |= error(_("%s points nowhere!"), argv[i]);
647 continue;