Skip to content

Commit 0871fb9

Browse files
committed
Merge branch 'mr/bisect-in-c-4'
Piecemeal of rewrite of "git bisect" in C continues. * mr/bisect-in-c-4: bisect--helper: retire `--check-and-set-terms` subcommand bisect--helper: reimplement `bisect_skip` shell function in C bisect--helper: retire `--bisect-auto-next` subcommand bisect--helper: use `res` instead of return in BISECT_RESET case option bisect--helper: retire `--bisect-write` subcommand bisect--helper: reimplement `bisect_replay` shell function in C bisect--helper: reimplement `bisect_log` shell function in C
2 parents 5bd0b21 + 97b8294 commit 0871fb9

File tree

2 files changed

+155
-86
lines changed

2 files changed

+155
-86
lines changed

builtin/bisect--helper.c

Lines changed: 152 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
2121

2222
static const char * const git_bisect_helper_usage[] = {
2323
N_("git bisect--helper --bisect-reset [<commit>]"),
24-
N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
25-
N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
2624
N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
2725
N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
2826
N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
2927
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
3028
N_("git bisect--helper --bisect-next"),
31-
N_("git bisect--helper --bisect-auto-next"),
3229
N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
3330
N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
31+
N_("git bisect--helper --bisect-replay <filename>"),
32+
N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
3433
NULL
3534
};
3635

@@ -904,28 +903,148 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, const char **a
904903
return bisect_auto_next(terms, NULL);
905904
}
906905

