{"thread":{"id":"43886","subject":"[PATCH v13 02/13] bisect: rewrite `check_term_format` shell function in C","startedAt":"2016-08-19T20:39:31Z","lastAt":"2016-08-21T11:18:14Z","messageCount":15,"participants":["Pranit Bauva"],"isPatch":true,"patchVersion":13,"patchTotal":13},"messages":[{"id":"299738","messageId":"01020156a4814591-eb28640c-8649-46be-93e2-0f583464ce18-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 02/13] bisect: rewrite `check_term_format` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:39:31Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `check_term_format` shell function in C and add\na `--check-term-format` subcommand to `git bisect--helper` to call it\nfrom git-bisect.sh\n\nUsing `--check-term-format` subcommand is a temporary measure to port\nshell function to C so as to use the existing test suite. As more\nfunctions are ported, this subcommand will be retired and its\nimplementation will be called by some other method/subcommand. For\neg. In conversion of write_terms() of git-bisect.sh, the subcommand will\nbe removed and instead check_term_format() will be called in its C\nimplementation while a new subcommand will be introduced for write_terms().\n\nHelped-by: Johannes Schindelein <Johannes.Schindelein@gmx.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 31 ++-----------------------\n 2 files changed, 61 insertions(+), 30 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 8111c91..a47f1f2 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -2,19 +2,73 @@\n #include \"cache.h\"\n #include \"parse-options.h\"\n #include \"bisect.h\"\n+#include \"refs.h\"\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n+\tN_(\"git bisect--helper --check-term-format <term> <orig_term>\"),\n \tNULL\n };\n \n+/*\n+ * Check whether the string `term` belongs to the set of strings\n+ * included in the variable arguments.\n+ */\n+LAST_ARG_MUST_BE_NULL\n+static int one_of(const char *term, ...)\n+{\n+\tint res = 0;\n+\tva_list matches;\n+\tconst char *match;\n+\n+\tva_start(matches, term);\n+\twhile (!res && (match = va_arg(matches, const char *)))\n+\t\tres = !strcmp(term, match);\n+\tva_end(matches);\n+\n+\treturn res;\n+}\n+\n+static int check_term_format(const char *term, const char *orig_term)\n+{\n+\tint res;\n+\tchar *new_term = xstrfmt(\"refs/bisect/%s\", term);\n+\n+\tres = check_refname_format(new_term, 0);\n+\tfree(new_term);\n+\n+\tif (res)\n+\t\treturn error(_(\"'%s' is not a valid term\"), term);\n+\n+\tif (one_of(term, \"help\", \"start\", \"skip\", \"next\", \"reset\",\n+\t\t\t\"visualize\", \"replay\", \"log\", \"run\", NULL))\n+\t\treturn error(_(\"can't use the builtin command '%s' as a term\"), term);\n+\n+\t/*\n+\t * In theory, nothing prevents swapping completely good and bad,\n+\t * but this situation could be confusing and hasn't been tested\n+\t * enough. Forbid it for now.\n+\t */\n+\n+\tif ((strcmp(orig_term, \"bad\") && one_of(term, \"bad\", \"new\", NULL)) ||\n+\t\t (strcmp(orig_term, \"good\") && one_of(term, \"good\", \"old\", NULL)))\n+\t\treturn error(_(\"can't change the meaning of the term '%s'\"), term);\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n-\tenum { NEXT_ALL = 1 } cmdmode = 0;\n+\tenum {\n+\t\tNEXT_ALL = 1,\n+\t\tCHECK_TERM_FMT\n+\t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n+\t\tOPT_CMDMODE(0, \"check-term-format\", &cmdmode,\n+\t\t\t N_(\"check format of the term\"), CHECK_TERM_FMT),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -29,6 +83,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tswitch (cmdmode) {\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n+\tcase CHECK_TERM_FMT:\n+\t\tif (argc != 2)\n+\t\t\tdie(_(\"--check-term-format requires two arguments\"));\n+\t\treturn check_term_format(argv[0], argv[1]);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex ae3cb01..a727c59 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -564,38 +564,11 @@ write_terms () {\n \tthen\n \t\tdie \"$(gettext \"please use two different terms\")\"\n \tfi\n-\tcheck_term_format \"$TERM_BAD\" bad\n-\tcheck_term_format \"$TERM_GOOD\" good\n+\tgit bisect--helper --check-term-format \"$TERM_BAD\" bad || exit\n+\tgit bisect--helper --check-term-format \"$TERM_GOOD\" good || exit\n \tprintf '%s\\n%s\\n' \"$TERM_BAD\" \"$TERM_GOOD\" >\"$GIT_DIR/BISECT_TERMS\"\n }\n \n-check_term_format () {\n-\tterm=$1\n-\tgit check-ref-format refs/bisect/\"$term\" ||\n-\tdie \"$(eval_gettext \"'\\$term' is not a valid term\")\"\n-\tcase \"$term\" in\n-\thelp|start|terms|skip|next|reset|visualize|replay|log|run)\n-\t\tdie \"$(eval_gettext \"can't use the builtin command '\\$term' as a term\")\"\n-\t\t;;\n-\tbad|new)\n-\t\tif test \"$2\" != bad\n-\t\tthen\n-\t\t\t# In theory, nothing prevents swapping\n-\t\t\t# completely good and bad, but this situation\n-\t\t\t# could be confusing and hasn't been tested\n-\t\t\t# enough. Forbid it for now.\n-\t\t\tdie \"$(eval_gettext \"can't change the meaning of term '\\$term'\")\"\n-\t\tfi\n-\t\t;;\n-\tgood|old)\n-\t\tif test \"$2\" != good\n-\t\tthen\n-\t\t\tdie \"$(eval_gettext \"can't change the meaning of term '\\$term'\")\"\n-\t\tfi\n-\t\t;;\n-\tesac\n-}\n-\n check_and_set_terms () {\n \tcmd=\"$1\"\n \tcase \"$cmd\" in\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299739","messageId":"01020156a48145d3-b12a4da0-9df9-4d16-92aa-eea8c52dbda3-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 13/13] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:40:43Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_start` shell function partially in C and add\n`bisect-start` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nThe last part is not converted because it calls another shell function.\n`bisect_start` shell function will be completed after the `bisect_next`\nshell function is ported in C.\n\nUsing `--bisect-start` subcommand is a temporary measure to port shell\nfunction in C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and will be called by some\nother methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 252 +++++++++++++++++++++++++++++++++++++++++++++--\n git-bisect.sh            | 133 +------------------------\n 2 files changed, 246 insertions(+), 139 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex e1cf956..ff1dfc7 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -7,6 +7,7 @@\n #include \"argv-array.h\"\n #include \"run-command.h\"\n #include \"prompt.h\"\n+#include \"quote.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -14,6 +15,8 @@ static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\n+static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n@@ -24,6 +27,8 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n \tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n+\tN_(\"git bisect--helper --bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]\"\n+\t\t\t\t\t      \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n \tNULL\n };\n \n@@ -303,7 +308,7 @@ static int bisect_next_check(const struct bisect_terms *terms,\n \t\t * have bad (or new) but not good (or old). We could bisect\n \t\t * although this is less optimum.\n \t\t */\n-\t\tfprintf(stderr, N_(\"Warning: bisecting only with a %s commit\\n\"),\n+\t\tfprintf(stderr, _(\"Warning: bisecting only with a %s commit\\n\"),\n \t\t\tterms->term_bad.buf);\n \t\tif (!isatty(0))\n \t\t\treturn 0;\n@@ -366,11 +371,11 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \tint i;\n \n \tif (get_terms(terms)) {\n-\t\tfprintf(stderr, N_(\"no terms defined\\n\"));\n+\t\tfprintf(stderr, _(\"no terms defined\\n\"));\n \t\treturn -1;\n \t}\n \tif (argc == 0) {\n-\t\tprintf(N_(\"Your current terms are %s for the old state\\nand \"\n+\t\tprintf(_(\"Your current terms are %s for the old state\\nand \"\n \t\t       \"%s for the new state.\\n\"), terms->term_good.buf,\n \t\t       terms->term_bad.buf);\n \t\treturn 0;\n@@ -378,11 +383,11 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \n \tfor (i = 0; i < argc; i++) {\n \t\tif (!strcmp(argv[i], \"--term-good\"))\n-\t\t\tprintf(N_(\"%s\\n\"), terms->term_good.buf);\n+\t\t\tprintf(_(\"%s\\n\"), terms->term_good.buf);\n \t\telse if (!strcmp(argv[i], \"--term-bad\"))\n-\t\t\tprintf(N_(\"%s\\n\"), terms->term_bad.buf);\n+\t\t\tprintf(_(\"%s\\n\"), terms->term_bad.buf);\n \t\telse\n-\t\t\tprintf(N_(\"invalid argument %s for 'git bisect \"\n+\t\t\tprintf(_(\"invalid argument %s for 'git bisect \"\n \t\t\t\t  \"terms'.\\nSupported options are: \"\n \t\t\t\t  \"--term-good|--term-old and \"\n \t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n@@ -391,6 +396,228 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \treturn 0;\n }\n \n+static int bisect_start(struct bisect_terms *terms, int no_checkout,\n+\t\t\tconst char **argv, int argc)\n+{\n+\tint i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;\n+\tint flags, pathspec_pos;\n+\tstruct string_list revs = STRING_LIST_INIT_DUP;\n+\tstruct string_list states = STRING_LIST_INIT_DUP;\n+\tstruct strbuf start_head = STRBUF_INIT;\n+\tstruct strbuf bisect_names = STRBUF_INIT;\n+\tstruct strbuf orig_args = STRBUF_INIT;\n+\tconst char *head;\n+\tunsigned char sha1[20];\n+\tFILE *fp;\n+\tstruct object_id oid;\n+\n+\tif (is_bare_repository())\n+\t\tno_checkout = 1;\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\thas_double_dash = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tchar *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\thas_double_dash = 1;\n+\t\t\tbreak;\n+\t\t} else if (!strcmp(argv[i], \"--no-checkout\"))\n+\t\t\tno_checkout = 1;\n+\t\telse if (!strcmp(argv[i], \"--term-good\") ||\n+\t\t\t !strcmp(argv[i], \"--term-old\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_good);\n+\t\t\tstrbuf_addstr(&terms->term_good, argv[++i]);\n+\t\t} else if (skip_prefix(argv[i], \"--term-good=\", &argv[i])) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_good);\n+\t\t\tstrbuf_addstr(&terms->term_good, argv[i]);\n+\t\t} else if (skip_prefix(argv[i], \"--term-old=\", &argv[i])) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_good);\n+\t\t\tstrbuf_addstr(&terms->term_good, argv[i]);\n+\t\t} else if (!strcmp(argv[i], \"--term-bad\") ||\n+\t\t\t !strcmp(argv[i], \"--term-new\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_bad);\n+\t\t\tstrbuf_addstr(&terms->term_bad, argv[++i]);\n+\t\t} else if (skip_prefix(argv[i], \"--term-bad=\", &argv[i])) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_bad);\n+\t\t\tstrbuf_addstr(&terms->term_bad, argv[i]);\n+\t\t} else if (skip_prefix(argv[i], \"--term-new=\", &argv[i])) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tstrbuf_reset(&terms->term_good);\n+\t\t\tstrbuf_addstr(&terms->term_good, argv[i]);\n+\t\t} else if (starts_with(argv[i], \"--\") &&\n+\t\t\t !one_of(argv[i], \"--term-good\", \"--term-bad\", NULL)) {\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\tdie(_(\"unrecognised option: '%s'\"), argv[i]);\n+\t\t} else if (get_oid(argv[i], &oid) && has_double_dash) {\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\tfree(commit_id);\n+\t\t\tdie(_(\"'%s' does not appear to be a valid revision\"), argv[i]);\n+\t\t} else {\n+\t\t\tfree(commit_id);\n+\t\t\tstring_list_append(&revs, oid_to_hex(&oid));\n+\t\t}\n+\t}\n+\tpathspec_pos = i;\n+\n+\t/*\n+\t * The user ran \"git bisect start <sha1> <sha1>\", hence did not\n+\t * explicitly specify the terms, but we are already starting to\n+\t * set references named with the default terms, and won't be able\n+\t * to change afterwards.\n+\t */\n+\tmust_write_terms |= !!revs.nr;\n+\tfor (i = 0; i < revs.nr; i++) {\n+\t\tif (bad_seen)\n+\t\t\tstring_list_append(&states, terms->term_good.buf);\n+\t\telse {\n+\t\t\tbad_seen = 1;\n+\t\t\tstring_list_append(&states, terms->term_bad.buf);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Verify HEAD\n+\t */\n+\thead = resolve_ref_unsafe(\"HEAD\", 0, sha1, &flags);\n+\tif (!head) {\n+\t\tif (get_sha1(\"HEAD\", sha1)) {\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\tdie(_(\"Bad HEAD - I need a HEAD\"));\n+\t\t}\n+\t}\n+\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\t/* Reset to the rev from where we started */\n+\t\tstrbuf_read_file(&start_head, git_path_bisect_start(), 0);\n+\t\tstrbuf_trim(&start_head);\n+\t\tif (!no_checkout) {\n+\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\t\targv_array_pushl(&argv, \"checkout\", start_head.buf,\n+\t\t\t\t\t \"--\", NULL);\n+\t\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\t\terror(_(\"checking out '%s' failed. Try 'git \"\n+\t\t\t\t\t\"bisect start <valid-branch>'.\"),\n+\t\t\t\t      start_head.buf);\n+\t\t\t\tstrbuf_release(&start_head);\n+\t\t\t\tstring_list_clear(&revs, 0);\n+\t\t\t\tstring_list_clear(&states, 0);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tif (starts_with(head, \"refs/heads/\") ||\n+\t\t    !get_oid_hex(head, &oid) || ref_exists(head)) {\n+\t\t\t/*\n+\t\t\t * This error message should only be triggered by\n+\t\t\t * cogito usage, and cogito users should understand\n+\t\t\t * it relates to cg-seek.\n+\t\t\t */\n+\t\t\tif (!is_empty_or_missing_file(git_path_head_name())) {\n+\t\t\t\tstrbuf_release(&start_head);\n+\t\t\t\tstring_list_clear(&revs, 0);\n+\t\t\t\tstring_list_clear(&states, 0);\n+\t\t\t\tdie(_(\"won't bisect on cg-seek'ed tree\"));\n+\t\t\t}\n+\t\t\tif (starts_with(head, \"refs/heads/\")) {\n+\t\t\t\tstrbuf_reset(&start_head);\n+\t\t\t\tstrbuf_addstr(&start_head, head + 11);\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tstrbuf_reset(&start_head);\n+\t\t\t\tstrbuf_addstr(&start_head, sha1_to_hex(sha1));\n+\t\t\t}\n+\t\t} else {\n+\t\t\tstrbuf_release(&start_head);\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\tdie(_(\"Bad HEAD - strange symbolic ref\"));\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Get rid of any old bisect state.\n+\t */\n+\tif (bisect_clean_state()) {\n+\t\treturn -1;\n+\t}\n+\t/*\n+\t * In case of mistaken revs or checkout error, or signals received,\n+\t * \"bisect_auto_next\" below may exit or misbehave.\n+\t * We have to trap this to be able to clean up using\n+\t * \"bisect_clean_state\".\n+\t */\n+\n+\t/*\n+\t * Write new start state\n+\t */\n+\twrite_file(git_path_bisect_start(), \"%s\\n\", start_head.buf);\n+\n+\tif (no_checkout) {\n+\t\tget_oid(start_head.buf, &oid);\n+\t\tif (update_ref(NULL, \"BISECT_HEAD\", oid.hash, NULL, 0,\n+\t\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\t\tstrbuf_release(&start_head);\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\tstrbuf_release(&start_head);\n+\n+\tif (pathspec_pos < argc - 1)\n+\t\tsq_quote_argv(&bisect_names, argv + pathspec_pos, 0);\n+\twrite_file(git_path_bisect_names(), \"%s\\n\", bisect_names.buf);\n+\tstrbuf_release(&bisect_names);\n+\n+\tfor (i = 0; i < states.nr; i++) {\n+\t\tif (bisect_write(states.items[i].string,\n+\t\t\t\t  revs.items[i].string, terms, 1)) {\n+\t\t\tstring_list_clear(&revs, 0);\n+\t\t\tstring_list_clear(&states, 0);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\tstring_list_clear(&revs, 0);\n+\tstring_list_clear(&states, 0);\n+\n+\tif (must_write_terms)\n+\t\tif (write_terms(terms->term_bad.buf, terms->term_good.buf))\n+\t\t\treturn -1;\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp)\n+\t\treturn -1;\n+\n+\tif (fprintf(fp, \"git bisect start\") < 1)\n+\t\treturn -1;\n+\n+\tsq_quote_argv(&orig_args, argv, 0);\n+\tif (fprintf(fp, \"%s\", orig_args.buf) < 0) {\n+\t\tstrbuf_release(&orig_args);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_release(&orig_args);\n+\tif (fprintf(fp, \"\\n\") < 1) {\n+\t\tfclose(fp);\n+\t\treturn -1;\n+\t}\n+\tfclose(fp);\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -402,7 +629,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n \t\tBISECT_NEXT_CHECK,\n-\t\tBISECT_TERMS\n+\t\tBISECT_TERMS,\n+\t\tBISECT_START\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -424,6 +652,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"check whether bad or good terms exist\"), BISECT_NEXT_CHECK),\n \t\tOPT_CMDMODE(0, \"bisect-terms\", &cmdmode,\n \t\t\t N_(\"print out the bisect terms\"), BISECT_TERMS),\n+\t\tOPT_CMDMODE(0, \"bisect-start\", &cmdmode,\n+\t\t\t N_(\"start the bisect session\"), BISECT_START),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -432,7 +662,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tbisect_terms_init(&terms);\n \n \targc = parse_options(argc, argv, prefix, options,\n-\t\t\t     git_bisect_helper_usage, PARSE_OPT_KEEP_UNKNOWN);\n+\t\t\t     git_bisect_helper_usage,\n+\t\t\t     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);\n \n \tif (!cmdmode)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n@@ -486,6 +717,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n \t\tres = bisect_terms(&terms, argv, argc);\n \t\tbreak;\n+\tcase BISECT_START:\n+\t\tstrbuf_addstr(&terms.term_good, \"good\");\n+\t\tstrbuf_addstr(&terms.term_bad, \"bad\");\n+\t\tres = bisect_start(&terms, no_checkout, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex d6c8b5a..f0896b3 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -71,122 +71,7 @@ bisect_autostart() {\n }\n \n bisect_start() {\n-\t#\n-\t# Check for one bad and then some good revisions.\n-\t#\n-\thas_double_dash=0\n-\tfor arg; do\n-\t\tcase \"$arg\" in --) has_double_dash=1; break ;; esac\n-\tdone\n-\torig_args=$(git rev-parse --sq-quote \"$@\")\n-\tbad_seen=0\n-\teval=''\n-\tmust_write_terms=0\n-\trevs=''\n-\tif test \"z$(git rev-parse --is-bare-repository)\" != zfalse\n-\tthen\n-\t\tmode=--no-checkout\n-\telse\n-\t\tmode=''\n-\tfi\n-\twhile [ $# -gt 0 ]; do\n-\t\targ=\"$1\"\n-\t\tcase \"$arg\" in\n-\t\t--)\n-\t\t\tshift\n-\t\t\tbreak\n-\t\t;;\n-\t\t--no-checkout)\n-\t\t\tmode=--no-checkout\n-\t\t\tshift ;;\n-\t\t--term-good|--term-old)\n-\t\t\tshift\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_GOOD=$1\n-\t\t\tshift ;;\n-\t\t--term-good=*|--term-old=*)\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_GOOD=${1#*=}\n-\t\t\tshift ;;\n-\t\t--term-bad|--term-new)\n-\t\t\tshift\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_BAD=$1\n-\t\t\tshift ;;\n-\t\t--term-bad=*|--term-new=*)\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_BAD=${1#*=}\n-\t\t\tshift ;;\n-\t\t--*)\n-\t\t\tdie \"$(eval_gettext \"unrecognised option: '\\$arg'\")\" ;;\n-\t\t*)\n-\t\t\trev=$(git rev-parse -q --verify \"$arg^{commit}\") || {\n-\t\t\t\ttest $has_double_dash -eq 1 &&\n-\t\t\t\tdie \"$(eval_gettext \"'\\$arg' does not appear to be a valid revision\")\"\n-\t\t\t\tbreak\n-\t\t\t}\n-\t\t\trevs=\"$revs $rev\"\n-\t\t\tshift\n-\t\t\t;;\n-\t\tesac\n-\tdone\n-\n-\tfor rev in $revs\n-\tdo\n-\t\t# The user ran \"git bisect start <sha1>\n-\t\t# <sha1>\", hence did not explicitly specify\n-\t\t# the terms, but we are already starting to\n-\t\t# set references named with the default terms,\n-\t\t# and won't be able to change afterwards.\n-\t\tmust_write_terms=1\n-\n-\t\tcase $bad_seen in\n-\t\t0) state=$TERM_BAD ; bad_seen=1 ;;\n-\t\t*) state=$TERM_GOOD ;;\n-\t\tesac\n-\t\teval=\"$eval git bisect--helper --bisect-write '$state' '$rev' '$TERM_GOOD' '$TERM_BAD' 'nolog' &&\"\n-\tdone\n-\t#\n-\t# Verify HEAD.\n-\t#\n-\thead=$(GIT_DIR=\"$GIT_DIR\" git symbolic-ref -q HEAD) ||\n-\thead=$(GIT_DIR=\"$GIT_DIR\" git rev-parse --verify HEAD) ||\n-\tdie \"$(gettext \"Bad HEAD - I need a HEAD\")\"\n-\n-\t#\n-\t# Check if we are bisecting.\n-\t#\n-\tstart_head=''\n-\tif test -s \"$GIT_DIR/BISECT_START\"\n-\tthen\n-\t\t# Reset to the rev from where we started.\n-\t\tstart_head=$(cat \"$GIT_DIR/BISECT_START\")\n-\t\tif test \"z$mode\" != \"z--no-checkout\"\n-\t\tthen\n-\t\t\tgit checkout \"$start_head\" -- ||\n-\t\t\tdie \"$(eval_gettext \"Checking out '\\$start_head' failed. Try 'git bisect reset <valid-branch>'.\")\"\n-\t\tfi\n-\telse\n-\t\t# Get rev from where we start.\n-\t\tcase \"$head\" in\n-\t\trefs/heads/*|$_x40)\n-\t\t\t# This error message should only be triggered by\n-\t\t\t# cogito usage, and cogito users should understand\n-\t\t\t# it relates to cg-seek.\n-\t\t\t[ -s \"$GIT_DIR/head-name\" ] &&\n-\t\t\t\tdie \"$(gettext \"won't bisect on cg-seek'ed tree\")\"\n-\t\t\tstart_head=\"${head#refs/heads/}\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\tdie \"$(gettext \"Bad HEAD - strange symbolic ref\")\"\n-\t\t\t;;\n-\t\tesac\n-\tfi\n-\n-\t#\n-\t# Get rid of any old bisect state.\n-\t#\n-\tgit bisect--helper --bisect-clean-state || exit\n+\tgit bisect--helper --bisect-start $@ || exit\n \n \t#\n \t# Change state.\n@@ -197,24 +82,10 @@ bisect_start() {\n \t#\n \ttrap 'git bisect--helper --bisect-clean-state' 0\n \ttrap 'exit 255' 1 2 3 15\n-\n-\t#\n-\t# Write new start state.\n-\t#\n-\techo \"$start_head\" >\"$GIT_DIR/BISECT_START\" && {\n-\t\ttest \"z$mode\" != \"z--no-checkout\" ||\n-\t\tgit update-ref --no-deref BISECT_HEAD \"$start_head\"\n-\t} &&\n-\tgit rev-parse --sq-quote \"$@\" >\"$GIT_DIR/BISECT_NAMES\" &&\n-\teval \"$eval true\" &&\n-\tif test $must_write_terms -eq 1\n-\tthen\n-\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\"\n-\tfi &&\n-\techo \"git bisect start$orig_args\" >>\"$GIT_DIR/BISECT_LOG\" || exit\n \t#\n \t# Check if we can proceed to the next bisect state.\n \t#\n+\tget_terms\n \tbisect_auto_next\n \n \ttrap '-' 0\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299742","messageId":"01020156a48145b6-e0aee940-119b-42b1-b0c4-80263426cd6e-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 07/13] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:50:39Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\nsubcommand to `git bisect--helper` to call it from git-bisect.sh .\n\nUsing `bisect_reset` subcommand is a temporary measure to port shell\nfunctions to C so as to use the existing test suite. As more functions\nare ported, this subcommand would be retired but its implementation will\nbe called by some other method.\n\nNote: --bisect-clean-state subcommand has not been retired as there are\nstill a function namely `bisect_start()` which still uses this\nsubcommand.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++--------------------------\n 2 files changed, 49 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex e50934c..9aba094 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,17 +3,22 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n+#include \"argv-array.h\"\n+#include \"run-command.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n+static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n+\tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tNULL\n };\n \n@@ -84,12 +89,47 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\n }\n \n+static int bisect_reset(const char *commit)\n+{\n+\tstruct strbuf branch = STRBUF_INIT;\n+\n+\tif (!commit) {\n+\t\tif (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n+\t\t\tprintf(\"We are not bisecting.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tstruct object_id oid;\n+\t\tif (get_oid(commit, &oid))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addstr(&branch, commit);\n+\t}\n+\n+\tif (!file_exists(git_path_bisect_head())) {\n+\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\targv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n+\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\terror(_(\"Could not check out original HEAD '%s'. Try \"\n+\t\t\t\t\"'git bisect reset <commit>'.\"), branch.buf);\n+\t\t\tstrbuf_release(&branch);\n+\t\t\targv_array_clear(&argv);\n+\t\t\treturn -1;\n+\t\t}\n+\t\targv_array_clear(&argv);\n+\t}\n+\n+\tstrbuf_release(&branch);\n+\treturn bisect_clean_state();\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n-\t\tBISECT_CLEAN_STATE\n+\t\tBISECT_CLEAN_STATE,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -99,6 +139,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n \t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n+\t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n+\t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -121,6 +163,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n \t\treturn bisect_clean_state();\n+\tcase BISECT_RESET:\n+\t\tif (argc > 1)\n+\t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n+\t\treturn bisect_reset(argc ? argv[0] : NULL);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex f1202df..442397b 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -409,35 +409,11 @@ bisect_visualize() {\n \teval '\"$@\"' --bisect -- $(cat \"$GIT_DIR/BISECT_NAMES\")\n }\n \n-bisect_reset() {\n-\ttest -s \"$GIT_DIR/BISECT_START\" || {\n-\t\tgettextln \"We are not bisecting.\"\n-\t\treturn\n-\t}\n-\tcase \"$#\" in\n-\t0) branch=$(cat \"$GIT_DIR/BISECT_START\") ;;\n-\t1) git rev-parse --quiet --verify \"$1^{commit}\" >/dev/null || {\n-\t\t\tinvalid=\"$1\"\n-\t\t\tdie \"$(eval_gettext \"'\\$invalid' is not a valid commit\")\"\n-\t\t}\n-\t\tbranch=\"$1\" ;;\n-\t*)\n-\t\tusage ;;\n-\tesac\n-\n-\tif ! test -f \"$GIT_DIR/BISECT_HEAD\" && ! git checkout \"$branch\" --\n-\tthen\n-\t\tdie \"$(eval_gettext \"Could not check out original HEAD '\\$branch'.\n-Try 'git bisect reset <commit>'.\")\"\n-\tfi\n-\tgit bisect--helper --bisect-clean-state || exit\n-}\n-\n bisect_replay () {\n \tfile=\"$1\"\n \ttest \"$#\" -eq 1 || die \"$(gettext \"No logfile given\")\"\n \ttest -r \"$file\" || die \"$(eval_gettext \"cannot read \\$file for replaying\")\"\n-\tbisect_reset\n+\tgit bisect--helper --bisect-reset || exit\n \twhile read git bisect command rev\n \tdo\n \t\ttest \"$git $bisect\" = \"git bisect\" || test \"$git\" = \"git-bisect\" || continue\n@@ -627,7 +603,7 @@ case \"$#\" in\n \tvisualize|view)\n \t\tbisect_visualize \"$@\" ;;\n \treset)\n-\t\tbisect_reset \"$@\" ;;\n+\t\tgit bisect--helper --bisect-reset \"$@\" ;;\n \treplay)\n \t\tbisect_replay \"$@\" ;;\n \tlog)\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299743","messageId":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"010201567675adc1-17e27495-6b36-40d1-836d-814da029fcc4-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 01/13] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:50:51Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"`--next-all` is meant to be used as a subcommand to support multiple\n\"operation mode\" though the current implementation does not contain any\nother subcommand along side with `--next-all` but further commits will\ninclude some more subcommands.\n\nHelped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 17 +++++++++++------\n 1 file changed, 11 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 3324229..8111c91 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -10,11 +10,11 @@ static const char * const git_bisect_helper_usage[] = {\n \n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n-\tint next_all = 0;\n+\tenum { NEXT_ALL = 1 } cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n-\t\tOPT_BOOL(0, \"next-all\", &next_all,\n-\t\t\t N_(\"perform 'git bisect next'\")),\n+\t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n+\t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -23,9 +23,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n \n-\tif (!next_all)\n+\tif (!cmdmode)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n-\t/* next-all */\n-\treturn bisect_next_all(prefix, no_checkout);\n+\tswitch (cmdmode) {\n+\tcase NEXT_ALL:\n+\t\treturn bisect_next_all(prefix, no_checkout);\n+\tdefault:\n+\t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n+\t}\n+\treturn 0;\n }\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299745","messageId":"01020156a48145c7-823bdd3d-88da-4e87-9170-9d95b48607dd-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 11/13] bisect--helper: `bisect_next_check` & bisect_voc shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:53:05Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_next_check` shell function in C and add\n`bisect-next-check` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nAlso reimplement `bisect_voc` shell function in C and call it from\n`bisect_next_check` implementation in C.\n\nUsing `--bisect-next-check` is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation will\nbe called by some other methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            |  60 ++-------------------------\n 2 files changed, 106 insertions(+), 57 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 450426c..ada3220d 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -6,6 +6,7 @@\n #include \"dir.h\"\n #include \"argv-array.h\"\n #include \"run-command.h\"\n+#include \"prompt.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -21,6 +22,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n+\tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n \tNULL\n };\n \n@@ -253,6 +255,95 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)\n \treturn 0;\n }\n \n+static int mark_good(const char *refname, const struct object_id *oid,\n+\t\t     int flag, void *cb_data)\n+{\n+\tint *m_good = (int *)cb_data;\n+\t*m_good = 0;\n+\treturn 1;\n+}\n+\n+static char *bisect_voc(char *revision_type)\n+{\n+\tif (!strcmp(revision_type, \"bad\"))\n+\t\treturn \"bad|new\";\n+\tif (!strcmp(revision_type, \"good\"))\n+\t\treturn \"good|old\";\n+\n+\treturn NULL;\n+}\n+\n+static int bisect_next_check(const struct bisect_terms *terms,\n+\t\t\t     const char *current_term)\n+{\n+\tint missing_good = 1, missing_bad = 1;\n+\tchar *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad.buf);\n+\tchar *good_glob = xstrfmt(\"%s-*\", terms->term_good.buf);\n+\tchar *bad_syn, *good_syn;\n+\n+\tif (ref_exists(bad_ref))\n+\t\tmissing_bad = 0;\n+\tfree(bad_ref);\n+\n+\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n+\t\t\t     (void *) &missing_good);\n+\tfree(good_glob);\n+\n+\tif (!missing_good && !missing_bad)\n+\t\treturn 0;\n+\n+\tif (!current_term)\n+\t\treturn -1;\n+\n+\tif (missing_good && !missing_bad && current_term &&\n+\t    !strcmp(current_term, terms->term_good.buf)) {\n+\t\tchar *yesno;\n+\t\t/*\n+\t\t * have bad (or new) but not good (or old). We could bisect\n+\t\t * although this is less optimum.\n+\t\t */\n+\t\tfprintf(stderr, N_(\"Warning: bisecting only with a %s commit\\n\"),\n+\t\t\tterms->term_bad.buf);\n+\t\tif (!isatty(0))\n+\t\t\treturn 0;\n+\t\t/*\n+\t\t * TRANSLATORS: Make sure to include [Y] and [n] in your\n+\t\t * translation. The program will only accept English input\n+\t\t * at this point.\n+\t\t */\n+\t\tyesno = git_prompt(_(\"Are you sure [Y/n]? \"), PROMPT_ECHO);\n+\t\tif (starts_with(yesno, \"N\") || starts_with(yesno, \"n\"))\n+\t\t\treturn -1;\n+\n+\t\treturn 0;\n+\t}\n+\tbad_syn = xstrdup(bisect_voc(\"bad\"));\n+\tgood_syn = xstrdup(bisect_voc(\"good\"));\n+\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\terror(_(\"You need to give me at least one %s and \"\n+\t\t\t\"%s revision. You can use \\\"git bisect %s\\\" \"\n+\t\t\t\"and \\\"git bisect %s\\\" for that. \\n\"),\n+\t\t\tbad_syn, good_syn, bad_syn, good_syn);\n+\t\tfree(bad_syn);\n+\t\tfree(good_syn);\n+\t\treturn -1;\n+\t}\n+\telse {\n+\t\terror(_(\"You need to start by \\\"git bisect start\\\". You \"\n+\t\t\t\"then need to give me at least one %s and %s \"\n+\t\t\t\"revision. You can use \\\"git bisect %s\\\" and \"\n+\t\t\t\"\\\"git bisect %s\\\" for that.\\n\"),\n+\t\t\tgood_syn, bad_syn, bad_syn, good_syn);\n+\t\tfree(bad_syn);\n+\t\tfree(good_syn);\n+\t\treturn -1;\n+\t}\n+\tfree(bad_syn);\n+\tfree(good_syn);\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -262,7 +353,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n-\t\tCHECK_AND_SET_TERMS\n+\t\tCHECK_AND_SET_TERMS,\n+\t\tBISECT_NEXT_CHECK\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -280,6 +372,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_CMDMODE(0, \"check-and-set-terms\", &cmdmode,\n \t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n+\t\tOPT_CMDMODE(0, \"bisect-next-check\", &cmdmode,\n+\t\t\t N_(\"check whether bad or good terms exist\"), BISECT_NEXT_CHECK),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -330,6 +424,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_addstr(&terms.term_bad, argv[2]);\n \t\tres = check_and_set_terms(&terms, argv[0]);\n \t\tbreak;\n+\tcase BISECT_NEXT_CHECK:\n+\t\tif (argc != 2 && argc != 3)\n+\t\t\tdie(_(\"--bisect-next-check requires 2 or 3 arguments\"));\n+\t\tstrbuf_addstr(&terms.term_good, argv[0]);\n+\t\tstrbuf_addstr(&terms.term_bad, argv[1]);\n+\t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex bdf2227..fe6c9d0 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -271,59 +271,14 @@ bisect_state() {\n \tbisect_auto_next\n }\n \n-bisect_next_check() {\n-\tmissing_good= missing_bad=\n-\tgit show-ref -q --verify refs/bisect/$TERM_BAD || missing_bad=t\n-\ttest -n \"$(git for-each-ref \"refs/bisect/$TERM_GOOD-*\")\" || missing_good=t\n-\n-\tcase \"$missing_good,$missing_bad,$1\" in\n-\t,,*)\n-\t\t: have both $TERM_GOOD and $TERM_BAD - ok\n-\t\t;;\n-\t*,)\n-\t\t# do not have both but not asked to fail - just report.\n-\t\tfalse\n-\t\t;;\n-\tt,,\"$TERM_GOOD\")\n-\t\t# have bad (or new) but not good (or old).  we could bisect although\n-\t\t# this is less optimum.\n-\t\teval_gettextln \"Warning: bisecting only with a \\$TERM_BAD commit.\" >&2\n-\t\tif test -t 0\n-\t\tthen\n-\t\t\t# TRANSLATORS: Make sure to include [Y] and [n] in your\n-\t\t\t# translation. The program will only accept English input\n-\t\t\t# at this point.\n-\t\t\tgettext \"Are you sure [Y/n]? \" >&2\n-\t\t\tread yesno\n-\t\t\tcase \"$yesno\" in [Nn]*) exit 1 ;; esac\n-\t\tfi\n-\t\t: bisect without $TERM_GOOD...\n-\t\t;;\n-\t*)\n-\t\tbad_syn=$(bisect_voc bad)\n-\t\tgood_syn=$(bisect_voc good)\n-\t\tif test -s \"$GIT_DIR/BISECT_START\"\n-\t\tthen\n-\n-\t\t\teval_gettextln \"You need to give me at least one \\$bad_syn and one \\$good_syn revision.\n-(You can use \\\"git bisect \\$bad_syn\\\" and \\\"git bisect \\$good_syn\\\" for that.)\" >&2\n-\t\telse\n-\t\t\teval_gettextln \"You need to start by \\\"git bisect start\\\".\n-You then need to give me at least one \\$good_syn and one \\$bad_syn revision.\n-(You can use \\\"git bisect \\$bad_syn\\\" and \\\"git bisect \\$good_syn\\\" for that.)\" >&2\n-\t\tfi\n-\t\texit 1 ;;\n-\tesac\n-}\n-\n bisect_auto_next() {\n-\tbisect_next_check && bisect_next || :\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD && bisect_next || :\n }\n \n bisect_next() {\n \tcase \"$#\" in 0) ;; *) usage ;; esac\n \tbisect_autostart\n-\tbisect_next_check $TERM_GOOD\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit\n \n \t# Perform all bisection computation, display and checkout\n \tgit bisect--helper --next-all $(test -f \"$GIT_DIR/BISECT_HEAD\" && echo --no-checkout)\n@@ -355,7 +310,7 @@ bisect_next() {\n }\n \n bisect_visualize() {\n-\tbisect_next_check fail\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit\n \n \tif test $# = 0\n \tthen\n@@ -409,7 +364,7 @@ bisect_replay () {\n }\n \n bisect_run () {\n-\tbisect_next_check fail\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit\n \n \twhile true\n \tdo\n@@ -482,13 +437,6 @@ get_terms () {\n \tfi\n }\n \n-bisect_voc () {\n-\tcase \"$1\" in\n-\tbad) echo \"bad|new\" ;;\n-\tgood) echo \"good|old\" ;;\n-\tesac\n-}\n-\n bisect_terms () {\n \tget_terms\n \tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299746","messageId":"01020156a48145cf-2a5f9f2d-d863-4f6d-8903-7d1b339b8fd3-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 12/13] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:53:24Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `get_terms` and `bisect_terms` shell function in C and\nadd `bisect-terms` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nUsing `--bisect-terms` subcommand is a temporary measure to port shell\nfunction in C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation will\nbe called by some other methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++--\n git-bisect.sh            | 35 ++--------------------------\n 2 files changed, 59 insertions(+), 35 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex ada3220d..e1cf956 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -23,6 +23,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n+\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n \tNULL\n };\n \n@@ -344,6 +345,52 @@ static int bisect_next_check(const struct bisect_terms *terms,\n \treturn 0;\n }\n \n+static int get_terms(struct bisect_terms *terms)\n+{\n+\tFILE *fp;\n+\tint res;\n+\tfp = fopen(git_path_bisect_terms(), \"r\");\n+\tif (!fp)\n+\t\treturn -1;\n+\n+\tbisect_terms_reset(terms);\n+\tres = strbuf_getline(&terms->term_bad, fp) == EOF ||\n+\t      strbuf_getline(&terms->term_good, fp) == EOF;\n+\n+\tfclose(fp);\n+\treturn res ? -1 : 0;\n+}\n+\n+static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n+{\n+\tint i;\n+\n+\tif (get_terms(terms)) {\n+\t\tfprintf(stderr, N_(\"no terms defined\\n\"));\n+\t\treturn -1;\n+\t}\n+\tif (argc == 0) {\n+\t\tprintf(N_(\"Your current terms are %s for the old state\\nand \"\n+\t\t       \"%s for the new state.\\n\"), terms->term_good.buf,\n+\t\t       terms->term_bad.buf);\n+\t\treturn 0;\n+\t}\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tif (!strcmp(argv[i], \"--term-good\"))\n+\t\t\tprintf(N_(\"%s\\n\"), terms->term_good.buf);\n+\t\telse if (!strcmp(argv[i], \"--term-bad\"))\n+\t\t\tprintf(N_(\"%s\\n\"), terms->term_bad.buf);\n+\t\telse\n+\t\t\tprintf(N_(\"invalid argument %s for 'git bisect \"\n+\t\t\t\t  \"terms'.\\nSupported options are: \"\n+\t\t\t\t  \"--term-good|--term-old and \"\n+\t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n+\t}\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -354,7 +401,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n-\t\tBISECT_NEXT_CHECK\n+\t\tBISECT_NEXT_CHECK,\n+\t\tBISECT_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -374,6 +422,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-next-check\", &cmdmode,\n \t\t\t N_(\"check whether bad or good terms exist\"), BISECT_NEXT_CHECK),\n+\t\tOPT_CMDMODE(0, \"bisect-terms\", &cmdmode,\n+\t\t\t N_(\"print out the bisect terms\"), BISECT_TERMS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -382,7 +432,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tbisect_terms_init(&terms);\n \n \targc = parse_options(argc, argv, prefix, options,\n-\t\t\t     git_bisect_helper_usage, 0);\n+\t\t\t     git_bisect_helper_usage, PARSE_OPT_KEEP_UNKNOWN);\n \n \tif (!cmdmode)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n@@ -431,6 +481,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_addstr(&terms.term_bad, argv[1]);\n \t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n \t\tbreak;\n+\tcase BISECT_TERMS:\n+\t\tif (argc > 1)\n+\t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n+\t\tres = bisect_terms(&terms, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex fe6c9d0..d6c8b5a 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -355,7 +355,7 @@ bisect_replay () {\n \t\t\"$TERM_GOOD\"|\"$TERM_BAD\"|skip)\n \t\t\tgit bisect--helper --bisect-write \"$command\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit;;\n \t\tterms)\n-\t\t\tbisect_terms $rev ;;\n+\t\t\tgit bisect--helper --bisect-terms $rev  || exit;;\n \t\t*)\n \t\t\tdie \"$(gettext \"?? what are you talking about?\")\" ;;\n \t\tesac\n@@ -437,37 +437,6 @@ get_terms () {\n \tfi\n }\n \n-bisect_terms () {\n-\tget_terms\n-\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\tthen\n-\t\tdie \"$(gettext \"no terms defined\")\"\n-\tfi\n-\tcase \"$#\" in\n-\t0)\n-\t\tgettextln \"Your current terms are $TERM_GOOD for the old state\n-and $TERM_BAD for the new state.\"\n-\t\t;;\n-\t1)\n-\t\targ=$1\n-\t\tcase \"$arg\" in\n-\t\t\t--term-good|--term-old)\n-\t\t\t\tprintf '%s\\n' \"$TERM_GOOD\"\n-\t\t\t\t;;\n-\t\t\t--term-bad|--term-new)\n-\t\t\t\tprintf '%s\\n' \"$TERM_BAD\"\n-\t\t\t\t;;\n-\t\t\t*)\n-\t\t\t\tdie \"$(eval_gettext \"invalid argument \\$arg for 'git bisect terms'.\n-Supported options are: --term-good|--term-old and --term-bad|--term-new.\")\"\n-\t\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t*)\n-\t\tusage ;;\n-\tesac\n-}\n-\n case \"$#\" in\n 0)\n \tusage ;;\n@@ -498,7 +467,7 @@ case \"$#\" in\n \trun)\n \t\tbisect_run \"$@\" ;;\n \tterms)\n-\t\tbisect_terms \"$@\" ;;\n+\t\tgit bisect--helper --bisect-terms \"$@\" || exit;;\n \t*)\n \t\tusage ;;\n \tesac\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299747","messageId":"01020156a48145b7-f7c8dc41-d388-4f3b-914a-1b2896e96671-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 09/13] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:53:49Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_write` shell function in C and add a\n`bisect-write` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh\n\nUsing `--bisect-write` subcommand is a temporary measure to port shell\nfunction in C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation will\nbe called by some other methods.\n\nNote: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\nfrom the global shell script thus we need to pass it to the subcommand\nusing the arguments. We then store them in a struct bisect_terms and\npass the memory address around functions.\n\nThis patch also introduces new methods namely bisect_state_init() and\nbisect_terms_release() for easy memory management for the struct\nbisect_terms.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++----\n git-bisect.sh            | 25 ++-----------\n 2 files changed, 94 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 711be75..5364960 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -19,9 +19,27 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n+\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tstruct strbuf term_good;\n+\tstruct strbuf term_bad;\n+};\n+\n+static void bisect_terms_init(struct bisect_terms *terms)\n+{\n+\tstrbuf_init(&terms->term_good, 0);\n+\tstrbuf_init(&terms->term_bad, 0);\n+}\n+\n+static void bisect_terms_release(struct bisect_terms *terms)\n+{\n+\tstrbuf_release(&terms->term_good);\n+\tstrbuf_release(&terms->term_bad);\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -149,6 +167,52 @@ static int check_expected_revs(const char **revs, int rev_nr)\n \treturn 0;\n }\n \n+static int bisect_write(const char *state, const char *rev,\n+\t\t\tconst struct bisect_terms *terms, int nolog)\n+{\n+\tstruct strbuf tag = STRBUF_INIT;\n+\tstruct strbuf commit_name = STRBUF_INIT;\n+\tstruct object_id oid;\n+\tstruct commit *commit;\n+\tstruct pretty_print_context pp = {0};\n+\tFILE *fp;\n+\n+\tif (!strcmp(state, terms->term_bad.buf))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\telse if (one_of(state, terms->term_good.buf, \"skip\", NULL))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\telse\n+\t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_release(&tag);\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp)\n+\t\treturn error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\n+\tcommit = lookup_commit_reference(oid.hash);\n+\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n+\t\tcommit_name.buf);\n+\tstrbuf_release(&commit_name);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+\tfclose(fp);\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -156,9 +220,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n \t\tBISECT_RESET,\n-\t\tCHECK_EXPECTED_REVS\n+\t\tCHECK_EXPECTED_REVS,\n+\t\tBISECT_WRITE\n \t} cmdmode = 0;\n-\tint no_checkout = 0;\n+\tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n@@ -170,10 +235,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n+\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n+\t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n \t};\n+\tstruct bisect_terms terms;\n+\tbisect_terms_init(&terms);\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -182,24 +251,38 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n \tswitch (cmdmode) {\n+\tint nolog;\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n-\t\treturn write_terms(argv[0], argv[1]);\n+\t\tres = write_terms(argv[0], argv[1]);\n+\t\tbreak;\n \tcase BISECT_CLEAN_STATE:\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n-\t\treturn bisect_clean_state();\n+\t\tres = bisect_clean_state();\n+\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n-\t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\t\tres = bisect_reset(argc ? argv[0] : NULL);\n+\t\tbreak;\n \tcase CHECK_EXPECTED_REVS:\n-\t\treturn check_expected_revs(argv, argc);\n+\t\tres = check_expected_revs(argv, argc);\n+\t\tbreak;\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n+\t\tstrbuf_addstr(&terms.term_good, argv[2]);\n+\t\tstrbuf_addstr(&terms.term_bad, argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tbisect_terms_release(&terms);\n+\treturn res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex c3e43248..dfdec33 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -144,7 +144,7 @@ bisect_start() {\n \t\t0) state=$TERM_BAD ; bad_seen=1 ;;\n \t\t*) state=$TERM_GOOD ;;\n \t\tesac\n-\t\teval=\"$eval bisect_write '$state' '$rev' 'nolog' &&\"\n+\t\teval=\"$eval git bisect--helper --bisect-write '$state' '$rev' '$TERM_GOOD' '$TERM_BAD' 'nolog' &&\"\n \tdone\n \t#\n \t# Verify HEAD.\n@@ -220,23 +220,6 @@ bisect_start() {\n \ttrap '-' 0\n }\n \n-bisect_write() {\n-\tstate=\"$1\"\n-\trev=\"$2\"\n-\tnolog=\"$3\"\n-\tcase \"$state\" in\n-\t\t\"$TERM_BAD\")\n-\t\t\ttag=\"$state\" ;;\n-\t\t\"$TERM_GOOD\"|skip)\n-\t\t\ttag=\"$state\"-\"$rev\" ;;\n-\t\t*)\n-\t\t\tdie \"$(eval_gettext \"Bad bisect_write argument: \\$state\")\" ;;\n-\tesac\n-\tgit update-ref \"refs/bisect/$tag\" \"$rev\" || exit\n-\techo \"# $state: $(git show-branch $rev)\" >>\"$GIT_DIR/BISECT_LOG\"\n-\ttest -n \"$nolog\" || echo \"git bisect $state $rev\" >>\"$GIT_DIR/BISECT_LOG\"\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -263,7 +246,7 @@ bisect_state() {\n \t\tbisected_head=$(bisect_head)\n \t\trev=$(git rev-parse --verify \"$bisected_head\") ||\n \t\t\tdie \"$(eval_gettext \"Bad rev input: \\$bisected_head\")\"\n-\t\tbisect_write \"$state\" \"$rev\"\n+\t\tgit bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n \t\tgit bisect--helper --check-expected-revs \"$rev\" ;;\n \t2,\"$TERM_BAD\"|*,\"$TERM_GOOD\"|*,skip)\n \t\tshift\n@@ -276,7 +259,7 @@ bisect_state() {\n \t\tdone\n \t\tfor rev in $hash_list\n \t\tdo\n-\t\t\tbisect_write \"$state\" \"$rev\"\n+\t\t\tgit bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n \t\tdone\n \t\tgit bisect--helper --check-expected-revs $hash_list ;;\n \t*,\"$TERM_BAD\")\n@@ -413,7 +396,7 @@ bisect_replay () {\n \t\t\tcmd=\"bisect_start $rev\"\n \t\t\teval \"$cmd\" ;;\n \t\t\"$TERM_GOOD\"|\"$TERM_BAD\"|skip)\n-\t\t\tbisect_write \"$command\" \"$rev\" ;;\n+\t\t\tgit bisect--helper --bisect-write \"$command\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit;;\n \t\tterms)\n \t\t\tbisect_terms $rev ;;\n \t\t*)\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299748","messageId":"01020156a48145b7-a23cda02-9f19-4948-ae45-3ed899906044-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 08/13] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T20:53:57Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `is_expected_rev` & `check_expected_revs` shell function in\nC and add a `--check-expected-revs` subcommand to `git bisect--helper` to\ncall it from git-bisect.sh .\n\nUsing `--check-expected-revs` subcommand is a temporary measure to port\nshell functions to C so as to use the existing test suite. As more\nfunctions are ported, this subcommand would be retired but its\nimplementation will be called by some other method.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 33 ++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 20 ++------------------\n 2 files changed, 34 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 9aba094..711be75 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static int is_expected_rev(const char *expected_hex)\n+{\n+\tstruct strbuf actual_hex = STRBUF_INIT;\n+\tint res = 0;\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 0) {\n+\t\tstrbuf_trim(&actual_hex);\n+\t\tres = !strcmp(actual_hex.buf, expected_hex);\n+\t}\n+\tstrbuf_release(&actual_hex);\n+\treturn res;\n+}\n+\n+static int check_expected_revs(const char **revs, int rev_nr)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < rev_nr; i++) {\n+\t\tif (!is_expected_rev(revs[i])) {\n+\t\t\tunlink_or_warn(git_path_bisect_ancestors_ok());\n+\t\t\tunlink_or_warn(git_path_bisect_expected_rev());\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n-\t\tBISECT_RESET\n+\t\tBISECT_RESET,\n+\t\tCHECK_EXPECTED_REVS\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -141,6 +168,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n+\t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n+\t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -167,6 +196,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n \t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\tcase CHECK_EXPECTED_REVS:\n+\t\treturn check_expected_revs(argv, argc);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 442397b..c3e43248 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -237,22 +237,6 @@ bisect_write() {\n \ttest -n \"$nolog\" || echo \"git bisect $state $rev\" >>\"$GIT_DIR/BISECT_LOG\"\n }\n \n-is_expected_rev() {\n-\ttest -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n-\ttest \"$1\" = $(cat \"$GIT_DIR/BISECT_EXPECTED_REV\")\n-}\n-\n-check_expected_revs() {\n-\tfor _rev in \"$@\"; do\n-\t\tif ! is_expected_rev \"$_rev\"\n-\t\tthen\n-\t\t\trm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\"\n-\t\t\trm -f \"$GIT_DIR/BISECT_EXPECTED_REV\"\n-\t\t\treturn\n-\t\tfi\n-\tdone\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -280,7 +264,7 @@ bisect_state() {\n \t\trev=$(git rev-parse --verify \"$bisected_head\") ||\n \t\t\tdie \"$(eval_gettext \"Bad rev input: \\$bisected_head\")\"\n \t\tbisect_write \"$state\" \"$rev\"\n-\t\tcheck_expected_revs \"$rev\" ;;\n+\t\tgit bisect--helper --check-expected-revs \"$rev\" ;;\n \t2,\"$TERM_BAD\"|*,\"$TERM_GOOD\"|*,skip)\n \t\tshift\n \t\thash_list=''\n@@ -294,7 +278,7 @@ bisect_state() {\n \t\tdo\n \t\t\tbisect_write \"$state\" \"$rev\"\n \t\tdone\n-\t\tcheck_expected_revs $hash_list ;;\n+\t\tgit bisect--helper --check-expected-revs $hash_list ;;\n \t*,\"$TERM_BAD\")\n \t\tdie \"$(eval_gettext \"'git bisect \\$TERM_BAD' can take only one argument.\")\" ;;\n \t*)\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299753","messageId":"01020156a4814596-b3b6ff6c-ab4a-492e-baa0-801dadf09a4e-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 03/13] bisect--helper: `write_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T21:07:47Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `write_terms` shell function in C and add a `write-terms`\nsubcommand to `git bisect--helper` to call it from git-bisect.sh . Also\nremove the subcommand `--check-term-format` as it can now be called from\ninside the function write_terms() C implementation.\n\nAlso `|| exit` is added when calling write-terms subcommand from\ngit-bisect.sh so as to exit whenever there is an error.\n\nUsing `--write-terms` subcommand is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and its implementation will\nbe called by some other method.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 36 +++++++++++++++++++++++++++++-------\n git-bisect.sh            | 22 +++++++---------------\n 2 files changed, 36 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex a47f1f2..30e1031 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,9 +4,11 @@\n #include \"bisect.h\"\n #include \"refs.h\"\n \n+static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+\n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n-\tN_(\"git bisect--helper --check-term-format <term> <orig_term>\"),\n+\tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tNULL\n };\n \n@@ -57,18 +59,38 @@ static int check_term_format(const char *term, const char *orig_term)\n \treturn 0;\n }\n \n+static int write_terms(const char *bad, const char *good)\n+{\n+\tFILE *fp;\n+\tint res;\n+\n+\tif (!strcmp(bad, good))\n+\t\treturn error(_(\"please use two different terms\"));\n+\n+\tif (check_term_format(bad, \"bad\") || check_term_format(good, \"good\"))\n+\t\treturn -1;\n+\n+\tfp = fopen(git_path_bisect_terms(), \"w\");\n+\tif (!fp)\n+\t\treturn error_errno(_(\"could not open the file BISECT_TERMS\"));\n+\n+\tres = fprintf(fp, \"%s\\n%s\\n\", bad, good);\n+\tres |= fclose(fp);\n+\treturn (res < 0) ? -1 : 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n-\t\tCHECK_TERM_FMT\n+\t\tWRITE_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n-\t\tOPT_CMDMODE(0, \"check-term-format\", &cmdmode,\n-\t\t\t N_(\"check format of the term\"), CHECK_TERM_FMT),\n+\t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n+\t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -83,10 +105,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tswitch (cmdmode) {\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n-\tcase CHECK_TERM_FMT:\n+\tcase WRITE_TERMS:\n \t\tif (argc != 2)\n-\t\t\tdie(_(\"--check-term-format requires two arguments\"));\n-\t\treturn check_term_format(argv[0], argv[1]);\n+\t\t\tdie(_(\"--write-terms requires two arguments\"));\n+\t\treturn write_terms(argv[0], argv[1]);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex a727c59..9ef6cb8 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -209,7 +209,7 @@ bisect_start() {\n \teval \"$eval true\" &&\n \tif test $must_write_terms -eq 1\n \tthen\n-\t\twrite_terms \"$TERM_BAD\" \"$TERM_GOOD\"\n+\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\"\n \tfi &&\n \techo \"git bisect start$orig_args\" >>\"$GIT_DIR/BISECT_LOG\" || exit\n \t#\n@@ -557,18 +557,6 @@ get_terms () {\n \tfi\n }\n \n-write_terms () {\n-\tTERM_BAD=$1\n-\tTERM_GOOD=$2\n-\tif test \"$TERM_BAD\" = \"$TERM_GOOD\"\n-\tthen\n-\t\tdie \"$(gettext \"please use two different terms\")\"\n-\tfi\n-\tgit bisect--helper --check-term-format \"$TERM_BAD\" bad || exit\n-\tgit bisect--helper --check-term-format \"$TERM_GOOD\" good || exit\n-\tprintf '%s\\n%s\\n' \"$TERM_BAD\" \"$TERM_GOOD\" >\"$GIT_DIR/BISECT_TERMS\"\n-}\n-\n check_and_set_terms () {\n \tcmd=\"$1\"\n \tcase \"$cmd\" in\n@@ -582,13 +570,17 @@ check_and_set_terms () {\n \t\tbad|good)\n \t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n \t\t\tthen\n-\t\t\t\twrite_terms bad good\n+\t\t\t\tTERM_BAD=bad\n+\t\t\t\tTERM_GOOD=good\n+\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n \t\t\tfi\n \t\t\t;;\n \t\tnew|old)\n \t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n \t\t\tthen\n-\t\t\t\twrite_terms new old\n+\t\t\t\tTERM_BAD=new\n+\t\t\t\tTERM_GOOD=old\n+\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n \t\t\tfi\n \t\t\t;;\n \t\tesac ;;\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299755","messageId":"01020156a48145b0-4867422a-b4a1-4587-8bc3-02c854330178-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 06/13] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T21:13:36Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"is_empty_file() can help to refactor a lot of code. This will be very\nhelpful in porting \"git bisect\" to C.\n\nSuggested-by: Torsten Bögershausen <tboegi@web.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/am.c | 20 ++------------------\n cache.h      |  3 +++\n wrapper.c    | 13 +++++++++++++\n 3 files changed, 18 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 739b34d..9e1e9d6 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -30,22 +30,6 @@\n #include \"mailinfo.h\"\n \n /**\n- * Returns 1 if the file is empty or does not exist, 0 otherwise.\n- */\n-static int is_empty_file(const char *filename)\n-{\n-\tstruct stat st;\n-\n-\tif (stat(filename, &st) < 0) {\n-\t\tif (errno == ENOENT)\n-\t\t\treturn 1;\n-\t\tdie_errno(_(\"could not stat %s\"), filename);\n-\t}\n-\n-\treturn !st.st_size;\n-}\n-\n-/**\n  * Returns the length of the first line of msg.\n  */\n static int linelen(const char *msg)\n@@ -1324,7 +1308,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \t\tgoto finish;\n \t}\n \n-\tif (is_empty_file(am_path(state, \"patch\"))) {\n+\tif (is_empty_or_missing_file(am_path(state, \"patch\"))) {\n \t\tprintf_ln(_(\"Patch is empty. Was it split wrong?\"));\n \t\tdie_user_resolve(state);\n \t}\n@@ -1896,7 +1880,7 @@ static void am_run(struct am_state *state, int resume)\n \t\tresume = 0;\n \t}\n \n-\tif (!is_empty_file(am_path(state, \"rewritten\"))) {\n+\tif (!is_empty_or_missing_file(am_path(state, \"rewritten\"))) {\n \t\tassert(state->rebasing);\n \t\tcopy_notes_for_rebase(state);\n \t\trun_post_rewrite_hook(state);\ndiff --git a/cache.h b/cache.h\nindex b780a91..49f214b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1916,4 +1916,7 @@ void sleep_millisec(int millisec);\n  */\n void safe_create_dir(const char *dir, int share);\n \n+/* Return 1 if the file is empty or does not exists, 0 otherwise. */\n+extern int is_empty_or_missing_file(const char *filename);\n+\n #endif /* CACHE_H */\ndiff --git a/wrapper.c b/wrapper.c\nindex e7f1979..78f6431 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -679,3 +679,16 @@ void sleep_millisec(int millisec)\n {\n \tpoll(NULL, 0, millisec);\n }\n+\n+int is_empty_or_missing_file(const char *filename)\n+{\n+\tstruct stat st;\n+\n+\tif (stat(filename, &st) < 0) {\n+\t\tif (errno == ENOENT)\n+\t\t\treturn 1;\n+\t\tdie_errno(_(\"could not stat %s\"), filename);\n+\t}\n+\n+\treturn !st.st_size;\n+}\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299757","messageId":"01020156a48145a8-d2a03d0a-e6e8-42ae-9960-2effc5547b7c-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 04/13] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T21:18:17Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_clean_state` shell function in C and add a\n`bisect-clean-state` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nUsing `--bisect-clean-state` subcommand is a measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation  will\nbe called by bisect_reset() and bisect_start().\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n bisect.c                 | 43 +++++++++++++++++++++++++++++++++++++++++++\n bisect.h                 |  2 ++\n builtin/bisect--helper.c | 14 +++++++++++++-\n git-bisect.sh            | 26 +++-----------------------\n 4 files changed, 61 insertions(+), 24 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 6f512c2..45d598d 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -430,6 +430,12 @@ static int read_bisect_refs(void)\n \n static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n+static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n+static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\n \n static void read_bisect_paths(struct argv_array *array)\n {\n@@ -1040,3 +1046,40 @@ int estimate_bisect_steps(int all)\n \n \treturn (e < 3 * x) ? n : n - 1;\n }\n+\n+static int mark_for_removal(const char *refname, const struct object_id *oid,\n+\t\t\t    int flag, void *cb_data)\n+{\n+\tstruct string_list *refs = cb_data;\n+\tchar *ref = xstrfmt(\"refs/bisect%s\", refname);\n+\tstring_list_append(refs, ref);\n+\treturn 0;\n+}\n+\n+int bisect_clean_state(void)\n+{\n+\tint result = 0;\n+\n+\t/* There may be some refs packed during bisection */\n+\tstruct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n+\tfor_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n+\tstring_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n+\tresult = delete_refs(&refs_for_removal, REF_NODEREF);\n+\trefs_for_removal.strdup_strings = 1;\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tunlink_or_warn(git_path_bisect_expected_rev());\n+\tunlink_or_warn(git_path_bisect_ancestors_ok());\n+\tunlink_or_warn(git_path_bisect_log());\n+\tunlink_or_warn(git_path_bisect_names());\n+\tunlink_or_warn(git_path_bisect_run());\n+\tunlink_or_warn(git_path_bisect_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tunlink_or_warn(git_path_head_name());\n+\t/*\n+\t * Cleanup BISECT_START last to support the --no-checkout option\n+\t * introduced in the commit 4796e823a.\n+\t */\n+\tunlink_or_warn(git_path_bisect_start());\n+\n+\treturn result;\n+}\ndiff --git a/bisect.h b/bisect.h\nindex acd12ef..0ae63d4 100644\n--- a/bisect.h\n+++ b/bisect.h\n@@ -28,4 +28,6 @@ extern int estimate_bisect_steps(int all);\n \n extern void read_bisect_terms(const char **bad, const char **good);\n \n+extern int bisect_clean_state(void);\n+\n #endif\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 30e1031..e50934c 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -5,10 +5,15 @@\n #include \"refs.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n+static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n+static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n+\tN_(\"git bisect--helper --bisect-clean-state\"),\n \tNULL\n };\n \n@@ -83,7 +88,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n-\t\tWRITE_TERMS\n+\t\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -91,6 +97,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n \t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n+\t\tOPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n+\t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -109,6 +117,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n \t\treturn write_terms(argv[0], argv[1]);\n+\tcase BISECT_CLEAN_STATE:\n+\t\tif (argc != 0)\n+\t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n+\t\treturn bisect_clean_state();\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 9ef6cb8..f1202df 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -186,7 +186,7 @@ bisect_start() {\n \t#\n \t# Get rid of any old bisect state.\n \t#\n-\tbisect_clean_state || exit\n+\tgit bisect--helper --bisect-clean-state || exit\n \n \t#\n \t# Change state.\n@@ -195,7 +195,7 @@ bisect_start() {\n \t# We have to trap this to be able to clean up using\n \t# \"bisect_clean_state\".\n \t#\n-\ttrap 'bisect_clean_state' 0\n+\ttrap 'git bisect--helper --bisect-clean-state' 0\n \ttrap 'exit 255' 1 2 3 15\n \n \t#\n@@ -430,27 +430,7 @@ bisect_reset() {\n \t\tdie \"$(eval_gettext \"Could not check out original HEAD '\\$branch'.\n Try 'git bisect reset <commit>'.\")\"\n \tfi\n-\tbisect_clean_state\n-}\n-\n-bisect_clean_state() {\n-\t# There may be some refs packed during bisection.\n-\tgit for-each-ref --format='%(refname) %(objectname)' refs/bisect/\\* |\n-\twhile read ref hash\n-\tdo\n-\t\tgit update-ref -d $ref $hash || exit\n-\tdone\n-\trm -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n-\trm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n-\trm -f \"$GIT_DIR/BISECT_LOG\" &&\n-\trm -f \"$GIT_DIR/BISECT_NAMES\" &&\n-\trm -f \"$GIT_DIR/BISECT_RUN\" &&\n-\trm -f \"$GIT_DIR/BISECT_TERMS\" &&\n-\t# Cleanup head-name if it got left by an old version of git-bisect\n-\trm -f \"$GIT_DIR/head-name\" &&\n-\tgit update-ref -d --no-deref BISECT_HEAD &&\n-\t# clean up BISECT_START last\n-\trm -f \"$GIT_DIR/BISECT_START\"\n+\tgit bisect--helper --bisect-clean-state || exit\n }\n \n bisect_replay () {\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299760","messageId":"01020156a48145c3-24771223-aca5-4838-b60f-a73a31d0eaf7-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 10/13] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T21:30:02Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `check_and_set_terms` shell function in C and add\n`check-and-set-terms` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh\n\nUsing `--check-and-set-terms` subcommand is a temporary measure to port\nshell function in C so as to use the existing test suite. As more\nfunctions are ported, this subcommand will be retired but its\nimplementation will be called by some other methods.\n\ncheck_and_set_terms() sets and receives two global variables namely\nTERM_GOOD and TERM_BAD in the shell script. Luckily the file BISECT_TERMS\nalso contains the value of those variables so its appropriate to evoke the\nmethod get_terms() after calling the subcommand so that it retrieves the\nvalue of TERM_GOOD and TERM_BAD from the file BISECT_TERMS. The two\nglobal variables are passed as arguments to the subcommand.\n\nAlso introduce bisect_terms_reset() to empty the contents of `term_good`\nand `term_bad` of `struct bisect_terms`.\n\nAlso introduce set_terms() to copy the `term_good` and `term_bad` into\n`struct bisect_terms` and write it out to the file BISECT_TERMS.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 36 ++++-----------------------------\n 2 files changed, 55 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 5364960..450426c 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -20,6 +20,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n+\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tNULL\n };\n \n@@ -40,6 +41,12 @@ static void bisect_terms_release(struct bisect_terms *terms)\n \tstrbuf_release(&terms->term_bad);\n }\n \n+static void bisect_terms_reset(struct bisect_terms *term)\n+{\n+\tstrbuf_reset(&term->term_good);\n+\tstrbuf_reset(&term->term_bad);\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -213,6 +220,39 @@ static int bisect_write(const char *state, const char *rev,\n \treturn 0;\n }\n \n+static int set_terms(struct bisect_terms *terms, const char *bad,\n+\t\t     const char *good)\n+{\n+\tbisect_terms_reset(terms);\n+\tstrbuf_addstr(&terms->term_good, good);\n+\tstrbuf_addstr(&terms->term_bad, bad);\n+\treturn write_terms(terms->term_bad.buf, terms->term_good.buf);\n+}\n+\n+static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)\n+{\n+\tint has_term_file = !is_empty_or_missing_file(git_path_bisect_terms());\n+\n+\tif (one_of(cmd, \"skip\", \"start\", \"terms\", NULL))\n+\t\treturn 0;\n+\n+\tif (has_term_file &&\n+\t    strcmp(cmd, terms->term_bad.buf) &&\n+\t    strcmp(cmd, terms->term_good.buf))\n+\t\treturn error(_(\"Invalid command: you're currently in a \"\n+\t\t\t\t\"%s/%s bisect\"), terms->term_bad.buf,\n+\t\t\t\tterms->term_good.buf);\n+\n+\tif (!has_term_file) {\n+\t\tif (one_of(cmd, \"bad\", \"good\", NULL))\n+\t\t\treturn set_terms(terms, \"bad\", \"good\");\n+\t\tif (one_of(cmd, \"new\", \"old\", NULL))\n+\t\t\treturn set_terms(terms, \"new\", \"old\");\n+\t}\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -221,7 +261,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_CLEAN_STATE,\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n-\t\tBISECT_WRITE\n+\t\tBISECT_WRITE,\n+\t\tCHECK_AND_SET_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -237,6 +278,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n \t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n \t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n+\t\tOPT_CMDMODE(0, \"check-and-set-terms\", &cmdmode,\n+\t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -280,6 +323,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_addstr(&terms.term_bad, argv[3]);\n \t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n \t\tbreak;\n+\tcase CHECK_AND_SET_TERMS:\n+\t\tif (argc != 3)\n+\t\t\tdie(_(\"--check-and-set-terms requires 3 arguments\"));\n+\t\tstrbuf_addstr(&terms.term_good, argv[1]);\n+\t\tstrbuf_addstr(&terms.term_bad, argv[2]);\n+\t\tres = check_and_set_terms(&terms, argv[0]);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex dfdec33..bdf2227 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -238,7 +238,8 @@ bisect_skip() {\n bisect_state() {\n \tbisect_autostart\n \tstate=$1\n-\tcheck_and_set_terms $state\n+\tgit bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n+\tget_terms\n \tcase \"$#,$state\" in\n \t0,*)\n \t\tdie \"Please call 'bisect_state' with at least one argument.\" ;;\n@@ -390,7 +391,8 @@ bisect_replay () {\n \t\t\tcommand=\"$bisect\"\n \t\tfi\n \t\tget_terms\n-\t\tcheck_and_set_terms \"$command\"\n+\t\tgit bisect--helper --check-and-set-terms \"$command\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n+\t\tget_terms\n \t\tcase \"$command\" in\n \t\tstart)\n \t\t\tcmd=\"bisect_start $rev\"\n@@ -480,36 +482,6 @@ get_terms () {\n \tfi\n }\n \n-check_and_set_terms () {\n-\tcmd=\"$1\"\n-\tcase \"$cmd\" in\n-\tskip|start|terms) ;;\n-\t*)\n-\t\tif test -s \"$GIT_DIR/BISECT_TERMS\" && test \"$cmd\" != \"$TERM_BAD\" && test \"$cmd\" != \"$TERM_GOOD\"\n-\t\tthen\n-\t\t\tdie \"$(eval_gettext \"Invalid command: you're currently in a \\$TERM_BAD/\\$TERM_GOOD bisect.\")\"\n-\t\tfi\n-\t\tcase \"$cmd\" in\n-\t\tbad|good)\n-\t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\t\t\tthen\n-\t\t\t\tTERM_BAD=bad\n-\t\t\t\tTERM_GOOD=good\n-\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n-\t\t\tfi\n-\t\t\t;;\n-\t\tnew|old)\n-\t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\t\t\tthen\n-\t\t\t\tTERM_BAD=new\n-\t\t\t\tTERM_GOOD=old\n-\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n-\t\t\tfi\n-\t\t\t;;\n-\t\tesac ;;\n-\tesac\n-}\n-\n bisect_voc () {\n \tcase \"$1\" in\n \tbad) echo \"bad|new\" ;;\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299766","messageId":"01020156a48145ab-f043dbb4-874b-4fe6-9176-b6aeae5bb3d7-000000@eu-west-1.amazonses.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"[PATCH v13 05/13] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-19T20:32:30Z","receivedAt":"2016-08-19T22:04:20Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Add test to explicitly check that 'git bisect reset' is working as\nexpected. This is already covered implicitly by the test suite.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n\n---\nI faced this problem while converting `bisect_clean_state` and the tests\nwhere showing breakages but it wasn't clear as to where exactly are they\nbreaking. This will patch  will help in that. Also I tested the test\ncoverage of the test suite before this patch and it covers this (I did\nthis by purposely changing names of files in git-bisect.sh and running\nthe test suite).\n---\n t/t6030-bisect-porcelain.sh | 17 +++++++++++++++++\n 1 file changed, 17 insertions(+)\n\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex 5e5370f..18e7998 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'git bisect reset cleans bisection state properly' '\n+\tgit bisect reset &&\n+\tgit bisect start &&\n+\tgit bisect good $HASH1 &&\n+\tgit bisect bad $HASH4 &&\n+\tgit bisect reset &&\n+\ttest -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_LOG\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_RUN\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_TERMS\" &&\n+\ttest_path_is_missing \"$GIT_DIR/head-name\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_HEAD\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_START\"\n+'\n+\n test_done\n\n--\nhttps://github.com/git/git/pull/281\n"},{"id":"299812","messageId":"CAFZEwPPmCyUC+mdHjYkgxhBvTwgTwyKz67T6YYJCEaBpmXyycw@mail.gmail.com","threadId":"43886","inReplyTo":"01020156a48144f8-c0e127c1-8cd9-4295-ac16-449a54315cac-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v13 01/13] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-21T11:14:38Z","receivedAt":"2016-08-21T11:14:45Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey everyone,\n\nOn Sat, Aug 20, 2016 at 2:02 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> `--next-all` is meant to be used as a subcommand to support multiple\n> \"operation mode\" though the current implementation does not contain any\n> other subcommand along side with `--next-all` but further commits will\n> include some more subcommands.\n>\n> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n> Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n> Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n>  builtin/bisect--helper.c | 17 +++++++++++------\n>  1 file changed, 11 insertions(+), 6 deletions(-)\n>\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 3324229..8111c91 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -10,11 +10,11 @@ static const char * const git_bisect_helper_usage[] = {\n>\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n> -       int next_all = 0;\n> +       enum { NEXT_ALL = 1 } cmdmode = 0;\n>         int no_checkout = 0;\n>         struct option options[] = {\n> -               OPT_BOOL(0, \"next-all\", &next_all,\n> -                        N_(\"perform 'git bisect next'\")),\n> +               OPT_CMDMODE(0, \"next-all\", &cmdmode,\n> +                        N_(\"perform 'git bisect next'\"), NEXT_ALL),\n>                 OPT_BOOL(0, \"no-checkout\", &no_checkout,\n>                          N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n>                 OPT_END()\n> @@ -23,9 +23,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>         argc = parse_options(argc, argv, prefix, options,\n>                              git_bisect_helper_usage, 0);\n>\n> -       if (!next_all)\n> +       if (!cmdmode)\n>                 usage_with_options(git_bisect_helper_usage, options);\n>\n> -       /* next-all */\n> -       return bisect_next_all(prefix, no_checkout);\n> +       switch (cmdmode) {\n> +       case NEXT_ALL:\n> +               return bisect_next_all(prefix, no_checkout);\n> +       default:\n> +               die(\"BUG: unknown subcommand '%d'\", cmdmode);\n> +       }\n> +       return 0;\n>  }\n\n\nThis is the same series (except for patch 04/13) and rebased on v2.10-rc0.\n\nRegards,\nPranit Bauva\n"},{"id":"299813","messageId":"CAFZEwPOLuOBdA5rD0oqwApZm=MfSpBX+cQFZhGkAASbM-_PVSg@mail.gmail.com","threadId":"43886","inReplyTo":"01020156a48145a8-d2a03d0a-e6e8-42ae-9960-2effc5547b7c-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v13 04/13] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-08-21T11:18:07Z","receivedAt":"2016-08-21T11:18:14Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey,\n\nOn Sat, Aug 20, 2016 at 2:02 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `bisect_clean_state` shell function in C and add a\n> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh .\n>\n> Using `--bisect-clean-state` subcommand is a measure to port shell\n> function to C so as to use the existing test suite. As more functions\n> are ported, this subcommand will be retired but its implementation  will\n> be called by bisect_reset() and bisect_start().\n>\n> Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n> Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n>  bisect.c                 | 43 +++++++++++++++++++++++++++++++++++++++++++\n>  bisect.h                 |  2 ++\n>  builtin/bisect--helper.c | 14 +++++++++++++-\n>  git-bisect.sh            | 26 +++-----------------------\n>  4 files changed, 61 insertions(+), 24 deletions(-)\n>\n> diff --git a/bisect.c b/bisect.c\n> index 6f512c2..45d598d 100644\n> --- a/bisect.c\n> +++ b/bisect.c\n> @@ -430,6 +430,12 @@ static int read_bisect_refs(void)\n>\n>  static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n>  static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n> +static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n> +static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n> +static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n> +static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n> +static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n> +static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\n>\n>  static void read_bisect_paths(struct argv_array *array)\n>  {\n> @@ -1040,3 +1046,40 @@ int estimate_bisect_steps(int all)\n>\n>         return (e < 3 * x) ? n : n - 1;\n>  }\n> +\n> +static int mark_for_removal(const char *refname, const struct object_id *oid,\n> +                           int flag, void *cb_data)\n> +{\n> +       struct string_list *refs = cb_data;\n> +       char *ref = xstrfmt(\"refs/bisect%s\", refname);\n> +       string_list_append(refs, ref);\n> +       return 0;\n> +}\n> +\n> +int bisect_clean_state(void)\n> +{\n> +       int result = 0;\n> +\n> +       /* There may be some refs packed during bisection */\n> +       struct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n> +       for_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n> +       string_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n> +       result = delete_refs(&refs_for_removal, REF_NODEREF);\n> +       refs_for_removal.strdup_strings = 1;\n> +       string_list_clear(&refs_for_removal, 0);\n> +       unlink_or_warn(git_path_bisect_expected_rev());\n> +       unlink_or_warn(git_path_bisect_ancestors_ok());\n> +       unlink_or_warn(git_path_bisect_log());\n> +       unlink_or_warn(git_path_bisect_names());\n> +       unlink_or_warn(git_path_bisect_run());\n> +       unlink_or_warn(git_path_bisect_terms());\n> +       /* Cleanup head-name if it got left by an old version of git-bisect */\n> +       unlink_or_warn(git_path_head_name());\n> +       /*\n> +        * Cleanup BISECT_START last to support the --no-checkout option\n> +        * introduced in the commit 4796e823a.\n> +        */\n> +       unlink_or_warn(git_path_bisect_start());\n> +\n> +       return result;\n> +}\n> diff --git a/bisect.h b/bisect.h\n> index acd12ef..0ae63d4 100644\n> --- a/bisect.h\n> +++ b/bisect.h\n> @@ -28,4 +28,6 @@ extern int estimate_bisect_steps(int all);\n>\n>  extern void read_bisect_terms(const char **bad, const char **good);\n>\n> +extern int bisect_clean_state(void);\n> +\n>  #endif\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 30e1031..e50934c 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -5,10 +5,15 @@\n>  #include \"refs.h\"\n>\n>  static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n> +static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n> +static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n> +static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n> +static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n>\n>  static const char * const git_bisect_helper_usage[] = {\n>         N_(\"git bisect--helper --next-all [--no-checkout]\"),\n>         N_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n> +       N_(\"git bisect--helper --bisect-clean-state\"),\n>         NULL\n>  };\n>\n> @@ -83,7 +88,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n>         enum {\n>                 NEXT_ALL = 1,\n> -               WRITE_TERMS\n> +               WRITE_TERMS,\n> +               BISECT_CLEAN_STATE\n>         } cmdmode = 0;\n>         int no_checkout = 0;\n>         struct option options[] = {\n> @@ -91,6 +97,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>                          N_(\"perform 'git bisect next'\"), NEXT_ALL),\n>                 OPT_CMDMODE(0, \"write-terms\", &cmdmode,\n>                          N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n> +               OPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n> +                        N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n>                 OPT_BOOL(0, \"no-checkout\", &no_checkout,\n>                          N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n>                 OPT_END()\n> @@ -109,6 +117,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>                 if (argc != 2)\n>                         die(_(\"--write-terms requires two arguments\"));\n>                 return write_terms(argv[0], argv[1]);\n> +       case BISECT_CLEAN_STATE:\n> +               if (argc != 0)\n> +                       die(_(\"--bisect-clean-state requires no arguments\"));\n> +               return bisect_clean_state();\n>         default:\n>                 die(\"BUG: unknown subcommand '%d'\", cmdmode);\n>         }\n> diff --git a/git-bisect.sh b/git-bisect.sh\n> index 9ef6cb8..f1202df 100755\n> --- a/git-bisect.sh\n> +++ b/git-bisect.sh\n> @@ -186,7 +186,7 @@ bisect_start() {\n>         #\n>         # Get rid of any old bisect state.\n>         #\n> -       bisect_clean_state || exit\n> +       git bisect--helper --bisect-clean-state || exit\n>\n>         #\n>         # Change state.\n> @@ -195,7 +195,7 @@ bisect_start() {\n>         # We have to trap this to be able to clean up using\n>         # \"bisect_clean_state\".\n>         #\n> -       trap 'bisect_clean_state' 0\n> +       trap 'git bisect--helper --bisect-clean-state' 0\n>         trap 'exit 255' 1 2 3 15\n>\n>         #\n> @@ -430,27 +430,7 @@ bisect_reset() {\n>                 die \"$(eval_gettext \"Could not check out original HEAD '\\$branch'.\n>  Try 'git bisect reset <commit>'.\")\"\n>         fi\n> -       bisect_clean_state\n> -}\n> -\n> -bisect_clean_state() {\n> -       # There may be some refs packed during bisection.\n> -       git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\\* |\n> -       while read ref hash\n> -       do\n> -               git update-ref -d $ref $hash || exit\n> -       done\n> -       rm -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n> -       rm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n> -       rm -f \"$GIT_DIR/BISECT_LOG\" &&\n> -       rm -f \"$GIT_DIR/BISECT_NAMES\" &&\n> -       rm -f \"$GIT_DIR/BISECT_RUN\" &&\n> -       rm -f \"$GIT_DIR/BISECT_TERMS\" &&\n> -       # Cleanup head-name if it got left by an old version of git-bisect\n> -       rm -f \"$GIT_DIR/head-name\" &&\n> -       git update-ref -d --no-deref BISECT_HEAD &&\n> -       # clean up BISECT_START last\n> -       rm -f \"$GIT_DIR/BISECT_START\"\n> +       git bisect--helper --bisect-clean-state || exit\n>  }\n>\n>  bisect_replay () {\n\nThe change as compared to the v12 is that the function\n`bisect_clean_state()` has been moved to bisect.c from\nbuiltin/bisect--helper.c because in a future function conversion\n(bisect_next()) I needed bisect_clean_state() in bisect.c because\nbisect.c uses exit() whose signals can be easily trapped by the shell\nfunction and then do the cleanup. But now it would be essential to\nconvert those exit() statements to return statements. This has been\ndone. One can find it here[1].\n\n[1]: https://github.com/pranitbauva1997/git/pull/22\n\nRegards,\nPranit Bauva\n"}]}