git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v11 00/10] bisect terms
@ 2015-06-29 15:40 Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 01/10] bisect: correction of typo Matthieu Moy
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

Hi,

So, here's a reroll that tries to address the ongoing discussion.

The first patches are preparatory steps, which are IMHO good
regardless of the features. I kept the user-interface to chose terms
at the end, and tried to keep the UI patches as small as possible.

I have the feeling that "bisect: add the terms old/new" should be
dropped, but I have no strong opinion on that. If you like the
feature, say so. If you think the feature doesn't bring enough, and
should eventually be obsoleted by "guess which commit is old and which
is new", say so too.

The beginning of the series didn't change much since v10. The major
change is that I gave up using "git bisect terms <foo> <bar>", and
implemented the same feature in "git bisect start". We're losing the
ability to run "git bisect terms" several times to change the terms
before we use them, but I'm not sure this was a useful feature. OTOH,
we're back to the principle "git bisect start" starts from a fresh
state, this avoids confusing the situation where the user has leftover
from yesterday's "git bisect terms". And the code is much, much
simpler.

Antoine Delaite (4):
  bisect: correction of typo
  bisect: replace hardcoded "bad|good" by variables
  bisect: simplify the addition of new bisect terms
  bisect: add the terms old/new

Matthieu Moy (5):
  Documentation/bisect: move getting help section to the end
  bisect: don't mix option parsing and non-trivial code
  bisect: sanity check on terms
  bisect: add 'git bisect terms' to view the current terms
  bisect: allow setting any user-specified in 'git bisect start'

Michael Haggerty (1):
  Documentation/bisect: revise overall content

 Documentation/git-bisect.txt | 236 ++++++++++++++++++++++++++++-----------
 bisect.c                     |  94 ++++++++++++----
 git-bisect.sh                | 255 +++++++++++++++++++++++++++++++++++--------
 revision.c                   |  19 +++-
 t/t6030-bisect-porcelain.sh  | 137 ++++++++++++++++++++++-
 5 files changed, 612 insertions(+), 129 deletions(-)

-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v11 01/10] bisect: correction of typo
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 02/10] Documentation/bisect: move getting help section to the end Matthieu Moy
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

From: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>

Signed-off-by: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 bisect.c                    | 2 +-
 t/t6030-bisect-porcelain.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bisect.c b/bisect.c
index 03d5cd9..5b8357d 100644
--- a/bisect.c
+++ b/bisect.c
@@ -743,7 +743,7 @@ static void handle_bad_merge_base(void)
 
 	fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n"
 		"git bisect cannot work properly in this case.\n"
-		"Maybe you mistake good and bad revs?\n");
+		"Maybe you mistook good and bad revs?\n");
 	exit(1);
 }
 
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 06b4868..9e2c203 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -362,7 +362,7 @@ test_expect_success 'bisect starting with a detached HEAD' '
 test_expect_success 'bisect errors out if bad and good are mistaken' '
 	git bisect reset &&
 	test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
-	grep "mistake good and bad" rev_list_error &&
+	grep "mistook good and bad" rev_list_error &&
 	git bisect reset
 '
 
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 02/10] Documentation/bisect: move getting help section to the end
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 01/10] bisect: correction of typo Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 03/10] Documentation/bisect: revise overall content Matthieu Moy
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 Documentation/git-bisect.txt | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 4cb52a7..2bdc3b8 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -31,12 +31,6 @@ This command uses 'git rev-list --bisect' to help drive the
 binary search process to find which change introduced a bug, given an
 old "good" commit object name and a later "bad" commit object name.
 
-Getting help
-~~~~~~~~~~~~
-
-Use "git bisect" to get a short usage description, and "git bisect
-help" or "git bisect -h" to get a long usage description.
-
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -379,6 +373,11 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
 has at least one parent whose reachable graph is fully traversable in the sense
 required by 'git pack objects'.
 
+Getting help
+~~~~~~~~~~~~
+
+Use `git bisect` to get a short usage description, and `git bisect
+help` or `git bisect -h` to get a long usage description.
 
 SEE ALSO
 --------
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 03/10] Documentation/bisect: revise overall content
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 01/10] bisect: correction of typo Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 02/10] Documentation/bisect: move getting help section to the end Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 04/10] bisect: replace hardcoded "bad|good" by variables Matthieu Moy
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Michael Haggerty, Matthieu Moy

From: Michael Haggerty <mhagger@alum.mit.edu>

Thoroughly revise the "git bisect" manpage, including:

* Beef up the "Description" section.

* Make the first long example less specific to kernel development.

* De-emphasize implementation details in a couple of places.

* Add "(roughly N steps)" in the places where example output is shown.

* Properly markup code within the prose.

