bisect--helper: finish porting `bisect_start()` to C

Add the subcommand to `git bisect--helper` and call it from git-bisect.sh. With the conversion of `bisect_auto_next()` from shell to C in a previous commit, `bisect_start()` can now be fully ported to C. So let's complete the `--bisect-start` subcommand of `git bisect--helper` so that it fully implements `bisect_start()`, and let's use this subcommand in `git-bisect.sh` instead of `bisect_start()`. Note that the `eval` in the changed line of `git-bisect.sh` cannot be dropped: it is necessary because the `rev` and the `tail` variables may contain multiple, quoted arguments that need to be passed to `bisect--helper` (without the quotes, naturally). 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> Reviewed-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pranit Bauva committed Oct 15, 2020 at 15:38 UTC 88ad372fc02c119a4e44ae71c93b6fab9d998512
2 files changed +29 -38
builtin/bisect--helper.c
+27 -14
@@ -85,6 +85,19 @@ static int one_of(const char *term, ...)
85 return res;
86 }
87
88 +/*
89 + * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
90 + * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
91 + * that indicate special success.
92 + */
93 +
94 +static int is_bisect_success(enum bisect_error res)
95 +{
96 + return !res ||
97 + res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ||
98 + res == BISECT_INTERNAL_SUCCESS_MERGE_BASE;
99 +}
100 +
101 static int write_in_file(const char *path, const char *mode, const char *format, va_list args)
102 {
103 FILE *fp = NULL;
@@ -609,12 +622,13 @@ static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char
622 return bisect_next(terms, prefix);
623 }
624
612 -static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
625 +static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc)
626 {
627 int no_checkout = 0;
628 int first_parent_only = 0;
629 int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
617 - int flags, pathspec_pos, res = 0;
630 + int flags, pathspec_pos;
631 + enum bisect_error res = BISECT_OK;
632 struct string_list revs = STRING_LIST_INIT_DUP;
633 struct string_list states = STRING_LIST_INIT_DUP;
634 struct strbuf start_head = STRBUF_INIT;
@@ -754,14 +768,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
768 * Get rid of any old bisect state.
769 */
770 if (bisect_clean_state())
757 - return -1;
758 -
759 - /*
760 - * In case of mistaken revs or checkout error, or signals received,
761 - * "bisect_auto_next" below may exit or misbehave.
762 - * We have to trap this to be able to clean up using
763 - * "bisect_clean_state".
764 - */
771 + return BISECT_FAILED;
772
773 /*
774 * Write new start state
@@ -778,7 +785,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
785 }
786 if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
787 UPDATE_REFS_MSG_ON_ERR)) {
781 - res = -1;
788 + res = BISECT_FAILED;
789 goto finish;
790 }
791 }
@@ -790,25 +797,31 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
797 for (i = 0; i < states.nr; i++)
798 if (bisect_write(states.items[i].string,
799 revs.items[i].string, terms, 1)) {
793 - res = -1;
800 + res = BISECT_FAILED;
801 goto finish;
802 }
803
804 if (must_write_terms && write_terms(terms->term_bad,
805 terms->term_good)) {
799 - res = -1;
806 + res = BISECT_FAILED;
807 goto finish;
808 }
809
810 res = bisect_append_log_quoted(argv);
811 if (res)
805 - res = -1;
812 + res = BISECT_FAILED;
813
814 finish:
815 string_list_clear(&revs, 0);
816 string_list_clear(&states, 0);
817 strbuf_release(&start_head);
818 strbuf_release(&bisect_names);
819 + if (res)
820 + return res;
821 +
822 + res = bisect_auto_next(terms, NULL);
823 + if (!is_bisect_success(res))
824 + bisect_clean_state();
825 return res;
826 }
827
git-bisect.sh
+2 -24
@@ -49,27 +49,6 @@ bisect_head()
49 fi
50 }
51
52 -bisect_start() {
53 - git bisect--helper --bisect-start $@ || exit
54 -
55 - #
56 - # Change state.
57 - # In case of mistaken revs or checkout error, or signals received,
58 - # "bisect_auto_next" below may exit or misbehave.
59 - # We have to trap this to be able to clean up using
60 - # "bisect_clean_state".
61 - #
62 - trap 'git bisect--helper --bisect-clean-state' 0
63 - trap 'exit 255' 1 2 3 15
64 -
65 - #
66 - # Check if we can proceed to the next bisect state.
67 - #
68 - git bisect--helper --bisect-auto-next || exit
69 -
70 - trap '-' 0
71 -}
72 -
52 bisect_skip() {
53 all=''
54 for arg in "$@"
@@ -163,8 +142,7 @@ bisect_replay () {
142 get_terms
143 case "$command" in
144 start)
166 - cmd="bisect_start $rev $tail"
167 - eval "$cmd" ;;
145 + eval "git bisect--helper --bisect-start $rev $tail" ;;
146 "$TERM_GOOD"|"$TERM_BAD"|skip)
147 git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;;
148 terms)
@@ -264,7 +242,7 @@ case "$#" in
242 help)
243 git bisect -h ;;
244 start)
267 - bisect_start "$@" ;;
245 + git bisect--helper --bisect-start "$@" ;;
246 bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
247 bisect_state "$cmd" "$@" ;;
248 skip)