summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranit Bauva <pranit.bauva@gmail.com>2017-10-27 15:06:37 +0000
committerJunio C Hamano <gitster@pobox.com>2017-10-28 02:08:32 +0900
commitca12543868a0ac7a724739502367cac1074ae9d4 (patch)
tree9c1ed3c5194386a252ee887033b51054385c05e9
parent7e9fdedc4545f519d6cbca34f047be995df1afdb (diff)
downloadgit-ca12543868a0ac7a724739502367cac1074ae9d4.tar.gz
bisect--helper: `bisect_next_check` shell function in C
Reimplement `bisect_next_check` shell function in C and add `bisect-next-check` subcommand to `git bisect--helper` to call it from git-bisect.sh . `bisect_voc` shell function is no longer useful now and is replaced by using a char *[] of "new|bad" and "good|old" values. Using `--bisect-next-check` is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired but its implementation will be called by some other methods. Helped-by: Stephan Beyer <s-beyer@gmx.net> Mentored-by: Lars Schneider <larsxschneider@gmail.com> Mentored-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/bisect--helper.c91
-rwxr-xr-xgit-bisect.sh60
2 files changed, 94 insertions, 57 deletions
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 65abf8a70c..0f9c3e6382 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -6,6 +6,7 @@
#include "dir.h"
#include "argv-array.h"
#include "run-command.h"
+#include "prompt.h"
static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
@@ -21,6 +22,7 @@ static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --bisect-reset [<commit>]"),
N_("git bisect--helper --bisect-write <state> <revision> <good_term> <bad_term> [<nolog>]"),
N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
+ N_("git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>"),
NULL
};
@@ -44,6 +46,11 @@ static void set_terms(struct bisect_terms *terms, const char *bad,
terms->term_bad = xstrdup(bad);
}
+static const char *voc[] = {
+ "bad|new",
+ "good|old"
+};
+
/*
* Check whether the string `term` belongs to the set of strings
* included in the variable arguments.
@@ -264,6 +271,79 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
return 0;
}
+static int mark_good(const char *refname, const struct object_id *oid,
+ int flag, void *cb_data)
+{
+ int *m_good = (int *)cb_data;
+ *m_good = 0;
+ return 1;
+}
+
+static int bisect_next_check(const struct bisect_terms *terms,
+ const char *current_term)
+{
+ int missing_good = 1, missing_bad = 1, retval = 0;
+ const char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
+ const char *good_glob = xstrfmt("%s-*", terms->term_good);
+
+ if (ref_exists(bad_ref))
+ missing_bad = 0;
+
+ for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
+ (void *) &missing_good);
+
+ if (!missing_good && !missing_bad)
+ goto finish;
+
+ if (!current_term)
+ goto fail;
+
+ if (missing_good && !missing_bad && current_term &&
+ !strcmp(current_term, terms->term_good)) {
+ char *yesno;
+ /*
+ * have bad (or new) but not good (or old). We could bisect
+ * although this is less optimum.
+ */
+ fprintf(stderr, _("Warning: bisecting only with a %s commit\n"),
+ terms->term_bad);
+ if (!isatty(0))
+ goto finish;
+ /*
+ * TRANSLATORS: Make sure to include [Y] and [n] in your
+ * translation. The program will only accept English input
+ * at this point.
+ */
+ yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
+ if (starts_with(yesno, "N") || starts_with(yesno, "n"))
+ goto fail;
+
+ goto finish;
+ }
+ if (!is_empty_or_missing_file(git_path_bisect_start())) {
+ error(_("You need to give me at least one %s and "
+ "%s revision. You can use \"git bisect %s\" "
+ "and \"git bisect %s\" for that.\n"),
+ voc[0], voc[1], voc[0], voc[1]);
+ goto fail;
+ } else {
+ error(_("You need to start by \"git bisect start\". You "
+ "then need to give me at least one %s and %s "
+ "revision. You can use \"git bisect %s\" and "
+ "\"git bisect %s\" for that.\n"),
+ voc[1], voc[0], voc[1], voc[0]);
+ goto fail;
+ }
+ goto finish;
+
+fail:
+ retval = -1;
+finish:
+ free((void *) good_glob);
+ free((void *) bad_ref);
+ return retval;
+}
+
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
enum {
@@ -273,7 +353,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
CHECK_EXPECTED_REVS,
BISECT_RESET,
BISECT_WRITE,
- CHECK_AND_SET_TERMS
+ CHECK_AND_SET_TERMS,
+ BISECT_NEXT_CHECK
} cmdmode = 0;
int no_checkout = 0, res = 0;
struct option options[] = {
@@ -291,6 +372,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
N_("update the refs according to the bisection state and may write it to BISECT_LOG"), BISECT_WRITE),
OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
+ OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
+ N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
OPT_BOOL(0, "no-checkout", &no_checkout,
N_("update BISECT_HEAD instead of checking out the current commit")),
OPT_END()
@@ -335,6 +418,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
set_terms(&terms, argv[2], argv[1]);
res = check_and_set_terms(&terms, argv[0]);
break;
+ case BISECT_NEXT_CHECK:
+ if (argc != 2 && argc != 3)
+ return error(_("--bisect-next-check requires 2 or 3 arguments"));
+ set_terms(&terms, argv[1], argv[0]);
+ res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
+ break;
default:
return error("BUG: unknown subcommand '%d'", cmdmode);
}
diff --git a/git-bisect.sh b/git-bisect.sh
index 0447b73aa5..c21fafc62d 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -271,59 +271,14 @@ bisect_state() {
bisect_auto_next
}
-bisect_next_check() {
- missing_good= missing_bad=
- git show-ref -q --verify refs/bisect/$TERM_BAD || missing_bad=t
- test -n "$(git for-each-ref "refs/bisect/$TERM_GOOD-*")" || missing_good=t
-
- case "$missing_good,$missing_bad,$1" in
- ,,*)
- : have both $TERM_GOOD and $TERM_BAD - ok
- ;;
- *,)
- # do not have both but not asked to fail - just report.
- false
- ;;
- t,,"$TERM_GOOD")
- # have bad (or new) but not good (or old). we could bisect although
- # this is less optimum.
- eval_gettextln "Warning: bisecting only with a \$TERM_BAD commit." >&2
- if test -t 0
- then
- # TRANSLATORS: Make sure to include [Y] and [n] in your
- # translation. The program will only accept English input
- # at this point.
- gettext "Are you sure [Y/n]? " >&2
- read yesno
- case "$yesno" in [Nn]*) exit 1 ;; esac
- fi
- : bisect without $TERM_GOOD...
- ;;
- *)
- bad_syn=$(bisect_voc bad)
- good_syn=$(bisect_voc good)
- if test -s "$GIT_DIR/BISECT_START"
- then
-
- eval_gettextln "You need to give me at least one \$bad_syn and one \$good_syn revision.
-(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
- else
- eval_gettextln "You need to start by \"git bisect start\".
-You then need to give me at least one \$good_syn and one \$bad_syn revision.
-(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
- fi
- exit 1 ;;
- esac
-}
-
bisect_auto_next() {
- bisect_next_check && bisect_next || :
+ git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD && bisect_next || :
}
bisect_next() {
case "$#" in 0) ;; *) usage ;; esac
bisect_autostart
- bisect_next_check $TERM_GOOD
+ git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit
# Perform all bisection computation, display and checkout
git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
@@ -355,7 +310,7 @@ bisect_next() {
}
bisect_visualize() {
- bisect_next_check fail
+ git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
if test $# = 0
then
@@ -409,7 +364,7 @@ bisect_replay () {
}
bisect_run () {
- bisect_next_check fail
+ git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
while true
do
@@ -482,13 +437,6 @@ get_terms () {
fi
}
-bisect_voc () {
- case "$1" in
- bad) echo "bad|new" ;;
- good) echo "good|old" ;;
- esac
-}
-
bisect_terms () {
get_terms
if ! test -s "$GIT_DIR/BISECT_TERMS"