* Lots of wordsmithing.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 Documentation/git-bisect.txt | 122 ++++++++++++++++++++++++-------------------
 1 file changed, 68 insertions(+), 54 deletions(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 2bdc3b8..e97f2de 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -3,7 +3,7 @@ git-bisect(1)
 
 NAME
 ----
-git-bisect - Find by binary search the change that introduced a bug
+git-bisect - Use binary search to find the commit that introduced a bug
 
 
 SYNOPSIS
@@ -16,7 +16,6 @@ DESCRIPTION
 The command takes various subcommands, and different options depending
 on the subcommand:
 
- git bisect help
  git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
  git bisect bad [<rev>]
  git bisect good [<rev>...]
@@ -26,58 +25,71 @@ on the subcommand:
  git bisect replay <logfile>
  git bisect log
  git bisect run <cmd>...
+ git bisect help
 
-This command uses 'git rev-list --bisect' to help drive the
-binary search process to find which change introduced a bug, given an
-old "good" commit object name and a later "bad" commit object name.
+This command uses a binary search algorithm to find which commit in
+your project's history introduced a bug. You use it by first telling
+it a "bad" commit that is known to contain the bug, and a "good"
+commit that is known to be before the bug was introduced. Then `git
+bisect` picks a commit between those two endpoints and asks you
+whether the selected commit is "good" or "bad". It continues narrowing
+down the range until it finds the exact commit that introduced the
+change.
 
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Using the Linux kernel tree as an example, basic use of the bisect
-command is as follows:
+As an example, suppose you are trying to find the commit that broke a
+feature that was known to work in version `v2.6.13-rc2` of your
+project. You start a bisect session as follows:
 
 ------------------------------------------------
 $ git bisect start
 $ git bisect bad                 # Current version is bad
-$ git bisect good v2.6.13-rc2    # v2.6.13-rc2 was the last version
-                                 # tested that was good
+$ git bisect good v2.6.13-rc2    # v2.6.13-rc2 is known to be good
+------------------------------------------------
+
+Once you have specified at least one bad and one good commit, `git
+bisect` selects a commit in the middle of that range of history,
+checks it out, and outputs something similar to the following:
+
+------------------------------------------------
+Bisecting: 675 revisions left to test after this (roughly 10 steps)
 ------------------------------------------------
 
-When you have specified at least one bad and one good version, the
-command bisects the revision tree and outputs something similar to
-the following:
+You should now compile the checked-out version and test it. If that
+version works correctly, type
 
 ------------------------------------------------
-Bisecting: 675 revisions left to test after this
+$ git bisect good
 ------------------------------------------------
 
-The state in the middle of the set of revisions is then checked out.
-You would now compile that kernel and boot it. If the booted kernel
-works correctly, you would then issue the following command:
+If that version is broken, type
 
 ------------------------------------------------
-$ git bisect good			# this one is good
+$ git bisect bad
 ------------------------------------------------
 
-The output of this command would be something similar to the following:
+Then `git bisect` will respond with something like
 
 ------------------------------------------------
-Bisecting: 337 revisions left to test after this
+Bisecting: 337 revisions left to test after this (roughly 9 steps)
 ------------------------------------------------
 
-You keep repeating this process, compiling the tree, testing it, and
-depending on whether it is good or bad issuing the command "git bisect good"
-or "git bisect bad" to ask for the next bisection.
+Keep repeating the process: compile the tree, test it, and depending
+on whether it is good or bad run `git bisect good` or `git bisect bad`
+to ask for the next commit that needs testing.
+
+Eventually there will be no more revisions left to inspect, and the
+command will print out a description of the first bad commit. The
+reference `refs/bisect/bad` will be left pointing at that commit.
 
-Eventually there will be no more revisions left to bisect, and you
-will have been left with the first bad kernel revision in "refs/bisect/bad".
 
 Bisect reset
 ~~~~~~~~~~~~
 
 After a bisect session, to clean up the bisection state and return to
-the original HEAD (i.e., to quit bisecting), issue the following command:
+the original HEAD, issue the following command:
 
 ------------------------------------------------
 $ git bisect reset
@@ -94,9 +106,10 @@ instead:
 $ git bisect reset <commit>
 ------------------------------------------------
 
-For example, `git bisect reset HEAD` will leave you on the current
-bisection commit and avoid switching commits at all, while `git bisect
-reset bisect/bad` will check out the first bad revision.
+For example, `git bisect reset bisect/bad` will check out the first
+bad revision, while `git bisect reset HEAD` will leave you on the
+current bisection commit and avoid switching commits at all.
+
 
 Bisect visualize
 ~~~~~~~~~~~~~~~~
@@ -141,17 +154,17 @@ $ git bisect replay that-file
 Avoiding testing a commit
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If, in the middle of a bisect session, you know that the next suggested
-revision is not a good one to test (e.g. the change the commit
-introduces is known not to work in your environment and you know it
-does not have anything to do with the bug you are chasing), you may
-want to find a nearby commit and try that instead.
+If, in the middle of a bisect session, you know that the suggested
+revision is not a good one to test (e.g. it fails to build and you
+know that the failure does not have anything to do with the bug you
+are chasing), you can manually select a nearby commit and test that
+one instead.
 
 For example:
 
 ------------
 $ git bisect good/bad			# previous round was good or bad.
-Bisecting: 337 revisions left to test after this
+Bisecting: 337 revisions left to test after this (roughly 9 steps)
 $ git bisect visualize			# oops, that is uninteresting.
 $ git reset --hard HEAD~3		# try 3 revisions before what
 					# was suggested
@@ -163,18 +176,19 @@ the revision as good or bad in the usual manner.
 Bisect skip
 ~~~~~~~~~~~~
 
-Instead of choosing by yourself a nearby commit, you can ask Git
-to do it for you by issuing the command:
+Instead of choosing a nearby commit by yourself, you can ask Git to do
+it for you by issuing the command:
 
 ------------
 $ git bisect skip                 # Current version cannot be tested
 ------------
 
-But Git may eventually be unable to tell the first bad commit among
-a bad commit and one or more skipped commits.
+However, if you skip a commit adjacent to the one you are looking for,
+Git will be unable to tell exactly which of those commits was the
+first bad one.
 
-You can even skip a range of commits, instead of just one commit,
-using the "'<commit1>'..'<commit2>'" notation. For example:
+You can also skip a range of commits, instead of just one commit,
+using range notation. For example:
 
 ------------
 $ git bisect skip v2.5..v2.6
@@ -190,8 +204,8 @@ would issue the command:
 $ git bisect skip v2.5 v2.5..v2.6
 ------------
 
-This tells the bisect process that the commits between `v2.5` included
-and `v2.6` included should be skipped.
+This tells the bisect process that the commits between `v2.5` and
+`v2.6` (inclusive) should be skipped.
 
 
 Cutting down bisection by giving more parameters to bisect start
@@ -225,14 +239,14 @@ or bad, you can bisect by issuing the command:
 $ git bisect run my_script arguments
 ------------
 
-Note that the script (`my_script` in the above example) should
-exit with code 0 if the current source code is good, and exit with a
-code between 1 and 127 (inclusive), except 125, if the current
-source code is bad.
+Note that the script (`my_script` in the above example) should exit
+with code 0 if the current source code is good/old, and exit with a
+code between 1 and 127 (inclusive), except 125, if the current source
+code is bad/new.
 
 Any other exit code will abort the bisect process. It should be noted
-that a program that terminates via "exit(-1)" leaves $? = 255, (see the
-exit(3) manual page), as the value is chopped with "& 0377".
+that a program that terminates via `exit(-1)` leaves $? = 255, (see the
+exit(3) manual page), as the value is chopped with `& 0377`.
 
 The special exit code 125 should be used when the current source code
 cannot be tested. If the script exits with this code, the current
@@ -241,7 +255,7 @@ as the highest sensible value to use for this purpose, because 126 and 127
 are used by POSIX shells to signal specific error status (127 is for
 command not found, 126 is for command found but not executable---these
 details do not matter, as they are normal errors in the script, as far as
-"bisect run" is concerned).
+`bisect run` is concerned).
 
 You may often find that during a bisect session you want to have
 temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
@@ -254,7 +268,7 @@ next revision to test, the script can apply the patch
 before compiling, run the real test, and afterwards decide if the
 revision (possibly with the needed patch) passed the test and then
 rewind the tree to the pristine state.  Finally the script should exit
-with the status of the real test to let the "git bisect run" command loop
+with the status of the real test to let the `git bisect run` command loop
 determine the eventual outcome of the bisect session.
 
 OPTIONS
@@ -301,12 +315,12 @@ $ git bisect run ~/test.sh
 $ git bisect reset                   # quit the bisect session
 ------------
 +
-Here we use a "test.sh" custom script. In this script, if "make"
+Here we use a `test.sh` custom script. In this script, if `make`
 fails, we skip the current commit.
-"check_test_case.sh" should "exit 0" if the test case passes,
-and "exit 1" otherwise.
+`check_test_case.sh` should `exit 0` if the test case passes,
+and `exit 1` otherwise.
 +
-It is safer if both "test.sh" and "check_test_case.sh" are
+It is safer if both `test.sh` and `check_test_case.sh` are
 outside the repository to prevent interactions between the bisect,
 make and test processes and the scripts.
 
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 04/10] bisect: replace hardcoded "bad|good" by variables
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (2 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 03/10] Documentation/bisect: revise overall content Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 05/10] bisect: simplify the addition of new bisect terms Matthieu Moy
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

From: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>

To add new tags like old/new and have keywords less confusing, the
first step is to avoid hardcoding the keywords.

The default mode is still bad/good.

Signed-off-by: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>
Signed-off-by: Louis Stuber <stuberl@ensimag.grenoble-inp.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 bisect.c      | 54 +++++++++++++++++++++++++++++++++++++-----------------
 git-bisect.sh | 57 +++++++++++++++++++++++++++++++--------------------------
 2 files changed, 68 insertions(+), 43 deletions(-)

diff --git a/bisect.c b/bisect.c
index 5b8357d..a96e485 100644
--- a/bisect.c
+++ b/bisect.c
@@ -21,6 +21,9 @@ static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
 static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
 
+static const char *term_bad;
+static const char *term_good;
+
 /* Remember to update object flag allocation in object.h */
 #define COUNTED		(1u<<16)
 
@@ -403,15 +406,21 @@ struct commit_list *find_bisection(struct commit_list *list,
 static int register_ref(const char *refname, const struct object_id *oid,
 			int flags, void *cb_data)
 {
-	if (!strcmp(refname, "bad")) {
+	struct strbuf good_prefix = STRBUF_INIT;
+	strbuf_addstr(&good_prefix, term_good);
+	strbuf_addstr(&good_prefix, "-");
+
+	if (!strcmp(refname, term_bad)) {
 		current_bad_oid = xmalloc(sizeof(*current_bad_oid));
 		oidcpy(current_bad_oid, oid);
-	} else if (starts_with(refname, "good-")) {
+	} else if (starts_with(refname, good_prefix.buf)) {
 		sha1_array_append(&good_revs, oid->hash);
 	} else if (starts_with(refname, "skip-")) {
 		sha1_array_append(&skipped_revs, oid->hash);
 	}
 
+	strbuf_release(&good_prefix);
+
 	return 0;
 }
 
@@ -634,7 +643,7 @@ static void exit_if_skipped_commits(struct commit_list *tried,
 		return;
 
 	printf("There are only 'skip'ped commits left to test.\n"
-	       "The first bad commit could be any of:\n");
+	       "The first %s commit could be any of:\n", term_bad);
 	print_commit_list(tried, "%s\n", "%s\n");
 	if (bad)
 		printf("%s\n", oid_to_hex(bad));
@@ -732,18 +741,24 @@ static void handle_bad_merge_base(void)
 	if (is_expected_rev(current_bad_oid)) {
 		char *bad_hex = oid_to_hex(current_bad_oid);
 		char *good_hex = join_sha1_array_hex(&good_revs, ' ');
-
-		fprintf(stderr, "The merge base %s is bad.\n"
-			"This means the bug has been fixed "
-			"between %s and [%s].\n",
-			bad_hex, bad_hex, good_hex);
-
+		if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) {
+			fprintf(stderr, "The merge base %s is bad.\n"
+				"This means the bug has been fixed "
+				"between %s and [%s].\n",
+				bad_hex, bad_hex, good_hex);
+		} else {
+			fprintf(stderr, "The merge base %s is %s.\n"
+				"This means the first '%s' commit is "
+				"between %s and [%s].\n",
+				bad_hex, term_bad, term_good, bad_hex, good_hex);
+		}
 		exit(3);
 	}
 
-	fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n"
+	fprintf(stderr, "Some %s revs are not ancestor of the %s rev.\n"
 		"git bisect cannot work properly in this case.\n"
-		"Maybe you mistook good and bad revs?\n");
+		"Maybe you mistook %s and %s revs?\n",
+		term_good, term_bad, term_good, term_bad);
 	exit(1);
 }
 
