bisect: introduce support for --no-checkout option.

If --no-checkout is specified, then the bisection process uses: git update-ref --no-deref HEAD <trial> at each trial instead of: git checkout <trial> Improved-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Jon Seymour <jon.seymour@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jon Seymour committed Aug 4, 2011 at 22:01 UTC fee92fc1dd4480d9d5c72bd67243d3f6a9b03132
3 files changed +28 -14
bisect.c
+22 -11
@@ -24,6 +24,7 @@ struct argv_array {
24
25 static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
26 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
27 +static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
28
29 /* bits #0-15 in revision.h */
30
@@ -707,16 +708,23 @@ static void mark_expected_rev(char *bisect_rev_hex)
708 die("closing file %s: %s", filename, strerror(errno));
709 }
710
710 -static int bisect_checkout(char *bisect_rev_hex)
711 +static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
712 {
713 int res;
714
715 mark_expected_rev(bisect_rev_hex);
716
717 argv_checkout[2] = bisect_rev_hex;
717 - res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
718 - if (res)
719 - exit(res);
718 + if (no_checkout) {
719 + argv_update_ref[3] = bisect_rev_hex;
720 + if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
721 + die("update-ref --no-deref HEAD failed on %s",
722 + bisect_rev_hex);
723 + } else {
724 + res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
725 + if (res)
726 + exit(res);
727 + }
728
729 argv_show_branch[1] = bisect_rev_hex;
730 return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
@@ -788,7 +796,7 @@ static void handle_skipped_merge_base(const unsigned char *mb)
796 * - If one is "skipped", we can't know but we should warn.
797 * - If we don't know, we should check it out and ask the user to test.
798 */
791 -static void check_merge_bases(void)
799 +static void check_merge_bases(int no_checkout)
800 {
801 struct commit_list *result;
802 int rev_nr;
@@ -806,7 +814,7 @@ static void check_merge_bases(void)
814 handle_skipped_merge_base(mb);
815 } else {
816 printf("Bisecting: a merge base must be tested\n");
809 - exit(bisect_checkout(sha1_to_hex(mb)));
817 + exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
818 }
819 }
820
@@ -849,7 +857,7 @@ static int check_ancestors(const char *prefix)
857 * If a merge base must be tested by the user, its source code will be
858 * checked out to be tested by the user and we will exit.
859 */
852 -static void check_good_are_ancestors_of_bad(const char *prefix)
860 +static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
861 {
862 const char *filename = git_path("BISECT_ANCESTORS_OK");
863 struct stat st;
@@ -868,7 +876,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
876
877 /* Check if all good revs are ancestor of the bad rev. */
878 if (check_ancestors(prefix))
871 - check_merge_bases();
879 + check_merge_bases(no_checkout);
880
881 /* Create file BISECT_ANCESTORS_OK. */
882 fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -908,8 +916,11 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
916 * We use the convention that exiting with an exit code 10 means that
917 * the bisection process finished successfully.
918 * In this case the calling shell script should exit 0.
919 + *
920 + * If no_checkout is non-zero, the bisection process does not
921 + * checkout the trial commit but instead simply updates BISECT_HEAD.
922 */
912 -int bisect_next_all(const char *prefix)
923 +int bisect_next_all(const char *prefix, int no_checkout)
924 {
925 struct rev_info revs;
926 struct commit_list *tried;
@@ -920,7 +931,7 @@ int bisect_next_all(const char *prefix)
931 if (read_bisect_refs())
932 die("reading bisect refs failed");
933
923 - check_good_are_ancestors_of_bad(prefix);
934 + check_good_are_ancestors_of_bad(prefix, no_checkout);
935
936 bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
937 revs.limited = 1;
@@ -966,6 +977,6 @@ int bisect_next_all(const char *prefix)
977 "(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
978 steps, (steps == 1 ? "" : "s"));
979
969 - return bisect_checkout(bisect_rev_hex);
980 + return bisect_checkout(bisect_rev_hex, no_checkout);
981 }
982
bisect.h
+1 -1
@@ -27,7 +27,7 @@ struct rev_list_info {
27 const char *header_prefix;
28 };
29
30 -extern int bisect_next_all(const char *prefix);
30 +extern int bisect_next_all(const char *prefix, int no_checkout);
31
32 extern int estimate_bisect_steps(int all);
33
builtin/bisect--helper.c
+5 -2
@@ -4,16 +4,19 @@
4 #include "bisect.h"
5
6 static const char * const git_bisect_helper_usage[] = {
7 - "git bisect--helper --next-all",
7 + "git bisect--helper --next-all [--no-checkout]",
8 NULL
9 };
10
11 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
12 {
13 int next_all = 0;
14 + int no_checkout = 0;
15 struct option options[] = {
16 OPT_BOOLEAN(0, "next-all", &next_all,
17 "perform 'git bisect next'"),
18 + OPT_BOOLEAN(0, "no-checkout", &no_checkout,
19 + "update BISECT_HEAD instead of checking out the current commit"),
20 OPT_END()
21 };
22
@@ -24,5 +27,5 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
27 usage_with_options(git_bisect_helper_usage, options);
28
29 /* next-all */
27 - return bisect_next_all(prefix);
30 + return bisect_next_all(prefix, no_checkout);
31 }