bisect--helper: reimplement `bisect_replay` shell function in C

Reimplement the `bisect_replay` shell function in C and also add `--bisect-replay` subcommand to `git bisect--helper` to call it from git-bisect.sh Using `--bisect-replay` subcommand is a temporary measure to port shell function to C so as to use the existing test suite. Mentored-by: Lars Schneider <larsxschneider@gmail.com> Mentored-by: Christian Couder <chriscool@tuxfamily.org> Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com> Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com> Signed-off-by: Miriam Rubio <mirucam@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pranit Bauva committed Feb 3, 2021 at 22:54 UTC 2b1fd947f6d81ae772ebb75ef2e668866ab38c55
2 files changed +84 -34
builtin/bisect--helper.c
+83 -1
@@ -31,6 +31,7 @@ static const char * const git_bisect_helper_usage[] = {
31 N_("git bisect--helper --bisect-auto-next"),
32 N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
33 N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
34 + N_("git bisect--helper --bisect-replay <filename>"),
35 NULL
36 };
37
@@ -921,6 +922,78 @@ static enum bisect_error bisect_log(void)
922 return status ? BISECT_FAILED : BISECT_OK;
923 }
924
925 +static int process_replay_line(struct bisect_terms *terms, struct strbuf *line)
926 +{
927 + const char *p = line->buf + strspn(line->buf, " \t");
928 + char *word_end, *rev;
929 +
930 + if ((!skip_prefix(p, "git bisect", &p) &&
931 + !skip_prefix(p, "git-bisect", &p)) || !isspace(*p))
932 + return 0;
933 + p += strspn(p, " \t");
934 +
935 + word_end = (char *)p + strcspn(p, " \t");
936 + rev = word_end + strspn(word_end, " \t");
937 + *word_end = '\0'; /* NUL-terminate the word */
938 +
939 + get_terms(terms);
940 + if (check_and_set_terms(terms, p))
941 + return -1;
942 +
943 + if (!strcmp(p, "start")) {
944 + struct strvec argv = STRVEC_INIT;
945 + int res;
946 + sq_dequote_to_strvec(rev, &argv);
947 + res = bisect_start(terms, argv.v, argv.nr);
948 + strvec_clear(&argv);
949 + return res;
950 + }
951 +
952 + if (one_of(p, terms->term_good,
953 + terms->term_bad, "skip", NULL))
954 + return bisect_write(p, rev, terms, 0);
955 +
956 + if (!strcmp(p, "terms")) {
957 + struct strvec argv = STRVEC_INIT;
958 + int res;
959 + sq_dequote_to_strvec(rev, &argv);
960 + res = bisect_terms(terms, argv.nr == 1 ? argv.v[0] : NULL);
961 + strvec_clear(&argv);
962 + return res;
963 + }
964 + error(_("'%s'?? what are you talking about?"), p);
965 +
966 + return -1;
967 +}
968 +
969 +static enum bisect_error bisect_replay(struct bisect_terms *terms, const char *filename)
970 +{
971 + FILE *fp = NULL;
972 + enum bisect_error res = BISECT_OK;
973 + struct strbuf line = STRBUF_INIT;
974 +
975 + if (is_empty_or_missing_file(filename))
976 + return error(_("cannot read file '%s' for replaying"), filename);
977 +
978 + if (bisect_reset(NULL))
979 + return BISECT_FAILED;
980 +
981 + fp = fopen(filename, "r");
982 + if (!fp)
983 + return BISECT_FAILED;
984 +
985 + while ((strbuf_getline(&line, fp) != EOF) && !res)
986 + res = process_replay_line(terms, &line);
987 +
988 + strbuf_release(&line);
989 + fclose(fp);
990 +
991 + if (res)
992 + return BISECT_FAILED;
993 +
994 + return bisect_auto_next(terms, NULL);
995 +}
996 +
997 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
998 {
999 enum {
@@ -934,7 +1007,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1007 BISECT_NEXT,
1008 BISECT_AUTO_NEXT,
1009 BISECT_STATE,
937 - BISECT_LOG
1010 + BISECT_LOG,
1011 + BISECT_REPLAY
1012 } cmdmode = 0;
1013 int res = 0, nolog = 0;
1014 struct option options[] = {
@@ -958,6 +1032,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1032 N_("mark the state of ref (or refs)"), BISECT_STATE),
1033 OPT_CMDMODE(0, "bisect-log", &cmdmode,
1034 N_("list the bisection steps so far"), BISECT_LOG),
1035 + OPT_CMDMODE(0, "bisect-replay", &cmdmode,
1036 + N_("replay the bisection process from the given file"), BISECT_REPLAY),
1037 OPT_BOOL(0, "no-log", &nolog,
1038 N_("no log for BISECT_WRITE")),
1039 OPT_END()
@@ -1025,6 +1101,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1101 return error(_("--bisect-log requires 0 arguments"));
1102 res = bisect_log();
1103 break;
1104 + case BISECT_REPLAY:
1105 + if (argc != 1)
1106 + return error(_("no logfile given"));
1107 + set_terms(&terms, "bad", "good");
1108 + res = bisect_replay(&terms, argv[0]);
1109 + break;
1110 default:
1111 BUG("unknown subcommand %d", cmdmode);
1112 }
git-bisect.sh
+1 -33
@@ -77,38 +77,6 @@ bisect_visualize() {
77 eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES")
78 }
79
80 -bisect_replay () {
81 - file="$1"
82 - test "$#" -eq 1 || die "$(gettext "No logfile given")"
83 - test -r "$file" || die "$(eval_gettext "cannot read \$file for replaying")"
84 - git bisect--helper --bisect-reset || exit
85 - oIFS="$IFS" IFS="$IFS$(printf '\015')"
86 - while read git bisect command rev tail
87 - do
88 - test "$git $bisect" = "git bisect" || test "$git" = "git-bisect" || continue
89 - if test "$git" = "git-bisect"
90 - then
91 - rev="$command"
92 - command="$bisect"
93 - fi
94 - get_terms
95 - git bisect--helper --check-and-set-terms "$command" "$TERM_GOOD" "$TERM_BAD" || exit
96 - get_terms
97 - case "$command" in
98 - start)
99 - eval "git bisect--helper --bisect-start $rev $tail" ;;
100 - "$TERM_GOOD"|"$TERM_BAD"|skip)
101 - git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;;
102 - terms)
103 - git bisect--helper --bisect-terms $rev || exit;;
104 - *)
105 - die "$(gettext "?? what are you talking about?")" ;;
106 - esac
107 - done <"$file"
108 - IFS="$oIFS"
109 - git bisect--helper --bisect-auto-next || exit
110 -}
111 -
80 bisect_run () {
81 git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
82
@@ -203,7 +171,7 @@ case "$#" in
171 reset)
172 git bisect--helper --bisect-reset "$@" ;;
173 replay)
206 - bisect_replay "$@" ;;
174 + git bisect--helper --bisect-replay "$@" || exit;;
175 log)
176 git bisect--helper --bisect-log || exit ;;
177 run)