@@ -755,10 +770,10 @@ static void handle_skipped_merge_base(const unsigned char *mb)
 
 	warning("the merge base between %s and [%s] "
 		"must be skipped.\n"
-		"So we cannot be sure the first bad commit is "
+		"So we cannot be sure the first %s commit is "
 		"between %s and %s.\n"
 		"We continue anyway.",
-		bad_hex, good_hex, mb_hex, bad_hex);
+		bad_hex, good_hex, term_bad, mb_hex, bad_hex);
 	free(good_hex);
 }
 
@@ -839,7 +854,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
 	int fd;
 
 	if (!current_bad_oid)
-		die("a bad revision is needed");
+		die("a %s revision is needed", term_bad);
 
 	/* Check if file BISECT_ANCESTORS_OK exists. */
 	if (!stat(filename, &st) && S_ISREG(st.st_mode))
@@ -905,6 +920,8 @@ int bisect_next_all(const char *prefix, int no_checkout)
 	const unsigned char *bisect_rev;
 	char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
 
+	term_bad = "bad";
+	term_good = "good";
 	if (read_bisect_refs())
 		die("reading bisect refs failed");
 
@@ -926,8 +943,10 @@ int bisect_next_all(const char *prefix, int no_checkout)
 		 */
 		exit_if_skipped_commits(tried, NULL);
 
-		printf("%s was both good and bad\n",
-		       oid_to_hex(current_bad_oid));
+		printf("%s was both %s and %s\n",
+		       oid_to_hex(current_bad_oid),
+		       term_good,
+		       term_bad);
 		exit(1);
 	}
 
@@ -942,7 +961,8 @@ int bisect_next_all(const char *prefix, int no_checkout)
 
 	if (!hashcmp(bisect_rev, current_bad_oid->hash)) {
 		exit_if_skipped_commits(tried, current_bad_oid);
-		printf("%s is the first bad commit\n", bisect_rev_hex);
+		printf("%s is the first %s commit\n", bisect_rev_hex,
+			term_bad);
 		show_diff_tree(prefix, revs.commits->item);
 		/* This means the bisection process succeeded. */
 		exit(10);
diff --git a/git-bisect.sh b/git-bisect.sh
index ae3fec2..fcbed22 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -32,6 +32,8 @@ OPTIONS_SPEC=
 
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+TERM_BAD=bad
+TERM_GOOD=good
 
 bisect_head()
 {
@@ -100,8 +102,8 @@ bisect_start() {
 				break
 			}
 			case $bad_seen in
-			0) state='bad' ; bad_seen=1 ;;
-			*) state='good' ;;
+			0) state=$TERM_BAD ; bad_seen=1 ;;
+			*) state=$TERM_GOOD ;;
 			esac
 			eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
 			shift
@@ -184,9 +186,12 @@ bisect_write() {
 	rev="$2"
 	nolog="$3"
 	case "$state" in
-		bad)		tag="$state" ;;
-		good|skip)	tag="$state"-"$rev" ;;
-		*)		die "$(eval_gettext "Bad bisect_write argument: \$state")" ;;
+		"$TERM_BAD")
+			tag="$state" ;;
+		"$TERM_GOOD"|skip)
+			tag="$state"-"$rev" ;;
+		*)
+			die "$(eval_gettext "Bad bisect_write argument: \$state")" ;;
 	esac
 	git update-ref "refs/bisect/$tag" "$rev" || exit
 	echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
@@ -230,12 +235,12 @@ bisect_state() {
 	case "$#,$state" in
 	0,*)
 		die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
-	1,bad|1,good|1,skip)
+	1,"$TERM_BAD"|1,"$TERM_GOOD"|1,skip)
 		rev=$(git rev-parse --verify $(bisect_head)) ||
 			die "$(gettext "Bad rev input: $(bisect_head)")"
 		bisect_write "$state" "$rev"
 		check_expected_revs "$rev" ;;
-	2,bad|*,good|*,skip)
+	2,"$TERM_BAD"|*,"$TERM_GOOD"|*,skip)
 		shift
 		hash_list=''
 		for rev in "$@"
@@ -249,8 +254,8 @@ bisect_state() {
 			bisect_write "$state" "$rev"
 		done
 		check_expected_revs $hash_list ;;
-	*,bad)
-		die "$(gettext "'git bisect bad' can take only one argument.")" ;;
+	*,"$TERM_BAD")
+		die "$(eval_gettext "'git bisect \$TERM_BAD' can take only one argument.")" ;;
 	*)
 		usage ;;
 	esac
@@ -259,21 +264,21 @@ bisect_state() {
 
 bisect_next_check() {
 	missing_good= missing_bad=
-	git show-ref -q --verify refs/bisect/bad || missing_bad=t
-	test -n "$(git for-each-ref "refs/bisect/good-*")" || missing_good=t
+	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 good and bad - ok
+		: have both $TERM_GOOD and $TERM_BAD - ok
 		;;
 	*,)
 		# do not have both but not asked to fail - just report.
 		false
 		;;
-	t,,good)
+	t,,"$TERM_GOOD")
 		# have bad but not good.  we could bisect although
 		# this is less optimum.
-		gettextln "Warning: bisecting only with a bad commit." >&2
+		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
@@ -283,7 +288,7 @@ bisect_next_check() {
 			read yesno
 			case "$yesno" in [Nn]*) exit 1 ;; esac
 		fi
-		: bisect without good...
+		: bisect without $TERM_GOOD...
 		;;
 	*)
 
@@ -307,7 +312,7 @@ bisect_auto_next() {
 bisect_next() {
 	case "$#" in 0) ;; *) usage ;; esac
 	bisect_autostart
-	bisect_next_check good
+	bisect_next_check $TERM_GOOD
 
 	# Perform all bisection computation, display and checkout
 	git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
@@ -316,18 +321,18 @@ bisect_next() {
 	# Check if we should exit because bisection is finished
 	if test $res -eq 10
 	then
-		bad_rev=$(git show-ref --hash --verify refs/bisect/bad)
+		bad_rev=$(git show-ref --hash --verify refs/bisect/$TERM_BAD)
 		bad_commit=$(git show-branch $bad_rev)
-		echo "# first bad commit: $bad_commit" >>"$GIT_DIR/BISECT_LOG"
+		echo "# first $TERM_BAD commit: $bad_commit" >>"$GIT_DIR/BISECT_LOG"
 		exit 0
 	elif test $res -eq 2
 	then
 		echo "# only skipped commits left to test" >>"$GIT_DIR/BISECT_LOG"
-		good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/good-*")
-		for skipped in $(git rev-list refs/bisect/bad --not $good_revs)
+		good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/$TERM_GOOD-*")
+		for skipped in $(git rev-list refs/bisect/$TERM_BAD --not $good_revs)
 		do
 			skipped_commit=$(git show-branch $skipped)
-			echo "# possible first bad commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG"
+			echo "# possible first $TERM_BAD commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG"
 		done
 		exit $res
 	fi
@@ -421,7 +426,7 @@ bisect_replay () {
 		start)
 			cmd="bisect_start $rev"
 			eval "$cmd" ;;
-		good|bad|skip)
+		$TERM_GOOD|$TERM_BAD|skip)
 			bisect_write "$command" "$rev" ;;
 		*)
 			die "$(gettext "?? what are you talking about?")" ;;
@@ -455,9 +460,9 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
 			state='skip'
 		elif [ $res -gt 0 ]
 		then
-			state='bad'
+			state="$TERM_BAD"
 		else
-			state='good'
+			state="$TERM_GOOD"
 		fi
 
 		# We have to use a subshell because "bisect_state" can exit.
@@ -466,7 +471,7 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
 
 		cat "$GIT_DIR/BISECT_RUN"
 