906+
static enum bisect_error bisect_log(void)
907+
{
908+
int fd, status;
909+
const char* filename = git_path_bisect_log();
910+
911+
if (is_empty_or_missing_file(filename))
912+
return error(_("We are not bisecting."));
913+
914+
fd = open(filename, O_RDONLY);
915+
if (fd < 0)
916+
return BISECT_FAILED;
917+
918+
status = copy_fd(fd, STDOUT_FILENO);
919+
close(fd);
920+
return status ? BISECT_FAILED : BISECT_OK;
921+
}
922+
923+
static int process_replay_line(struct bisect_terms *terms, struct strbuf *line)
924+
{
925+
const char *p = line->buf + strspn(line->buf, " \t");
926+
char *word_end, *rev;
927+
928+
if ((!skip_prefix(p, "git bisect", &p) &&
929+
!skip_prefix(p, "git-bisect", &p)) || !isspace(*p))
930+
return 0;
931+
p += strspn(p, " \t");
932+
933+
word_end = (char *)p + strcspn(p, " \t");
934+
rev = word_end + strspn(word_end, " \t");
935+
*word_end = '\0'; /* NUL-terminate the word */
936+
937+
get_terms(terms);
938+
if (check_and_set_terms(terms, p))
939+
return -1;
940+
941+
if (!strcmp(p, "start")) {
942+
struct strvec argv = STRVEC_INIT;
943+
int res;
944+
sq_dequote_to_strvec(rev, &argv);
945+
res = bisect_start(terms, argv.v, argv.nr);
946+
strvec_clear(&argv);
947+
return res;
948+
}
949+
950+
if (one_of(p, terms->term_good,
951+
terms->term_bad, "skip", NULL))
952+
return bisect_write(p, rev, terms, 0);
953+
954+
if (!strcmp(p, "terms")) {
955+
struct strvec argv = STRVEC_INIT;
956+
int res;
957+
sq_dequote_to_strvec(rev, &argv);
958+
res = bisect_terms(terms, argv.nr == 1 ? argv.v[0] : NULL);
959+
strvec_clear(&argv);
960+
return res;
961+
}
962+
error(_("'%s'?? what are you talking about?"), p);
963+
964+
return -1;
965+
}
966+
967+
static enum bisect_error bisect_replay(struct bisect_terms *terms, const char *filename)
968+
{
969+
FILE *fp = NULL;
970+
enum bisect_error res = BISECT_OK;
971+
struct strbuf line = STRBUF_INIT;
972+
973+
if (is_empty_or_missing_file(filename))
974+
return error(_("cannot read file '%s' for replaying"), filename);
975+
976+
if (bisect_reset(NULL))
977+
return BISECT_FAILED;
978+
979+
fp = fopen(filename, "r");
980+
if (!fp)
981+
return BISECT_FAILED;
982+
983+
while ((strbuf_getline(&line, fp) != EOF) && !res)
984+
res = process_replay_line(terms, &line);
985+
986+
strbuf_release(&line);
987+
fclose(fp);
988+
989+
if (res)
990+
return BISECT_FAILED;
991+
992+
return bisect_auto_next(terms, NULL);
993+
}
994+
995+
static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **argv, int argc)
996+
{
997+
int i;
998+
enum bisect_error res;
999+
struct strvec argv_state = STRVEC_INIT;
1000+
1001+
strvec_push(&argv_state, "skip");
1002+
1003+
for (i = 0; i < argc; i++) {
1004+
const char *dotdot = strstr(argv[i], "..");
1005+
1006+
if (dotdot) {
1007+
struct rev_info revs;
1008+
struct commit *commit;
1009+
1010+
init_revisions(&revs, NULL);
1011+
setup_revisions(2, argv + i - 1, &revs, NULL);
1012+
1013+
if (prepare_revision_walk(&revs))
1014+
die(_("revision walk setup failed\n"));
1015+
while ((commit = get_revision(&revs)) != NULL)
1016+
strvec_push(&argv_state,
1017+
oid_to_hex(&commit->object.oid));
1018+
1019+
reset_revision_walk();
1020+
} else {
1021+
strvec_push(&argv_state, argv[i]);
1022+
}
1023+
}
1024+
res = bisect_state(terms, argv_state.v, argv_state.nr);
1025+
1026+
strvec_clear(&argv_state);
1027+
return res;
1028+
}
1029+
9071030
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
9081031
{
9091032
enum {
9101033
BISECT_RESET = 1,
911-
BISECT_WRITE,
912-
CHECK_AND_SET_TERMS,
9131034
BISECT_NEXT_CHECK,
9141035
BISECT_TERMS,
9151036
BISECT_START,
9161037
BISECT_AUTOSTART,
9171038
BISECT_NEXT,
918-
BISECT_AUTO_NEXT,
919-
BISECT_STATE
1039+
BISECT_STATE,
1040+
BISECT_LOG,
1041+
BISECT_REPLAY,
1042+
BISECT_SKIP
9201043
} cmdmode = 0;
9211044
int res = 0, nolog = 0;
9221045
struct option options[] = {
9231046
OPT_CMDMODE(0, "bisect-reset", &cmdmode,
9241047
N_("reset the bisection state"), BISECT_RESET),
925-
OPT_CMDMODE(0, "bisect-write", &cmdmode,
926-
N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
927-
OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
928-
N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
9291048
OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
9301049
N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
9311050
OPT_CMDMODE(0, "bisect-terms", &cmdmode,
@@ -934,10 +1053,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
9341053
N_("start the bisect session"), BISECT_START),
9351054
OPT_CMDMODE(0, "bisect-next", &cmdmode,
9361055
N_("find the next bisection commit"), BISECT_NEXT),
937-
OPT_CMDMODE(0, "bisect-auto-next", &cmdmode,
938-
N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),
9391056
OPT_CMDMODE(0, "bisect-state", &cmdmode,
9401057
N_("mark the state of ref (or refs)"), BISECT_STATE),
1058+
OPT_CMDMODE(0, "bisect-log", &cmdmode,
1059+
N_("list the bisection steps so far"), BISECT_LOG),
1060+
OPT_CMDMODE(0, "bisect-replay", &cmdmode,
1061+
N_("replay the bisection process from the given file"), BISECT_REPLAY),
1062+
OPT_CMDMODE(0, "bisect-skip", &cmdmode,
1063+
N_("skip some commits for checkout"), BISECT_SKIP),
9411064
OPT_BOOL(0, "no-log", &nolog,
9421065
N_("no log for BISECT_WRITE")),
9431066
OPT_END()
@@ -955,18 +1078,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
9551078
case BISECT_RESET:
9561079
if (argc > 1)
9571080
return error(_("--bisect-reset requires either no argument or a commit"));
958-
return !!bisect_reset(argc ? argv[0] : NULL);
959-
case BISECT_WRITE:
960-
if (argc != 4 && argc != 5)
961-
return error(_("--bisect-write requires either 4 or 5 arguments"));
962-
set_terms(&terms, argv[3], argv[2]);
963-
res = bisect_write(argv[0], argv[1], &terms, nolog);
964-
break;
965-
case CHECK_AND_SET_TERMS:
966-
if (argc != 3)
967-
return error(_("--check-and-set-terms requires 3 arguments"));
968-
set_terms(&terms, argv[2], argv[1]);
969-
res = check_and_set_terms(&terms, argv[0]);
1081+
res = bisect_reset(argc ? argv[0] : NULL);
9701082
break;
9711083
case BISECT_NEXT_CHECK:
9721084
if (argc != 2 && argc != 3)
@@ -989,17 +1101,26 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
9891101
get_terms(&terms);
9901102
res = bisect_next(&terms, prefix);
9911103
break;
992-
case BISECT_AUTO_NEXT:
993-
if (argc)
994-
return error(_("--bisect-auto-next requires 0 arguments"));
995-
get_terms(&terms);
996-
res = bisect_auto_next(&terms, prefix);
997-
break;
9981104
case BISECT_STATE:
9991105
set_terms(&terms, "bad", "good");
10001106
get_terms(&terms);
10011107
res = bisect_state(&terms, argv, argc);
10021108
break;
1109+
case BISECT_LOG:
1110+
if (argc)
1111+
return error(_("--bisect-log requires 0 arguments"));
1112+
res = bisect_log();
1113+
break;
1114+
case BISECT_REPLAY:
1115+
if (argc != 1)
1116+
return error(_("no logfile given"));
1117+
set_terms(&terms, "bad", "good");
1118+
res = bisect_replay(&terms, argv[0]);
1119+
break;
1120+
case BISECT_SKIP:
1121+
set_terms(&terms, "bad", "good");
1122+
res = bisect_skip(&terms, argv, argc);
1123+
break;
10031124
default:
10041125
BUG("unknown subcommand %d", cmdmode);
10051126
}

git-bisect.sh

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,6 @@ _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
3939
TERM_BAD=bad
4040
TERM_GOOD=good
4141

42-
bisect_skip() {
43-
all=''
44-
for arg in "$@"
45-
do
46-
case "$arg" in
47-
*..*)
48-
revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
49-
*)
50-
revs=$(git rev-parse --sq-quote "$arg") ;;
51-
esac
52-
all="$all $revs"
53-
done
54-
eval git bisect--helper --bisect-state 'skip' $all
55-
}
56-
5742
bisect_visualize() {
5843
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
5944

@@ -77,38 +62,6 @@ bisect_visualize() {
7762
eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES")
7863
}
7964

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-
11265
bisect_run () {
11366
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
11467

@@ -169,11 +122,6 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
169122
done
170123
}
171124

172-
bisect_log () {
173-
test -s "$GIT_DIR/BISECT_LOG" || die "$(gettext "We are not bisecting.")"
174-
cat "$GIT_DIR/BISECT_LOG"
175-
}
176-
177125
get_terms () {
178126
if test -s "$GIT_DIR/BISECT_TERMS"
179127
then
@@ -199,7 +147,7 @@ case "$#" in
199147
bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
200148
git bisect--helper --bisect-state "$cmd" "$@" ;;
201149
skip)
202-
bisect_skip "$@" ;;
150+
git bisect--helper --bisect-skip "$@" || exit;;
203151
next)
204152
# Not sure we want "next" at the UI level anymore.
205153
git bisect--helper --bisect-next "$@" || exit ;;
@@ -208,9 +156,9 @@ case "$#" in
208156
reset)
209157
git bisect--helper --bisect-reset "$@" ;;
210158
replay)
211-
bisect_replay "$@" ;;
159+
git bisect--helper --bisect-replay "$@" || exit;;
212160
log)
213-
bisect_log ;;
161+
git bisect--helper --bisect-log || exit ;;
214162
run)
215163
bisect_run "$@" ;;
216164
terms)

0 commit comments

Comments
 (0)