{"thread":{"id":"19255","subject":"[PATCH 02/10] bisect: implement \"rev_argv_push\" to fill an argv with revs","startedAt":"2009-05-09T15:55:37Z","lastAt":"2009-05-11T00:44:02Z","messageCount":14,"participants":["Christian Couder","Jakub Narebski","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"113404","messageId":"20090509154419.5324.96204.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":null,"subject":"[PATCH 00/10] bisect: port git bisect merge base checking to C","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:37Z","receivedAt":"2009-05-09T15:55:37Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch series continues porting \"git bisect next\" code\nfrom shell in \"git-bisect.sh\" to C in \"bisect.c\".\n\nAfter this series, the bisect ref lookup is done only once in the\nC code, instead of once in the shell code and once in the C code.\n\n  bisect: use \"sha1_array\" to store skipped revisions\n  bisect: implement \"rev_argv_push\" to fill an argv with revs\n  bisect: store good revisions in a \"sha1_array\"\n  bisect: use new \"struct argv_array\" to prepare argv for\n    \"setup_revisions\"\n  bisect: remove too much function nesting\n  bisect: make skipped array functions more generic\n  bisect: automatically sort sha1_array if needed when looking it up\n  bisect: implement the \"check_merge_bases\" function\n  bisect: add \"check_good_are_ancestors_of_bad\" function\n  bisect: make \"git bisect\" use new \"--next-all\" bisect-helper function\n\n bisect.c                 |  342 ++++++++++++++++++++++++++++++++++++++--------\n bisect.h                 |    2 +-\n builtin-bisect--helper.c |   14 +-\n git-bisect.sh            |  127 +-----------------\n 4 files changed, 296 insertions(+), 189 deletions(-)\n"},{"id":"113403","messageId":"20090509155548.5387.50168.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 01/10] bisect: use \"sha1_array\" to store skipped revisions","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:38Z","receivedAt":"2009-05-09T15:55:38Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch creates a \"struct sha1_array\" to store skipped revisions,\nso that the same struct can be reused in a later patch for good\nrevisions.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   25 +++++++++++++++----------\n 1 files changed, 15 insertions(+), 10 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 4796aa9..12df855 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -9,9 +9,13 @@\n #include \"run-command.h\"\n #include \"bisect.h\"\n \n-static unsigned char (*skipped_sha1)[20];\n-static int skipped_sha1_nr;\n-static int skipped_sha1_alloc;\n+struct sha1_array {\n+\tunsigned char (*sha1)[20];\n+\tint sha1_nr;\n+\tint sha1_alloc;\n+};\n+\n+static struct sha1_array skipped_revs;\n \n static const char **rev_argv;\n static int rev_argv_nr;\n@@ -420,9 +424,9 @@ static int register_ref(const char *refname, const unsigned char *sha1,\n \t\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n \t\trev_argv[rev_argv_nr++] = good;\n \t} else if (!prefixcmp(refname, \"skip-\")) {\n-\t\tALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,\n-\t\t\t   skipped_sha1_alloc);\n-\t\thashcpy(skipped_sha1[skipped_sha1_nr++], sha1);\n+\t\tALLOC_GROW(skipped_revs.sha1, skipped_revs.sha1_nr + 1,\n+\t\t\t   skipped_revs.sha1_alloc);\n+\t\thashcpy(skipped_revs.sha1[skipped_revs.sha1_nr++], sha1);\n \t}\n \n \treturn 0;\n@@ -466,7 +470,8 @@ static int skipcmp(const void *a, const void *b)\n \n static void prepare_skipped(void)\n {\n-\tqsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);\n+\tqsort(skipped_revs.sha1, skipped_revs.sha1_nr,\n+\t      sizeof(*skipped_revs.sha1), skipcmp);\n }\n \n static const unsigned char *skipped_sha1_access(size_t index, void *table)\n@@ -477,7 +482,7 @@ static const unsigned char *skipped_sha1_access(size_t index, void *table)\n \n static int lookup_skipped(unsigned char *sha1)\n {\n-\treturn sha1_pos(sha1, skipped_sha1, skipped_sha1_nr,\n+\treturn sha1_pos(sha1, skipped_revs.sha1, skipped_revs.sha1_nr,\n \t\t\tskipped_sha1_access);\n }\n \n@@ -489,7 +494,7 @@ struct commit_list *filter_skipped(struct commit_list *list,\n \n \t*tried = NULL;\n \n-\tif (!skipped_sha1_nr)\n+\tif (!skipped_revs.sha1_nr)\n \t\treturn list;\n \n \tprepare_skipped();\n@@ -551,7 +556,7 @@ static void bisect_common(struct rev_info *revs, const char *prefix,\n \t\tmark_edges_uninteresting(revs->commits, revs, NULL);\n \n \trevs->commits = find_bisection(revs->commits, reaches, all,\n-\t\t\t\t       !!skipped_sha1_nr);\n+\t\t\t\t       !!skipped_revs.sha1_nr);\n }\n \n static void exit_if_skipped_commits(struct commit_list *tried,\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113402","messageId":"20090509155548.5387.25844.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 02/10] bisect: implement \"rev_argv_push\" to fill an argv with revs","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:39Z","receivedAt":"2009-05-09T15:55:39Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch is a minor clean up right now, but the new function\nwill evolve and be used more later.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   19 +++++++++++--------\n 1 files changed, 11 insertions(+), 8 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 12df855..f99637d 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -409,20 +409,23 @@ struct commit_list *find_bisection(struct commit_list *list,\n \treturn best;\n }\n \n+static void rev_argv_push(const unsigned char *sha1, const char *format)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tstrbuf_addf(&buf, format, sha1_to_hex(sha1));\n+\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n+\trev_argv[rev_argv_nr++] = strbuf_detach(&buf, NULL);\n+}\n+\n static int register_ref(const char *refname, const unsigned char *sha1,\n \t\t\tint flags, void *cb_data)\n {\n \tif (!strcmp(refname, \"bad\")) {\n-\t\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n \t\tcurrent_bad_sha1 = sha1;\n-\t\trev_argv[rev_argv_nr++] = xstrdup(sha1_to_hex(sha1));\n+\t\trev_argv_push(sha1, \"%s\");\n \t} else if (!prefixcmp(refname, \"good-\")) {\n-\t\tconst char *hex = sha1_to_hex(sha1);\n-\t\tchar *good = xmalloc(strlen(hex) + 2);\n-\t\t*good = '^';\n-\t\tmemcpy(good + 1, hex, strlen(hex) + 1);\n-\t\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n-\t\trev_argv[rev_argv_nr++] = good;\n+\t\trev_argv_push(sha1, \"^%s\");\n \t} else if (!prefixcmp(refname, \"skip-\")) {\n \t\tALLOC_GROW(skipped_revs.sha1, skipped_revs.sha1_nr + 1,\n \t\t\t   skipped_revs.sha1_alloc);\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113406","messageId":"20090509155548.5387.1802.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 03/10] bisect: store good revisions in a \"sha1_array\"","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:40Z","receivedAt":"2009-05-09T15:55:40Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This will make it easier to use good revisions for checking merge\nbases later.\n\nTo simplify the code, a new \"sha1_array_push\" function is also\nintroduced.\n\nAnd while at it we move the earlier part of the code to fill the\nargv that is passed to \"setup_revisions\", so that all this code is\nnow completely after \"read_bisect_refs\".\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   26 +++++++++++++++++++-------\n 1 files changed, 19 insertions(+), 7 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex f99637d..7976cbf 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -15,6 +15,7 @@ struct sha1_array {\n \tint sha1_alloc;\n };\n \n+static struct sha1_array good_revs;\n static struct sha1_array skipped_revs;\n \n static const char **rev_argv;\n@@ -418,18 +419,22 @@ static void rev_argv_push(const unsigned char *sha1, const char *format)\n \trev_argv[rev_argv_nr++] = strbuf_detach(&buf, NULL);\n }\n \n+static void sha1_array_push(struct sha1_array *array,\n+\t\t\t    const unsigned char *sha1)\n+{\n+\tALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc);\n+\thashcpy(array->sha1[array->sha1_nr++], sha1);\n+}\n+\n static int register_ref(const char *refname, const unsigned char *sha1,\n \t\t\tint flags, void *cb_data)\n {\n \tif (!strcmp(refname, \"bad\")) {\n \t\tcurrent_bad_sha1 = sha1;\n-\t\trev_argv_push(sha1, \"%s\");\n \t} else if (!prefixcmp(refname, \"good-\")) {\n-\t\trev_argv_push(sha1, \"^%s\");\n+\t\tsha1_array_push(&good_revs, sha1);\n \t} else if (!prefixcmp(refname, \"skip-\")) {\n-\t\tALLOC_GROW(skipped_revs.sha1, skipped_revs.sha1_nr + 1,\n-\t\t\t   skipped_revs.sha1_alloc);\n-\t\thashcpy(skipped_revs.sha1[skipped_revs.sha1_nr++], sha1);\n+\t\tsha1_array_push(&skipped_revs, sha1);\n \t}\n \n \treturn 0;\n@@ -524,16 +529,23 @@ struct commit_list *filter_skipped(struct commit_list *list,\n \n static void bisect_rev_setup(struct rev_info *revs, const char *prefix)\n {\n+\tint i;\n+\n \tinit_revisions(revs, prefix);\n \trevs->abbrev = 0;\n \trevs->commit_format = CMIT_FMT_UNSPECIFIED;\n \n+\tif (read_bisect_refs())\n+\t\tdie(\"reading bisect refs failed\");\n+\n \t/* argv[0] will be ignored by setup_revisions */\n \tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n \trev_argv[rev_argv_nr++] = xstrdup(\"bisect_rev_setup\");\n \n-\tif (read_bisect_refs())\n-\t\tdie(\"reading bisect refs failed\");\n+\trev_argv_push(current_bad_sha1, \"%s\");\n+\n+\tfor (i = 0; i < good_revs.sha1_nr; i++)\n+\t\trev_argv_push(good_revs.sha1[i], \"^%s\");\n \n \tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n \trev_argv[rev_argv_nr++] = xstrdup(\"--\");\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113405","messageId":"20090509155548.5387.51730.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 04/10] bisect: use new \"struct argv_array\" to prepare argv for \"setup_revisions\"","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:41Z","receivedAt":"2009-05-09T15:55:41Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Because we will use other instances of this struct.\n\nThe \"rev_argv_push\" function is changed into 2 functions\n\"argv_array_push\" and \"argv_array_push_sha1\" that take a \"struct\nargv_array *\" as first argument. And these functions are used to\nsimplify \"bisect_rev_setup\".\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   57 +++++++++++++++++++++++++++++----------------------------\n 1 files changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 7976cbf..8e34186 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -18,12 +18,16 @@ struct sha1_array {\n static struct sha1_array good_revs;\n static struct sha1_array skipped_revs;\n \n-static const char **rev_argv;\n-static int rev_argv_nr;\n-static int rev_argv_alloc;\n-\n static const unsigned char *current_bad_sha1;\n \n+struct argv_array {\n+\tconst char **argv;\n+\tint argv_nr;\n+\tint argv_alloc;\n+};\n+\n+struct argv_array rev_argv;\n+\n static const char *argv_diff_tree[] = {\"diff-tree\", \"--pretty\", NULL, NULL};\n static const char *argv_checkout[] = {\"checkout\", \"-q\", NULL, \"--\", NULL};\n static const char *argv_show_branch[] = {\"show-branch\", NULL, NULL};\n@@ -410,13 +414,19 @@ struct commit_list *find_bisection(struct commit_list *list,\n \treturn best;\n }\n \n-static void rev_argv_push(const unsigned char *sha1, const char *format)\n+static void argv_array_push(struct argv_array *array, const char *string)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tALLOC_GROW(array->argv, array->argv_nr + 1, array->argv_alloc);\n+\tarray->argv[array->argv_nr++] = string;\n+}\n \n+static void argv_array_push_sha1(struct argv_array *array,\n+\t\t\t\t const unsigned char *sha1,\n+\t\t\t\t const char *format)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n \tstrbuf_addf(&buf, format, sha1_to_hex(sha1));\n-\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n-\trev_argv[rev_argv_nr++] = strbuf_detach(&buf, NULL);\n+\targv_array_push(array, strbuf_detach(&buf, NULL));\n }\n \n static void sha1_array_push(struct sha1_array *array,\n@@ -445,7 +455,7 @@ static int read_bisect_refs(void)\n \treturn for_each_ref_in(\"refs/bisect/\", register_ref, NULL);\n }\n \n-void read_bisect_paths(void)\n+void read_bisect_paths(struct argv_array *array)\n {\n \tstruct strbuf str = STRBUF_INIT;\n \tconst char *filename = git_path(\"BISECT_NAMES\");\n@@ -460,8 +470,8 @@ void read_bisect_paths(void)\n \n \t\tstrbuf_trim(&str);\n \t\tquoted = strbuf_detach(&str, NULL);\n-\t\tres = sq_dequote_to_argv(quoted, &rev_argv,\n-\t\t\t\t\t &rev_argv_nr, &rev_argv_alloc);\n+\t\tres = sq_dequote_to_argv(quoted, &array->argv,\n+\t\t\t\t\t &array->argv_nr, &array->argv_alloc);\n \t\tif (res)\n \t\t\tdie(\"Badly quoted content in file '%s': %s\",\n \t\t\t    filename, quoted);\n@@ -538,25 +548,16 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix)\n \tif (read_bisect_refs())\n \t\tdie(\"reading bisect refs failed\");\n \n-\t/* argv[0] will be ignored by setup_revisions */\n-\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n-\trev_argv[rev_argv_nr++] = xstrdup(\"bisect_rev_setup\");\n-\n-\trev_argv_push(current_bad_sha1, \"%s\");\n-\n+\t/* rev_argv.argv[0] will be ignored by setup_revisions */\n+\targv_array_push(&rev_argv, xstrdup(\"bisect_rev_setup\"));\n+\targv_array_push_sha1(&rev_argv, current_bad_sha1, \"%s\");\n \tfor (i = 0; i < good_revs.sha1_nr; i++)\n-\t\trev_argv_push(good_revs.sha1[i], \"^%s\");\n-\n-\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n-\trev_argv[rev_argv_nr++] = xstrdup(\"--\");\n-\n-\tread_bisect_paths();\n-\n-\tALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);\n-\trev_argv[rev_argv_nr++] = NULL;\n-\n-\tsetup_revisions(rev_argv_nr, rev_argv, revs, NULL);\n+\t\targv_array_push_sha1(&rev_argv, good_revs.sha1[i], \"^%s\");\n+\targv_array_push(&rev_argv, xstrdup(\"--\"));\n+\tread_bisect_paths(&rev_argv);\n+\targv_array_push(&rev_argv, NULL);\n \n+\tsetup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);\n \trevs->limited = 1;\n }\n \n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113407","messageId":"20090509155548.5387.95855.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 05/10] bisect: remove too much function nesting","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:42Z","receivedAt":"2009-05-09T15:55:42Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch moves some function calls into \"bisect_next_exit\" so\nthat functions are nesting less.\n\nThe call to \"bisect_rev_setup\" is moved from \"bisect_common\" into\n\"bisect_next_exit\" and the call to \"read_bisect_refs\" from\n\"bisect_rev_setup\" into \"bisect_next_exit\".\n\nWhile at it, \"rev_argv\" is moved into \"bisect_rev_setup\".\n\nThis will make it easier and cleaner to implement checking merge\nbases.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   18 ++++++++----------\n 1 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 8e34186..9e01b9e 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -26,8 +26,6 @@ struct argv_array {\n \tint argv_alloc;\n };\n \n-struct argv_array rev_argv;\n-\n static const char *argv_diff_tree[] = {\"diff-tree\", \"--pretty\", NULL, NULL};\n static const char *argv_checkout[] = {\"checkout\", \"-q\", NULL, \"--\", NULL};\n static const char *argv_show_branch[] = {\"show-branch\", NULL, NULL};\n@@ -539,15 +537,13 @@ struct commit_list *filter_skipped(struct commit_list *list,\n \n static void bisect_rev_setup(struct rev_info *revs, const char *prefix)\n {\n+\tstruct argv_array rev_argv = { NULL, 0, 0 };\n \tint i;\n \n \tinit_revisions(revs, prefix);\n \trevs->abbrev = 0;\n \trevs->commit_format = CMIT_FMT_UNSPECIFIED;\n \n-\tif (read_bisect_refs())\n-\t\tdie(\"reading bisect refs failed\");\n-\n \t/* rev_argv.argv[0] will be ignored by setup_revisions */\n \targv_array_push(&rev_argv, xstrdup(\"bisect_rev_setup\"));\n \targv_array_push_sha1(&rev_argv, current_bad_sha1, \"%s\");\n@@ -561,11 +557,8 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix)\n \trevs->limited = 1;\n }\n \n-static void bisect_common(struct rev_info *revs, const char *prefix,\n-\t\t\t  int *reaches, int *all)\n+static void bisect_common(struct rev_info *revs, int *reaches, int *all)\n {\n-\tbisect_rev_setup(revs, prefix);\n-\n \tif (prepare_revision_walk(revs))\n \t\tdie(\"revision walk setup failed\");\n \tif (revs->tree_objects)\n@@ -636,7 +629,12 @@ int bisect_next_exit(const char *prefix)\n \tconst unsigned char *bisect_rev;\n \tchar bisect_rev_hex[41];\n \n-\tbisect_common(&revs, prefix, &reaches, &all);\n+\tif (read_bisect_refs())\n+\t\tdie(\"reading bisect refs failed\");\n+\n+\tbisect_rev_setup(&revs, prefix);\n+\n+\tbisect_common(&revs, &reaches, &all);\n \n \trevs.commits = filter_skipped(revs.commits, &tried, 0);\n \n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113411","messageId":"20090509155548.5387.88589.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 06/10] bisect: make skipped array functions more generic","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:43Z","receivedAt":"2009-05-09T15:55:43Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"So they can be used on the good array too.\n\nThis is done by renaming many functions and some variables to\nremove \"skip\" in the name, and by adding a\n\"struct sha1_array *array\" argument where needed.\n\nWhile at it, make the second argument to \"lookup_sha1_array\"\nconst. It becomes \"const unsigned char *sha1\".\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   24 ++++++++++++------------\n 1 files changed, 12 insertions(+), 12 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 9e01b9e..77edeca 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -479,27 +479,26 @@ void read_bisect_paths(struct argv_array *array)\n \tfclose(fp);\n }\n \n-static int skipcmp(const void *a, const void *b)\n+static int array_cmp(const void *a, const void *b)\n {\n \treturn hashcmp(a, b);\n }\n \n-static void prepare_skipped(void)\n+static void sort_sha1_array(struct sha1_array *array)\n {\n-\tqsort(skipped_revs.sha1, skipped_revs.sha1_nr,\n-\t      sizeof(*skipped_revs.sha1), skipcmp);\n+\tqsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp);\n }\n \n-static const unsigned char *skipped_sha1_access(size_t index, void *table)\n+static const unsigned char *sha1_access(size_t index, void *table)\n {\n-\tunsigned char (*skipped)[20] = table;\n-\treturn skipped[index];\n+\tunsigned char (*array)[20] = table;\n+\treturn array[index];\n }\n \n-static int lookup_skipped(unsigned char *sha1)\n+static int lookup_sha1_array(struct sha1_array *array,\n+\t\t\t     const unsigned char *sha1)\n {\n-\treturn sha1_pos(sha1, skipped_revs.sha1, skipped_revs.sha1_nr,\n-\t\t\tskipped_sha1_access);\n+\treturn sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);\n }\n \n struct commit_list *filter_skipped(struct commit_list *list,\n@@ -513,12 +512,13 @@ struct commit_list *filter_skipped(struct commit_list *list,\n \tif (!skipped_revs.sha1_nr)\n \t\treturn list;\n \n-\tprepare_skipped();\n+\tsort_sha1_array(&skipped_revs);\n \n \twhile (list) {\n \t\tstruct commit_list *next = list->next;\n \t\tlist->next = NULL;\n-\t\tif (0 <= lookup_skipped(list->item->object.sha1)) {\n+\t\tif (0 <= lookup_sha1_array(&skipped_revs,\n+\t\t\t\t\t   list->item->object.sha1)) {\n \t\t\t/* Move current to tried list */\n \t\t\t*tried = list;\n \t\t\ttried = &list->next;\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113412","messageId":"20090509155548.5387.70784.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 07/10] bisect: automatically sort sha1_array if needed when looking it up","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:44Z","receivedAt":"2009-05-09T15:55:44Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This makes sha1_array easier to use, so later patches will be simpler.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |    8 ++++++--\n 1 files changed, 6 insertions(+), 2 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 77edeca..d2a34d1 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -13,6 +13,7 @@ struct sha1_array {\n \tunsigned char (*sha1)[20];\n \tint sha1_nr;\n \tint sha1_alloc;\n+\tint sorted;\n };\n \n static struct sha1_array good_revs;\n@@ -487,6 +488,8 @@ static int array_cmp(const void *a, const void *b)\n static void sort_sha1_array(struct sha1_array *array)\n {\n \tqsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp);\n+\n+\tarray->sorted = 1;\n }\n \n static const unsigned char *sha1_access(size_t index, void *table)\n@@ -498,6 +501,9 @@ static const unsigned char *sha1_access(size_t index, void *table)\n static int lookup_sha1_array(struct sha1_array *array,\n \t\t\t     const unsigned char *sha1)\n {\n+\tif (!array->sorted)\n+\t\tsort_sha1_array(array);\n+\n \treturn sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);\n }\n \n@@ -512,8 +518,6 @@ struct commit_list *filter_skipped(struct commit_list *list,\n \tif (!skipped_revs.sha1_nr)\n \t\treturn list;\n \n-\tsort_sha1_array(&skipped_revs);\n-\n \twhile (list) {\n \t\tstruct commit_list *next = list->next;\n \t\tlist->next = NULL;\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113408","messageId":"20090509155548.5387.22043.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 08/10] bisect: implement the \"check_merge_bases\" function","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:45Z","receivedAt":"2009-05-09T15:55:45Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"And all functions needed to make it work.\n\nThis is a port from the shell function with the same name\n\"git-bisect.sh\". This function is not used yet but it will be used\nlater.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |  130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 130 insertions(+), 0 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex d2a34d1..b24ee78 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -507,6 +507,20 @@ static int lookup_sha1_array(struct sha1_array *array,\n \treturn sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);\n }\n \n+static char *join_sha1_array_hex(struct sha1_array *array, char delim)\n+{\n+\tstruct strbuf joined_hexs = STRBUF_INIT;\n+\tint i;\n+\n+\tfor (i = 0; i < array->sha1_nr; i++) {\n+\t\tstrbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));\n+\t\tif (i + 1 < array->sha1_nr)\n+\t\t\tstrbuf_addch(&joined_hexs, delim);\n+\t}\n+\n+\treturn strbuf_detach(&joined_hexs, NULL);\n+}\n+\n struct commit_list *filter_skipped(struct commit_list *list,\n \t\t\t\t   struct commit_list **tried,\n \t\t\t\t   int show_all)\n@@ -587,6 +601,30 @@ static void exit_if_skipped_commits(struct commit_list *tried,\n \texit(2);\n }\n \n+static int is_expected_rev(const unsigned char *sha1)\n+{\n+\tconst char *filename = git_path(\"BISECT_EXPECTED_REV\");\n+\tstruct stat st;\n+\tstruct strbuf str = STRBUF_INIT;\n+\tFILE *fp;\n+\tint res = 0;\n+\n+\tif (stat(filename, &st) || !S_ISREG(st.st_mode))\n+\t\treturn 0;\n+\n+\tfp = fopen(filename, \"r\");\n+\tif (!fp)\n+\t\treturn 0;\n+\n+\tif (strbuf_getline(&str, fp, '\\n') != EOF)\n+\t\tres = !strcmp(str.buf, sha1_to_hex(sha1));\n+\n+\tstrbuf_release(&str);\n+\tfclose(fp);\n+\n+\treturn res;\n+}\n+\n static void mark_expected_rev(char *bisect_rev_hex)\n {\n \tint len = strlen(bisect_rev_hex);\n@@ -620,6 +658,98 @@ static int bisect_checkout(char *bisect_rev_hex)\n \treturn run_command_v_opt(argv_show_branch, RUN_GIT_CMD);\n }\n \n+static struct commit *get_commit_reference(const unsigned char *sha1)\n+{\n+\tstruct commit *r = lookup_commit_reference(sha1);\n+\tif (!r)\n+\t\tdie(\"Not a valid commit name %s\", sha1_to_hex(sha1));\n+\treturn r;\n+}\n+\n+static struct commit **get_bad_and_good_commits(int *rev_nr)\n+{\n+\tint len = 1 + good_revs.sha1_nr;\n+\tstruct commit **rev = xmalloc(len * sizeof(*rev));\n+\tint i, n = 0;\n+\n+\trev[n++] = get_commit_reference(current_bad_sha1);\n+\tfor (i = 0; i < good_revs.sha1_nr; i++)\n+\t\trev[n++] = get_commit_reference(good_revs.sha1[i]);\n+\t*rev_nr = n;\n+\n+\treturn rev;\n+}\n+\n+static void handle_bad_merge_base(void)\n+{\n+\tif (is_expected_rev(current_bad_sha1)) {\n+\t\tchar *bad_hex = sha1_to_hex(current_bad_sha1);\n+\t\tchar *good_hex = join_sha1_array_hex(&good_revs, ' ');\n+\n+\t\tfprintf(stderr, \"The merge base %s is bad.\\n\"\n+\t\t\t\"This means the bug has been fixed \"\n+\t\t\t\"between %s and [%s].\\n\",\n+\t\t\tbad_hex, bad_hex, good_hex);\n+\n+\t\texit(3);\n+\t}\n+\n+\tfprintf(stderr, \"Some good revs are not ancestor of the bad rev.\\n\"\n+\t\t\"git bisect cannot work properly in this case.\\n\"\n+\t\t\"Maybe you mistake good and bad revs?\\n\");\n+\texit(1);\n+}\n+\n+void handle_skipped_merge_base(const unsigned char *mb)\n+{\n+\tchar *mb_hex = sha1_to_hex(mb);\n+\tchar *bad_hex = sha1_to_hex(current_bad_sha1);\n+\tchar *good_hex = join_sha1_array_hex(&good_revs, ' ');\n+\n+\tfprintf(stderr, \"Warning: the merge base between %s and [%s] \"\n+\t\t\"must be skipped.\\n\"\n+\t\t\"So we cannot be sure the first bad commit is \"\n+\t\t\"between %s and %s.\\n\"\n+\t\t\"We continue anyway.\\n\",\n+\t\tbad_hex, good_hex, mb_hex, bad_hex);\n+\tfree(good_hex);\n+}\n+\n+/*\n+ * \"check_merge_bases\" checks that merge bases are not \"bad\".\n+ *\n+ * - If one is \"bad\", it means the user assumed something wrong\n+ * and we must exit with a non 0 error code.\n+ * - If one is \"good\", that's good, we have nothing to do.\n+ * - If one is \"skipped\", we can't know but we should warn.\n+ * - If we don't know, we should check it out and ask the user to test.\n+ */\n+static void check_merge_bases(void)\n+{\n+\tstruct commit_list *result;\n+\tint rev_nr;\n+\tstruct commit **rev = get_bad_and_good_commits(&rev_nr);\n+\n+\tresult = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);\n+\n+\tfor (; result; result = result->next) {\n+\t\tconst unsigned char *mb = result->item->object.sha1;\n+\t\tif (!hashcmp(mb, current_bad_sha1)) {\n+\t\t\thandle_bad_merge_base();\n+\t\t} else if (0 <= lookup_sha1_array(&good_revs, mb)) {\n+\t\t\tcontinue;\n+\t\t} else if (0 <= lookup_sha1_array(&skipped_revs, mb)) {\n+\t\t\thandle_skipped_merge_base(mb);\n+\t\t} else {\n+\t\t\tprintf(\"Bisecting: a merge base must be tested\\n\");\n+\t\t\texit(bisect_checkout(sha1_to_hex(mb)));\n+\t\t}\n+\t}\n+\n+\tfree(rev);\n+\tfree_commit_list(result);\n+}\n+\n /*\n  * We use the convention that exiting with an exit code 10 means that\n  * the bisection process finished successfully.\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113409","messageId":"20090509155548.5387.30838.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 09/10] bisect: add \"check_good_are_ancestors_of_bad\" function","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:46Z","receivedAt":"2009-05-09T15:55:46Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This is a port of the function with the same name that is in\n\"git-bisect.sh\". The new function is not used yet but will be in\na later patch.\n\nWe also implement an helper \"check_ancestors\" function that use\n\"start_command\" and \"finish_command\" to launch\n\"git rev-list $good ^$bad\".\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 75 insertions(+), 0 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex b24ee78..09102da 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -751,6 +751,81 @@ static void check_merge_bases(void)\n }\n \n /*\n+ * This function runs the command \"git rev-list $_good ^$_bad\"\n+ * and returns 1 if it produces some output, 0 otherwise.\n+ */\n+static int check_ancestors(void)\n+{\n+\tstruct argv_array rev_argv = { NULL, 0, 0 };\n+\tstruct strbuf str = STRBUF_INIT;\n+\tint i, result = 0;\n+\tstruct child_process rls;\n+\tFILE *rls_fout;\n+\n+\targv_array_push(&rev_argv, xstrdup(\"rev-list\"));\n+\targv_array_push_sha1(&rev_argv, current_bad_sha1, \"^%s\");\n+\tfor (i = 0; i < good_revs.sha1_nr; i++)\n+\t\targv_array_push_sha1(&rev_argv, good_revs.sha1[i], \"%s\");\n+\targv_array_push(&rev_argv, NULL);\n+\n+\tmemset(&rls, 0, sizeof(rls));\n+\trls.argv = rev_argv.argv;\n+\trls.out = -1;\n+\trls.git_cmd = 1;\n+\tif (start_command(&rls))\n+\t\tdie(\"Could not launch 'git rev-list' command.\");\n+\trls_fout = fdopen(rls.out, \"r\");\n+\twhile (strbuf_getline(&str, rls_fout, '\\n') != EOF) {\n+\t\tstrbuf_trim(&str);\n+\t\tif (*str.buf) {\n+\t\t\tresult = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tfclose(rls_fout);\n+\tfinish_command(&rls);\n+\n+\treturn result;\n+}\n+\n+/*\n+ * \"check_good_are_ancestors_of_bad\" checks that all \"good\" revs are\n+ * ancestor of the \"bad\" rev.\n+ *\n+ * If that's not the case, we need to check the merge bases.\n+ * If a merge base must be tested by the user, its source code will be\n+ * checked out to be tested by the user and we will exit.\n+ */\n+static void check_good_are_ancestors_of_bad(const char *prefix)\n+{\n+\tconst char *filename = git_path(\"BISECT_ANCESTORS_OK\");\n+\tstruct stat st;\n+\tint fd;\n+\n+\tif (!current_bad_sha1)\n+\t\tdie(\"a bad revision is needed\");\n+\n+\t/* Check if file BISECT_ANCESTORS_OK exists. */\n+\tif (!stat(filename, &st) && S_ISREG(st.st_mode))\n+\t\treturn;\n+\n+\t/* Bisecting with no good rev is ok. */\n+\tif (good_revs.sha1_nr == 0)\n+\t\treturn;\n+\n+\tif (check_ancestors())\n+\t\tcheck_merge_bases();\n+\n+\t/* Create file BISECT_ANCESTORS_OK. */\n+\tfd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);\n+\tif (fd < 0)\n+\t\twarning(\"could not create file '%s': %s\",\n+\t\t\tfilename, strerror(errno));\n+\telse\n+\t\tclose(fd);\n+}\n+\n+/*\n  * We use the convention that exiting with an exit code 10 means that\n  * the bisection process finished successfully.\n  * In this case the calling shell script should exit 0.\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113410","messageId":"20090509155548.5387.83292.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"20090509154419.5324.96204.chriscool@tuxfamily.org","subject":"[PATCH 10/10] bisect: make \"git bisect\" use new \"--next-all\" bisect-helper function","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-09T15:55:47Z","receivedAt":"2009-05-09T15:55:47Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch replace the \"--next-exit\" option of \"git bisect--helper\"\nwith a \"--next-all\" option that does merge base checking using\nthe \"check_good_are_ancestors_of_bad\" function implemented in\n\"bisect.c\" in a former patch.\n\nThe new \"--next-all\" option is then used in \"git-bisect.sh\" instead\nof the \"--next-exit\" option, and all the shell functions in\n\"git-bisect.sh\" that are now unused are removed.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n bisect.c                 |    4 +-\n bisect.h                 |    2 +-\n builtin-bisect--helper.c |   14 +++---\n git-bisect.sh            |  127 +---------------------------------------------\n 4 files changed, 13 insertions(+), 134 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 09102da..f57b62c 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -830,7 +830,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)\n  * the bisection process finished successfully.\n  * In this case the calling shell script should exit 0.\n  */\n-int bisect_next_exit(const char *prefix)\n+int bisect_next_all(const char *prefix)\n {\n \tstruct rev_info revs;\n \tstruct commit_list *tried;\n@@ -841,6 +841,8 @@ int bisect_next_exit(const char *prefix)\n \tif (read_bisect_refs())\n \t\tdie(\"reading bisect refs failed\");\n \n+\tcheck_good_are_ancestors_of_bad(prefix);\n+\n \tbisect_rev_setup(&revs, prefix);\n \n \tbisect_common(&revs, &reaches, &all);\ndiff --git a/bisect.h b/bisect.h\nindex 0b5d122..fb744fd 100644\n--- a/bisect.h\n+++ b/bisect.h\n@@ -27,7 +27,7 @@ struct rev_list_info {\n \n extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);\n \n-extern int bisect_next_exit(const char *prefix);\n+extern int bisect_next_all(const char *prefix);\n \n extern int estimate_bisect_steps(int all);\n \ndiff --git a/builtin-bisect--helper.c b/builtin-bisect--helper.c\nindex aca7018..cb3e155 100644\n--- a/builtin-bisect--helper.c\n+++ b/builtin-bisect--helper.c\n@@ -4,24 +4,24 @@\n #include \"bisect.h\"\n \n static const char * const git_bisect_helper_usage[] = {\n-\t\"git bisect--helper --next-exit\",\n+\t\"git bisect--helper --next-all\",\n \tNULL\n };\n \n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n-\tint next_exit = 0;\n+\tint next_all = 0;\n \tstruct option options[] = {\n-\t\tOPT_BOOLEAN(0, \"next-exit\", &next_exit,\n-\t\t\t    \"output bisect result and exit instuctions\"),\n+\t\tOPT_BOOLEAN(0, \"next-all\", &next_all,\n+\t\t\t    \"perform 'git bisect next'\"),\n \t\tOPT_END()\n \t};\n \n \targc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);\n \n-\tif (!next_exit)\n+\tif (!next_all)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n-\t/* next-exit */\n-\treturn bisect_next_exit(prefix);\n+\t/* next-all */\n+\treturn bisect_next_all(prefix);\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 786b7b9..8969553 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -167,10 +167,6 @@ is_expected_rev() {\n \ttest \"$1\" = $(cat \"$GIT_DIR/BISECT_EXPECTED_REV\")\n }\n \n-mark_expected_rev() {\n-\techo \"$1\" > \"$GIT_DIR/BISECT_EXPECTED_REV\"\n-}\n-\n check_expected_revs() {\n \tfor _rev in \"$@\"; do\n \t\tif ! is_expected_rev \"$_rev\"; then\n@@ -269,132 +265,13 @@ bisect_auto_next() {\n \tbisect_next_check && bisect_next || :\n }\n \n-bisect_checkout() {\n-\t_rev=\"$1\"\n-\t_msg=\"$2\"\n-\techo \"Bisecting: $_msg\"\n-\tmark_expected_rev \"$_rev\"\n-\tgit checkout -q \"$_rev\" -- || exit\n-\tgit show-branch \"$_rev\"\n-}\n-\n-is_among() {\n-\t_rev=\"$1\"\n-\t_list=\"$2\"\n-\tcase \"$_list\" in *$_rev*) return 0 ;; esac\n-\treturn 1\n-}\n-\n-handle_bad_merge_base() {\n-\t_badmb=\"$1\"\n-\t_good=\"$2\"\n-\tif is_expected_rev \"$_badmb\"; then\n-\t\tcat >&2 <<EOF\n-The merge base $_badmb is bad.\n-This means the bug has been fixed between $_badmb and [$_good].\n-EOF\n-\t\texit 3\n-\telse\n-\t\tcat >&2 <<EOF\n-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-EOF\n-\t\texit 1\n-\tfi\n-}\n-\n-handle_skipped_merge_base() {\n-\t_mb=\"$1\"\n-\t_bad=\"$2\"\n-\t_good=\"$3\"\n-\tcat >&2 <<EOF\n-Warning: the merge base between $_bad and [$_good] must be skipped.\n-So we cannot be sure the first bad commit is between $_mb and $_bad.\n-We continue anyway.\n-EOF\n-}\n-\n-#\n-# \"check_merge_bases\" checks that merge bases are not \"bad\".\n-#\n-# - If one is \"good\", that's good, we have nothing to do.\n-# - If one is \"bad\", it means the user assumed something wrong\n-# and we must exit.\n-# - If one is \"skipped\", we can't know but we should warn.\n-# - If we don't know, we should check it out and ask the user to test.\n-#\n-# In the last case we will return 1, and otherwise 0.\n-#\n-check_merge_bases() {\n-\t_bad=\"$1\"\n-\t_good=\"$2\"\n-\t_skip=\"$3\"\n-\tfor _mb in $(git merge-base --all $_bad $_good)\n-\tdo\n-\t\tif is_among \"$_mb\" \"$_good\"; then\n-\t\t\tcontinue\n-\t\telif test \"$_mb\" = \"$_bad\"; then\n-\t\t\thandle_bad_merge_base \"$_bad\" \"$_good\"\n-\t\telif is_among \"$_mb\" \"$_skip\"; then\n-\t\t\thandle_skipped_merge_base \"$_mb\" \"$_bad\" \"$_good\"\n-\t\telse\n-\t\t\tbisect_checkout \"$_mb\" \"a merge base must be tested\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n-\treturn 0\n-}\n-\n-#\n-# \"check_good_are_ancestors_of_bad\" checks that all \"good\" revs are\n-# ancestor of the \"bad\" rev.\n-#\n-# If that's not the case, we need to check the merge bases.\n-# If a merge base must be tested by the user we return 1 and\n-# otherwise 0.\n-#\n-check_good_are_ancestors_of_bad() {\n-\ttest -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n-\t\treturn\n-\n-\t_bad=\"$1\"\n-\t_good=$(echo $2 | sed -e 's/\\^//g')\n-\t_skip=\"$3\"\n-\n-\t# Bisecting with no good rev is ok\n-\ttest -z \"$_good\" && return\n-\n-\t_side=$(git rev-list $_good ^$_bad)\n-\tif test -n \"$_side\"; then\n-\t\t# Return if a checkout was done\n-\t\tcheck_merge_bases \"$_bad\" \"$_good\" \"$_skip\" || return\n-\tfi\n-\n-\t: > \"$GIT_DIR/BISECT_ANCESTORS_OK\"\n-\n-\treturn 0\n-}\n-\n bisect_next() {\n \tcase \"$#\" in 0) ;; *) usage ;; esac\n \tbisect_autostart\n \tbisect_next_check good\n \n-\t# Get bad, good and skipped revs\n-\tbad=$(git rev-parse --verify refs/bisect/bad) &&\n-\tgood=$(git for-each-ref --format='^%(objectname)' \\\n-\t\t\"refs/bisect/good-*\" | tr '\\012' ' ') &&\n-\tskip=$(git for-each-ref --format='%(objectname)' \\\n-\t\t\"refs/bisect/skip-*\" | tr '\\012' ' ') || exit\n-\n-\t# Maybe some merge bases must be tested first\n-\tcheck_good_are_ancestors_of_bad \"$bad\" \"$good\" \"$skip\"\n-\t# Return now if a checkout has already been done\n-\ttest \"$?\" -eq \"1\" && return\n-\n-\t# Perform bisection computation, display and checkout\n-\tgit bisect--helper --next-exit\n+\t# Perform all bisection computation, display and checkout\n+\tgit bisect--helper --next-all\n \tres=$?\n \n         # Check if we should exit because bisection is finished\n-- \n1.6.3.rc1.112.g17e25\n"},{"id":"113413","messageId":"m3ljp6me9v.fsf@localhost.localdomain","threadId":"19255","inReplyTo":"20090509155548.5387.70784.chriscool@tuxfamily.org","subject":"Re: [PATCH 07/10] bisect: automatically sort sha1_array if needed when looking it up","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-05-09T16:28:47Z","receivedAt":"2009-05-09T16:28:47Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Christian Couder <chriscool@tuxfamily.org> writes:\n\n> This makes sha1_array easier to use, so later patches will be simpler.\n\nHmmm... sort on lookup array. I wonder if it would be worth\nlibrarizing, and if there is any smart optimization for that (like\ne.g. heap for fast access to smallest value and fast insertion, using\ninsertion sort for almost sorted array, etc.).\n\nBTW. does it become unsorted anywhere?\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"113445","messageId":"200905100644.14786.chriscool@tuxfamily.org","threadId":"19255","inReplyTo":"m3ljp6me9v.fsf@localhost.localdomain","subject":"Re: [PATCH 07/10] bisect: automatically sort sha1_array if needed when looking it up","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-05-10T04:44:14Z","receivedAt":"2009-05-10T04:44:14Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Le samedi 9 mai 2009, Jakub Narebski a écrit :\n> Christian Couder <chriscool@tuxfamily.org> writes:\n> > This makes sha1_array easier to use, so later patches will be simpler.\n>\n> Hmmm... sort on lookup array. I wonder if it would be worth\n> librarizing, and if there is any smart optimization for that (like\n> e.g. heap for fast access to smallest value and fast insertion, using\n> insertion sort for almost sorted array, etc.).\n>\n> BTW. does it become unsorted anywhere?\n\nNo, it doesn't. We first read all the \"refs/bisect/good-*\" \nand \"refs/bisect/skip-*\" and put them in some \"struct sha1_array\".\nThen later we may lookup sha1 there from 2 different functions:\n\"check_merge_bases\" first and then \"filter_skipped\".\n\nThis patch optimizes by not sorting before we lookup, so if we don't lookup \nanything, we pay no sorting price.\n\nBest regards,\nChristian.\n"},{"id":"113504","messageId":"7v8wl4tqnh.fsf@alter.siamese.dyndns.org","threadId":"19255","inReplyTo":"20090509155548.5387.83292.chriscool@tuxfamily.org","subject":"Re: [PATCH 10/10] bisect: make \"git bisect\" use new \"--next-all\" bisect-helper function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-11T00:44:02Z","receivedAt":"2009-05-11T00:44:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <chriscool@tuxfamily.org> writes:\n\n> This patch replace the \"--next-exit\" option of \"git bisect--helper\"\n> with a \"--next-all\" option that does merge base checking using\n> the \"check_good_are_ancestors_of_bad\" function implemented in\n> \"bisect.c\" in a former patch.\n>\n> The new \"--next-all\" option is then used in \"git-bisect.sh\" instead\n> of the \"--next-exit\" option, and all the shell functions in\n> \"git-bisect.sh\" that are now unused are removed.\n>\n> Signed-off-by: Christian Couder <chriscool@tuxfamily.org>\n> ---\n>  bisect.c                 |    4 +-\n>  bisect.h                 |    2 +-\n>  builtin-bisect--helper.c |   14 +++---\n>  git-bisect.sh            |  127 +---------------------------------------------\n>  4 files changed, 13 insertions(+), 134 deletions(-)\n\nNice.\n\nAll patches looked sensible; will queue.\n\nThanks.\n"}]}