-		if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
+		if sane_grep "first $TERM_BAD commit could be any of" "$GIT_DIR/BISECT_RUN" \
 			>/dev/null
 		then
 			gettextln "bisect run cannot continue any more" >&2
@@ -480,7 +485,7 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
 			exit $res
 		fi
 
-		if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" >/dev/null
+		if sane_grep "is the first $TERM_BAD commit" "$GIT_DIR/BISECT_RUN" >/dev/null
 		then
 			gettextln "bisect run success"
 			exit 0;
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 05/10] bisect: simplify the addition of new bisect terms
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (3 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 04/10] bisect: replace hardcoded "bad|good" by variables Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code Matthieu Moy
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

From: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>

We create a file BISECT_TERMS in the repository .git to be read during a
bisection. There's no user-interface yet, but "git bisect" works if terms
other than old/new or bad/good are set in .git/BISECT_TERMS. The
fonctions to be changed if we add new terms are quite few.

In git-bisect.sh:
	check_and_set_terms
	bisect_voc

Co-authored-by: Louis Stuber <stuberl@ensimag.grenoble-inp.fr>
Tweaked-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>
Signed-off-by: Louis Stuber <stuberl@ensimag.grenoble-inp.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 bisect.c      | 33 +++++++++++++++++++++++--
 git-bisect.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 revision.c    | 19 ++++++++++++--
 3 files changed, 119 insertions(+), 12 deletions(-)

