{"thread":{"id":"18278","subject":"[PATCH 4/7] rev-list: implement \"--bisect-skip\" option","startedAt":"2009-03-12T07:51:26Z","lastAt":"2009-03-12T07:51:26Z","messageCount":1,"participants":["Christian Couder"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"107775","messageId":"20090312085126.823c1bc2.chriscool@tuxfamily.org","threadId":"18278","inReplyTo":null,"subject":"[PATCH 4/7] rev-list: implement \"--bisect-skip\" option","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-03-12T07:51:26Z","receivedAt":"2009-03-12T07:51:26Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"When bisecting, skipped revisions used to be filtered by the\n\"filter_skipped\" function in \"git-bisect.sh\". This was not very\nefficient and error prone, and it made it difficult to implement\nnew behaviors when skipping commits.\n\nThis patch moves the logic from the \"filter_skipped\" shell function\ninto a new \"bisect-skip.c\" file. And a new \"--bisect-skip\" option is\nimplemented in \"builtin-rev-list.c\" to use this logic.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n Makefile           |    1 +\n bisect-skip.c      |   90 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n bisect.h           |    5 +++\n builtin-rev-list.c |   40 +++++++++++++++++++++--\n 4 files changed, 132 insertions(+), 4 deletions(-)\n create mode 100644 bisect-skip.c\n\n\tI know that there is no documentation along with this, but I am\n\tworking on it and hope to send it soon.\n\ndiff --git a/Makefile b/Makefile\nindex 9500c5e..126a06d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -415,6 +415,7 @@ LIB_OBJS += archive-zip.o\n LIB_OBJS += attr.o\n LIB_OBJS += base85.o\n LIB_OBJS += bisect.o\n+LIB_OBJS += bisect-skip.o\n LIB_OBJS += blob.o\n LIB_OBJS += branch.o\n LIB_OBJS += bundle.o\ndiff --git a/bisect-skip.c b/bisect-skip.c\nnew file mode 100644\nindex 0000000..9228465\n--- /dev/null\n+++ b/bisect-skip.c\n@@ -0,0 +1,90 @@\n+#include \"cache.h\"\n+#include \"commit.h\"\n+#include \"strbuf.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+\n+void register_skipped(const char *skipped)\n+{\n+\tstruct strbuf sb, **list, **it, *cur;\n+\tint len = strlen(skipped);\n+\n+\tstrbuf_init(&sb, len);\n+\tstrbuf_add(&sb, skipped, len);\n+\n+\tlist = strbuf_split(&sb, ',', 0);\n+\n+\tfor (it = list; (cur = *it); it++) {\n+\t\tALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,\n+\t\t\t   skipped_sha1_alloc);\n+\t\tif (get_sha1(cur->buf, skipped_sha1[skipped_sha1_nr++]))\n+\t\t\tdie(\"Bad bisect skip ref: %s\", cur->buf);\n+\t}\n+\n+\tstrbuf_list_free(list);\n+\tstrbuf_release(&sb);\n+}\n+\n+static int skipcmp(const void *a, const void *b)\n+{\n+\treturn hashcmp(a, b);\n+}\n+\n+static void prepare_skipped(void)\n+{\n+\tqsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);\n+}\n+\n+static int lookup_skipped(unsigned char *sha1)\n+{\n+\tint lo, hi;\n+\tlo = 0;\n+\thi = skipped_sha1_nr;\n+\twhile (lo < hi) {\n+\t\tint mi = (lo + hi) / 2;\n+\t\tint cmp = hashcmp(sha1, skipped_sha1[mi]);\n+\t\tif (!cmp)\n+\t\t\treturn mi;\n+\t\tif (cmp < 0)\n+\t\t\thi = mi;\n+\t\telse\n+\t\t\tlo = mi + 1;\n+\t}\n+\treturn -lo - 1;\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+{\n+\tstruct commit_list *filtered = NULL, **f = &filtered;\n+\n+\t*tried = NULL;\n+\n+\tif (!skipped_sha1_nr)\n+\t\treturn list;\n+\n+\tprepare_skipped();\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\t\t/* Move current to tried list */\n+\t\t\t*tried = list;\n+\t\t\ttried = &list->next;\n+\t\t} else {\n+\t\t\tif (!show_all)\n+\t\t\t\treturn list;\n+\t\t\t/* Move current to filtered list */\n+\t\t\t*f = list;\n+\t\t\tf = &list->next;\n+\t\t}\n+\t\tlist = next;\n+\t}\n+\n+\treturn filtered;\n+}\ndiff --git a/bisect.h b/bisect.h\nindex cce268d..c5f9fe1 100644\n--- a/bisect.h\n+++ b/bisect.h\n@@ -1,6 +1,11 @@\n #ifndef BISECT_H\n #define BISECT_H\n \n+void register_skipped(const char *skipped);\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+\n struct commit_list *find_bisection(struct commit_list *list,\n \t\t\t\t   int *reaches, int *all,\n \t\t\t\t   int find_all);\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex b1e8200..b50d304 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -39,7 +39,8 @@ static const char rev_list_usage[] =\n \"  special purpose:\\n\"\n \"    --bisect\\n\"\n \"    --bisect-vars\\n\"\n-\"    --bisect-all\"\n+\"    --bisect-all\\n\"\n+\"    --bisect-skip\"\n ;\n \n static struct rev_info revs;\n@@ -226,6 +227,16 @@ static int estimate_bisect_steps(int all)\n \treturn (e < 3 * x) ? n : n - 1;\n }\n \n+static void show_tried(struct commit_list *tried)\n+{\n+\tprintf(\"bisect_tried='\");\n+\tfor (;tried; tried = tried->next) {\n+\t\tchar *format = tried->next ? \"%s|\" : \"%s\";\n+\t\tprintf(format, sha1_to_hex(tried->item->object.sha1));\n+\t}\n+\tprintf(\"'\\n\");\n+}\n+\n int cmd_rev_list(int argc, const char **argv, const char *prefix)\n {\n \tstruct commit_list *list;\n@@ -234,6 +245,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tint bisect_list = 0;\n \tint bisect_show_vars = 0;\n \tint bisect_find_all = 0;\n+\tint bisect_show_all = 0;\n+\tint bisect_skip = 0;\n \tint quiet = 0;\n \n \tgit_config(git_default_config, NULL);\n@@ -261,6 +274,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\tif (!strcmp(arg, \"--bisect-all\")) {\n \t\t\tbisect_list = 1;\n \t\t\tbisect_find_all = 1;\n+\t\t\tbisect_show_all = 1;\n \t\t\trevs.show_decorations = 1;\n \t\t\tcontinue;\n \t\t}\n@@ -269,6 +283,14 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\t\tbisect_show_vars = 1;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!prefixcmp(arg, \"--bisect-skip=\")) {\n+\t\t\tbisect_list = 1;\n+\t\t\tbisect_show_vars = 1;\n+\t\t\tbisect_find_all = 1;\n+\t\t\tbisect_skip = 1;\n+\t\t\tregister_skipped(arg + 14);\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--stdin\")) {\n \t\t\tif (read_from_stdin++)\n \t\t\t\tdie(\"--stdin given twice?\");\n@@ -310,13 +332,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \n \tif (bisect_list) {\n \t\tint reaches = reaches, all = all;\n+\t\tstruct commit_list *tried;\n \n \t\trevs.commits = find_bisection(revs.commits, &reaches, &all,\n \t\t\t\t\t      bisect_find_all);\n+\n+\t\trevs.commits = filter_skipped(revs.commits, &tried,\n+\t\t\t\t\t      bisect_show_all);\n+\n \t\tif (bisect_show_vars) {\n \t\t\tint cnt;\n \t\t\tchar hex[41];\n-\t\t\tif (!revs.commits)\n+\t\t\tif (!revs.commits && !bisect_skip)\n \t\t\t\treturn 1;\n \t\t\t/*\n \t\t\t * revs.commits can reach \"reaches\" commits among\n@@ -330,13 +357,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\t\tcnt = all - reaches;\n \t\t\tif (cnt < reaches)\n \t\t\t\tcnt = reaches;\n-\t\t\tstrcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));\n+\t\t\tif (revs.commits)\n+\t\t\t\tstrcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));\n+\t\t\telse\n+\t\t\t\thex[0] = '\\0';\n \n-\t\t\tif (bisect_find_all) {\n+\t\t\tif (bisect_show_all) {\n \t\t\t\ttraverse_commit_list(&revs, show_commit, show_object);\n \t\t\t\tprintf(\"------\\n\");\n \t\t\t}\n \n+\t\t\tif (bisect_skip)\n+\t\t\t\tshow_tried(tried);\n \t\t\tprintf(\"bisect_rev=%s\\n\"\n \t\t\t       \"bisect_nr=%d\\n\"\n \t\t\t       \"bisect_good=%d\\n\"\n-- \n1.6.2.83.g012a16.dirty\n"}]}