builtin/reflog.c: use parse-options api for expire, delete subcommands
Switching out manual arg parsing for the parse-options API for the expire and delete subcommands. Move explicit_expiry flag into cmd_reflog_expire_cb struct so callbacks can set both the value of the timestamp as well as the explicit_expiry flag. Signed-off-by: "John Cai" <johncai86@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
John Cai committed
Jan 6, 2022 at 19:06 UTC
33d7bdd64592d6dc86583a817719f91d7344e958
1 file changed
+97
-79
builtin/reflog.c
+97
-79
@@ -12,15 +12,6 @@
12
#include "reachable.h"
13
#include "worktree.h"
14
15
-/* NEEDSWORK: switch to using parse_options */
16
-static const char reflog_expire_usage[] =
17
-N_("git reflog expire [--expire=<time>] "
18
- "[--expire-unreachable=<time>] "
19
- "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
20
- "[--verbose] [--all] <refs>...");
21
-static const char reflog_delete_usage[] =
22
-N_("git reflog delete [--rewrite] [--updateref] "
23
- "[--dry-run | -n] [--verbose] <refs>...");
15
static const char reflog_exists_usage[] =
16
N_("git reflog exists <ref>");
17
@@ -29,6 +20,7 @@ static timestamp_t default_reflog_expire_unreachable;
20
21
struct cmd_reflog_expire_cb {
22
int stalefix;
23
+ int explicit_expiry;
24
timestamp_t expire_total;
25
timestamp_t expire_unreachable;
26
int recno;
@@ -520,18 +512,18 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
512
return 0;
513
}
514
523
-static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, const char *ref)
515
+static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char *ref)
516
{
517
struct reflog_expire_cfg *ent;
518
527
- if (slot == (EXPIRE_TOTAL|EXPIRE_UNREACH))
519
+ if (cb->explicit_expiry == (EXPIRE_TOTAL|EXPIRE_UNREACH))
520
return; /* both given explicitly -- nothing to tweak */
521
522
for (ent = reflog_expire_cfg; ent; ent = ent->next) {
523
if (!wildmatch(ent->pattern, ref, 0)) {
532
- if (!(slot & EXPIRE_TOTAL))
524
+ if (!(cb->explicit_expiry & EXPIRE_TOTAL))
525
cb->expire_total = ent->expire_total;
534
- if (!(slot & EXPIRE_UNREACH))
526
+ if (!(cb->explicit_expiry & EXPIRE_UNREACH))
527
cb->expire_unreachable = ent->expire_unreachable;
528
return;
529
}
@@ -541,29 +533,89 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c
533
* If unconfigured, make stash never expire
534
*/
535
if (!strcmp(ref, "refs/stash")) {
544
- if (!(slot & EXPIRE_TOTAL))
536
+ if (!(cb->explicit_expiry & EXPIRE_TOTAL))
537
cb->expire_total = 0;
546
- if (!(slot & EXPIRE_UNREACH))
538
+ if (!(cb->explicit_expiry & EXPIRE_UNREACH))
539
cb->expire_unreachable = 0;
540
return;
541
}
542
543
/* Nothing matched -- use the default value */
552
- if (!(slot & EXPIRE_TOTAL))
544
+ if (!(cb->explicit_expiry & EXPIRE_TOTAL))
545
cb->expire_total = default_reflog_expire;
554
- if (!(slot & EXPIRE_UNREACH))
546
+ if (!(cb->explicit_expiry & EXPIRE_UNREACH))
547
cb->expire_unreachable = default_reflog_expire_unreachable;
548
}
549
550
+static const char * reflog_expire_usage[] = {
551
+ N_("git reflog expire [--expire=<time>] "
552
+ "[--expire-unreachable=<time>] "
553
+ "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
554
+ "[--verbose] [--all] <refs>..."),
555
+ NULL
556
+};
557
+
558
+static int expire_unreachable_callback(const struct option *opt,
559
+ const char *arg,
560
+ int unset)
561
+{
562
+ struct cmd_reflog_expire_cb *cmd = opt->value;
563
+
564
+ if (parse_expiry_date(arg, &cmd->expire_unreachable))
565
+ die(_("invalid timestamp '%s' given to '--%s'"),
566
+ arg, opt->long_name);
567
+
568
+ cmd->explicit_expiry |= EXPIRE_UNREACH;
569
+ return 0;
570
+}
571
+
572
+static int expire_total_callback(const struct option *opt,
573
+ const char *arg,
574
+ int unset)
575
+{
576
+ struct cmd_reflog_expire_cb *cmd = opt->value;
577
+
578
+ if (parse_expiry_date(arg, &cmd->expire_total))
579
+ die(_("invalid timestamp '%s' given to '--%s'"),
580
+ arg, opt->long_name);
581
+
582
+ cmd->explicit_expiry |= EXPIRE_TOTAL;
583
+ return 0;
584
+}
585
+
586
static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
587
{
588
struct cmd_reflog_expire_cb cmd = { 0 };
589
timestamp_t now = time(NULL);
590
int i, status, do_all, all_worktrees = 1;
563
- int explicit_expiry = 0;
591
unsigned int flags = 0;
592
int verbose = 0;
593
reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent;
594
+ const struct option options[] = {
595
+ OPT_BIT(0, "dry-run", &flags, N_("do not actually prune any entries"),
596
+ EXPIRE_REFLOGS_DRY_RUN),
597
+ OPT_BIT(0, "rewrite", &flags,
598
+ N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
599
+ EXPIRE_REFLOGS_REWRITE),
600
+ OPT_BIT(0, "updateref", &flags,
601
+ N_("update the reference to the value of the top reflog entry"),
602
+ EXPIRE_REFLOGS_UPDATE_REF),
603
+ OPT_BOOL(0, "verbose", &verbose, N_("print extra information on screen.")),
604
+ OPT_CALLBACK_F(0, "expire", &cmd, N_("timestamp"),
605
+ N_("prune entries older than the specified time"),
606
+ PARSE_OPT_NONEG,
607
+ expire_total_callback),
608
+ OPT_CALLBACK_F(0, "expire-unreachable", &cmd, N_("timestamp"),
609
+ N_("prune entries older than <time> that are not reachable from the current tip of the branch"),
610
+ PARSE_OPT_NONEG,
611
+ expire_unreachable_callback),
612
+ OPT_BOOL(0, "stale-fix", &cmd.stalefix,
613
+ N_("prune any reflog entries that point to broken commits")),
614
+ OPT_BOOL(0, "all", &do_all, N_("process the reflogs of all references")),
615
+ OPT_BOOL(1, "single-worktree", &all_worktrees,
616
+ N_("limits processing to reflogs from the current worktree only.")),
617
+ OPT_END()
618
+ };
619
620
default_reflog_expire_unreachable = now - 30 * 24 * 3600;
621
default_reflog_expire = now - 90 * 24 * 3600;
@@ -572,45 +624,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
624
save_commit_buffer = 0;
625
do_all = status = 0;
626
627
+ cmd.explicit_expiry = 0;
628
cmd.expire_total = default_reflog_expire;
629
cmd.expire_unreachable = default_reflog_expire_unreachable;
630
578
- for (i = 1; i < argc; i++) {
579
- const char *arg = argv[i];
580
-
581
- if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
582
- flags |= EXPIRE_REFLOGS_DRY_RUN;
583
- else if (skip_prefix(arg, "--expire=", &arg)) {
584
- if (parse_expiry_date(arg, &cmd.expire_total))
585
- die(_("'%s' is not a valid timestamp"), arg);
586
- explicit_expiry |= EXPIRE_TOTAL;
587
- }
588
- else if (skip_prefix(arg, "--expire-unreachable=", &arg)) {
589
- if (parse_expiry_date(arg, &cmd.expire_unreachable))
590
- die(_("'%s' is not a valid timestamp"), arg);
591
- explicit_expiry |= EXPIRE_UNREACH;
592
- }
593
- else if (!strcmp(arg, "--stale-fix"))
594
- cmd.stalefix = 1;
595
- else if (!strcmp(arg, "--rewrite"))
596
- flags |= EXPIRE_REFLOGS_REWRITE;
597
- else if (!strcmp(arg, "--updateref"))
598
- flags |= EXPIRE_REFLOGS_UPDATE_REF;
599
- else if (!strcmp(arg, "--all"))
600
- do_all = 1;
601
- else if (!strcmp(arg, "--single-worktree"))
602
- all_worktrees = 0;
603
- else if (!strcmp(arg, "--verbose"))
604
- verbose = 1;
605
- else if (!strcmp(arg, "--")) {
606
- i++;
607
- break;
608
- }
609
- else if (arg[0] == '-')
610
- usage(_(reflog_expire_usage));
611
- else
612
- break;
613
- }
631
+ argc = parse_options(argc, argv, prefix, options, reflog_expire_usage, 0);
632
633
if (verbose)
634
should_prune_fn = should_expire_reflog_ent_verbose;
@@ -657,7 +675,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
675
.dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN),
676
};
677
660
- set_reflog_expiry_param(&cb.cmd, explicit_expiry, item->string);
678
+ set_reflog_expiry_param(&cb.cmd, item->string);
679
status |= reflog_expire(item->string, flags,
680
reflog_expiry_prepare,
681
should_prune_fn,
@@ -667,7 +685,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
685
string_list_clear(&collected.reflogs, 0);
686
}
687
670
- for (; i < argc; i++) {
688
+ for (i = 0; i < argc; i++) {
689
char *ref;
690
struct expire_reflog_policy_cb cb = { .cmd = cmd };
691
@@ -675,7 +693,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
693
status |= error(_("%s points nowhere!"), argv[i]);
694
continue;
695
}
678
- set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);
696
+ set_reflog_expiry_param(&cb.cmd, ref);
697
status |= reflog_expire(ref, flags,
698
reflog_expiry_prepare,
699
should_prune_fn,
@@ -696,6 +714,12 @@ static int count_reflog_ent(struct object_id *ooid, struct object_id *noid,
714
return 0;
715
}
716
717
+static const char * reflog_delete_usage[] = {
718
+ N_("git reflog delete [--rewrite] [--updateref] "
719
+ "[--dry-run | -n] [--verbose] <refs>..."),
720
+ NULL
721
+};
722
+
723
static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
724
{
725
struct cmd_reflog_expire_cb cmd = { 0 };
@@ -703,34 +727,28 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
727
unsigned int flags = 0;
728
int verbose = 0;
729
reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent;
706
-
707
- for (i = 1; i < argc; i++) {
708
- const char *arg = argv[i];
709
- if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
710
- flags |= EXPIRE_REFLOGS_DRY_RUN;
711
- else if (!strcmp(arg, "--rewrite"))
712
- flags |= EXPIRE_REFLOGS_REWRITE;
713
- else if (!strcmp(arg, "--updateref"))
714
- flags |= EXPIRE_REFLOGS_UPDATE_REF;
715
- else if (!strcmp(arg, "--verbose"))
716
- verbose = 1;
717
- else if (!strcmp(arg, "--")) {
718
- i++;
719
- break;
720
- }
721
- else if (arg[0] == '-')
722
- usage(_(reflog_delete_usage));
723
- else
724
- break;
725
- }
730
+ const struct option options[] = {
731
+ OPT_BIT(0, "dry-run", &flags, N_("do not actually prune any entries"),
732
+ EXPIRE_REFLOGS_DRY_RUN),
733
+ OPT_BIT(0, "rewrite", &flags,
734
+ N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
735
+ EXPIRE_REFLOGS_REWRITE),
736
+ OPT_BIT(0, "updateref", &flags,
737
+ N_("update the reference to the value of the top reflog entry"),
738
+ EXPIRE_REFLOGS_UPDATE_REF),
739
+ OPT_BOOL(0, "verbose", &verbose, N_("print extra information on screen.")),
740
+ OPT_END()
741
+ };
742
+
743
+ argc = parse_options(argc, argv, prefix, options, reflog_delete_usage, 0);
744
745
if (verbose)
746
should_prune_fn = should_expire_reflog_ent_verbose;
747
730
- if (argc - i < 1)
748
+ if (argc < 1)
749
return error(_("no reflog specified to delete"));
750
733
- for ( ; i < argc; i++) {
751
+ for (i = 0; i < argc; i++) {
752
const char *spec = strstr(argv[i], "@{");
753
char *ep, *ref;
754
int recno;