diff --git a/bisect.c b/bisect.c
index a96e485..857cf59 100644
--- a/bisect.c
+++ b/bisect.c
@@ -905,6 +905,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
 }
 
 /*
+ * The terms used for this bisect session are stored in BISECT_TERMS.
+ * We read them and store them to adapt the messages accordingly.
+ * Default is bad/good.
+ */
+void read_bisect_terms(const char **read_bad, const char **read_good)
+{
+	struct strbuf str = STRBUF_INIT;
+	const char *filename = git_path("BISECT_TERMS");
+	FILE *fp = fopen(filename, "r");
+
+	if (!fp) {
+		if (errno == ENOENT) {
+			*read_bad = "bad";
+			*read_good = "good";
+			return;
+		} else {
+			die("could not read file '%s': %s", filename,
+				strerror(errno));
+		}
+	} else {
+		strbuf_getline(&str, fp, '\n');
+		*read_bad = strbuf_detach(&str, NULL);
+		strbuf_getline(&str, fp, '\n');
+		*read_good = strbuf_detach(&str, NULL);
+	}
+	strbuf_release(&str);
+	fclose(fp);
+}
+
+/*
  * We use the convention that exiting with an exit code 10 means that
  * the bisection process finished successfully.
  * In this case the calling shell script should exit 0.
@@ -920,8 +950,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
 	const unsigned char *bisect_rev;
 	char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
 
-	term_bad = "bad";
-	term_good = "good";
+	read_bisect_terms(&term_bad, &term_good);
 	if (read_bisect_refs())
 		die("reading bisect refs failed");
 
diff --git a/git-bisect.sh b/git-bisect.sh
index fcbed22..dcd7e59 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -77,6 +77,7 @@ bisect_start() {
 	orig_args=$(git rev-parse --sq-quote "$@")
 	bad_seen=0
 	eval=''
+	must_write_terms=0
 	if test "z$(git rev-parse --is-bare-repository)" != zfalse
 	then
 		mode=--no-checkout
@@ -101,6 +102,14 @@ bisect_start() {
 				die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
 				break
 			}
+
+			# The user ran "git bisect start <sha1>
+			# <sha1>", hence did not explicitly specify
+			# the terms, but we are already starting to
+			# set references named with the default terms,
+			# and won't be able to change afterwards.
+			must_write_terms=1
+
 			case $bad_seen in
 			0) state=$TERM_BAD ; bad_seen=1 ;;
 			*) state=$TERM_GOOD ;;
@@ -172,6 +181,10 @@ bisect_start() {
 	} &&
 	git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
 	eval "$eval true" &&
+	if test $must_write_terms -eq 1
+	then
+		write_terms "$TERM_BAD" "$TERM_GOOD"
+	fi &&
 	echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
 	#
 	# Check if we can proceed to the next bisect state.
@@ -232,6 +245,7 @@ bisect_skip() {
 bisect_state() {
 	bisect_autostart
 	state=$1
+	check_and_set_terms $state
 	case "$#,$state" in
 	0,*)
 		die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
@@ -291,15 +305,17 @@ bisect_next_check() {
 		: bisect without $TERM_GOOD...
 		;;
 	*)
-
+		bad_syn=$(bisect_voc bad)
+		good_syn=$(bisect_voc good)
 		if test -s "$GIT_DIR/BISECT_START"
 		then
-			gettextln "You need to give me at least one good and one bad revision.
-(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
+
+			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
-			gettextln "You need to start by \"git bisect start\".
-You then need to give me at least one good and one bad revision.
-(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
+			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
@@ -402,6 +418,7 @@ bisect_clean_state() {
 	rm -f "$GIT_DIR/BISECT_LOG" &&
 	rm -f "$GIT_DIR/BISECT_NAMES" &&
 	rm -f "$GIT_DIR/BISECT_RUN" &&
+	rm -f "$GIT_DIR/BISECT_TERMS" &&
 	# Cleanup head-name if it got left by an old version of git-bisect
 	rm -f "$GIT_DIR/head-name" &&
 	git update-ref -d --no-deref BISECT_HEAD &&
@@ -422,11 +439,13 @@ bisect_replay () {
 			rev="$command"
 			command="$bisect"
 		fi
+		get_terms
+		check_and_set_terms "$command"
 		case "$command" in
 		start)
 			cmd="bisect_start $rev"
 			eval "$cmd" ;;
-		$TERM_GOOD|$TERM_BAD|skip)
+		"$TERM_GOOD"|"$TERM_BAD"|skip)
 			bisect_write "$command" "$rev" ;;
 		*)
 			die "$(gettext "?? what are you talking about?")" ;;
@@ -499,18 +518,62 @@ bisect_log () {
 	cat "$GIT_DIR/BISECT_LOG"
 }
 
+get_terms () {
+	if test -s "$GIT_DIR/BISECT_TERMS"
+	then
+		{
+		read TERM_BAD
+		read TERM_GOOD
+		} <"$GIT_DIR/BISECT_TERMS"
+	fi
+}
+
+write_terms () {
+	TERM_BAD=$1
+	TERM_GOOD=$2
+	printf '%s\n%s\n' "$TERM_BAD" "$TERM_GOOD" >"$GIT_DIR/BISECT_TERMS"
+}
+
+check_and_set_terms () {
+	cmd="$1"
+	case "$cmd" in
+	skip|start|terms) ;;
+	*)
+		if test -s "$GIT_DIR/BISECT_TERMS" && test "$cmd" != "$TERM_BAD" && test "$cmd" != "$TERM_GOOD"
+		then
+			die "$(eval_gettext "Invalid command: you're currently in a \$TERM_BAD/\$TERM_GOOD bisect.")"
+		fi
+		case "$cmd" in
+		bad|good)
+			if ! test -s "$GIT_DIR/BISECT_TERMS"
+			then
+				write_terms bad good
+			fi
+			;;
+		esac ;;
+	esac
+}
+
+bisect_voc () {
+	case "$1" in
+	bad) echo "bad" ;;
+	good) echo "good" ;;
+	esac
+}
+
 case "$#" in
 0)
 	usage ;;
 *)
 	cmd="$1"
+	get_terms
 	shift
 	case "$cmd" in
 	help)
 		git bisect -h ;;
 	start)
 		bisect_start "$@" ;;
-	bad|good)
+	bad|good|"$TERM_BAD"|"$TERM_GOOD")
 		bisect_state "$cmd" "$@" ;;
 	skip)
 		bisect_skip "$@" ;;
diff --git a/revision.c b/revision.c
index 3ff8723..7b35c5c 100644
--- a/revision.c
+++ b/revision.c
@@ -21,6 +21,9 @@
 
 volatile show_early_output_fn_t show_early_output;
 
+static const char *term_bad;
+static const char *term_good;
+
 char *path_name(const struct name_path *path, const char *name)
 {
 	const struct name_path *p;
@@ -2076,14 +2079,25 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
 	ctx->argc -= n;
 }
 
+extern void read_bisect_terms(const char **bad, const char **good);
+
+static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
+	struct strbuf bisect_refs = STRBUF_INIT;
+	int status;
+	strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
+	status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+	strbuf_release(&bisect_refs);
+	return status;
+}
+
 static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-	return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
+	return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
 }
 
 static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-	return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
+	return for_each_bisect_ref(submodule, fn, cb_data, term_good);
 }
 
 static int handle_revision_pseudo_opt(const char *submodule,
@@ -2112,6 +2126,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
 		handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
 		clear_ref_exclusion(&revs->ref_excludes);
 	} else if (!strcmp(arg, "--bisect")) {
+		read_bisect_terms(&term_bad, &term_good);
 		handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
 		handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
 		revs->bisect = 1;
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (4 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 05/10] bisect: simplify the addition of new bisect terms Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 20:28   ` Junio C Hamano
  2015-06-29 15:40 ` [PATCH v11 07/10] bisect: sanity check on terms Matthieu Moy
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

As-is, the revisions that appear on the command-line are processed in
order. This would mix badly with code that changes the configuration
(e.g. change $TERM_GOOD and $TERM_BAD) while processing the options.

Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 git-bisect.sh | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/git-bisect.sh b/git-bisect.sh
index dcd7e59..f32fd2d 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -78,6 +78,7 @@ bisect_start() {
 	bad_seen=0
 	eval=''
 	must_write_terms=0
+	revs=''
 	if test "z$(git rev-parse --is-bare-repository)" != zfalse
 	then
 		mode=--no-checkout
@@ -102,25 +103,27 @@ bisect_start() {
 				die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
 				break
 			}
-
-			# The user ran "git bisect start <sha1>
-			# <sha1>", hence did not explicitly specify
-			# the terms, but we are already starting to
-			# set references named with the default terms,
-			# and won't be able to change afterwards.
-			must_write_terms=1
-
-			case $bad_seen in
-			0) state=$TERM_BAD ; bad_seen=1 ;;
-			*) state=$TERM_GOOD ;;
-			esac
-			eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
+			revs="$revs $rev"
 			shift
 			;;
 		esac
 	done
 
+	for rev in $revs
+	do
+		# The user ran "git bisect start <sha1>
+		# <sha1>", hence did not explicitly specify
+		# the terms, but we are already starting to
+		# set references named with the default terms,
+		# and won't be able to change afterwards.
+		must_write_terms=1
+
+		case $bad_seen in
+		0) state=$TERM_BAD ; bad_seen=1 ;;
+		*) state=$TERM_GOOD ;;
+		esac
+		eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
+	done
 	#
 	# Verify HEAD.
 	#
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 07/10] bisect: sanity check on terms
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (5 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 08/10] bisect: add the terms old/new Matthieu Moy
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

This is currently only a defensive check since the only terms are
bad/good and new/old, which pass it, but this is a preparation step for
accepting user-supplied terms.

Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 git-bisect.sh | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/git-bisect.sh b/git-bisect.sh
index f32fd2d..0b3c820 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -535,9 +535,42 @@ get_terms () {
 write_terms () {
 	TERM_BAD=$1
 	TERM_GOOD=$2
+	if test "$TERM_BAD" = "$TERM_GOOD"
+	then
+		die "$(gettext "please use two different terms")"
+	fi
+	check_term_format "$TERM_BAD" bad
+	check_term_format "$TERM_GOOD" good
 	printf '%s\n%s\n' "$TERM_BAD" "$TERM_GOOD" >"$GIT_DIR/BISECT_TERMS"
 }
 
+check_term_format () {
+	term=$1
+	git check-ref-format refs/bisect/"$term" ||
+	die "$(eval_gettext "'\$term' is not a valid term")"
+	case "$term" in
+	help|start|terms|skip|next|reset|visualize|replay|log|run)
+		die "$(eval_gettext "can't use the builtin command '\$term' as a term")"
+		;;
+	bad|new)
+		if test "$2" != bad
+		then
+			# In theory, nothing prevents swapping
+			# completely good and bad, but this situation
+			# could be confusing and hasn't been tested
+			# enough. Forbid it for now.
+			die "$(eval_gettext "can't change the meaning of term '\$term'")"
+		fi
+		;;
+	good|old)
+		if test "$2" != good
+		then
+			die "$(eval_gettext "can't change the meaning of term '\$term'")"
+		fi
+		;;
+	esac
+}
+
 check_and_set_terms () {
 	cmd="$1"
 	case "$cmd" in
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 08/10] bisect: add the terms old/new
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (6 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 07/10] bisect: sanity check on terms Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 09/10] bisect: add 'git bisect terms' to view the current terms Matthieu Moy
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

From: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>

When not looking for a regression during a bisect but for a fix or a
change in another given property, it can be confusing to use 'good'
and 'bad'.

This patch introduce `git bisect new` and `git bisect old` as an
alternative to 'bad' and good': the commits which have a certain
property must be marked as `new` and the ones which do not as `old`.

The output will be the first commit after the change in the property.
During a new/old bisect session you cannot use bad/good commands and
vice-versa.

Some commands are still not available for old/new:
     * git rev-list --bisect does not treat the revs/bisect/new and
       revs/bisect/old-SHA1 files.

Old discussions:
	- http://thread.gmane.org/gmane.comp.version-control.git/86063
		introduced bisect fix unfixed to find fix.
	- http://thread.gmane.org/gmane.comp.version-control.git/182398
		discussion around bisect yes/no or old/new.
	- http://thread.gmane.org/gmane.comp.version-control.git/199758
		last discussion and reviews
New discussions:
	- http://thread.gmane.org/gmane.comp.version-control.git/271320
		( v2 1/7-4/7 )
	- http://comments.gmane.org/gmane.comp.version-control.git/271343
		( v2 5/7-7/7 )

Signed-off-by: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr>
Signed-off-by: Louis Stuber <stuberl@ensimag.grenoble-inp.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 Documentation/git-bisect.txt | 58 ++++++++++++++++++++++++++++++++++++++++++--
 bisect.c                     | 11 ++++++---
 git-bisect.sh                | 26 +++++++++++++-------
 t/t6030-bisect-porcelain.sh  | 38 +++++++++++++++++++++++++++++
 4 files changed, 119 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index e97f2de..abaf462 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -17,8 +17,8 @@ The command takes various subcommands, and different options depending
 on the subcommand:
 
  git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
- git bisect bad [<rev>]
- git bisect good [<rev>...]
+ git bisect (bad|new) [<rev>]
+ git bisect (good|old) [<rev>...]
  git bisect skip [(<rev>|<range>)...]
  git bisect reset [<commit>]
  git bisect visualize
@@ -36,6 +36,13 @@ whether the selected commit is "good" or "bad". It continues narrowing
 down the range until it finds the exact commit that introduced the
 change.
 
+In fact, `git bisect` can be used to find the commit that changed
+*any* property of your project; e.g., the commit that fixed a bug, or
+the commit that caused a benchmark's performance to improve. To
+support this more general usage, the terms "old" and "new" can be used
+in place of "good" and "bad". See
+section "Alternate terms" below for more information.
+
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -111,6 +118,45 @@ bad revision, while `git bisect reset HEAD` will leave you on the
 current bisection commit and avoid switching commits at all.
 
 
+Alternate terms
+~~~~~~~~~~~~~~~
+
+Sometimes you are not looking for the commit that introduced a
+breakage, but rather for a commit that caused a change between some
+other "old" state and "new" state. For example, you might be looking
+for the commit that introduced a particular fix. Or you might be
+looking for the first commit in which the source-code filenames were
+finally all converted to your company's naming standard. Or whatever.
+
+In such cases it can be very confusing to use the terms "good" and
+"bad" to refer to "the state before the change" and "the state after
+the change". So instead, you can use the terms "old" and "new",
+respectively, in place of "good" and "bad". (But note that you cannot
+mix "good" and "bad" with "old" and "new" in a single session.)
+
+In this more general usage, you provide `git bisect` with a "new"
+commit has some property and an "old" commit that doesn't have that
+property. Each time `git bisect` checks out a commit, you test if that
+commit has the property. If it does, mark the commit as "new";
+otherwise, mark it as "old". When the bisection is done, `git bisect`
+will report which commit introduced the property.
+
+To use "old" and "new" instead of "good" and bad, you must run `git
+bisect start` without commits as argument and then run the following
+commands to add the commits:
+
+------------------------------------------------
+git bisect old [<rev>]
+------------------------------------------------
+
+to indicate that a commit was before the sought change, or
+
+------------------------------------------------
+git bisect new [<rev>...]
+------------------------------------------------
+
+to indicate that it was after.
+
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
@@ -387,6 +433,14 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
 has at least one parent whose reachable graph is fully traversable in the sense
 required by 'git pack objects'.
 
+* Look for a fix instead of a regression in the code
++
+------------
+$ git bisect start
+$ git bisect new HEAD    # current commit is marked as new
+$ git bisect old HEAD~10 # the tenth commit from now is marked as old
+------------
+
 Getting help
 ~~~~~~~~~~~~
 
diff --git a/bisect.c b/bisect.c
index 857cf59..f7292cb 100644
--- a/bisect.c
+++ b/bisect.c
@@ -746,6 +746,11 @@ static void handle_bad_merge_base(void)
 				"This means the bug has been fixed "
 				"between %s and [%s].\n",
 				bad_hex, bad_hex, good_hex);
+		} else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
+			fprintf(stderr, "The merge base %s is new.\n"
+				"The property has changed "
+				"between %s and [%s].\n",
+				bad_hex, bad_hex, good_hex);
 		} else {
 			fprintf(stderr, "The merge base %s is %s.\n"
 				"This means the first '%s' commit is "
@@ -778,11 +783,11 @@ static void handle_skipped_merge_base(const unsigned char *mb)
 }
 
 /*
- * "check_merge_bases" checks that merge bases are not "bad".
+ * "check_merge_bases" checks that merge bases are not "bad" (or "new").
  *
- * - If one is "bad", it means the user assumed something wrong
+ * - If one is "bad" (or "new"), it means the user assumed something wrong
  * and we must exit with a non 0 error code.
- * - If one is "good", that's good, we have nothing to do.
+ * - If one is "good" (or "old"), that's good, we have nothing to do.
  * - If one is "skipped", we can't know but we should warn.
  * - If we don't know, we should check it out and ask the user to test.
  */
