]>
Commit | Line | Data |
---|---|---|
1bf072e3 CC |
1 | #include "builtin.h" |
2 | #include "cache.h" | |
3 | #include "parse-options.h" | |
4 | #include "bisect.h" | |
4ba1e5c4 | 5 | #include "refs.h" |
1bf072e3 CC |
6 | |
7 | static const char * const git_bisect_helper_usage[] = { | |
9e7bbe2d | 8 | N_("git bisect--helper --next-all [--no-checkout]"), |
4ba1e5c4 | 9 | N_("git bisect--helper --check-term-format <term> <orig_term>"), |
1bf072e3 CC |
10 | NULL |
11 | }; | |
12 | ||
4ba1e5c4 PB |
13 | /* |
14 | * Check whether the string `term` belongs to the set of strings | |
15 | * included in the variable arguments. | |
16 | */ | |
17 | LAST_ARG_MUST_BE_NULL | |
18 | static int one_of(const char *term, ...) | |
19 | { | |
20 | int res = 0; | |
21 | va_list matches; | |
22 | const char *match; | |
23 | ||
24 | va_start(matches, term); | |
25 | while (!res && (match = va_arg(matches, const char *))) | |
26 | res = !strcmp(term, match); | |
27 | va_end(matches); | |
28 | ||
29 | return res; | |
30 | } | |
31 | ||
32 | static int check_term_format(const char *term, const char *orig_term) | |
33 | { | |
34 | int res; | |
35 | char *new_term = xstrfmt("refs/bisect/%s", term); | |
36 | ||
37 | res = check_refname_format(new_term, 0); | |
38 | free(new_term); | |
39 | ||
40 | if (res) | |
41 | return error(_("'%s' is not a valid term"), term); | |
42 | ||
43 | if (one_of(term, "help", "start", "skip", "next", "reset", | |
44 | "visualize", "replay", "log", "run", "terms", NULL)) | |
45 | return error(_("can't use the builtin command '%s' as a term"), term); | |
46 | ||
47 | /* | |
48 | * In theory, nothing prevents swapping completely good and bad, | |
49 | * but this situation could be confusing and hasn't been tested | |
50 | * enough. Forbid it for now. | |
51 | */ | |
52 | ||
53 | if ((strcmp(orig_term, "bad") && one_of(term, "bad", "new", NULL)) || | |
54 | (strcmp(orig_term, "good") && one_of(term, "good", "old", NULL))) | |
55 | return error(_("can't change the meaning of the term '%s'"), term); | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
1bf072e3 CC |
60 | int cmd_bisect__helper(int argc, const char **argv, const char *prefix) |
61 | { | |
4ba1e5c4 PB |
62 | enum { |
63 | NEXT_ALL = 1, | |
64 | CHECK_TERM_FMT | |
65 | } cmdmode = 0; | |
fee92fc1 | 66 | int no_checkout = 0; |
1bf072e3 | 67 | struct option options[] = { |
9e1c84df PB |
68 | OPT_CMDMODE(0, "next-all", &cmdmode, |
69 | N_("perform 'git bisect next'"), NEXT_ALL), | |
4ba1e5c4 PB |
70 | OPT_CMDMODE(0, "check-term-format", &cmdmode, |
71 | N_("check format of the term"), CHECK_TERM_FMT), | |
d5d09d47 SB |
72 | OPT_BOOL(0, "no-checkout", &no_checkout, |
73 | N_("update BISECT_HEAD instead of checking out the current commit")), | |
1bf072e3 CC |
74 | OPT_END() |
75 | }; | |
76 | ||
37782920 SB |
77 | argc = parse_options(argc, argv, prefix, options, |
78 | git_bisect_helper_usage, 0); | |
1bf072e3 | 79 | |
9e1c84df | 80 | if (!cmdmode) |
1bf072e3 CC |
81 | usage_with_options(git_bisect_helper_usage, options); |
82 | ||
9e1c84df PB |
83 | switch (cmdmode) { |
84 | case NEXT_ALL: | |
85 | return bisect_next_all(prefix, no_checkout); | |
4ba1e5c4 PB |
86 | case CHECK_TERM_FMT: |
87 | if (argc != 2) | |
88 | return error(_("--check-term-format requires two arguments")); | |
89 | return check_term_format(argv[0], argv[1]); | |
9e1c84df PB |
90 | default: |
91 | return error("BUG: unknown subcommand '%d'", cmdmode); | |
92 | } | |
93 | return 0; | |
1bf072e3 | 94 | } |