{"thread":{"id":"9948","subject":"[PATCH] rev-list --bisect: Fix best == NULL case.","startedAt":"2007-09-20T05:23:01Z","lastAt":"2007-09-20T07:08:00Z","messageCount":3,"participants":["Christian Couder","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"53626","messageId":"20070920072301.689b96c9.chriscool@tuxfamily.org","threadId":"9948","inReplyTo":null,"subject":"[PATCH] rev-list --bisect: Fix best == NULL case.","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2007-09-20T05:23:01Z","receivedAt":"2007-09-20T05:23:01Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Signed-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin-rev-list.c |    6 +++---\n 1 files changed, 3 insertions(+), 3 deletions(-)\n\n Not sure if the \"if (best)\" check is really needed, but it looks safer\n with this patch.\n\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex 899a31d..3894633 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -436,10 +436,10 @@ static struct commit_list *find_bisection(struct commit_list *list,\n \t/* Do the real work of finding bisection commit. */\n \tbest = do_find_bisection(list, nr, weights);\n \n-\tif (best)\n+\tif (best) {\n \t\tbest->next = NULL;\n-\n-\t*reaches = weight(best);\n+\t\t*reaches = weight(best);\n+\t}\n \tfree(weights);\n \n \treturn best;\n-- \n1.5.3.2.80.g077d6f\n"},{"id":"53629","messageId":"7vmyvhltpy.fsf@gitster.siamese.dyndns.org","threadId":"9948","inReplyTo":"20070920072301.689b96c9.chriscool@tuxfamily.org","subject":"Re: [PATCH] rev-list --bisect: Fix best == NULL case.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-20T06:46:33Z","receivedAt":"2007-09-20T06:46:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The patch makes sense.  In fact you can crash any released\nversion like this:\n\n    $ git rev-list --bisect v1.5.2..v1.5.0\n\nI'll need to apply a moral equivalent to 'maint'.\n\nBy the way, you may find the attached patch an interesting food\nfor thought, on top of your patch.\n\n    $ git rev-list --bisect-all --pretty=oneline v1.5.2.5..v1.5.3.2\n\n---\n\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex 3894633..e4ef172 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -9,6 +9,7 @@\n #include \"revision.h\"\n #include \"list-objects.h\"\n #include \"builtin.h\"\n+#include \"log-tree.h\"\n \n /* bits #0-15 in revision.h */\n \n@@ -74,6 +75,7 @@ static void show_commit(struct commit *commit)\n \t\t\tparents = parents->next;\n \t\t}\n \t}\n+\tshow_decorations(commit);\n \tif (revs.commit_format == CMIT_FMT_ONELINE)\n \t\tputchar(' ');\n \telse\n@@ -278,6 +280,57 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)\n \treturn best;\n }\n \n+struct commit_dist {\n+\tstruct commit *commit;\n+\tint distance;\n+};\n+\n+static int compare_commit_dist(const void *a_, const void *b_)\n+{\n+\tstruct commit_dist *a, *b;\n+\n+\ta = (struct commit_dist *)a_;\n+\tb = (struct commit_dist *)b_;\n+\tif (a->distance != b->distance)\n+\t\treturn b->distance - a->distance; /* desc sort */\n+\treturn hashcmp(a->commit->object.sha1, b->commit->object.sha1);\n+}\n+\n+static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)\n+{\n+\tstruct commit_list *p;\n+\tstruct commit_dist *array = xcalloc(nr, sizeof(*array));\n+\tint cnt, i;\n+\n+\tfor (p = list, cnt = 0; p; p = p->next) {\n+\t\tint distance;\n+\t\tunsigned flags = p->item->object.flags;\n+\n+\t\tif (revs.prune_fn && !(flags & TREECHANGE))\n+\t\t\tcontinue;\n+\t\tdistance = weight(p);\n+\t\tif (nr - distance < distance)\n+\t\t\tdistance = nr - distance;\n+\t\tarray[cnt].commit = p->item;\n+\t\tarray[cnt].distance = distance;\n+\t\tcnt++;\n+\t}\n+\tqsort(array, cnt, sizeof(*array), compare_commit_dist);\n+\tfor (p = list, i = 0; i < cnt; i++) {\n+\t\tstruct name_decoration *r = xmalloc(sizeof(*r) + 100);\n+\t\tstruct object *obj = &(array[i].commit->object);\n+\n+\t\tsprintf(r->name, \"dist=%d\", array[i].distance);\n+\t\tr->next = add_decoration(&name_decoration, obj, r);\n+\t\tp->item = array[i].commit;\n+\t\tp = p->next;\n+\t}\n+\tif (p)\n+\t\tp->next = NULL;\n+\tfree(array);\n+\treturn list;\n+}\n+\n /*\n  * zero or positive weight is the number of interesting commits it can\n  * reach, including itself.  Especially, weight = 0 means it does not\n@@ -292,7 +345,8 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)\n  * or positive distance.\n  */\n static struct commit_list *do_find_bisection(struct commit_list *list,\n-\t\t\t\t\t     int nr, int *weights)\n+\t\t\t\t\t     int nr, int *weights,\n+\t\t\t\t\t     int find_all)\n {\n \tint n, counted;\n \tstruct commit_list *p;\n@@ -351,7 +405,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,\n \t\tclear_distance(list);\n \n \t\t/* Does it happen to be at exactly half-way? */\n-\t\tif (halfway(p, nr))\n+\t\tif (!find_all && halfway(p, nr))\n \t\t\treturn p;\n \t\tcounted++;\n \t}\n@@ -389,19 +443,22 @@ static struct commit_list *do_find_bisection(struct commit_list *list,\n \t\t\t\tweight_set(p, weight(q));\n \n \t\t\t/* Does it happen to be at exactly half-way? */\n-\t\t\tif (halfway(p, nr))\n+\t\t\tif (!find_all && halfway(p, nr))\n \t\t\t\treturn p;\n \t\t}\n \t}\n \n \tshow_list(\"bisection 2 counted all\", counted, nr, list);\n \n-\t/* Then find the best one */\n-\treturn best_bisection(list, nr);\n+\tif (!find_all)\n+\t\treturn best_bisection(list, nr);\n+\telse\n+\t\treturn best_bisection_sorted(list, nr);\n }\n \n static struct commit_list *find_bisection(struct commit_list *list,\n-\t\t\t\t\t  int *reaches, int *all)\n+\t\t\t\t\t  int *reaches, int *all,\n+\t\t\t\t\t  int find_all)\n {\n \tint nr, on_list;\n \tstruct commit_list *p, *best, *next, *last;\n@@ -434,14 +491,12 @@ static struct commit_list *find_bisection(struct commit_list *list,\n \tweights = xcalloc(on_list, sizeof(*weights));\n \n \t/* Do the real work of finding bisection commit. */\n-\tbest = do_find_bisection(list, nr, weights);\n-\n-\tif (best) {\n+\tbest = do_find_bisection(list, nr, weights, find_all);\n+\tif (!find_all && best) {\n \t\tbest->next = NULL;\n \t\t*reaches = weight(best);\n \t}\n \tfree(weights);\n-\n \treturn best;\n }\n \n@@ -468,6 +523,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tint i;\n \tint read_from_stdin = 0;\n \tint bisect_show_vars = 0;\n+\tint bisect_find_all = 0;\n \n \tgit_config(git_default_config);\n \tinit_revisions(&revs, prefix);\n@@ -490,6 +546,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\t\tbisect_list = 1;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"--bisect-all\")) {\n+\t\t\tbisect_list = 1;\n+\t\t\tbisect_find_all = 1;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--bisect-vars\")) {\n \t\t\tbisect_list = 1;\n \t\t\tbisect_show_vars = 1;\n@@ -536,7 +597,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tif (bisect_list) {\n \t\tint reaches = reaches, all = all;\n \n-\t\trevs.commits = find_bisection(revs.commits, &reaches, &all);\n+\t\trevs.commits = find_bisection(revs.commits, &reaches, &all,\n+\t\t\t\t\t      bisect_find_all);\n \t\tif (bisect_show_vars) {\n \t\t\tint cnt;\n \t\t\tif (!revs.commits)\ndiff --git a/log-tree.c b/log-tree.c\nindex a642371..32e360b 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -15,7 +15,7 @@ static void show_parents(struct commit *commit, int abbrev)\n \t}\n }\n \n-static void show_decorations(struct commit *commit)\n+void show_decorations(struct commit *commit)\n {\n \tconst char *prefix;\n \tstruct name_decoration *decoration;\ndiff --git a/log-tree.h b/log-tree.h\nindex e82b56a..b33f7cd 100644\n--- a/log-tree.h\n+++ b/log-tree.h\n@@ -12,5 +12,6 @@ int log_tree_diff_flush(struct rev_info *);\n int log_tree_commit(struct rev_info *, struct commit *);\n int log_tree_opt_parse(struct rev_info *, const char **, int);\n void show_log(struct rev_info *opt, const char *sep);\n+void show_decorations(struct commit *commit);\n \n #endif\n"},{"id":"53630","messageId":"7vhclplsq7.fsf@gitster.siamese.dyndns.org","threadId":"9948","inReplyTo":"7vmyvhltpy.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] rev-list --bisect: Fix best == NULL case.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-20T07:08:00Z","receivedAt":"2007-09-20T07:08:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> The patch makes sense.  In fact you can crash any released\n> version like this:\n>\n>     $ git rev-list --bisect v1.5.2..v1.5.0\n>\n> I'll need to apply a moral equivalent to 'maint'.\n\nI spoke too fast.  This is not broken in any released version.\n\nOnly with the patch from somebody that broke it with commit\nce0cbad7727457854d631a6314d9aee7c837cb65 (rev-list --bisect:\nMove finding bisection into do_find_bisection.), the \"empty set\"\ncase would segfault ;-).\n"}]}