diff --git a/git-bisect.sh b/git-bisect.sh
index 0b3c820..42e1cee 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -1,14 +1,16 @@
 #!/bin/sh
 
-USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
+USAGE='[help|start|bad|good|new|old|skip|next|reset|visualize|replay|log|run]'
 LONG_USAGE='git bisect help
 	print this long help message.
 git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
 	reset bisect state and start bisection.
-git bisect bad [<rev>]
-	mark <rev> a known-bad revision.
-git bisect good [<rev>...]
-	mark <rev>... known-good revisions.
+git bisect (bad|new) [<rev>]
+	mark <rev> a known-bad revision/
+		a revision after change in a given property.
+git bisect (good|old) [<rev>...]
+	mark <rev>... known-good revisions/
+		revisions before change in a given property.
 git bisect skip [(<rev>|<range>)...]
 	mark <rev>... untestable revisions.
 git bisect next
@@ -294,7 +296,7 @@ bisect_next_check() {
 		false
 		;;
 	t,,"$TERM_GOOD")
-		# have bad but not good.  we could bisect although
+		# 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
@@ -587,14 +589,20 @@ check_and_set_terms () {
 				write_terms bad good
 			fi
 			;;
+		new|old)
+			if ! test -s "$GIT_DIR/BISECT_TERMS"
+			then
+				write_terms new old
+			fi
+			;;
 		esac ;;
 	esac
 }
 
 bisect_voc () {
 	case "$1" in
-	bad) echo "bad" ;;
-	good) echo "good" ;;
+	bad) echo "bad|new" ;;
+	good) echo "good|old" ;;
 	esac
 }
 
@@ -610,7 +618,7 @@ case "$#" in
 		git bisect -h ;;
 	start)
 		bisect_start "$@" ;;
-	bad|good|"$TERM_BAD"|"$TERM_GOOD")
+	bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
 		bisect_state "$cmd" "$@" ;;
 	skip)
 		bisect_skip "$@" ;;
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 9e2c203..983c503 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -759,4 +759,42 @@ test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
 	git bisect reset
 '
 
+test_expect_success 'bisect starts with only one new' '
+	git bisect reset &&
+	git bisect start &&
+	git bisect new $HASH4 &&
+	git bisect next
+'
+
+test_expect_success 'bisect does not start with only one old' '
+	git bisect reset &&
+	git bisect start &&
+	git bisect old $HASH1 &&
+	test_must_fail git bisect next
+'
+
+test_expect_success 'bisect start with one new and old' '
+	git bisect reset &&
+	git bisect start &&
+	git bisect old $HASH1 &&
+	git bisect new $HASH4 &&
+	git bisect new &&
+	git bisect new >bisect_result &&
+	grep "$HASH2 is the first new commit" bisect_result &&
+	git bisect log >log_to_replay.txt &&
+	git bisect reset
+'
+
+test_expect_success 'bisect replay with old and new' '
+	git bisect replay log_to_replay.txt >bisect_result &&
+	grep "$HASH2 is the first new commit" bisect_result &&
+	git bisect reset
+'
+
+test_expect_success 'bisect cannot mix old/new and good/bad' '
+	git bisect start &&
+	git bisect bad $HASH4 &&
+	test_must_fail git bisect old $HASH1
+'
+
 test_done
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 09/10] bisect: add 'git bisect terms' to view the current terms
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (7 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 08/10] bisect: add the terms old/new Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 15:40 ` [PATCH v11 10/10] bisect: allow setting any user-specified in 'git bisect start' Matthieu Moy
  2015-06-29 16:44 ` [PATCH v11 00/10] bisect terms Junio C Hamano
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 Documentation/git-bisect.txt | 10 ++++++++++
 git-bisect.sh                | 39 ++++++++++++++++++++++++++++++++++++++-
 t/t6030-bisect-porcelain.sh  | 20 ++++++++++++++++++++
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index abaf462..4dd6295 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -19,6 +19,7 @@ on the subcommand:
  git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
  git bisect (bad|new) [<rev>]
  git bisect (good|old) [<rev>...]
+ git bisect terms [--term-good | --term-bad]
  git bisect skip [(<rev>|<range>)...]
  git bisect reset [<commit>]
  git bisect visualize
@@ -157,6 +158,15 @@ git bisect new [<rev>...]
 
 to indicate that it was after.
 
+To get a reminder of the currently used terms, use
+
+------------------------------------------------
+git bisect terms
+------------------------------------------------
+
+You can get just the old (respectively new) term with `git bisect term
+--term-old` or `git bisect term --term-good`.
+
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
diff --git a/git-bisect.sh b/git-bisect.sh
index 42e1cee..da86d9e 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-USAGE='[help|start|bad|good|new|old|skip|next|reset|visualize|replay|log|run]'
+USAGE='[help|start|bad|good|new|old|terms|skip|next|reset|visualize|replay|log|run]'
 LONG_USAGE='git bisect help
 	print this long help message.
 git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
@@ -11,6 +11,8 @@ git bisect (bad|new) [<rev>]
 git bisect (good|old) [<rev>...]
 	mark <rev>... known-good revisions/
 		revisions before change in a given property.
+git bisect terms [--term-good | --term-bad]
+	show the terms used for old and new commits (default: bad, good)
 git bisect skip [(<rev>|<range>)...]
 	mark <rev>... untestable revisions.
 git bisect next
@@ -453,6 +455,8 @@ bisect_replay () {
 			eval "$cmd" ;;
 		"$TERM_GOOD"|"$TERM_BAD"|skip)
 			bisect_write "$command" "$rev" ;;
+		terms)
+			bisect_terms $rev ;;
 		*)
 			die "$(gettext "?? what are you talking about?")" ;;
 		esac
@@ -606,6 +610,37 @@ bisect_voc () {
 	esac
 }
 
+bisect_terms () {
+	get_terms
+	if ! test -s "$GIT_DIR/BISECT_TERMS"
+	then
+		die "$(gettext "no terms defined")"
+	fi
+	case "$#" in
+	0)
+		gettextln "Your current terms are $TERM_GOOD for the old state
+and $TERM_BAD for the new state."
+		;;
+	1)
+		arg=$1
+		case "$arg" in
+			--term-good|--term-old)
+				printf '%s\n' "$TERM_GOOD"
+				;;
+			--term-bad|--term-new)
+				printf '%s\n' "$TERM_BAD"
+				;;
+			*)
+				die "$(eval_gettext "invalid argument \$arg for 'git bisect terms'.
+Supported options are: --term-good|--term-old and --term-bad|--term-new.")"
+				;;
+		esac
+		;;
+	*)
+		usage ;;
+	esac
+}
+
 case "$#" in
 0)
 	usage ;;
@@ -635,6 +670,8 @@ case "$#" in
 		bisect_log ;;
 	run)
 		bisect_run "$@" ;;
+	terms)
+		bisect_terms "$@" ;;
 	*)
 		usage ;;
 	esac
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 983c503..9393488 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -797,4 +797,24 @@ test_expect_success 'bisect cannot mix old/new and good/bad' '
 	test_must_fail git bisect old $HASH1
 '
 
+test_expect_success 'bisect terms needs 0 or 1 argument' '
+	git bisect reset &&
+	test_must_fail git bisect terms only-one &&
+	test_must_fail git bisect terms 1 2 &&
+	test_must_fail git bisect terms 2>actual &&
+	echo "no terms defined" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'bisect terms shows good/bad after start' '
+	git bisect reset &&
+	git bisect start HEAD $HASH1 &&
+	git bisect terms --term-good >actual &&
+	echo good >expected &&
+	test_cmp expected actual &&
+	git bisect terms --term-bad >actual &&
+	echo bad >expected &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v11 10/10] bisect: allow setting any user-specified in 'git bisect start'
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (8 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 09/10] bisect: add 'git bisect terms' to view the current terms Matthieu Moy
@ 2015-06-29 15:40 ` Matthieu Moy
  2015-06-29 16:44 ` [PATCH v11 00/10] bisect terms Junio C Hamano
  10 siblings, 0 replies; 15+ messages in thread
From: Matthieu Moy @ 2015-06-29 15:40 UTC (permalink / raw)
  To: gitster
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray, Matthieu Moy

This allows a natural user-interface when looking for any change in the
code, not just regression. For example:

git bisect start --term-old fast --term-new slow
git bisect fast
git bisect slow
...

There were several proposed user-interfaces for this feature. This patch
implements it as options to 'git bisect start' for the following reasons:

* By construction, the terms will be valid for one and only one
  bisection.

* Unlike positional arguments, using named options avoid having to
  remember an order.

* We can combine user-defined terms and passing old/new commits as
  argument to "git bisect start".

* The implementation is relatively simple.

See previous discussions:

  http://mid.gmane.org/1435337896-20709-3-git-send-email-Matthieu.Moy@imag.fr

Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
 Documentation/git-bisect.txt | 37 +++++++++++++++++++--
 git-bisect.sh                | 21 +++++++++++-
 t/t6030-bisect-porcelain.sh  | 77 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 4dd6295..340f3c1 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -16,7 +16,8 @@ DESCRIPTION
 The command takes various subcommands, and different options depending
 on the subcommand:
 
- git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
+ git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
+                  [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
  git bisect (bad|new) [<rev>]
  git bisect (good|old) [<rev>...]
  git bisect terms [--term-good | --term-bad]
@@ -41,7 +42,7 @@ In fact, `git bisect` can be used to find the commit that changed
 *any* property of your project; e.g., the commit that fixed a bug, or
 the commit that caused a benchmark's performance to improve. To
 support this more general usage, the terms "old" and "new" can be used
-in place of "good" and "bad". See
+in place of "good" and "bad", or you can choose your own terms. See
 section "Alternate terms" below for more information.
 
 Basic bisect commands: start, bad, good
@@ -167,6 +168,31 @@ git bisect terms
 You can get just the old (respectively new) term with `git bisect term
 --term-old` or `git bisect term --term-good`.
 
+If you would like to use your own terms instead of "bad"/"good" or
+"new"/"old", you can choose any names you like (except existing bisect
+subcommands like `reset`, `start`, ...) by starting the
+bisection using
+
+------------------------------------------------
+git bisect start --term-old <term-old> --term-new <term-new>
+------------------------------------------------
+
+For example, if you are looking for a commit that introduced a
+performance regression, you might use
+
+------------------------------------------------
+git bisect start --term-old fast --term-new slow
+------------------------------------------------
+
+Or if you are looking for the commit that fixed a bug, you might use
+
+------------------------------------------------
+git bisect start --term-new fixed --term-old broken
+------------------------------------------------
+
+Then, use `git bisect <term-old>` and `git bisect <term-new>` instead
+of `git bisect good` and `git bisect bad` to mark commits.
+
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
@@ -450,6 +476,13 @@ $ git bisect start
 $ git bisect new HEAD    # current commit is marked as new
 $ git bisect old HEAD~10 # the tenth commit from now is marked as old
 ------------
++
+or:
+------------
+$ git bisect start --term-old broken --term-new fixed
+$ git bisect fixed
+$ git bisect broken HEAD~10
+------------
 
 Getting help
 ~~~~~~~~~~~~
diff --git a/git-bisect.sh b/git-bisect.sh
index da86d9e..718902b 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -3,7 +3,8 @@
 USAGE='[help|start|bad|good|new|old|terms|skip|next|reset|visualize|replay|log|run]'
 LONG_USAGE='git bisect help
 	print this long help message.
-git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
+git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
+                 [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
 	reset bisect state and start bisection.
 git bisect (bad|new) [<rev>]
 	mark <rev> a known-bad revision/
@@ -99,6 +100,24 @@ bisect_start() {
 		--no-checkout)
 			mode=--no-checkout
 			shift ;;
+		--term-good|--term-old)
+			shift
+			must_write_terms=1
+			TERM_GOOD=$1
+			shift ;;
+		--term-good=*|--term-old=*)
+			must_write_terms=1
+			TERM_GOOD=${1#*=}
+			shift ;;
+		--term-bad|--term-new)
+			shift
+			must_write_terms=1
+			TERM_BAD=$1
+			shift ;;
+		--term-bad=*|--term-new=*)
+			must_write_terms=1
+			TERM_BAD=${1#*=}
+			shift ;;
 		--*)
 			die "$(eval_gettext "unrecognised option: '\$arg'")" ;;
 		*)
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 9393488..e74662b 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -817,4 +817,81 @@ test_expect_success 'bisect terms shows good/bad after start' '
 	test_cmp expected actual
 '
 
+test_expect_success 'bisect start with one term1 and term2' '
+	git bisect reset &&
+	git bisect start --term-old term2 --term-new term1 &&
+	git bisect term2 $HASH1 &&
+	git bisect term1 $HASH4 &&
+	git bisect term1 &&
+	git bisect term1 >bisect_result &&
+	grep "$HASH2 is the first term1 commit" bisect_result &&
+	git bisect log >log_to_replay.txt &&
+	git bisect reset
+'
+
+test_expect_success 'bisect replay with term1 and term2' '
+	git bisect replay log_to_replay.txt >bisect_result &&
+	grep "$HASH2 is the first term1 commit" bisect_result &&
+	git bisect reset
+'
+
+test_expect_success 'bisect start term1 term2' '
+	git bisect reset &&
+	git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
+	git bisect term1 &&
+	git bisect term1 >bisect_result &&
+	grep "$HASH2 is the first term1 commit" bisect_result &&
+	git bisect log >log_to_replay.txt &&
+	git bisect reset
+'
+
+test_expect_success 'bisect cannot mix terms' '
+	git bisect reset &&
+	git bisect start --term-good term1 --term-bad term2 $HASH4 $HASH1 &&
+	test_must_fail git bisect a &&
+	test_must_fail git bisect b &&
+	test_must_fail git bisect bad &&
+	test_must_fail git bisect good &&
+	test_must_fail git bisect new &&
+	test_must_fail git bisect old
+'
+
+test_expect_success 'bisect terms rejects invalid terms' '
+	git bisect reset &&
+	test_must_fail git bisect start --term-good invalid..term &&
+	test_must_fail git bisect terms --term-bad invalid..term &&
+	test_must_fail git bisect terms --term-good bad &&
+	test_must_fail git bisect terms --term-good old &&
+	test_must_fail git bisect terms --term-good skip &&
+	test_must_fail git bisect terms --term-good reset &&
+	test_path_is_missing .git/BISECT_TERMS
+'
+
+test_expect_success 'bisect start --term-* does store terms' '
+	git bisect reset &&
+	git bisect start --term-bad=one --term-good=two &&
+	git bisect terms >actual &&
+	cat <<-EOF >expected &&
+	Your current terms are two for the old state
+	and one for the new state.
+	EOF
+	test_cmp expected actual &&
+	git bisect terms --term-bad >actual &&
+	echo one >expected &&
+	test_cmp expected actual &&
+	git bisect terms --term-good >actual &&
+	echo two >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'bisect start takes options and revs in any order' '
+	git bisect reset &&
+	git bisect start --term-good one $HASH4 \
+		--term-good two --term-bad bad-term \
+		$HASH1 --term-good three -- &&
+	(git bisect terms --term-bad && git bisect terms --term-good) >actual &&
+	printf "%s\n%s\n" bad-term three >expected &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.5.0.rc0.10.gd2bff5d

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v11 00/10] bisect terms
  2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
                   ` (9 preceding siblings ...)
  2015-06-29 15:40 ` [PATCH v11 10/10] bisect: allow setting any user-specified in 'git bisect start' Matthieu Moy
@ 2015-06-29 16:44 ` Junio C Hamano
  10 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2015-06-29 16:44 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray

Matthieu Moy <Matthieu.Moy@imag.fr> writes:

> So, here's a reroll that tries to address the ongoing discussion.
>
> The first patches are preparatory steps, which are IMHO good
> regardless of the features. I kept the user-interface to chose terms
> at the end, and tried to keep the UI patches as small as possible.
>
> I have the feeling that "bisect: add the terms old/new" should be
> dropped, but I have no strong opinion on that. If you like the
> feature, say so. If you think the feature doesn't bring enough, and
> should eventually be obsoleted by "guess which commit is old and which
> is new", say so too.

I personally do not mind having old/new, as long as it does not make
it harder to build on top of the codebase (and existing user
experience) to eventually transition to "you can always say good or
bad and we'll figure out which of old/new they map to".  Obviously
we will never guess which is old/new when the user uses old/new as
the chosen terms, and having to special case that might complicat
things, which is where that "as long as it does not make it harder"
above comes from.

> The beginning of the series didn't change much since v10. The major
> change is that I gave up using "git bisect terms <foo> <bar>", and
> implemented the same feature in "git bisect start". We're losing the
> ability to run "git bisect terms" several times to change the terms
> before we use them, but I'm not sure this was a useful feature. OTOH,
> we're back to the principle "git bisect start" starts from a fresh
> state, this avoids confusing the situation where the user has leftover
> from yesterday's "git bisect terms". And the code is much, much
> simpler.

I like that direction.  But let's first wait to see what others say.

Thanks.

>
> Antoine Delaite (4):
>   bisect: correction of typo
>   bisect: replace hardcoded "bad|good" by variables
>   bisect: simplify the addition of new bisect terms
>   bisect: add the terms old/new
>
> Matthieu Moy (5):
>   Documentation/bisect: move getting help section to the end
>   bisect: don't mix option parsing and non-trivial code
>   bisect: sanity check on terms
>   bisect: add 'git bisect terms' to view the current terms
>   bisect: allow setting any user-specified in 'git bisect start'
>
> Michael Haggerty (1):
>   Documentation/bisect: revise overall content
>
>  Documentation/git-bisect.txt | 236 ++++++++++++++++++++++++++++-----------
>  bisect.c                     |  94 ++++++++++++----
>  git-bisect.sh                | 255 +++++++++++++++++++++++++++++++++++--------
>  revision.c                   |  19 +++-
>  t/t6030-bisect-porcelain.sh  | 137 ++++++++++++++++++++++-
>  5 files changed, 612 insertions(+), 129 deletions(-)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code
  2015-06-29 15:40 ` [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code Matthieu Moy
@ 2015-06-29 20:28   ` Junio C Hamano
  2015-06-30 11:46     ` Matthieu Moy
  0 siblings, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2015-06-29 20:28 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray

Matthieu, are you allowing your editor to corrupt the number of
lines in the hunk on the @@ ... @@ hunk header?  "diff" mode in
Emacs does that, and there may be other editors that has the same
bug, but please be careful---they make the patch unapplicable.

Count the preimage lines in the hunk below.  I count 24 but somebody
is lying there.

> @@ -102,25 +103,27 @@ bisect_start() {
>  				die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
>  				break
>  			}
> -
> -			# The user ran "git bisect start <sha1>
> -			# <sha1>", hence did not explicitly specify
> -			# the terms, but we are already starting to
> -			# set references named with the default terms,
> -			# and won't be able to change afterwards.
> -			must_write_terms=1
> -
> -			case $bad_seen in
> -			0) state=$TERM_BAD ; bad_seen=1 ;;
> -			*) state=$TERM_GOOD ;;
> -			esac
> -			eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
> +			revs="$revs $rev"
>  			shift
>  			;;
>  		esac
>  	done
>  
> +	for rev in $revs
> +	do
> +		# The user ran "git bisect start <sha1>
> +		# <sha1>", hence did not explicitly specify
> +		# the terms, but we are already starting to
> +		# set references named with the default terms,
> +		# and won't be able to change afterwards.
> +		must_write_terms=1
> +
> +		case $bad_seen in
> +		0) state=$TERM_BAD ; bad_seen=1 ;;
> +		*) state=$TERM_GOOD ;;
> +		esac
> +		eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
> +	done
>  	#
>  	# Verify HEAD.
>  	#
> -- 
> 2.5.0.rc0.10.gd2bff5d

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code
  2015-06-29 20:28   ` Junio C Hamano
@ 2015-06-30 11:46     ` Matthieu Moy
  2015-06-30 15:56       ` Junio C Hamano
  0 siblings, 1 reply; 15+ messages in thread
From: Matthieu Moy @ 2015-06-30 11:46 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray

Junio C Hamano <gitster@pobox.com> writes:

> Matthieu, are you allowing your editor to corrupt the number of
> lines in the hunk on the @@ ... @@ hunk header?  "diff" mode in
> Emacs does that,

Indeed. There's magic in Emac's diff-mode to keep the header up to date,
but it seems totally buggy. I manually deleted a tab (no line added, no
line removed) and it changed the number of lines in the header.

I see that you still managed to apply the series in pu, thanks and sorry
for the inconvenience.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code
  2015-06-30 11:46     ` Matthieu Moy
@ 2015-06-30 15:56       ` Junio C Hamano
  0 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2015-06-30 15:56 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: git, antoine.delaite, louis--alexandre.stuber, chriscool,
	thomasxnguy, valentinduperray

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:

> Junio C Hamano <gitster@pobox.com> writes:
>
>> Matthieu, are you allowing your editor to corrupt the number of
>> lines in the hunk on the @@ ... @@ hunk header?  "diff" mode in
>> Emacs does that,
>
> Indeed. There's magic in Emac's diff-mode to keep the header up to date,
> but it seems totally buggy. I manually deleted a tab (no line added, no
> line removed) and it changed the number of lines in the header.

I'd hesitate to call it "totally buggy", but (without reading its
code, merely an observation of its behaviour from the outside) it
seems that this behaviour comes from the fact that its theory of
operation is fundamentally flawed.

If it trusted the the original @@ ... @@ hunk header line and then
adjusted the numbers as the user adds, deletes or modifies lines, we
wouldn't be seeing this problem.  Instead, it seems to totally
ignore the original number of lines recorded on the hunk header, and
counts what it deems to be part of the patch.

The thing is, when people edit a patch, they do not start from
scratch.  They somehow prepare a patch with a tool, and its output
is far more likely than not to record the correct number of lines on
the hunk header.  Not reading and trusting these numbers to see
where the original patch before it lets the user edit it, and
incorrectly including text outside the original patch in its own
count, is simply being silly.

Often, the last hunk of format-patch output has the "-- " signature
marker, which looks to Emacs as if the patch wants to delete a line
that has a dash and a space on it at the end.

> I see that you still managed to apply the series in pu, thanks and sorry
> for the inconvenience.

It's just the matter of realizing how it was corrupt and then
recounting the number of lines---a minor annoyance, not a big deal.

Thanks.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2015-06-30 15:56 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-29 15:40 [PATCH v11 00/10] bisect terms Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 01/10] bisect: correction of typo Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 02/10] Documentation/bisect: move getting help section to the end Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 03/10] Documentation/bisect: revise overall content Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 04/10] bisect: replace hardcoded "bad|good" by variables Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 05/10] bisect: simplify the addition of new bisect terms Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 06/10] bisect: don't mix option parsing and non-trivial code Matthieu Moy
2015-06-29 20:28   ` Junio C Hamano
2015-06-30 11:46     ` Matthieu Moy
2015-06-30 15:56       ` Junio C Hamano
2015-06-29 15:40 ` [PATCH v11 07/10] bisect: sanity check on terms Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 08/10] bisect: add the terms old/new Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 09/10] bisect: add 'git bisect terms' to view the current terms Matthieu Moy
2015-06-29 15:40 ` [PATCH v11 10/10] bisect: allow setting any user-specified in 'git bisect start' Matthieu Moy
2015-06-29 16:44 ` [PATCH v11 00/10] bisect terms Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).