{"thread":{"id":"47045","subject":"[PATCH v16 Part II 7/8] bisect--helper: `bisect_start` shell function partially in C","startedAt":"2017-10-27T15:06:46Z","lastAt":"2019-01-07T09:15:59Z","messageCount":50,"participants":["Pranit Bauva","Martin Ågren","Junio C Hamano","Stephan Beyer","Ramsay Jones","SZEDER Gábor","Johannes Schindelin","Pranit Bauva via GitGitGadget","Tanushree Tumane via GitGitGadget","TANUSHREE TUMANE"],"isPatch":true,"patchVersion":16,"patchTotal":8},"messages":[{"id":"331157","messageId":"0102015f5e5ee2f5-3d106a61-7f79-4973-851f-f55a691a6189-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 7/8] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06:46Z","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\nAlso introduce a method `bisect_append_log_quoted` to keep things short\nand crisp.\n\nHelped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\nHelped-by: Stephan Beyer <s-beyer@gmx.net>\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 | 228 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 132 +--------------------------\n 2 files changed, 228 insertions(+), 132 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex ab0580ce0089a..4ac175c49e80c 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_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\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> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\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@@ -401,6 +406,217 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \treturn 0;\n }\n \n+static int bisect_append_log_quoted(const char **argv)\n+{\n+\tint retval = 0;\n+\tFILE *fp = fopen(git_path_bisect_log(), \"a\");\n+\tstruct strbuf orig_args = STRBUF_INIT;\n+\n+\tif (!fp)\n+\t\treturn -1;\n+\n+\tif (fprintf(fp, \"git bisect start\") < 1)\n+\t\tgoto fail;\n+\n+\tsq_quote_argv(&orig_args, argv, 0);\n+\tif (fprintf(fp, \"%s\\n\", orig_args.buf) < 1)\n+\t\tgoto fail;\n+\n+\tgoto finish;\n+\n+fail:\n+\tretval = -1;\n+finish:\n+\tfclose(fp);\n+\tstrbuf_release(&orig_args);\n+\treturn retval;\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, retval = 0;\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 object_id head_oid;\n+\tstruct object_id oid;\n+\tconst char *head;\n+\n+\tif (is_bare_repository())\n+\t\tno_checkout = 1;\n+\n+\t/*\n+\t * Check for one bad and then some good revisions\n+\t */\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\tconst char *arg = argv[i];\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\tbreak;\n+\t\t} else if (!strcmp(arg, \"--no-checkout\")) {\n+\t\t\tno_checkout = 1;\n+\t\t} else if (!strcmp(arg, \"--term-good\") ||\n+\t\t\t !strcmp(arg, \"--term-old\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_good);\n+\t\t\tterms->term_good = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg) ||\n+\t\t\t   skip_prefix(arg, \"--term-old=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_good);\n+\t\t\tterms->term_good = xstrdup(arg);\n+\t\t} else if (!strcmp(arg, \"--term-bad\") ||\n+\t\t\t !strcmp(arg, \"--term-new\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_bad);\n+\t\t\tterms->term_bad = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg) ||\n+\t\t\t   skip_prefix(arg, \"--term-new=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_bad);\n+\t\t\tterms->term_bad = xstrdup(arg);\n+\t\t} else if (starts_with(arg, \"--\") &&\n+\t\t\t !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n+\t\t\treturn error(_(\"unrecognised option: '%s'\"), arg);\n+\t\t} else {\n+\t\t\tchar *commit_id = xstrfmt(\"%s^{commit}\", arg);\n+\t\t\tif (get_oid(commit_id, &oid) && has_double_dash)\n+\t\t\t\tdie(_(\"'%s' does not appear to be a valid \"\n+\t\t\t\t      \"revision\"), arg);\n+\n+\t\t\tstring_list_append(&revs, oid_to_hex(&oid));\n+\t\t\tfree(commit_id);\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);\n+\t\t} else {\n+\t\t\tbad_seen = 1;\n+\t\t\tstring_list_append(&states, terms->term_bad);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Verify HEAD\n+\t */\n+\thead = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, &flags);\n+\tif (!head)\n+\t\tif (get_oid(\"HEAD\", &head_oid))\n+\t\t\treturn error(_(\"Bad HEAD - I need a HEAD\"));\n+\n+\t/*\n+\t * Check if we are bisecting\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+\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\tgoto fail;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\t/* Get the rev from where we start. */\n+\t\tif (!get_oid(head, &head_oid) &&\n+\t\t    !starts_with(head, \"refs/heads/\")) {\n+\t\t\tstrbuf_reset(&start_head);\n+\t\t\tstrbuf_addstr(&start_head, sha1_to_hex(head_oid.hash));\n+\t\t} else if (!get_oid(head, &head_oid) &&\n+\t\t\t   skip_prefix(head, \"refs/heads/\", &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\treturn error(_(\"won't bisect on cg-seek'ed tree\"));\n+\t\t\tstrbuf_addstr(&start_head, head);\n+\t\t} else {\n+\t\t\treturn error(_(\"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+\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, NULL, 0,\n+\t\t\t       UPDATE_REFS_MSG_ON_ERR))\n+\t\t\tgoto fail;\n+\t}\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+\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\tgoto fail;\n+\n+\tif (must_write_terms)\n+\t\tif (write_terms(terms->term_bad, terms->term_good))\n+\t\t\tgoto fail;\n+\n+\tretval = bisect_append_log_quoted(argv);\n+\tif (retval)\n+\t\tgoto fail;\n+\n+\tgoto finish;\n+\n+fail:\n+\tretval = -1;\n+finish:\n+\tstring_list_clear(&revs, 0);\n+\tstring_list_clear(&states, 0);\n+\tstrbuf_release(&start_head);\n+\tstrbuf_release(&bisect_names);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -412,7 +628,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@@ -434,6 +651,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@@ -441,7 +660,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tstruct bisect_terms 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@@ -489,6 +709,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n \t\tres = bisect_terms(&terms, argv, argc);\n \t\tbreak;\n+\tcase BISECT_START:\n+\t\tset_terms(&terms, \"bad\", \"good\");\n+\t\tres = bisect_start(&terms, no_checkout, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 1bc5749f78484..9d2f8936198d2 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@@ -199,22 +84,9 @@ bisect_start() {\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\" || exit\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/420\n"},{"id":"331158","messageId":"0102015f5e5ee22c-ea9c3a38-5d42-4dce-a54b-45c59768a70b-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06: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\nAdd a log_commit() helper function to write the contents of the commit message\nheader to a file which will be re-used in future parts of the code as\nwell.\n\nAlso introduce a function free_terms() to free the memory of `struct\nbisect_terms` and set_terms() to set the values of members in `struct\nbisect_terms`.\n\nHelped-by: Ramsay Jones <ramsay@ramsayjones.plus.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 | 107 +++++++++++++++++++++++++++++++++++++++++++++--\n git-bisect.sh            |  25 ++---------\n 2 files changed, 108 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 12754448f7b6a..6295f53c850a8 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -12,15 +12,37 @@ 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_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\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+\tN_(\"git bisect--helper --bisect-write <state> <revision> <good_term> <bad_term> [<nolog>]\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tconst char *term_good;\n+\tconst char *term_bad;\n+};\n+\n+static void free_terms(struct bisect_terms *terms)\n+{\n+\tif (!terms->term_good)\n+\t\tfree((void *) terms->term_good);\n+\tif (!terms->term_bad)\n+\t\tfree((void *) terms->term_bad);\n+}\n+\n+static void set_terms(struct bisect_terms *terms, const char *bad,\n+\t\t      const char *good)\n+{\n+\tterms->term_good = xstrdup(good);\n+\tterms->term_bad = xstrdup(bad);\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -146,6 +168,72 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static void log_commit(FILE *fp, char *fmt, const char *state,\n+\t\t       struct commit *commit)\n+{\n+\tstruct pretty_print_context pp = {0};\n+\tstruct strbuf commit_msg = STRBUF_INIT;\n+\tchar *label = xstrfmt(fmt, state);\n+\n+\tformat_commit_message(commit, \"%s\", &commit_msg, &pp);\n+\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", label, oid_to_hex(&commit->object.oid),\n+\t\tcommit_msg.buf);\n+\n+\tstrbuf_release(&commit_msg);\n+\tfree(label);\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 object_id oid;\n+\tstruct commit *commit;\n+\tFILE *fp = NULL;\n+\tint retval = 0;\n+\n+\tif (!strcmp(state, terms->term_bad)) {\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\t} else if (one_of(state, terms->term_good, \"skip\", NULL)) {\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\t} else {\n+\t\terror(_(\"Bad bisect_write argument: %s\"), state);\n+\t\tgoto fail;\n+\t}\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\terror(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t\tgoto fail;\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, &oid, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR))\n+\t\tgoto fail;\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp) {\n+\t\terror_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\t\tgoto fail;\n+\t}\n+\n+\tcommit = lookup_commit_reference(&oid);\n+\tlog_commit(fp, \"%s\", state, commit);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+\tgoto finish;\n+\n+fail:\n+\tretval = -1;\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&tag);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -153,9 +241,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n \t\tCHECK_EXPECTED_REVS,\n-\t\tBISECT_RESET\n+\t\tBISECT_RESET,\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@@ -167,10 +256,13 @@ 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-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n+\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n+\t\t\t N_(\"update the refs according to the bisection state and may write it to 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 \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -179,6 +271,7 @@ 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@@ -196,8 +289,16 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc > 1)\n \t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n \t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\treturn error(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n+\t\tset_terms(&terms, argv[3], argv[2]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tfree_terms(&terms);\n+\treturn res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 4d403242482cf..1eab94ec943a1 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/420\n"},{"id":"331159","messageId":"0102015f5e5ee273-03ff1203-7c84-4260-bda7-c27a87646517-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 3/8] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06:51Z","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 4b6f1534f8840..2afaaabcdbecf 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -34,22 +34,6 @@\n #include \"packfile.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@@ -1298,7 +1282,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.\"));\n \t\tdie_user_resolve(state);\n \t}\n@@ -1880,7 +1864,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 25adcf681531c..f05056a2d7fa1 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1958,4 +1958,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 61aba0b5c1bec..21c0fee2db459 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -690,3 +690,16 @@ int xgethostname(char *buf, size_t len)\n \t\tbuf[len - 1] = 0;\n \treturn ret;\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/420\n"},{"id":"331160","messageId":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06:54Z","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\n`bisect_voc` shell function is no longer useful now and is replaced by\nusing a char *[] of \"new|bad\" and \"good|old\" values.\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\nHelped-by: Stephan Beyer <s-beyer@gmx.net>\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 | 91 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 60 +++----------------------------\n 2 files changed, 94 insertions(+), 57 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 65abf8a70c6d9..0f9c3e63821b8 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> <good_term> <bad_term> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n+\tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n \tNULL\n };\n \n@@ -44,6 +46,11 @@ static void set_terms(struct bisect_terms *terms, const char *bad,\n \tterms->term_bad = xstrdup(bad);\n }\n \n+static const char *voc[] = {\n+\t\"bad|new\",\n+\t\"good|old\"\n+};\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -264,6 +271,79 @@ 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 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, retval = 0;\n+\tconst char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n+\tconst char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n+\n+\tif (ref_exists(bad_ref))\n+\t\tmissing_bad = 0;\n+\n+\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n+\t\t\t     (void *) &missing_good);\n+\n+\tif (!missing_good && !missing_bad)\n+\t\tgoto finish;\n+\n+\tif (!current_term)\n+\t\tgoto fail;\n+\n+\tif (missing_good && !missing_bad && current_term &&\n+\t    !strcmp(current_term, terms->term_good)) {\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, _(\"Warning: bisecting only with a %s commit\\n\"),\n+\t\t\tterms->term_bad);\n+\t\tif (!isatty(0))\n+\t\t\tgoto finish;\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\tgoto fail;\n+\n+\t\tgoto finish;\n+\t}\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\tvoc[0], voc[1], voc[0], voc[1]);\n+\t\tgoto fail;\n+\t} else {\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\tvoc[1], voc[0], voc[1], voc[0]);\n+\t\tgoto fail;\n+\t}\n+\tgoto finish;\n+\n+fail:\n+\tretval = -1;\n+finish:\n+\tfree((void *) good_glob);\n+\tfree((void *) bad_ref);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -273,7 +353,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_RESET,\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@@ -291,6 +372,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"update the refs according to the bisection state and may write it to 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@@ -335,6 +418,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[2], argv[1]);\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\treturn error(_(\"--bisect-next-check requires 2 or 3 arguments\"));\n+\t\tset_terms(&terms, argv[1], argv[0]);\n+\t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 0447b73aa588b..c21fafc62d71f 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/420\n"},{"id":"331161","messageId":"0102015f5e5ee2f8-9c3b0a3a-ba4f-4a50-8791-69fa5e336b7e-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 8/8] t6030: make various test to pass GETTEXT_POISON tests","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06:56Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n t/t6030-bisect-porcelain.sh | 120 ++++++++++++++++++++++----------------------\n 1 file changed, 60 insertions(+), 60 deletions(-)\n\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex 55835ee4a4715..f9e61c6540e57 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -133,21 +133,21 @@ test_expect_success 'bisect reset removes bisect state after --no-checkout' '\n \n test_expect_success 'bisect start: back in good branch' '\n \tgit branch > branch.output &&\n-\tgrep \"* other\" branch.output > /dev/null &&\n+\ttest_i18ngrep \"* other\" branch.output > /dev/null &&\n \tgit bisect start $HASH4 $HASH1 -- &&\n \tgit bisect good &&\n \tgit bisect start $HASH4 $HASH1 -- &&\n \tgit bisect bad &&\n \tgit bisect reset &&\n \tgit branch > branch.output &&\n-\tgrep \"* other\" branch.output > /dev/null\n+\ttest_i18ngrep \"* other\" branch.output > /dev/null\n '\n \n test_expect_success 'bisect start: no \".git/BISECT_START\" created if junk rev' '\n \tgit bisect reset &&\n \ttest_must_fail git bisect start $HASH4 foo -- &&\n \tgit branch > branch.output &&\n-\tgrep \"* other\" branch.output > /dev/null &&\n+\ttest_i18ngrep \"* other\" branch.output > /dev/null &&\n \ttest_must_fail test -e .git/BISECT_START\n '\n \n@@ -158,14 +158,14 @@ test_expect_success 'bisect start: existing \".git/BISECT_START\" not modified if\n \ttest_must_fail git bisect start $HASH4 foo -- &&\n \tgit branch > branch.output &&\n \ttest_i18ngrep \"* (no branch, bisect started on other)\" branch.output > /dev/null &&\n-\ttest_cmp saved .git/BISECT_START\n+\ttest_i18ncmp saved .git/BISECT_START\n '\n test_expect_success 'bisect start: no \".git/BISECT_START\" if mistaken rev' '\n \tgit bisect start $HASH4 $HASH1 -- &&\n \tgit bisect good &&\n \ttest_must_fail git bisect start $HASH1 $HASH4 -- &&\n \tgit branch > branch.output &&\n-\tgrep \"* other\" branch.output > /dev/null &&\n+\ttest_i18ngrep \"* other\" branch.output > /dev/null &&\n \ttest_must_fail test -e .git/BISECT_START\n '\n \n@@ -174,7 +174,7 @@ test_expect_success 'bisect start: no \".git/BISECT_START\" if checkout error' '\n \ttest_must_fail git bisect start $HASH4 $HASH1 -- &&\n \tgit branch &&\n \tgit branch > branch.output &&\n-\tgrep \"* other\" branch.output > /dev/null &&\n+\ttest_i18ngrep \"* other\" branch.output > /dev/null &&\n \ttest_must_fail test -e .git/BISECT_START &&\n \ttest -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n \tgit checkout HEAD hello\n@@ -189,7 +189,7 @@ test_expect_success 'bisect skip: successful result' '\n \tgit bisect start $HASH4 $HASH1 &&\n \tgit bisect skip &&\n \tgit bisect bad > my_bisect_log.txt &&\n-\tgrep \"$HASH2 is the first bad commit\" my_bisect_log.txt\n+\ttest_i18ngrep \"$HASH2 is the first bad commit\" my_bisect_log.txt\n '\n \n # $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2\n@@ -200,11 +200,11 @@ test_expect_success 'bisect skip: cannot tell between 3 commits' '\n \tgit bisect start $HASH4 $HASH1 &&\n \tgit bisect skip &&\n \ttest_expect_code 2 git bisect skip >my_bisect_log.txt &&\n-\tgrep \"first bad commit could be any of\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt &&\n \t! grep $HASH1 my_bisect_log.txt &&\n-\tgrep $HASH2 my_bisect_log.txt &&\n-\tgrep $HASH3 my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt\n+\ttest_i18ngrep $HASH2 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH3 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt\n '\n \n # $HASH1 is good, $HASH4 is bad, we skip $HASH3\n@@ -216,11 +216,11 @@ test_expect_success 'bisect skip: cannot tell between 2 commits' '\n \tgit bisect start $HASH4 $HASH1 &&\n \tgit bisect skip &&\n \ttest_expect_code 2 git bisect good >my_bisect_log.txt &&\n-\tgrep \"first bad commit could be any of\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt &&\n \t! grep $HASH1 my_bisect_log.txt &&\n \t! grep $HASH2 my_bisect_log.txt &&\n-\tgrep $HASH3 my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt\n+\ttest_i18ngrep $HASH3 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt\n '\n \n # $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3\n@@ -235,11 +235,11 @@ test_expect_success 'bisect skip: with commit both bad and skipped' '\n \tgit bisect good $HASH1 &&\n \tgit bisect skip &&\n \ttest_expect_code 2 git bisect good >my_bisect_log.txt &&\n-\tgrep \"first bad commit could be any of\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt &&\n \t! grep $HASH1 my_bisect_log.txt &&\n-\t! grep $HASH2 my_bisect_log.txt &&\n-\tgrep $HASH3 my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt\n+\t! rep $HASH2 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH3 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt\n '\n \n # We want to automatically find the commit that\n@@ -254,7 +254,7 @@ test_expect_success \\\n      git bisect good $HASH1 &&\n      git bisect bad $HASH4 &&\n      git bisect run ./test_script.sh > my_bisect_log.txt &&\n-     grep \"$HASH3 is the first bad commit\" my_bisect_log.txt &&\n+     test_i18ngrep \"$HASH3 is the first bad commit\" my_bisect_log.txt &&\n      git bisect reset'\n \n # We want to automatically find the commit that\n@@ -267,7 +267,7 @@ test_expect_success \\\n      chmod +x test_script.sh &&\n      git bisect start $HASH4 $HASH1 &&\n      git bisect run ./test_script.sh > my_bisect_log.txt &&\n-     grep \"$HASH4 is the first bad commit\" my_bisect_log.txt &&\n+     test_i18ngrep \"$HASH4 is the first bad commit\" my_bisect_log.txt &&\n      git bisect reset'\n \n # $HASH1 is good, $HASH5 is bad, we skip $HASH3\n@@ -280,14 +280,14 @@ test_expect_success 'bisect skip: add line and then a new test' '\n \tgit bisect start $HASH5 $HASH1 &&\n \tgit bisect skip &&\n \tgit bisect good > my_bisect_log.txt &&\n-\tgrep \"$HASH5 is the first bad commit\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"$HASH5 is the first bad commit\" my_bisect_log.txt &&\n \tgit bisect log > log_to_replay.txt &&\n \tgit bisect reset\n '\n \n test_expect_success 'bisect skip and bisect replay' '\n \tgit bisect replay log_to_replay.txt > my_bisect_log.txt &&\n-\tgrep \"$HASH5 is the first bad commit\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"$HASH5 is the first bad commit\" my_bisect_log.txt &&\n \tgit bisect reset\n '\n \n@@ -307,11 +307,11 @@ test_expect_success 'bisect run & skip: cannot tell between 2' '\n \t\tfalse\n \telse\n \t\ttest $? -eq 2 &&\n-\t\tgrep \"first bad commit could be any of\" my_bisect_log.txt &&\n+\t\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt &&\n \t\t! grep $HASH3 my_bisect_log.txt &&\n \t\t! grep $HASH6 my_bisect_log.txt &&\n-\t\tgrep $HASH4 my_bisect_log.txt &&\n-\t\tgrep $HASH5 my_bisect_log.txt\n+\t\ttest_i18ngrep $HASH4 my_bisect_log.txt &&\n+\t\ttest_i18ngrep $HASH5 my_bisect_log.txt\n \tfi\n '\n \n@@ -328,7 +328,7 @@ test_expect_success 'bisect run & skip: find first bad' '\n \tchmod +x test_script.sh &&\n \tgit bisect start $HASH7 $HASH1 &&\n \tgit bisect run ./test_script.sh > my_bisect_log.txt &&\n-\tgrep \"$HASH6 is the first bad commit\" my_bisect_log.txt\n+\ttest_i18ngrep \"$HASH6 is the first bad commit\" my_bisect_log.txt\n '\n \n test_expect_success 'bisect skip only one range' '\n@@ -337,7 +337,7 @@ test_expect_success 'bisect skip only one range' '\n \tgit bisect skip $HASH1..$HASH5 &&\n \ttest \"$HASH6\" = \"$(git rev-parse --verify HEAD)\" &&\n \ttest_must_fail git bisect bad > my_bisect_log.txt &&\n-\tgrep \"first bad commit could be any of\" my_bisect_log.txt\n+\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt\n '\n \n test_expect_success 'bisect skip many ranges' '\n@@ -346,7 +346,7 @@ test_expect_success 'bisect skip many ranges' '\n \tgit bisect skip $HASH2 $HASH2.. ..$HASH5 &&\n \ttest \"$HASH6\" = \"$(git rev-parse --verify HEAD)\" &&\n \ttest_must_fail git bisect bad > my_bisect_log.txt &&\n-\tgrep \"first bad commit could be any of\" my_bisect_log.txt\n+\ttest_i18ngrep \"first bad commit could be any of\" my_bisect_log.txt\n '\n \n test_expect_success 'bisect starting with a detached HEAD' '\n@@ -378,7 +378,7 @@ test_expect_success 'bisect does not create a \"bisect\" branch' '\n \trev_hash6=$(git rev-parse --verify HEAD) &&\n \ttest \"$rev_hash6\" = \"$HASH6\" &&\n \tgit bisect good > my_bisect_log.txt &&\n-\tgrep \"$HASH7 is the first bad commit\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"$HASH7 is the first bad commit\" my_bisect_log.txt &&\n \tgit bisect reset &&\n \trev_hash6=$(git rev-parse --verify bisect) &&\n \ttest \"$rev_hash6\" = \"$HASH6\" &&\n@@ -405,26 +405,26 @@ test_expect_success 'side branch creation' '\n test_expect_success 'good merge base when good and bad are siblings' '\n \tgit bisect start \"$HASH7\" \"$SIDE_HASH7\" > my_bisect_log.txt &&\n \ttest_i18ngrep \"merge base must be tested\" my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt &&\n \tgit bisect good > my_bisect_log.txt &&\n \t! grep \"merge base must be tested\" my_bisect_log.txt &&\n-\tgrep $HASH6 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH6 my_bisect_log.txt &&\n \tgit bisect reset\n '\n test_expect_success 'skipped merge base when good and bad are siblings' '\n \tgit bisect start \"$SIDE_HASH7\" \"$HASH7\" > my_bisect_log.txt &&\n \ttest_i18ngrep \"merge base must be tested\" my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt &&\n \tgit bisect skip > my_bisect_log.txt 2>&1 &&\n-\tgrep \"warning\" my_bisect_log.txt &&\n-\tgrep $SIDE_HASH6 my_bisect_log.txt &&\n+\ttest_i18ngrep \"warning\" my_bisect_log.txt &&\n+\ttest_i18ngrep $SIDE_HASH6 my_bisect_log.txt &&\n \tgit bisect reset\n '\n \n test_expect_success 'bad merge base when good and bad are siblings' '\n \tgit bisect start \"$HASH7\" HEAD > my_bisect_log.txt &&\n \ttest_i18ngrep \"merge base must be tested\" my_bisect_log.txt &&\n-\tgrep $HASH4 my_bisect_log.txt &&\n+\ttest_i18ngrep $HASH4 my_bisect_log.txt &&\n \ttest_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&\n \ttest_i18ngrep \"merge base $HASH4 is bad\" my_bisect_log.txt &&\n \ttest_i18ngrep \"fixed between $HASH4 and \\[$SIDE_HASH7\\]\" my_bisect_log.txt &&\n@@ -454,8 +454,8 @@ test_expect_success 'many merge bases creation' '\n \tB_HASH=$(git rev-parse --verify HEAD) &&\n \tgit merge-base --all \"$A_HASH\" \"$B_HASH\" > merge_bases.txt &&\n \ttest_line_count = 2 merge_bases.txt &&\n-\tgrep \"$HASH5\" merge_bases.txt &&\n-\tgrep \"$SIDE_HASH5\" merge_bases.txt\n+\ttest_i18ngrep \"$HASH5\" merge_bases.txt &&\n+\ttest_i18ngrep \"$SIDE_HASH5\" merge_bases.txt\n '\n \n test_expect_success 'good merge bases when good and bad are siblings' '\n@@ -465,11 +465,11 @@ test_expect_success 'good merge bases when good and bad are siblings' '\n \ttest_i18ngrep \"merge base must be tested\" my_bisect_log2.txt &&\n \t{\n \t\t{\n-\t\t\tgrep \"$SIDE_HASH5\" my_bisect_log.txt &&\n-\t\t\tgrep \"$HASH5\" my_bisect_log2.txt\n+\t\t\ttest_i18ngrep \"$SIDE_HASH5\" my_bisect_log.txt &&\n+\t\t\ttest_i18ngrep \"$HASH5\" my_bisect_log2.txt\n \t\t} || {\n-\t\t\tgrep \"$SIDE_HASH5\" my_bisect_log2.txt &&\n-\t\t\tgrep \"$HASH5\" my_bisect_log.txt\n+\t\t\ttest_i18ngrep \"$SIDE_HASH5\" my_bisect_log2.txt &&\n+\t\t\ttest_i18ngrep \"$HASH5\" my_bisect_log.txt\n \t\t}\n \t} &&\n \tgit bisect reset\n@@ -478,7 +478,7 @@ test_expect_success 'good merge bases when good and bad are siblings' '\n test_expect_success 'optimized merge base checks' '\n \tgit bisect start \"$HASH7\" \"$SIDE_HASH7\" > my_bisect_log.txt &&\n \ttest_i18ngrep \"merge base must be tested\" my_bisect_log.txt &&\n-\tgrep \"$HASH4\" my_bisect_log.txt &&\n+\ttest_i18ngrep \"$HASH4\" my_bisect_log.txt &&\n \tgit bisect good > my_bisect_log2.txt &&\n \ttest -f \".git/BISECT_ANCESTORS_OK\" &&\n \ttest \"$HASH6\" = $(git rev-parse --verify HEAD) &&\n@@ -527,7 +527,7 @@ test_expect_success 'restricting bisection on one dir' '\n \tpara1=$(git rev-parse --verify HEAD) &&\n \ttest \"$para1\" = \"$PARA_HASH1\" &&\n \tgit bisect bad > my_bisect_log.txt &&\n-\tgrep \"$PARA_HASH1 is the first bad commit\" my_bisect_log.txt\n+\ttest_i18ngrep \"$PARA_HASH1 is the first bad commit\" my_bisect_log.txt\n '\n \n test_expect_success 'restricting bisection on one dir and a file' '\n@@ -545,7 +545,7 @@ test_expect_success 'restricting bisection on one dir and a file' '\n \tpara1=$(git rev-parse --verify HEAD) &&\n \ttest \"$para1\" = \"$PARA_HASH1\" &&\n \tgit bisect good > my_bisect_log.txt &&\n-\tgrep \"$PARA_HASH4 is the first bad commit\" my_bisect_log.txt\n+\ttest_i18ngrep \"$PARA_HASH4 is the first bad commit\" my_bisect_log.txt\n '\n \n test_expect_success 'skipping away from skipped commit' '\n@@ -576,7 +576,7 @@ test_expect_success 'test bisection on bare repo - --no-checkout specified' '\n \t\t\t\"test \\$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0\" \\\n \t\t\t>../nocheckout.log\n \t) &&\n-\tgrep \"$HASH3 is the first bad commit\" nocheckout.log\n+\ttest_i18ngrep \"$HASH3 is the first bad commit\" nocheckout.log\n '\n \n \n@@ -591,7 +591,7 @@ test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '\n \t\t\t\"test \\$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0\" \\\n \t\t\t>../defaulted.log\n \t) &&\n-\tgrep \"$HASH3 is the first bad commit\" defaulted.log\n+\ttest_i18ngrep \"$HASH3 is the first bad commit\" defaulted.log\n '\n \n #\n@@ -633,7 +633,7 @@ EOF\n test_expect_success 'bisect fails if tree is broken on start commit' '\n \tgit bisect reset &&\n \ttest_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt &&\n-\ttest_cmp expected.missing-tree.default error.txt\n+\ttest_i18ncmp expected.missing-tree.default error.txt\n '\n \n test_expect_success 'bisect fails if tree is broken on trial commit' '\n@@ -641,7 +641,7 @@ test_expect_success 'bisect fails if tree is broken on trial commit' '\n \ttest_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt &&\n \tgit reset --hard broken &&\n \tgit checkout broken &&\n-\ttest_cmp expected.missing-tree.default error.txt\n+\ttest_i18ncmp expected.missing-tree.default error.txt\n '\n \n check_same()\n@@ -726,7 +726,7 @@ test_expect_success 'bisect log: successful result' '\n \tgit bisect start $HASH4 $HASH2 &&\n \tgit bisect good &&\n \tgit bisect log >bisect-log.txt &&\n-\ttest_cmp expected.bisect-log bisect-log.txt &&\n+\ttest_i18ncmp expected.bisect-log bisect-log.txt &&\n \tgit bisect reset\n '\n \n@@ -746,7 +746,7 @@ test_expect_success 'bisect log: only skip commits left' '\n \tgit bisect start $HASH4 $HASH2 &&\n \ttest_must_fail git bisect skip &&\n \tgit bisect log >bisect-skip-log.txt &&\n-\ttest_cmp expected.bisect-skip-log bisect-skip-log.txt &&\n+\ttest_i18ncmp expected.bisect-skip-log bisect-skip-log.txt &&\n \tgit bisect reset\n '\n \n@@ -780,14 +780,14 @@ test_expect_success 'bisect start with one new and old' '\n \tgit bisect new $HASH4 &&\n \tgit bisect new &&\n \tgit bisect new >bisect_result &&\n-\tgrep \"$HASH2 is the first new commit\" bisect_result &&\n+\ttest_i18ngrep \"$HASH2 is the first new commit\" bisect_result &&\n \tgit bisect log >log_to_replay.txt &&\n \tgit bisect reset\n '\n \n test_expect_success 'bisect replay with old and new' '\n \tgit bisect replay log_to_replay.txt >bisect_result &&\n-\tgrep \"$HASH2 is the first new commit\" bisect_result &&\n+\ttest_i18ngrep \"$HASH2 is the first new commit\" bisect_result &&\n \tgit bisect reset\n '\n \n@@ -811,10 +811,10 @@ test_expect_success 'bisect terms shows good/bad after start' '\n \tgit bisect start HEAD $HASH1 &&\n \tgit bisect terms --term-good >actual &&\n \techo good >expected &&\n-\ttest_cmp expected actual &&\n+\ttest_i18ncmp expected actual &&\n \tgit bisect terms --term-bad >actual &&\n \techo bad >expected &&\n-\ttest_cmp expected actual\n+\ttest_i18ncmp expected actual\n '\n \n test_expect_success 'bisect start with one term1 and term2' '\n@@ -824,14 +824,14 @@ test_expect_success 'bisect start with one term1 and term2' '\n \tgit bisect term1 $HASH4 &&\n \tgit bisect term1 &&\n \tgit bisect term1 >bisect_result &&\n-\tgrep \"$HASH2 is the first term1 commit\" bisect_result &&\n+\ttest_i18ngrep \"$HASH2 is the first term1 commit\" bisect_result &&\n \tgit bisect log >log_to_replay.txt &&\n \tgit bisect reset\n '\n \n test_expect_success 'bisect replay with term1 and term2' '\n \tgit bisect replay log_to_replay.txt >bisect_result &&\n-\tgrep \"$HASH2 is the first term1 commit\" bisect_result &&\n+\ttest_i18ngrep \"$HASH2 is the first term1 commit\" bisect_result &&\n \tgit bisect reset\n '\n \n@@ -840,7 +840,7 @@ test_expect_success 'bisect start term1 term2' '\n \tgit bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&\n \tgit bisect term1 &&\n \tgit bisect term1 >bisect_result &&\n-\tgrep \"$HASH2 is the first term1 commit\" bisect_result &&\n+\ttest_i18ngrep \"$HASH2 is the first term1 commit\" bisect_result &&\n \tgit bisect log >log_to_replay.txt &&\n \tgit bisect reset\n '\n@@ -878,10 +878,10 @@ test_expect_success 'bisect start --term-* does store terms' '\n \ttest_i18ncmp expected actual &&\n \tgit bisect terms --term-bad >actual &&\n \techo one >expected &&\n-\ttest_cmp expected actual &&\n+\ttest_i18ncmp expected actual &&\n \tgit bisect terms --term-good >actual &&\n \techo two >expected &&\n-\ttest_cmp expected actual\n+\ttest_i18ncmp expected actual\n '\n \n test_expect_success 'bisect start takes options and revs in any order' '\n@@ -891,7 +891,7 @@ test_expect_success 'bisect start takes options and revs in any order' '\n \t\t$HASH1 --term-good three -- &&\n \t(git bisect terms --term-bad && git bisect terms --term-good) >actual &&\n \tprintf \"%s\\n%s\\n\" bad-term three >expected &&\n-\ttest_cmp expected actual\n+\ttest_i18ncmp expected actual\n '\n \n test_expect_success 'git bisect reset cleans bisection state properly' '\n\n--\nhttps://github.com/git/git/pull/420\n"},{"id":"331162","messageId":"0102015f5e5ee273-de8fa1d2-1d59-4990-93f5-d36a6cb3f45a-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 4/8] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:06:59Z","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\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 | 41 ++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 36 ++++--------------------------------\n 2 files changed, 44 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 6295f53c850a8..65abf8a70c6d9 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> <good_term> <bad_term> [<nolog>]\"),\n+\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n \tNULL\n };\n \n@@ -234,6 +235,35 @@ static int bisect_write(const char *state, const char *rev,\n \treturn retval;\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 && strcmp(cmd, terms->term_bad) &&\n+\t    strcmp(cmd, terms->term_good))\n+\t\treturn error(_(\"Invalid command: you're currently in a \"\n+\t\t\t\t\"%s/%s bisect\"), terms->term_bad,\n+\t\t\t\tterms->term_good);\n+\n+\tif (!has_term_file) {\n+\t\tif (one_of(cmd, \"bad\", \"good\", NULL)) {\n+\t\t\tfree_terms(terms);\n+\t\t\tset_terms(terms, \"bad\", \"good\");\n+\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n+\t\t}\n+\t\telse if (one_of(cmd, \"new\", \"old\", NULL)) {\n+\t\t\tfree_terms(terms);\n+\t\t\tset_terms(terms, \"new\", \"old\");\n+\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n+\t\t}\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@@ -242,7 +272,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_CLEAN_STATE,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_RESET,\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@@ -258,6 +289,8 @@ 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, \"bisect-write\", &cmdmode,\n \t\t\t N_(\"update the refs according to the bisection state and may write it to 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@@ -296,6 +329,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[3], argv[2]);\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\treturn error(_(\"--check-and-set-terms requires 3 arguments\"));\n+\t\tset_terms(&terms, argv[2], argv[1]);\n+\t\tres = check_and_set_terms(&terms, argv[0]);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 1eab94ec943a1..0447b73aa588b 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/420\n"},{"id":"331163","messageId":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015ecc65d695-22151d3b-752b-4c10-a3a3-b8ef52491664-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:07:03Z","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---\nHey,\n\nThis is the part 2 of the initial series[1] on bisect re-write. When I\nsubmitted my patches of the part 1 of the bisect series, Ramsay informed\nthat he has been working on my previous patches and pointed me to his\npatches. I have incorporated his changes into this series. Stephan did a\nawesome job in reviewing my series and I have incorporated those changes\nas well.\n\nRamsay's requested changes which have been incorporated:\n * bisect--helper: convert to struct object_id: I have took out the bits\n   which were in this series and hand-picked them in this series.\n * bisect--helper: add a log_commit() helper function: This function\n   might not seem to be very relevant in this part of the series, but it\n   is going to be in future parts of the series as described in\n   `188ea5855d93df` of Ramsay's git.git repo[2].\n * bisect--helper: reduce scope of a variable in `bisect_start`\n * bisect--helper: remove useless sub-expression in condition: I had\n   already done this change as suggested by Stephan.\n * bisect--helper: set correct term from --term-new= option: I had\n   already done this change as suggested by Stephan.\n * bisect--helper: remove redundant assignment to has_double_dash\n * bisect--helper: remove redundant goto's\n * bisect--helper: add some vertical whitespace\n * bisect--helper: fixup some coding style issues\n\nRamsay's changes which I had already done ([]-ed comments):\n * `bisect_write`: add a GIT_PATH_FUNC() removed earlier\n * `bisect_write`: lookup_commit_reference() now takes an object_id\n * `bisect_next_check`: addressed comments in Stephan's review and\n   Junio's squash\n * `bisect_terms`: fixed up usage string and tested for --term-[good|old] and\n   --term-[bad|new] in bisect-terms subcommand argument processing:\n   instead of fixing up usage string, I just removed it as Stephan\n   suggested.\n\nStephan's requested changes which have been incorporated:\n * Use goto's using `goto fail` and `goto finish`\n * Marking strings for translation\n * Stored res value and then returned it at the end\n * Implement set_terms() and free_terms() for proper memory handling for\n   struct bisect_terms and fixed all leakages\n * Remove bisect_voc() function\n * Remove the bisect_term_usage string in bisect_terms()\n * Use return error() every where instead of die()\n * Improving readability of a message in bisect_terms()\n * bisect_start(): fix some typos, remove has_double_dash, join the two\n   if branches, fix the bug when it should be terms->term_bad,\n   decomposed it into smaller functions by introducing\n   bisect_append_log()\n\nA big thanks to Stephan and Ramsay for patiently reviewing my series and\nhelping me get this merged.\n\n[1]:\nhttps://public-inbox.org/git/0102015ecc65d695-22151d3b-752b-4c10-a3a3-b8ef52491664-000000@eu-west-1.amazonses.com/\n\n[2]: git://repo.or.cz/git/raj.git\nRegards,\nPranit Bauva\n---\n builtin/bisect--helper.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++-------------------------\n 2 files changed, 50 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 35d2105f941c6..12754448f7b6a 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,15 +3,21 @@\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_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@@ -106,13 +112,48 @@ static void check_expected_revs(const char **revs, int rev_nr)\n \t}\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\treturn !printf(_(\"We are not bisecting.\\n\"));\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tstruct object_id oid;\n+\n+\t\tif (get_oid_commit(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+\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\tCHECK_EXPECTED_REVS\n+\t\tCHECK_EXPECTED_REVS,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -124,6 +165,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, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\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@@ -149,6 +192,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tcase CHECK_EXPECTED_REVS:\n \t\tcheck_expected_revs(argv, argc);\n \t\treturn 0;\n+\tcase BISECT_RESET:\n+\t\tif (argc > 1)\n+\t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n+\t\treturn bisect_reset(argc ? argv[0] : NULL);\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 0138a8860e377..4d403242482cf 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -393,35 +393,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@@ -611,7 +587,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/420\n"},{"id":"331164","messageId":"0102015f5e5ee303-449f1b76-ff53-433c-8973-8b4850466810-000000@eu-west-1.amazonses.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:06:37Z","receivedAt":"2017-10-27T15:07:05Z","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\nAlso use error() to report \"no terms defined\" and accordingly change the\ntest in t6030.\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    | 69 +++++++++++++++++++++++++++++++++++++++++++--\n git-bisect.sh               | 35 ++---------------------\n t/t6030-bisect-porcelain.sh |  2 +-\n 3 files changed, 70 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 0f9c3e63821b8..ab0580ce0089a 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> <good_term> <bad_term> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n+\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n \tNULL\n };\n \n@@ -344,6 +345,62 @@ static int bisect_next_check(const struct bisect_terms *terms,\n \treturn retval;\n }\n \n+static int get_terms(struct bisect_terms *terms)\n+{\n+\tstruct strbuf str = STRBUF_INIT;\n+\tFILE *fp = NULL;\n+\tint res = 0;\n+\n+\tfp = fopen(git_path_bisect_terms(), \"r\");\n+\tif (!fp)\n+\t\tgoto fail;\n+\n+\tfree_terms(terms);\n+\tstrbuf_getline_lf(&str, fp);\n+\tterms->term_bad = strbuf_detach(&str, NULL);\n+\tstrbuf_getline_lf(&str, fp);\n+\tterms->term_good = strbuf_detach(&str, NULL);\n+\tgoto finish;\n+\n+fail:\n+\tres = -1;\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&str);\n+\treturn res;\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\treturn error(_(\"no terms defined\"));\n+\n+\tif (argc > 1)\n+\t\treturn error(_(\"--bisect-term requires exactly one argument\"));\n+\n+\tif (argc == 0)\n+\t\treturn !printf(_(\"Your current terms are %s for the old state\\n\"\n+\t\t\t\t \"and %s for the new state.\\n\"),\n+\t\t\t\t terms->term_good, terms->term_bad);\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tif (!strcmp(argv[i], \"--term-good\"))\n+\t\t\tprintf(_(\"%s\\n\"), terms->term_good);\n+\t\telse if (!strcmp(argv[i], \"--term-bad\"))\n+\t\t\tprintf(_(\"%s\\n\"), terms->term_bad);\n+\t\telse\n+\t\t\terror(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n+\t\t\t\t  \"Supported 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 +411,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_RESET,\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 +432,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@@ -381,7 +441,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tstruct bisect_terms 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@@ -424,6 +484,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[1], argv[0]);\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\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n+\t\tres = bisect_terms(&terms, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex c21fafc62d71f..1bc5749f78484 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\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex f84ff941c3624..55835ee4a4715 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -802,7 +802,7 @@ test_expect_success 'bisect terms needs 0 or 1 argument' '\n \ttest_must_fail git bisect terms only-one &&\n \ttest_must_fail git bisect terms 1 2 &&\n \ttest_must_fail git bisect terms 2>actual &&\n-\techo \"no terms defined\" >expected &&\n+\techo \"error: no terms defined\" >expected &&\n \ttest_i18ncmp expected actual\n '\n \n\n--\nhttps://github.com/git/git/pull/420\n"},{"id":"331169","messageId":"CAFZEwPPxuno5ey9qWVVE9=CU5f-BmBZjhQMrHOXS1tFG6r4LkQ@mail.gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-27T15:32:36Z","receivedAt":"2017-10-27T15:32:42Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey,\n\nI forgot to mention. One can find the travis build here[1] which is passing.\n\n[1]: https://travis-ci.org/git/git/builds/293725346\n\nRegards,\nPranit Bauva\n"},{"id":"331181","messageId":"20171027172845.15437-1-martin.agren@gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee22c-ea9c3a38-5d42-4dce-a54b-45c59768a70b-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2017-10-27T17:28:45Z","receivedAt":"2017-10-27T17:29:18Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> +static void free_terms(struct bisect_terms *terms)\n> +{\n> +       if (!terms->term_good)\n> +               free((void *) terms->term_good);\n> +       if (!terms->term_bad)\n> +               free((void *) terms->term_bad);\n> +}\n\nThese look like no-ops. Remove `!` for correctness, or `if (...)` for\nsimplicity, since `free()` can handle NULL.\n\nYou leave the pointers dangling, but you're ok for now since this is the\nlast thing that happens in `cmd_bisect__helper()`. Your later patches\nadd more users, but they're also ok, since they immediately assign new\nvalues.\n\nIn case you (and others) find it useful, the below is a patch I've been\nsitting on for a while as part of a series to plug various memory-leaks.\n`FREE_AND_NULL_CONST()` would be useful in precisely these situations.\n\n-- >8 --\nSubject: git-compat-util: add FREE_AND_NULL_CONST() wrapper\n\nCommit 481df65 (\"git-compat-util: add a FREE_AND_NULL() wrapper around\nfree(ptr); ptr = NULL\", 2017-06-15) added `FREE_AND_NULL()`. One\nadvantage of this macro is that it reduces risk of copy-paste errors and\nreviewer-fatigue, especially when cleaning up more than just a single\npointer.\n\nHowever, `FREE_AND_NULL()` can not be used with a const-pointer:\n\n  struct foo { const char *bar; }\n  ...\n  FREE_AND_NULL(baz.bar);\n\nThis causes the compiler to barf as `free()` is called: \"error: passing\nargument 1 of ‘free’ discards ‘const’ qualifier from pointer target\ntype\". A naive attempt to remedy this might look like this:\n\n  FREE_AND_NULL((void *)baz.bar);\n\nNow the assignment is problematic: \"error: lvalue required as left\noperand of assignment\".\n\nAdd a `FREE_AND_NULL_CONST()` wrapper macro which acts as\n`FREE_AND_NULL()`, except it casts to `(void *)` when freeing. As a\ndemonstration, use this in two existing code paths that were identified\nby some grepping. Future patches will use it to clean up struct-fields:\n\n  FREE_AND_NULL_CONST(baz.bar);\n\nThis macro is a slightly bigger hammer than `FREE_AND_NULL` and has a\nslightly larger potential for misuse. Document that `FREE_AND_NULL`\nshould be preferred.\n\nSigned-off-by: Martin Ågren <martin.agren@gmail.com>\n---\n argv-array.c      | 3 +--\n git-compat-util.h | 8 ++++++++\n submodule.c       | 3 +--\n 3 files changed, 10 insertions(+), 4 deletions(-)\n\ndiff --git a/argv-array.c b/argv-array.c\nindex 5d370fa33..433a5997a 100644\n--- a/argv-array.c\n+++ b/argv-array.c\n@@ -59,8 +59,7 @@ void argv_array_pop(struct argv_array *array)\n {\n \tif (!array->argc)\n \t\treturn;\n-\tfree((char *)array->argv[array->argc - 1]);\n-\tarray->argv[array->argc - 1] = NULL;\n+\tFREE_AND_NULL_CONST(array->argv[array->argc - 1]);\n \tarray->argc--;\n }\n \ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex cedad4d58..ca3dcbc58 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -815,6 +815,14 @@ extern FILE *fopen_or_warn(const char *path, const char *mode);\n  */\n #define FREE_AND_NULL(p) do { free(p); (p) = NULL; } while (0)\n \n+/*\n+ * FREE_AND_NULL_CONST(ptr) is like FREE_AND_NULL(ptr) except it casts\n+ * to (void *) when calling free. This is useful when handling, e.g., a\n+ * `const char *`, but it can also be misused. Prefer FREE_AND_NULL, and\n+ * use this only when you need to and it is safe to do so.\n+ */\n+#define FREE_AND_NULL_CONST(p) do { free((void *)(p)); (p) = NULL; } while (0)\n+\n #define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))\n #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))\n \ndiff --git a/submodule.c b/submodule.c\nindex 63e7094e1..7759f9050 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -364,8 +364,7 @@ int parse_submodule_update_strategy(const char *value,\n {\n \tenum submodule_update_type type;\n \n-\tfree((void*)dst->command);\n-\tdst->command = NULL;\n+\tFREE_AND_NULL_CONST(dst->command);\n \n \ttype = parse_submodule_update_type(value);\n \tif (type == SM_UPDATE_UNSPECIFIED)\n-- \n2.15.0.rc2.5.g97dd00bb7\n\n"},{"id":"331182","messageId":"CAN0heSpRc5VwuMgusoPBegUSsc3t8USK6hm2wd5CyqNpKUiObg@mail.gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2017-10-27T17:35:22Z","receivedAt":"2017-10-27T17:35:28Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> +               /*\n> +                * have bad (or new) but not good (or old). We could bisect\n> +                * although this is less optimum.\n> +                */\n> +               fprintf(stderr, _(\"Warning: bisecting only with a %s commit\\n\"),\n> +                       terms->term_bad);\n\nMaybe this should use `warning()`?\n\n> -               # have bad (or new) but not good (or old).  we could bisect although\n> -               # this is less optimum.\n> -               eval_gettextln \"Warning: bisecting only with a \\$TERM_BAD commit.\" >&2\n\nI wonder if we can somehow pick up the existing translation? It would\nnow be fuzzy, in some sense, but since the string was originally in a\ndifferent file, maybe the po-tools won't be able to discover the\nfuzzyness? We could add a TRANSLATORS-comment, so that the translators\nknow that this string matches an old one. There are more strings like\nthat in this patch, and maybe in some others as well, I haven't looked.\n\n(Adding Jiang to cc.)\n"},{"id":"331183","messageId":"xmqqshe4bib0.fsf@gitster.mtv.corp.google.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-10-27T17:40:35Z","receivedAt":"2017-10-27T17:40:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Pranit Bauva <pranit.bauva@gmail.com> writes:\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\treturn !printf(_(\"We are not bisecting.\\n\"));\n> +\t\tstrbuf_rtrim(&branch);\n> +\t} else {\n> +\t\tstruct object_id oid;\n> +\n> +\t\tif (get_oid_commit(commit, &oid))\n> +\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n> +\t\tstrbuf_addstr(&branch, commit);\n\nThe original checks \"test -s BISECT_START\" and complains, even when\nan explicit commit is given.  With this change, when the user is not\nbisecting, giving \"git bisect reset master\" goes ahead---it is\nlikely that BISECT_HEAD does not exist and we may hit \"Could not\ncheck out\" error, but if BISECT_HEAD is left behind from a previous\nrun (which is likely completely unrelated to whatever the user\ncurrently is doing), we'd end up doing quite a random thing, no?\n\n> +\t}\n> +\n> +\tif (!file_exists(git_path_bisect_head())) {\n> +\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n> +\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\nHow does this return value affect the value eventually given to\nexit(3), called by somewhere in git.c that called this function?\n\nThe call graph would be\n\n    common-main.c::main()\n    -> git.c::cmd_main()\n       -> handle_builtin()\n          . exit(run_builtin())\n          -> run_builtin()\n             . status = p->fn()\n             -> cmd_bisect__helper()\n                . return bisect_reset()\n                -> bisect_reset()\n                   . return -1\n             . if (status) return status;\n\nSo the -1 is returned throughout the callchain and exit(3) ends up\ngetting it---which is not quite right.  We shouldn't be giving\nnegative value to exit(3).  bisect_clean_state() and other helper\nfunctions may already share the same issue.\n\n> +\t\t}\n> +\t\targv_array_clear(&argv);\n> +\t}\n> +\n> +\tstrbuf_release(&branch);\n> +\treturn bisect_clean_state();\n> +}\n"},{"id":"331184","messageId":"xmqqo9osbghy.fsf@gitster.mtv.corp.google.com","threadId":"47045","inReplyTo":"0102015f5e5ee22c-ea9c3a38-5d42-4dce-a54b-45c59768a70b-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-10-27T18:19:37Z","receivedAt":"2017-10-27T18:19:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Pranit Bauva <pranit.bauva@gmail.com> writes:\n\n> -\t\tbisect_write \"$state\" \"$rev\"\n> +\t\tgit bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n\nI can see why two extra \"terms\" parameters need to be passed to this\nhelper at this step; looking at patches around 4/8 and 6/8 where C\ncode can directly find out what words are used for GOOD and BAD, we\nshould be able to lose these two extra parameters from this helper\nby internally making a call to get_terms() from bisect_write() ;-)\n"},{"id":"331186","messageId":"CAN0heSrWbgNEfeXj0D0SBiyC_9i++qecBcb5Kuf4WtS1wFxKDQ@mail.gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee303-449f1b76-ff53-433c-8973-8b4850466810-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2017-10-27T20:04:47Z","receivedAt":"2017-10-27T20:04:54Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> +       for (i = 0; i < argc; i++) {\n> +               if (!strcmp(argv[i], \"--term-good\"))\n> +                       printf(_(\"%s\\n\"), terms->term_good);\n> +               else if (!strcmp(argv[i], \"--term-bad\"))\n> +                       printf(_(\"%s\\n\"), terms->term_bad);\n\nYou seem to have lost --term-old and --term-new. I also wonder why these\nwould need translating. You break GETTEXT_POISON here, then fix it in\npatch 8/8.\n\nI'm not even sure you need patch 8/8. If I drop these two `_()`, I can\nrun `git rebase -ix \"make GETTEXT_POISON=Yes test\"` on the entire series\nwithout failure. Patch 8/8 also switches to `test_i18ngrep` for some\nusages of `git branch` and for some checks on `.git/BISECT_START`. I'm\nnot sure that's needed.\n\n> +               else\n> +                       error(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n> +                                 \"Supported options are: \"\n> +                                 \"--term-good|--term-old and \"\n> +                                 \"--term-bad|--term-new.\"), argv[i]);\n> +       }\n"},{"id":"331356","messageId":"7d978e14-2eec-23b9-c25f-e6b361101b03@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-10-30T13:22:34Z","receivedAt":"2017-10-30T13:22:42Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 10/27/2017 05:06 PM, Pranit Bauva wrote:\n> A big thanks to Stephan and Ramsay for patiently reviewing my series and\n> helping me get this merged.\n\nYou're welcome. ;)\n\nIn addition to the things mentioned by the other reviewers, only a minor\nthing:\n\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 35d2105f941c6..12754448f7b6a 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n[...]> @@ -106,13 +112,48 @@ static void check_expected_revs(const char\n**revs, int rev_nr)\n>  \t}\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\treturn !printf(_(\"We are not bisecting.\\n\"));\n\nThis is weird; I had to look up the return value of printf first before\nI could understand what you are doing ;) I think that it is meant as a\nshortcut for\n\n\tprintf(_(\"We are not bisecting.\\n\"));\n\treturn 0;\n\nbut please also express it with these two lines. (Or what is the point\nof returning a non-zero value only in the case when nothing could be\nprinted?)\n\nBest,\nStephan\n"},{"id":"331357","messageId":"49b9e9e6-8aeb-9a14-9309-f9274fe13e7d@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee22c-ea9c3a38-5d42-4dce-a54b-45c59768a70b-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-10-30T13:38:35Z","receivedAt":"2017-10-30T13:38:42Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Also just a minor in addition to the others:\n\n> @@ -153,9 +241,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tWRITE_TERMS,\n>  \t\tBISECT_CLEAN_STATE,\n>  \t\tCHECK_EXPECTED_REVS,\n> -\t\tBISECT_RESET\n> +\t\tBISECT_RESET,\n> +\t\tBISECT_WRITE\n>  \t} cmdmode = 0;\n> -\tint no_checkout = 0;\n> +\tint no_checkout = 0, res = 0;\n\nThis last change is not necessary. You never use \"res\".\n\nStephan\n"},{"id":"331360","messageId":"ff95b58e-ed76-ebe3-fee9-7f73f1a0c868@gmx.net","threadId":"47045","inReplyTo":"49b9e9e6-8aeb-9a14-9309-f9274fe13e7d@gmx.net","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-10-30T16:24:17Z","receivedAt":"2017-10-30T16:24:24Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On 10/30/2017 02:38 PM, Stephan Beyer wrote:\n> This last change is not necessary. You never use \"res\".\n\nWhoops, ignore this!\nI compared old and new diff and mixed something up, it seems.\n\nSorry,\nStephan\n"},{"id":"331363","messageId":"af5f503a-6c2c-436f-ae74-cfbb11cb7a7f@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee303-449f1b76-ff53-433c-8973-8b4850466810-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-10-30T16:34:54Z","receivedAt":"2017-10-30T16:35:01Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On 10/27/2017 05:06 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 0f9c3e63821b8..ab0580ce0089a 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\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\treturn error(_(\"no terms defined\"));\n> +\n> +\tif (argc > 1)\n> +\t\treturn error(_(\"--bisect-term requires exactly one argument\"));\n> +\n> +\tif (argc == 0)\n> +\t\treturn !printf(_(\"Your current terms are %s for the old state\\n\"\n> +\t\t\t\t \"and %s for the new state.\\n\"),\n> +\t\t\t\t terms->term_good, terms->term_bad);\n\nSame as in 1/8: you probably want \"printf(...); return 0;\" except there\nis a good reason.\n\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tif (!strcmp(argv[i], \"--term-good\"))\n> +\t\t\tprintf(_(\"%s\\n\"), terms->term_good);\n> +\t\telse if (!strcmp(argv[i], \"--term-bad\"))\n> +\t\t\tprintf(_(\"%s\\n\"), terms->term_bad);\n\nThe last two printfs: I think there is no point in translating \"%s\\n\",\nso using \"%s\\n\" instead of _(\"%s\\n\") looks more reasonable.\n\n> +\t\telse\n> +\t\t\terror(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n> +\t\t\t\t  \"Supported options are: \"\n> +\t\t\t\t  \"--term-good|--term-old and \"\n> +\t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n\nShould this be \"return error(...)\"?\n\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n\nStephan\n"},{"id":"331366","messageId":"c26e1cab-a3d0-8cae-b18b-eaa02ce1240c@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee2f5-3d106a61-7f79-4973-851f-f55a691a6189-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 7/8] bisect--helper: `bisect_start` shell function partially in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-10-30T16:51:52Z","receivedAt":"2017-10-30T16:51:59Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\n> +\t\t\treturn error(_(\"unrecognised option: '%s'\"), arg);\n\nPlease write \"unrecogni_z_ed\".\n\nSince the string for translation changed from\n\t\"unrecognised option: '$arg'\"\nto\n\t\"unrecognised option: '%s'\"\nanyway, it does not result in further work for the translators to\ncorrect it to\n\t\"unrecognized option: '%s'\"\n\nStephan\n"},{"id":"331383","messageId":"CAFZEwPPq30e_5Zp0UZ8UgTG415w3vLq_J6e=GFxThCZdCFjUxA@mail.gmail.com","threadId":"47045","inReplyTo":"xmqqshe4bib0.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:26:28Z","receivedAt":"2017-10-30T17:26:35Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Junio,\n\nOn Fri, Oct 27, 2017 at 11:10 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Pranit Bauva <pranit.bauva@gmail.com> writes:\n>\n>> +static int bisect_reset(const char *commit)\n>> +{\n>> +     struct strbuf branch = STRBUF_INIT;\n>> +\n>> +     if (!commit) {\n>> +             if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1)\n>> +                     return !printf(_(\"We are not bisecting.\\n\"));\n>> +             strbuf_rtrim(&branch);\n>> +     } else {\n>> +             struct object_id oid;\n>> +\n>> +             if (get_oid_commit(commit, &oid))\n>> +                     return error(_(\"'%s' is not a valid commit\"), commit);\n>> +             strbuf_addstr(&branch, commit);\n>\n> The original checks \"test -s BISECT_START\" and complains, even when\n> an explicit commit is given.  With this change, when the user is not\n> bisecting, giving \"git bisect reset master\" goes ahead---it is\n> likely that BISECT_HEAD does not exist and we may hit \"Could not\n> check out\" error, but if BISECT_HEAD is left behind from a previous\n> run (which is likely completely unrelated to whatever the user\n> currently is doing), we'd end up doing quite a random thing, no?\n\nYes. Thanks for mentioning this point. I don't quite remember things\nright now about what made me do this change. There might have been\nsomething which had made me do this change because this isn't just a\nsilly mistake. Any which ways, I couldn't recollect the reason (should\nbe more careful to put code comments).\n\n>> +     }\n>> +\n>> +     if (!file_exists(git_path_bisect_head())) {\n>> +             struct argv_array argv = ARGV_ARRAY_INIT;\n>> +\n>> +             argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n>> +             if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n>> +                     error(_(\"Could not check out original HEAD '%s'. Try \"\n>> +                             \"'git bisect reset <commit>'.\"), branch.buf);\n>> +                     strbuf_release(&branch);\n>> +                     argv_array_clear(&argv);\n>> +                     return -1;\n>\n> How does this return value affect the value eventually given to\n> exit(3), called by somewhere in git.c that called this function?\n>\n> The call graph would be\n>\n>     common-main.c::main()\n>     -> git.c::cmd_main()\n>        -> handle_builtin()\n>           . exit(run_builtin())\n>           -> run_builtin()\n>              . status = p->fn()\n>              -> cmd_bisect__helper()\n>                 . return bisect_reset()\n>                 -> bisect_reset()\n>                    . return -1\n>              . if (status) return status;\n>\n> So the -1 is returned throughout the callchain and exit(3) ends up\n> getting it---which is not quite right.  We shouldn't be giving\n> negative value to exit(3).  bisect_clean_state() and other helper\n> functions may already share the same issue.\n\nI had totally missed that exit() takes only single byte value and thus\nonly positive integers. I think changing it to \"return 1;\" will do.\nThere are a few places in the previous series which use \"return -1;\"\nwhich would need to be changed. I will resend that series.\n\n>> +             }\n>> +             argv_array_clear(&argv);\n>> +     }\n>> +\n>> +     strbuf_release(&branch);\n>> +     return bisect_clean_state();\n>> +}\n\nRegards,\nPranit Bauva\n"},{"id":"331384","messageId":"CAFZEwPN2GpFy6r1vRpS6oB-qC0r5ymGB_q0AJWueLPyGj7-uvw@mail.gmail.com","threadId":"47045","inReplyTo":"7d978e14-2eec-23b9-c25f-e6b361101b03@gmx.net","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:27:47Z","receivedAt":"2017-10-30T17:27:52Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Mon, Oct 30, 2017 at 6:52 PM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit,\n>> +static int bisect_reset(const char *commit)\n>> +{\n>> +     struct strbuf branch = STRBUF_INIT;\n>> +\n>> +     if (!commit) {\n>> +             if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1)\n>> +                     return !printf(_(\"We are not bisecting.\\n\"));\n>\n> This is weird; I had to look up the return value of printf first before\n> I could understand what you are doing ;) I think that it is meant as a\n> shortcut for\n>\n>         printf(_(\"We are not bisecting.\\n\"));\n>         return 0;\n>\n> but please also express it with these two lines. (Or what is the point\n> of returning a non-zero value only in the case when nothing could be\n> printed?)\n\nI was just being a little lazy I suppose. I will stick to doing it in\ntwo lines and avoiding fancy things.\n\nRegards,\nPranit Bauva\n"},{"id":"331386","messageId":"CAFZEwPM5-e4DVApGPmeLr95t1YseSaswxitq5zY=EYpnucu-yg@mail.gmail.com","threadId":"47045","inReplyTo":"c26e1cab-a3d0-8cae-b18b-eaa02ce1240c@gmx.net","subject":"Re: [PATCH v16 Part II 7/8] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:28:23Z","receivedAt":"2017-10-30T17:28:31Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Mon, Oct 30, 2017 at 10:21 PM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n>> +                     return error(_(\"unrecognised option: '%s'\"), arg);\n>\n> Please write \"unrecogni_z_ed\".\n>\n> Since the string for translation changed from\n>         \"unrecognised option: '$arg'\"\n> to\n>         \"unrecognised option: '%s'\"\n> anyway, it does not result in further work for the translators to\n> correct it to\n>         \"unrecognized option: '%s'\"\n\nYeah Sure!\n\nRegards,\nPranit Bauva\n"},{"id":"331387","messageId":"CAFZEwPMpsJAQP6ZGNUTi+A_27o7_mMRD8p=3RAf0fywjOjY0vA@mail.gmail.com","threadId":"47045","inReplyTo":"af5f503a-6c2c-436f-ae74-cfbb11cb7a7f@gmx.net","subject":"Re: [PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:31:32Z","receivedAt":"2017-10-30T17:31:38Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Mon, Oct 30, 2017 at 10:04 PM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> On 10/27/2017 05:06 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 0f9c3e63821b8..ab0580ce0089a 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n> [...]\n>> +static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>> +{\n>> +     int i;\n>> +\n>> +     if (get_terms(terms))\n>> +             return error(_(\"no terms defined\"));\n>> +\n>> +     if (argc > 1)\n>> +             return error(_(\"--bisect-term requires exactly one argument\"));\n>> +\n>> +     if (argc == 0)\n>> +             return !printf(_(\"Your current terms are %s for the old state\\n\"\n>> +                              \"and %s for the new state.\\n\"),\n>> +                              terms->term_good, terms->term_bad);\n>\n> Same as in 1/8: you probably want \"printf(...); return 0;\" except there\n> is a good reason.\n\nNo good reason. I will make the change.\n\n>> +\n>> +     for (i = 0; i < argc; i++) {\n>> +             if (!strcmp(argv[i], \"--term-good\"))\n>> +                     printf(_(\"%s\\n\"), terms->term_good);\n>> +             else if (!strcmp(argv[i], \"--term-bad\"))\n>> +                     printf(_(\"%s\\n\"), terms->term_bad);\n>\n> The last two printfs: I think there is no point in translating \"%s\\n\",\n> so using \"%s\\n\" instead of _(\"%s\\n\") looks more reasonable.\n\nAlso this probably does weird things with GETTEXT_POISON. I am\ninvestigating what's happening as Martin pointed out in other thread..\n\n>> +             else\n>> +                     error(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n>> +                               \"Supported options are: \"\n>> +                               \"--term-good|--term-old and \"\n>> +                               \"--term-bad|--term-new.\"), argv[i]);\n>\n> Should this be \"return error(...)\"?\n\nYeah. I missed this\n\n>> +     }\n>> +\n>> +     return 0;\n>> +}\n>> +\n>\n> Stephan\n\nRegards,\nPranit Bauva\n"},{"id":"331389","messageId":"CAFZEwPP7dkWwRJD2ohDfnV_Phb0ga7YPZoVC920JPrQXLAGekw@mail.gmail.com","threadId":"47045","inReplyTo":"20171027172845.15437-1-martin.agren@gmail.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:35:15Z","receivedAt":"2017-10-30T17:35:20Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Martin,\n\nOn Fri, Oct 27, 2017 at 10:58 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> +static void free_terms(struct bisect_terms *terms)\n>> +{\n>> +       if (!terms->term_good)\n>> +               free((void *) terms->term_good);\n>> +       if (!terms->term_bad)\n>> +               free((void *) terms->term_bad);\n>> +}\n>\n> These look like no-ops. Remove `!` for correctness, or `if (...)` for\n> simplicity, since `free()` can handle NULL.\n\nI probably forgot to do this here. I will make the change.\n\n> You leave the pointers dangling, but you're ok for now since this is the\n> last thing that happens in `cmd_bisect__helper()`. Your later patches\n> add more users, but they're also ok, since they immediately assign new\n> values.\n>\n> In case you (and others) find it useful, the below is a patch I've been\n> sitting on for a while as part of a series to plug various memory-leaks.\n> `FREE_AND_NULL_CONST()` would be useful in precisely these situations.\n\nHonestly, I wouldn't be the best person to judge this.\n\nRegards,\nPranit Bauva\n"},{"id":"331390","messageId":"CAFZEwPOThFTLzfiPWs_2NVQ3BbQ26asTOyvGp72L-_OEuTfujQ@mail.gmail.com","threadId":"47045","inReplyTo":"xmqqo9osbghy.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:38:39Z","receivedAt":"2017-10-30T17:38:45Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Junio,\n\nOn Fri, Oct 27, 2017 at 11:49 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Pranit Bauva <pranit.bauva@gmail.com> writes:\n>\n>> -             bisect_write \"$state\" \"$rev\"\n>> +             git bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n>\n> I can see why two extra \"terms\" parameters need to be passed to this\n> helper at this step; looking at patches around 4/8 and 6/8 where C\n> code can directly find out what words are used for GOOD and BAD, we\n> should be able to lose these two extra parameters from this helper\n> by internally making a call to get_terms() from bisect_write() ;-)\n\nYes quite true, but then after converting bisect_skip() we can\ncompletely get rid of this line and then it won't be needed in the\nported C code.\n\nPS: I have already ported that function but those patches are local as of now.\n\nRegards,\nPranit Bauva\n"},{"id":"331394","messageId":"CAFZEwPPH+pZQ2OtQjbDqjz3L_WCU2UvRQx60WFg8y-jTNUKnQQ@mail.gmail.com","threadId":"47045","inReplyTo":"CAN0heSpRc5VwuMgusoPBegUSsc3t8USK6hm2wd5CyqNpKUiObg@mail.gmail.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:40:59Z","receivedAt":"2017-10-30T17:41:06Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Martin,\n\nOn Fri, Oct 27, 2017 at 11:05 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> +               /*\n>> +                * have bad (or new) but not good (or old). We could bisect\n>> +                * although this is less optimum.\n>> +                */\n>> +               fprintf(stderr, _(\"Warning: bisecting only with a %s commit\\n\"),\n>> +                       terms->term_bad);\n>\n> Maybe this should use `warning()`?\n\nYeah. That would be better.\n\n>> -               # have bad (or new) but not good (or old).  we could bisect although\n>> -               # this is less optimum.\n>> -               eval_gettextln \"Warning: bisecting only with a \\$TERM_BAD commit.\" >&2\n>\n> I wonder if we can somehow pick up the existing translation? It would\n> now be fuzzy, in some sense, but since the string was originally in a\n> different file, maybe the po-tools won't be able to discover the\n> fuzzyness? We could add a TRANSLATORS-comment, so that the translators\n> know that this string matches an old one. There are more strings like\n> that in this patch, and maybe in some others as well, I haven't looked.\n>\n> (Adding Jiang to cc.)\n\nSince I am re-rolling my previous series as well, I can make the\nchange in all patches.\n\nRegards,\nPranit Bauva\n"},{"id":"331395","messageId":"CAFZEwPMp_sMNVaQxVJNuNGBt0S28J9Ho41ESLuFgsudc+VLbsw@mail.gmail.com","threadId":"47045","inReplyTo":"CAN0heSrWbgNEfeXj0D0SBiyC_9i++qecBcb5Kuf4WtS1wFxKDQ@mail.gmail.com","subject":"Re: [PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-10-30T17:45:17Z","receivedAt":"2017-10-30T17:45:23Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Martin,\n\nOn Sat, Oct 28, 2017 at 1:34 AM, Martin Ågren <martin.agren@gmail.com> wrote:\n> On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> +       for (i = 0; i < argc; i++) {\n>> +               if (!strcmp(argv[i], \"--term-good\"))\n>> +                       printf(_(\"%s\\n\"), terms->term_good);\n>> +               else if (!strcmp(argv[i], \"--term-bad\"))\n>> +                       printf(_(\"%s\\n\"), terms->term_bad);\n>\n> You seem to have lost --term-old and --term-new. I also wonder why these\n> would need translating. You break GETTEXT_POISON here, then fix it in\n> patch 8/8.\n>\n> I'm not even sure you need patch 8/8. If I drop these two `_()`, I can\n> run `git rebase -ix \"make GETTEXT_POISON=Yes test\"` on the entire series\n> without failure. Patch 8/8 also switches to `test_i18ngrep` for some\n> usages of `git branch` and for some checks on `.git/BISECT_START`. I'm\n> not sure that's needed.\n\nMaybe. I am not quite familiar with what does GETTEXT_POISON exactly\ndoes, so I will probably investigate further in this.\n\nRegards,\nPranit Bauva\n"},{"id":"332041","messageId":"272aaa88-99c2-83a8-7343-c65797566a14@ramsayjones.plus.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 1/8] bisect--helper: `bisect_reset` shell function in C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2017-11-08T00:07:10Z","receivedAt":"2017-11-08T00:07:19Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 27/10/17 16:06, Pranit Bauva wrote:\n> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n> \n> Using `bisect_reset` subcommand is a temporary measure to port shell\n> functions to C so as to use the existing test suite. As more functions\n> are ported, this subcommand would be retired but its implementation will\n> be called by some other method.\n> \n> Note: --bisect-clean-state subcommand has not been retired as there are\n> still a function namely `bisect_start()` which still uses this\n> subcommand.\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> ---\n[snip]\n\nSorry for not responding sooner, I've been a bit busy.\n\nUnfortunately, I have only had time to skim the patches, but\nI haven't noticed anything too serious.\n\n>  builtin/bisect--helper.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-\n>  git-bisect.sh            | 28 ++-------------------------\n>  2 files changed, 50 insertions(+), 27 deletions(-)\n> \n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 35d2105f941c6..12754448f7b6a 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -3,15 +3,21 @@\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_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> @@ -106,13 +112,48 @@ static void check_expected_revs(const char **revs, int rev_nr)\n>  \t}\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\treturn !printf(_(\"We are not bisecting.\\n\"));\n\nI've no idea what this is about! If printf encounters an error, then\nthis will be equivalent to !-1. If printf does not encounter an error,\nthen this will be !<length of output> (whatever that may be, given that\nthe string is marked for translation).\n\nI would suggest that you don't want to do that. ;-)\n\nATB,\nRamsay Jones\n\n"},{"id":"332045","messageId":"a6f8d81e-22de-8dd6-da11-3bda69f8da27@ramsayjones.plus.com","threadId":"47045","inReplyTo":"0102015f5e5ee22c-ea9c3a38-5d42-4dce-a54b-45c59768a70b-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2017-11-08T00:26:20Z","receivedAt":"2017-11-08T00:26:40Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 27/10/17 16:06, Pranit Bauva wrote:\n> Reimplement the `bisect_write` shell function in C and add a\n> `bisect-write` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh\n> \n> Using `--bisect-write` subcommand is a temporary measure to port shell\n> function in 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 some other methods.\n> \n> Note: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\n> from the global shell script thus we need to pass it to the subcommand\n> using the arguments. We then store them in a struct bisect_terms and\n> pass the memory address around functions.\n> \n> Add a log_commit() helper function to write the contents of the commit message\n> header to a file which will be re-used in future parts of the code as\n> well.\n> \n> Also introduce a function free_terms() to free the memory of `struct\n> bisect_terms` and set_terms() to set the values of members in `struct\n> bisect_terms`.\n> \n> Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\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 | 107 +++++++++++++++++++++++++++++++++++++++++++++--\n>  git-bisect.sh            |  25 ++---------\n>  2 files changed, 108 insertions(+), 24 deletions(-)\n> \n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 12754448f7b6a..6295f53c850a8 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -12,15 +12,37 @@ 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_start, \"BISECT_START\")\n>  static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n> +static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\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> +\tN_(\"git bisect--helper --bisect-write <state> <revision> <good_term> <bad_term> [<nolog>]\"),\n>  \tNULL\n>  };\n>  \n> +struct bisect_terms {\n> +\tconst char *term_good;\n> +\tconst char *term_bad;\n> +};\n> +\n> +static void free_terms(struct bisect_terms *terms)\n> +{\n> +\tif (!terms->term_good)\n> +\t\tfree((void *) terms->term_good);> +\tif (!terms->term_bad)\n> +\t\tfree((void *) terms->term_bad);\nYou can pass a NULL pointer to free(), so the conditionals here\nare not required.\n\n> +}\n> +\n> +static void set_terms(struct bisect_terms *terms, const char *bad,\n> +\t\t      const char *good)\n> +{\n> +\tterms->term_good = xstrdup(good);\n> +\tterms->term_bad = xstrdup(bad);\n> +}\n> +\n>  /*\n>   * Check whether the string `term` belongs to the set of strings\n>   * included in the variable arguments.\n> @@ -146,6 +168,72 @@ static int bisect_reset(const char *commit)\n>  \treturn bisect_clean_state();\n>  }\n>  \n> +static void log_commit(FILE *fp, char *fmt, const char *state,\n> +\t\t       struct commit *commit)\n> +{\n> +\tstruct pretty_print_context pp = {0};\n> +\tstruct strbuf commit_msg = STRBUF_INIT;\n> +\tchar *label = xstrfmt(fmt, state);\n> +\n> +\tformat_commit_message(commit, \"%s\", &commit_msg, &pp);\n> +\n> +\tfprintf(fp, \"# %s: [%s] %s\\n\", label, oid_to_hex(&commit->object.oid),\n> +\t\tcommit_msg.buf);\n> +\n> +\tstrbuf_release(&commit_msg);\n> +\tfree(label);\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 object_id oid;\n> +\tstruct commit *commit;\n> +\tFILE *fp = NULL;\n> +\tint retval = 0;\n> +\n> +\tif (!strcmp(state, terms->term_bad)) {\n> +\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n> +\t} else if (one_of(state, terms->term_good, \"skip\", NULL)) {\n> +\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n> +\t} else {\n> +\t\terror(_(\"Bad bisect_write argument: %s\"), state);\n> +\t\tgoto fail;\n> +\t}\n> +\n> +\tif (get_oid(rev, &oid)) {\n> +\t\terror(_(\"couldn't get the oid of the rev '%s'\"), rev);\n> +\t\tgoto fail;\n> +\t}\n> +\n> +\tif (update_ref(NULL, tag.buf, &oid, NULL, 0,\n> +\t\t       UPDATE_REFS_MSG_ON_ERR))\n> +\t\tgoto fail;\n> +\n> +\tfp = fopen(git_path_bisect_log(), \"a\");\n> +\tif (!fp) {\n> +\t\terror_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n> +\t\tgoto fail;\n> +\t}\n> +\n> +\tcommit = lookup_commit_reference(&oid);\n> +\tlog_commit(fp, \"%s\", state, commit);\n> +\n> +\tif (!nolog)\n> +\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n> +\n> +\tgoto finish;\n> +\n> +fail:\n> +\tretval = -1;\n> +finish:\n> +\tif (fp)\n> +\t\tfclose(fp);\n> +\tstrbuf_release(&tag);\n> +\treturn retval;\n> +}\n> +\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n>  \tenum {\n> @@ -153,9 +241,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tWRITE_TERMS,\n>  \t\tBISECT_CLEAN_STATE,\n>  \t\tCHECK_EXPECTED_REVS,\n> -\t\tBISECT_RESET\n> +\t\tBISECT_RESET,\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> @@ -167,10 +256,13 @@ 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-reset\", &cmdmode,\n>  \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n> +\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n> +\t\t\t N_(\"update the refs according to the bisection state and may write it to BISECT_LOG\"), BISECT_WRITE),\n\nIs the \"... and may write it to\" necessary? ;-)\n[The original was just: \"write out the bisection state in BISECT_LOG\"]\n\nATB,\nRamsay Jones\n\n"},{"id":"332047","messageId":"1af55a7a-d58c-6f36-3a2f-25c79cbfb84e@ramsayjones.plus.com","threadId":"47045","inReplyTo":"0102015f5e5ee273-de8fa1d2-1d59-4990-93f5-d36a6cb3f45a-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 4/8] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2017-11-08T00:37:57Z","receivedAt":"2017-11-08T00:38:05Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 27/10/17 16:06, Pranit Bauva wrote:\n> 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\n> git-bisect.sh\n> \n> Using `--check-and-set-terms` subcommand is a temporary measure to port\n> shell function in C so as to use the existing test suite. As more\n> functions are ported, this subcommand will be retired but its\n> implementation will be called by some other methods.\n> \n> check_and_set_terms() sets and receives two global variables namely\n> TERM_GOOD and TERM_BAD in the shell script. Luckily the file BISECT_TERMS\n> also contains the value of those variables so its appropriate to evoke the\n> method get_terms() after calling the subcommand so that it retrieves the\n> value of TERM_GOOD and TERM_BAD from the file BISECT_TERMS. The two\n> global variables are passed as arguments to the subcommand.\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>  builtin/bisect--helper.c | 41 ++++++++++++++++++++++++++++++++++++++++-\n>  git-bisect.sh            | 36 ++++--------------------------------\n>  2 files changed, 44 insertions(+), 33 deletions(-)\n> \n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 6295f53c850a8..65abf8a70c6d9 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> <good_term> <bad_term> [<nolog>]\"),\n> +\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n>  \tNULL\n>  };\n>  \n> @@ -234,6 +235,35 @@ static int bisect_write(const char *state, const char *rev,\n>  \treturn retval;\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 && strcmp(cmd, terms->term_bad) &&\n> +\t    strcmp(cmd, terms->term_good))\n> +\t\treturn error(_(\"Invalid command: you're currently in a \"\n> +\t\t\t\t\"%s/%s bisect\"), terms->term_bad,\n> +\t\t\t\tterms->term_good);\n> +\n> +\tif (!has_term_file) {\n> +\t\tif (one_of(cmd, \"bad\", \"good\", NULL)) {\n> +\t\t\tfree_terms(terms);\n> +\t\t\tset_terms(terms, \"bad\", \"good\");\n> +\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n> +\t\t}\n> +\t\telse if (one_of(cmd, \"new\", \"old\", NULL)) {\n\ncuddle the else: '} else if (one_of(....)) {'\nOR, simply remove the else.\n\nATB,\nRamsay Jones\n\n"},{"id":"332051","messageId":"8d59ede3-043d-6a48-b290-bf4d49e650f1@ramsayjones.plus.com","threadId":"47045","inReplyTo":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2017-11-08T00:48:57Z","receivedAt":"2017-11-08T00:49:05Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 27/10/17 16:06, Pranit Bauva wrote:\n> Reimplement `bisect_next_check` shell function in C and add\n> `bisect-next-check` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh .\n> \n> `bisect_voc` shell function is no longer useful now and is replaced by\n> using a char *[] of \"new|bad\" and \"good|old\" values.\n> \n> Using `--bisect-next-check` is a temporary 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 some other methods.\n> \n> Helped-by: Stephan Beyer <s-beyer@gmx.net>\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 | 91 +++++++++++++++++++++++++++++++++++++++++++++++-\n>  git-bisect.sh            | 60 +++----------------------------\n>  2 files changed, 94 insertions(+), 57 deletions(-)\n> \n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 65abf8a70c6d9..0f9c3e63821b8 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> <good_term> <bad_term> [<nolog>]\"),\n>  \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n> +\tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n>  \tNULL\n>  };\n>  \n> @@ -44,6 +46,11 @@ static void set_terms(struct bisect_terms *terms, const char *bad,\n>  \tterms->term_bad = xstrdup(bad);\n>  }\n>  \n> +static const char *voc[] = {\n> +\t\"bad|new\",\n> +\t\"good|old\"\n> +};\n> +\nIn my version I had this instead:\n\n+static const char *vocab_bad = \"bad|new\";\n+static const char *vocab_good = \"good|old\";\n+\n\nwhich I prefer, because ...\n\n>  /*\n>   * Check whether the string `term` belongs to the set of strings\n>   * included in the variable arguments.\n> @@ -264,6 +271,79 @@ 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 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, retval = 0;\n> +\tconst char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n> +\tconst char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n> +\n> +\tif (ref_exists(bad_ref))\n> +\t\tmissing_bad = 0;\n> +\n> +\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n> +\t\t\t     (void *) &missing_good);\n> +\n> +\tif (!missing_good && !missing_bad)\n> +\t\tgoto finish;\n> +\n> +\tif (!current_term)\n> +\t\tgoto fail;\n> +\n> +\tif (missing_good && !missing_bad && current_term &&\n> +\t    !strcmp(current_term, terms->term_good)) {\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, _(\"Warning: bisecting only with a %s commit\\n\"),\n> +\t\t\tterms->term_bad);\n> +\t\tif (!isatty(0))\n> +\t\t\tgoto finish;\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\tgoto fail;\n> +\n> +\t\tgoto finish;\n> +\t}\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\tvoc[0], voc[1], voc[0], voc[1]);\n\n... this is (arguably) easier to read:\n+\t\t\tvocab_bad, vocab_good, vocab_bad, vocab_good);\n\n> +\t\tgoto fail;\n> +\t} else {\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\tvoc[1], voc[0], voc[1], voc[0]);\n\nditto\n\nATB,\nRamsay Jones\n\n"},{"id":"332054","messageId":"aacc7970-6952-206e-5ef0-10e0cf3d7373@ramsayjones.plus.com","threadId":"47045","inReplyTo":"0102015f5e5ee303-449f1b76-ff53-433c-8973-8b4850466810-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 6/8] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2017-11-08T00:59:00Z","receivedAt":"2017-11-08T00:59:06Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 27/10/17 16:06, Pranit Bauva wrote:\n> Reimplement the `get_terms` and `bisect_terms` shell function in C and\n> add `bisect-terms` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh .\n> \n> Using `--bisect-terms` subcommand is a temporary measure to port shell\n> function in 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 some other methods.\n> \n> Also use error() to report \"no terms defined\" and accordingly change the\n> test in t6030.\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>  builtin/bisect--helper.c    | 69 +++++++++++++++++++++++++++++++++++++++++++--\n>  git-bisect.sh               | 35 ++---------------------\n>  t/t6030-bisect-porcelain.sh |  2 +-\n>  3 files changed, 70 insertions(+), 36 deletions(-)\n> \n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 0f9c3e63821b8..ab0580ce0089a 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> <good_term> <bad_term> [<nolog>]\"),\n>  \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n>  \tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n> +\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n>  \tNULL\n>  };\n>  \n> @@ -344,6 +345,62 @@ static int bisect_next_check(const struct bisect_terms *terms,\n>  \treturn retval;\n>  }\n>  \n> +static int get_terms(struct bisect_terms *terms)\n> +{\n> +\tstruct strbuf str = STRBUF_INIT;\n> +\tFILE *fp = NULL;\n> +\tint res = 0;\n> +\n> +\tfp = fopen(git_path_bisect_terms(), \"r\");\n> +\tif (!fp)\n> +\t\tgoto fail;\n> +\n> +\tfree_terms(terms);\n> +\tstrbuf_getline_lf(&str, fp);\n> +\tterms->term_bad = strbuf_detach(&str, NULL);\n> +\tstrbuf_getline_lf(&str, fp);\n> +\tterms->term_good = strbuf_detach(&str, NULL);\n> +\tgoto finish;\n> +\n> +fail:\n> +\tres = -1;\n> +finish:\n> +\tif (fp)\n> +\t\tfclose(fp);\n> +\tstrbuf_release(&str);\n> +\treturn res;\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\treturn error(_(\"no terms defined\"));\n> +\n> +\tif (argc > 1)\n> +\t\treturn error(_(\"--bisect-term requires exactly one argument\"));\n> +\n> +\tif (argc == 0)\n> +\t\treturn !printf(_(\"Your current terms are %s for the old state\\n\"\n> +\t\t\t\t \"and %s for the new state.\\n\"),\n> +\t\t\t\t terms->term_good, terms->term_bad);\n\nAgain, I don't think you want to do this. :-D\n\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tif (!strcmp(argv[i], \"--term-good\"))> +\t\t\tprintf(_(\"%s\\n\"), terms->term_good);\n> +\t\telse if (!strcmp(argv[i], \"--term-bad\"))\n> +\t\t\tprintf(_(\"%s\\n\"), terms->term_bad);\n> +\t\telse\n\nHere, you want to check for the pairs \"--term-{good,old}\" and\n\"--term-{bad,new}\", so maybe this instead:\n\n+\t\tif (one_of(argv[i], \"--term-good\", \"--term-old\", NULL))\n+\t\t\tprintf(\"%s\\n\", terms->term_good);\n+\t\telse if (one_of(argv[i], \"--term-bad\", \"--term-new\", NULL))\n+\t\t\tprintf(\"%s\\n\", terms->term_bad);\n+\t\telse\n\n> +\t\t\terror(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n> +\t\t\t\t  \"Supported 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\nATB,\nRamsay Jones\n\n\n"},{"id":"332355","messageId":"d0994817-25be-25b8-565e-d81c5f18b210@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-11-12T19:19:46Z","receivedAt":"2017-11-12T19:19:54Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nanother minor:\n\nOn 10/27/2017 05:06 PM, Pranit Bauva wrote:\n> @@ -264,6 +271,79 @@ 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 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, retval = 0;\n> +\tconst char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n> +\tconst char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n> +\n> +\tif (ref_exists(bad_ref))\n> +\t\tmissing_bad = 0;\n> +\n> +\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n> +\t\t\t     (void *) &missing_good);\n> +\n> +\tif (!missing_good && !missing_bad)\n> +\t\tgoto finish;\n> +\n> +\tif (!current_term)\n> +\t\tgoto fail;\n> +\n> +\tif (missing_good && !missing_bad && current_term &&\n\nThis check for \"current_term\" is not necessary; it can be asserted to be\nnon-NULL, otherwise you would have jumped to \"fail\"\n\nStephan\n"},{"id":"332356","messageId":"81ae6057-d293-2dcd-64db-4dac41849131@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-11-12T19:27:40Z","receivedAt":"2017-11-12T19:27:47Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"> @@ -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> <good_term> <bad_term> [<nolog>]\"),\n>  \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n> +\tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n\nI think the order is wrong. It is <good_term> <bad_term> [<term>]\n"},{"id":"332358","messageId":"214cfc63-79a8-a46f-4440-5e223186f2ff@gmx.net","threadId":"47045","inReplyTo":"0102015f5e5ee2ca-bf824205-86e6-4259-b7d7-a68e2fbb087d-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-11-12T20:03:45Z","receivedAt":"2017-11-12T20:03:52Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi again ;)\n\nOn 10/27/2017 05:06 PM, Pranit Bauva wrote:\n> @@ -44,6 +46,11 @@ static void set_terms(struct bisect_terms *terms, const char *bad,\n>  \tterms->term_bad = xstrdup(bad);\n>  }\n>  \n> +static const char *voc[] = {\n> +\t\"bad|new\",\n> +\t\"good|old\"\n> +};\n> +\n>  /*\n>   * Check whether the string `term` belongs to the set of strings\n>   * included in the variable arguments.\n> @@ -264,6 +271,79 @@ 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 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, retval = 0;\n> +\tconst char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n> +\tconst char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n> +\n> +\tif (ref_exists(bad_ref))\n> +\t\tmissing_bad = 0;\n> +\n> +\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n> +\t\t\t     (void *) &missing_good);\n> +\n> +\tif (!missing_good && !missing_bad)\n> +\t\tgoto finish;\n> +\n> +\tif (!current_term)\n> +\t\tgoto fail;\n> +\n> +\tif (missing_good && !missing_bad && current_term &&\n> +\t    !strcmp(current_term, terms->term_good)) {\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, _(\"Warning: bisecting only with a %s commit\\n\"),\n> +\t\t\tterms->term_bad);\n> +\t\tif (!isatty(0))\n> +\t\t\tgoto finish;\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\tgoto fail;\n> +\n> +\t\tgoto finish;\n> +\t}\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\tvoc[0], voc[1], voc[0], voc[1]);\n> +\t\tgoto fail;\n> +\t} else {\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\tvoc[1], voc[0], voc[1], voc[0]);\n> +\t\tgoto fail;\n\nIn both of the above \"error\" calls, you should drop the final \"\\n\"\nbecause \"error\" does that already.\n\nOn the other hand, you have dropped the \"\\n\"s of the orginal error\nmessages. So it should probably be\n\n _(\"You need to give me at least one %s and %s revision.\\n\"\n   \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\")\n\nand\n\n _(\"You need to start by \\\"git bisect start\\\".\\n\"\n   \"You then need to give me at least one %s and %s revision.\\n\"\n   \"You can use \\\"git bisect %s\\\" and \"\\\"git bisect %s\\\" for that.\")\n\nStephan\n"},{"id":"332390","messageId":"xmqqineeal29.fsf@gitster.mtv.corp.google.com","threadId":"47045","inReplyTo":"214cfc63-79a8-a46f-4440-5e223186f2ff@gmx.net","subject":"Re: [PATCH v16 Part II 5/8] bisect--helper: `bisect_next_check` shell function in C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-11-13T03:56:14Z","receivedAt":"2017-11-13T03:56:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> Hi again ;)\n> ...\n> In both of the above \"error\" calls, you should drop the final \"\\n\"\n> because \"error\" does that already.\n>\n> On the other hand, you have dropped the \"\\n\"s of the orginal error\n> messages. So it should probably be\n>\n>  _(\"You need to give me at least one %s and %s revision.\\n\"\n>    \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\")\n>\n> and\n>\n>  _(\"You need to start by \\\"git bisect start\\\".\\n\"\n>    \"You then need to give me at least one %s and %s revision.\\n\"\n>    \"You can use \\\"git bisect %s\\\" and \"\\\"git bisect %s\\\" for that.\")\n>\n> Stephan\n\nThanks for reviews (not just this patch, but for reviews on other\npatches, too).\n"},{"id":"339526","messageId":"20180216012243.14169-1-szeder.dev@gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee2f5-3d106a61-7f79-4973-851f-f55a691a6189-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v16 Part II 7/8] bisect--helper: `bisect_start` shell function partially in C","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2018-02-16T01:22:43Z","receivedAt":"2018-02-16T01:23:06Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index ab0580ce0089a..4ac175c49e80c 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n\n> +\t/*\n> +\t * Check if we are bisecting\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> +\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\tgoto fail;\n> +\t\t\t}\n> +\t\t}\n> +\t} else {\n> +\t\t/* Get the rev from where we start. */\n> +\t\tif (!get_oid(head, &head_oid) &&\n> +\t\t    !starts_with(head, \"refs/heads/\")) {\n> +\t\t\tstrbuf_reset(&start_head);\n> +\t\t\tstrbuf_addstr(&start_head, sha1_to_hex(head_oid.hash));\n\nPlease use oid_to_hex(&head_oid) instead of sha1_to_hex().\n\n"},{"id":"363959","messageId":"nycvar.QRO.7.76.6.1811231111030.41@tvgsbejvaqbjf.bet","threadId":"47045","inReplyTo":"CAFZEwPP7dkWwRJD2ohDfnV_Phb0ga7YPZoVC920JPrQXLAGekw@mail.gmail.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-11-23T10:13:44Z","receivedAt":"2018-11-23T10:13:47Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Pranit,\n\n(Cc:ing Tanushree because they will try to pick up this patch series as\npart of the Outreachy program.)\n\nOn Mon, 30 Oct 2017, Pranit Bauva wrote:\n\n> On Fri, Oct 27, 2017 at 10:58 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> > On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> >> +static void free_terms(struct bisect_terms *terms)\n> >> +{\n> >> +       if (!terms->term_good)\n> >> +               free((void *) terms->term_good);\n> >> +       if (!terms->term_bad)\n> >> +               free((void *) terms->term_bad);\n> >> +}\n> >\n> > These look like no-ops. Remove `!` for correctness, or `if (...)` for\n> > simplicity, since `free()` can handle NULL.\n> \n> I probably forgot to do this here. I will make the change.\n> \n> > You leave the pointers dangling, but you're ok for now since this is the\n> > last thing that happens in `cmd_bisect__helper()`. Your later patches\n> > add more users, but they're also ok, since they immediately assign new\n> > values.\n> >\n> > In case you (and others) find it useful, the below is a patch I've been\n> > sitting on for a while as part of a series to plug various memory-leaks.\n> > `FREE_AND_NULL_CONST()` would be useful in precisely these situations.\n> \n> Honestly, I wouldn't be the best person to judge this.\n\nGit's source code implicitly assumes that any `const` pointer refers to\nmemory owned by another code path. It is therefore probably not a good\nidea to encourage `free()`ing a `const` pointer.\n\nWhich brings me back to the question: who really owns that allocated\nmemory to which `term_good` and `term_bad` refer?\n\nCiao,\nJohannes"},{"id":"363973","messageId":"CAN0heSpaW5C_dMh7gh0ezyzACBgZ2SYXP67E_3moeKNyTvu9xg@mail.gmail.com","threadId":"47045","inReplyTo":"nycvar.QRO.7.76.6.1811231111030.41@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-11-23T12:22:07Z","receivedAt":"2018-11-23T12:22:24Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On Fri, 23 Nov 2018 at 11:13, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> On Mon, 30 Oct 2017, Pranit Bauva wrote:\n>\n> > On Fri, Oct 27, 2017 at 10:58 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> > > On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> > >> +static void free_terms(struct bisect_terms *terms)\n> > >> +{\n> > >> +       if (!terms->term_good)\n> > >> +               free((void *) terms->term_good);\n> > >> +       if (!terms->term_bad)\n> > >> +               free((void *) terms->term_bad);\n> > >> +}\n\n> > > You leave the pointers dangling, but you're ok for now since this is the\n> > > last thing that happens in `cmd_bisect__helper()`. Your later patches\n> > > add more users, but they're also ok, since they immediately assign new\n> > > values.\n> > >\n> > > In case you (and others) find it useful, the below is a patch I've been\n> > > sitting on for a while as part of a series to plug various memory-leaks.\n> > > `FREE_AND_NULL_CONST()` would be useful in precisely these situations.\n> >\n> > Honestly, I wouldn't be the best person to judge this.\n>\n> Git's source code implicitly assumes that any `const` pointer refers to\n> memory owned by another code path. It is therefore probably not a good\n> idea to encourage `free()`ing a `const` pointer.\n\nYeah, I never submitted that patch as part of a real series. I remember\nhaving a funky feeling about it, and whatever use-case I had for this\nmacro, I managed to solve the memory leak in some other way in a\nrewrite.\n\nThanks for a sanity check.\n\nMartin\n"},{"id":"364089","messageId":"nycvar.QRO.7.76.6.1811261918170.41@tvgsbejvaqbjf.bet","threadId":"47045","inReplyTo":"CAN0heSpaW5C_dMh7gh0ezyzACBgZ2SYXP67E_3moeKNyTvu9xg@mail.gmail.com","subject":"Re: [PATCH v16 Part II 2/8] bisect--helper: `bisect_write` shell function in C","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-11-26T18:18:52Z","receivedAt":"2018-11-26T18:19:12Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Martin,\n\nOn Fri, 23 Nov 2018, Martin Ågren wrote:\n\n> On Fri, 23 Nov 2018 at 11:13, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n> > On Mon, 30 Oct 2017, Pranit Bauva wrote:\n> >\n> > > On Fri, Oct 27, 2017 at 10:58 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> > > > On 27 October 2017 at 17:06, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> > > >> +static void free_terms(struct bisect_terms *terms)\n> > > >> +{\n> > > >> +       if (!terms->term_good)\n> > > >> +               free((void *) terms->term_good);\n> > > >> +       if (!terms->term_bad)\n> > > >> +               free((void *) terms->term_bad);\n> > > >> +}\n> \n> > > > You leave the pointers dangling, but you're ok for now since this is the\n> > > > last thing that happens in `cmd_bisect__helper()`. Your later patches\n> > > > add more users, but they're also ok, since they immediately assign new\n> > > > values.\n> > > >\n> > > > In case you (and others) find it useful, the below is a patch I've been\n> > > > sitting on for a while as part of a series to plug various memory-leaks.\n> > > > `FREE_AND_NULL_CONST()` would be useful in precisely these situations.\n> > >\n> > > Honestly, I wouldn't be the best person to judge this.\n> >\n> > Git's source code implicitly assumes that any `const` pointer refers to\n> > memory owned by another code path. It is therefore probably not a good\n> > idea to encourage `free()`ing a `const` pointer.\n> \n> Yeah, I never submitted that patch as part of a real series. I remember\n> having a funky feeling about it, and whatever use-case I had for this\n> macro, I managed to solve the memory leak in some other way in a\n> rewrite.\n> \n> Thanks for a sanity check.\n\nI am glad you agree, and it's just fair that I contribute a sanity check\non this here list when I have benefitted so many times from the same.\n\nCiao,\nJohannes"},{"id":"366034","messageId":"338ebdc97a86295495fa9da638e0b96c2ea746ee.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 1/7] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:31Z","receivedAt":"2019-01-02T15:38:35Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement `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>\nMentored by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c | 51 +++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++--------------------\n 2 files changed, 52 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 4b5fadcbe1..aa6495dc84 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,15 +3,21 @@\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_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@@ -106,13 +112,50 @@ static void check_expected_revs(const char **revs, int rev_nr)\n \t}\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+\n+\t\tif (get_oid_commit(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+\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\tstrbuf_release(&branch);\n+\t\t\targv_array_clear(&argv);\n+\t\t\treturn error(_(\"could not check out original\"\n+\t\t\t\t       \" HEAD '%s'. Try 'git bisect\"\n+\t\t\t\t       \"reset <commit>'.\"), branch.buf);\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\tCHECK_EXPECTED_REVS\n+\t\tCHECK_EXPECTED_REVS,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -124,6 +167,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, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\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@@ -149,6 +194,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tcase CHECK_EXPECTED_REVS:\n \t\tcheck_expected_revs(argv, argc);\n \t\treturn 0;\n+\tcase BISECT_RESET:\n+\t\tif (argc > 1)\n+\t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n+\t\treturn !!bisect_reset(argc ? argv[0] : NULL);\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 54cbfecc5a..afbfbc1f8e 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -393,35 +393,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@@ -613,7 +589,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-- \ngitgitgadget\n\n"},{"id":"366035","messageId":"pull.101.v17.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"0102015f5e5ee171-f30f4868-886f-47a1-a4e4-b4936afc545d-000000@eu-west-1.amazonses.com","subject":"[PATCH v17 0/7] git bisect: convert from shell to C","fromName":"Tanushree Tumane via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:29Z","receivedAt":"2019-01-02T15:38:37Z","isPatch":true,"sender":{"key":"tanushreetumane@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22275398?v=4"},"body":"Changes since Pranit's v16:\n===========================\n\nbisect--helper: bisect_reset shell function in C\n================================================\n\n * The return !printf(...); construct was considered unsafe and disentangled\n   into printf(...); return 0;\n * It is more elegant to release branch and argv first, and then return\n   error(...) than to error(...); release branch; clear argv; return -1;\n * Prefix !! to bisect_reset(...) function call in cmd_bisect__helper(...) \n   because its return value will be given to exit()\n\nbisect--helper: bisect_write shell function in C\n================================================\n\n * The option [--no-log] is passed before <state>.\n * Remove const from struct bisect_terms variables because const pointers\n   refers to memory owned by another code path.\n * Use FREE_AND_NULL(...) in free_terms(...).\n * It makes more sense to free terms before set in set_terms(...) to avoid\n   memory leak.\n * Remove fail: retval = -1; for cleaner code flow, replace goto fail; with \n   retval = -1; goto finish; or retval = error(...); goto finish;\n * It is more consistent to introduce --no-log as option like --no-checkout.\n * Initialize struct bisect_terms terms in cmd_bisect__helper(...).\n * The return res; in cmd_bisect__helper(...) may return -1, so prefixed !! \n   to handle such cases.\n\nbisect--helper: check_and_set_terms shell function in C\n=======================================================\n\n * free_terms() before set_terms() is obsolete as set_terms() frees terms\n   before set.\n\nbisect--helper: bisect_next_check shell function in C\n=====================================================\n\n * [<term>] is first argument of bisect-next-check.\n * vocab_good and vocab_bad for easier readability.\n * Declare *_warning char pointers.\n * Remove fail: label, its only job was to set retval = -1;.\n\nbisect--helper: get_terms & bisect_terms shell function in C\n============================================================\n\n * Remove fail: label, its only job was to set res = -1;.\n * Parse the argv in cmd_bisect__helper() and pass option to bisect_terms().\n\nbisect--helper: bisect_start shell function partially in C\n==========================================================\n\n * Remove fail: label, its only job was to set retval = -1;.\n * Spell correction unrecognised to unrecognized.\n * if (revs.nr) must_write_terms = 1; is more readable than must_write_terms\n   |= !!revs.nr;.\n * error() messages starts with small letters.\n * sha1_to_hex() is old practice.\n * sq_quote_argv() now requires only two args.\n * Instead of nesting ifs, use &&.\n\nPranit Bauva (7):\n  bisect--helper: `bisect_reset` shell function in C\n  bisect--helper: `bisect_write` shell function in C\n  wrapper: move is_empty_file() and rename it as\n    is_empty_or_missing_file()\n  bisect--helper: `check_and_set_terms` shell function in C\n  bisect--helper: `bisect_next_check` shell function in C\n  bisect--helper: `get_terms` & `bisect_terms` shell function in C\n  bisect--helper: `bisect_start` shell function partially in C\n\n builtin/am.c                |  20 +-\n builtin/bisect--helper.c    | 563 +++++++++++++++++++++++++++++++++++-\n cache.h                     |   3 +\n git-bisect.sh               | 314 ++------------------\n t/t6030-bisect-porcelain.sh |   2 +-\n wrapper.c                   |  13 +\n 6 files changed, 595 insertions(+), 320 deletions(-)\n\n\nbase-commit: 7f4e64169352e03476b0ea64e7e2973669e491a2\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-101%2Ftanushree27%2Fgit-bisect_part2_fixup-v17\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-101/tanushree27/git-bisect_part2_fixup-v17\nPull-Request: https://github.com/gitgitgadget/git/pull/101\n\nRange-diff vs v16:\n\n 1:  f1e89ba517 ! 1:  338ebdc97a bisect--helper: `bisect_reset` shell function in C\n     @@ -16,8 +16,9 @@\n      \n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n     @@ -53,8 +54,10 @@\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\treturn !printf(_(\"We are not bisecting.\\n\"));\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     @@ -69,11 +72,11 @@\n      +\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\treturn error(_(\"could not check out original\"\n     ++\t\t\t\t       \" HEAD '%s'. Try 'git bisect\"\n     ++\t\t\t\t       \"reset <commit>'.\"), branch.buf);\n      +\t\t}\n      +\t\targv_array_clear(&argv);\n      +\t}\n     @@ -110,7 +113,7 @@\n      +\tcase BISECT_RESET:\n      +\t\tif (argc > 1)\n      +\t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n     -+\t\treturn bisect_reset(argc ? argv[0] : NULL);\n     ++\t\treturn !!bisect_reset(argc ? argv[0] : NULL);\n       \tdefault:\n       \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n       \t}\n 2:  da4ac60ad4 ! 2:  7d6291d9dd bisect--helper: `bisect_write` shell function in C\n     @@ -27,8 +27,9 @@\n          Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n     @@ -44,27 +45,27 @@\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> <good_term> <bad_term> [<nolog>]\"),\n     ++\tN_(\"git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>\"),\n       \tNULL\n       };\n       \n      +struct bisect_terms {\n     -+\tconst char *term_good;\n     -+\tconst char *term_bad;\n     ++\tchar *term_good;\n     ++\tchar *term_bad;\n      +};\n      +\n      +static void free_terms(struct bisect_terms *terms)\n      +{\n     -+\tif (!terms->term_good)\n     -+\t\tfree((void *) terms->term_good);\n     -+\tif (!terms->term_bad)\n     -+\t\tfree((void *) terms->term_bad);\n     ++\tFREE_AND_NULL(terms->term_good);\n     ++\tFREE_AND_NULL(terms->term_bad);\n      +}\n      +\n      +static void set_terms(struct bisect_terms *terms, const char *bad,\n      +\t\t      const char *good)\n      +{\n     ++\tfree((void *)terms->term_good);\n      +\tterms->term_good = xstrdup(good);\n     ++\tfree((void *)terms->term_bad);\n      +\tterms->term_bad = xstrdup(bad);\n      +}\n      +\n     @@ -105,35 +106,33 @@\n      +\t} else if (one_of(state, terms->term_good, \"skip\", NULL)) {\n      +\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n      +\t} else {\n     -+\t\terror(_(\"Bad bisect_write argument: %s\"), state);\n     -+\t\tgoto fail;\n     ++\t\tretval = error(_(\"Bad bisect_write argument: %s\"), state);\n     ++\t\tgoto finish;\n      +\t}\n      +\n      +\tif (get_oid(rev, &oid)) {\n     -+\t\terror(_(\"couldn't get the oid of the rev '%s'\"), rev);\n     -+\t\tgoto fail;\n     ++\t\tretval = error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n     ++\t\tgoto finish;\n      +\t}\n      +\n      +\tif (update_ref(NULL, tag.buf, &oid, NULL, 0,\n     -+\t\t       UPDATE_REFS_MSG_ON_ERR))\n     -+\t\tgoto fail;\n     ++\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n     ++\t\tretval = -1;\n     ++\t\tgoto finish;\n     ++\t}\n      +\n      +\tfp = fopen(git_path_bisect_log(), \"a\");\n      +\tif (!fp) {\n     -+\t\terror_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n     -+\t\tgoto fail;\n     ++\t\tretval = error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n     ++\t\tgoto finish;\n      +\t}\n      +\n     -+\tcommit = lookup_commit_reference(&oid);\n     ++\tcommit = lookup_commit_reference(the_repository, &oid);\n      +\tlog_commit(fp, \"%s\", state, commit);\n      +\n      +\tif (!nolog)\n      +\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n      +\n     -+\tgoto finish;\n     -+\n     -+fail:\n     -+\tretval = -1;\n      +finish:\n      +\tif (fp)\n      +\t\tfclose(fp);\n     @@ -153,7 +152,7 @@\n      +\t\tBISECT_WRITE\n       \t} cmdmode = 0;\n      -\tint no_checkout = 0;\n     -+\tint no_checkout = 0, res = 0;\n     ++\tint no_checkout = 0, res = 0, nolog = 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     @@ -162,31 +161,24 @@\n       \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n       \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n      +\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n     -+\t\t\t N_(\"update the refs according to the bisection state and may write it to BISECT_LOG\"), BISECT_WRITE),\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_BOOL(0, \"no-log\", &nolog,\n     ++\t\t\t N_(\"no log for BISECT_WRITE \")),\n       \t\tOPT_END()\n       \t};\n     -+\tstruct bisect_terms terms;\n     ++\tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\n       \n       \targc = parse_options(argc, argv, prefix, options,\n       \t\t\t     git_bisect_helper_usage, 0);\n     -@@\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      @@\n       \t\tif (argc > 1)\n       \t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n     - \t\treturn bisect_reset(argc ? argv[0] : NULL);\n     + \t\treturn !!bisect_reset(argc ? argv[0] : NULL);\n      +\tcase BISECT_WRITE:\n      +\t\tif (argc != 4 && argc != 5)\n      +\t\t\treturn error(_(\"--bisect-write requires either 4 or 5 arguments\"));\n     -+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n      +\t\tset_terms(&terms, argv[3], argv[2]);\n      +\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n      +\t\tbreak;\n     @@ -195,7 +187,7 @@\n       \t}\n      -\treturn 0;\n      +\tfree_terms(&terms);\n     -+\treturn res;\n     ++\treturn !!res;\n       }\n      \n       diff --git a/git-bisect.sh b/git-bisect.sh\n 3:  8874ae1a3a ! 3:  5f24e7cef2 wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()\n     @@ -9,14 +9,13 @@\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     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/builtin/am.c b/builtin/am.c\n       --- a/builtin/am.c\n       +++ b/builtin/am.c\n      @@\n     - #include \"string-list.h\"\n       #include \"packfile.h\"\n     + #include \"repository.h\"\n       \n      -/**\n      - * Returns 1 if the file is empty or does not exist, 0 otherwise.\n     @@ -61,7 +60,7 @@\n       +++ b/cache.h\n      @@\n        */\n     - void safe_create_dir(const char *dir, int share);\n     + extern int print_sha1_ellipsis(void);\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 4:  7e9fdedc45 ! 4:  4e97a08a10 bisect--helper: `check_and_set_terms` shell function in C\n     @@ -20,8 +20,9 @@\n      \n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n     @@ -29,7 +30,7 @@\n      @@\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> <good_term> <bad_term> [<nolog>]\"),\n     + \tN_(\"git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>\"),\n      +\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n       \tNULL\n       };\n     @@ -53,12 +54,10 @@\n      +\n      +\tif (!has_term_file) {\n      +\t\tif (one_of(cmd, \"bad\", \"good\", NULL)) {\n     -+\t\t\tfree_terms(terms);\n      +\t\t\tset_terms(terms, \"bad\", \"good\");\n      +\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n      +\t\t}\n     -+\t\telse if (one_of(cmd, \"new\", \"old\", NULL)) {\n     -+\t\t\tfree_terms(terms);\n     ++\t\tif (one_of(cmd, \"new\", \"old\", NULL)) {\n      +\t\t\tset_terms(terms, \"new\", \"old\");\n      +\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n      +\t\t}\n     @@ -78,17 +77,17 @@\n      +\t\tBISECT_WRITE,\n      +\t\tCHECK_AND_SET_TERMS\n       \t} cmdmode = 0;\n     - \tint no_checkout = 0, res = 0;\n     + \tint no_checkout = 0, res = 0, nolog = 0;\n       \tstruct option options[] = {\n      @@\n       \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n       \t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n     - \t\t\t N_(\"update the refs according to the bisection state and may write it to BISECT_LOG\"), BISECT_WRITE),\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     + \t\tOPT_BOOL(0, \"no-log\", &nolog,\n      @@\n       \t\tset_terms(&terms, argv[3], argv[2]);\n       \t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n 5:  ca12543868 ! 5:  e9f400b1d6 bisect--helper: `bisect_next_check` shell function in C\n     @@ -17,8 +17,9 @@\n          Helped-by: Stephan Beyer <s-beyer@gmx.net>\n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n     @@ -33,9 +34,9 @@\n       static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n      @@\n       \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n     - \tN_(\"git bisect--helper --bisect-write <state> <revision> <good_term> <bad_term> [<nolog>]\"),\n     + \tN_(\"git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>\"),\n       \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n     -+\tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n     ++\tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\n       \tNULL\n       };\n       \n     @@ -43,10 +44,8 @@\n       \tterms->term_bad = xstrdup(bad);\n       }\n       \n     -+static const char *voc[] = {\n     -+\t\"bad|new\",\n     -+\t\"good|old\"\n     -+};\n     ++static const char *vocab_bad = \"bad|new\";\n     ++static const char *vocab_good = \"good|old\";\n      +\n       /*\n        * Check whether the string `term` belongs to the set of strings\n     @@ -63,6 +62,15 @@\n      +\treturn 1;\n      +}\n      +\n     ++static const char *need_bad_and_good_revision_warning =\n     ++\tN_(\"You need to give me at least one %s and %s revision.\\n\"\n     ++\t   \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\");\n     ++\n     ++static const char *need_bisect_start_warning =\n     ++\tN_(\"You need to start by \\\"git bisect start\\\".\\n\"\n     ++\t   \"You then need to give me at least one %s and %s revision.\\n\"\n     ++\t   \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\");\n     ++\n      +static int bisect_next_check(const struct bisect_terms *terms,\n      +\t\t\t     const char *current_term)\n      +{\n     @@ -79,18 +87,19 @@\n      +\tif (!missing_good && !missing_bad)\n      +\t\tgoto finish;\n      +\n     -+\tif (!current_term)\n     -+\t\tgoto fail;\n     ++\tif (!current_term) {\n     ++\t\tretval = -1;\n     ++\t\tgoto finish;\n     ++\t}\n      +\n     -+\tif (missing_good && !missing_bad && current_term &&\n     ++\tif (missing_good && !missing_bad &&\n      +\t    !strcmp(current_term, terms->term_good)) {\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, _(\"Warning: bisecting only with a %s commit\\n\"),\n     -+\t\t\tterms->term_bad);\n     ++\t\twarning(_(\"bisecting only with a %s commit\"), terms->term_bad);\n      +\t\tif (!isatty(0))\n      +\t\t\tgoto finish;\n      +\t\t/*\n     @@ -100,28 +109,17 @@\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\tgoto fail;\n     -+\n     ++\t\t\tretval = -1;\n      +\t\tgoto finish;\n      +\t}\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\tvoc[0], voc[1], voc[0], voc[1]);\n     -+\t\tgoto fail;\n     ++\t\tretval = error(_(need_bad_and_good_revision_warning),\n     ++\t\t\t       vocab_bad, vocab_good, vocab_bad, vocab_good);\n      +\t} else {\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\tvoc[1], voc[0], voc[1], voc[0]);\n     -+\t\tgoto fail;\n     ++\t\tretval = error(_(need_bisect_start_warning),\n     ++\t\t\t       vocab_good, vocab_bad, vocab_good, vocab_bad);\n      +\t}\n     -+\tgoto finish;\n      +\n     -+fail:\n     -+\tretval = -1;\n      +finish:\n      +\tfree((void *) good_glob);\n      +\tfree((void *) bad_ref);\n     @@ -139,17 +137,17 @@\n      +\t\tCHECK_AND_SET_TERMS,\n      +\t\tBISECT_NEXT_CHECK\n       \t} cmdmode = 0;\n     - \tint no_checkout = 0, res = 0;\n     + \tint no_checkout = 0, res = 0, nolog = 0;\n       \tstruct option options[] = {\n      @@\n     - \t\t\t N_(\"update the refs according to the bisection state and may write it to BISECT_LOG\"), BISECT_WRITE),\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     + \t\tOPT_BOOL(0, \"no-log\", &nolog,\n      @@\n       \t\tset_terms(&terms, argv[2], argv[1]);\n       \t\tres = check_and_set_terms(&terms, argv[0]);\n     @@ -245,8 +243,8 @@\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     + \ttest -n \"$*\" || die \"$(gettext \"bisect run failed: no command provided.\")\"\n     + \n      @@\n       \tfi\n       }\n 6:  db7b281c8c ! 6:  f2b1706e5b bisect--helper: `get_terms` & `bisect_terms` shell function in C\n     @@ -14,18 +14,24 @@\n          Also use error() to report \"no terms defined\" and accordingly change the\n          test in t6030.\n      \n     +    We need to use PARSE_OPT_KEEP_UNKNOWN here to allow for parameters that\n     +    look like options (e.g --term-good) but should not be parsed by\n     +    cmd_bisect__helper(). This change is safe because all other cmdmodes have\n     +    strict argc checks already.\n     +\n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n       +++ b/builtin/bisect--helper.c\n      @@\n     - \tN_(\"git bisect--helper --bisect-write <state> <revision> <good_term> <bad_term> [<nolog>]\"),\n     + \tN_(\"git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>\"),\n       \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n     - \tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n     + \tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\n      +\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n       \tNULL\n       };\n     @@ -41,18 +47,17 @@\n      +\tint res = 0;\n      +\n      +\tfp = fopen(git_path_bisect_terms(), \"r\");\n     -+\tif (!fp)\n     -+\t\tgoto fail;\n     ++\tif (!fp) {\n     ++\t\tres = -1;\n     ++\t\tgoto finish;\n     ++\t}\n      +\n      +\tfree_terms(terms);\n      +\tstrbuf_getline_lf(&str, fp);\n      +\tterms->term_bad = strbuf_detach(&str, NULL);\n      +\tstrbuf_getline_lf(&str, fp);\n      +\tterms->term_good = strbuf_detach(&str, NULL);\n     -+\tgoto finish;\n      +\n     -+fail:\n     -+\tres = -1;\n      +finish:\n      +\tif (fp)\n      +\t\tfclose(fp);\n     @@ -60,32 +65,26 @@\n      +\treturn res;\n      +}\n      +\n     -+static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n     ++static int bisect_terms(struct bisect_terms *terms, const char *option)\n      +{\n     -+\tint i;\n     -+\n      +\tif (get_terms(terms))\n      +\t\treturn error(_(\"no terms defined\"));\n      +\n     -+\tif (argc > 1)\n     -+\t\treturn error(_(\"--bisect-term requires exactly one argument\"));\n     -+\n     -+\tif (argc == 0)\n     -+\t\treturn !printf(_(\"Your current terms are %s for the old state\\n\"\n     -+\t\t\t\t \"and %s for the new state.\\n\"),\n     -+\t\t\t\t terms->term_good, terms->term_bad);\n     -+\n     -+\tfor (i = 0; i < argc; i++) {\n     -+\t\tif (!strcmp(argv[i], \"--term-good\"))\n     -+\t\t\tprintf(_(\"%s\\n\"), terms->term_good);\n     -+\t\telse if (!strcmp(argv[i], \"--term-bad\"))\n     -+\t\t\tprintf(_(\"%s\\n\"), terms->term_bad);\n     -+\t\telse\n     -+\t\t\terror(_(\"BUG: invalid argument %s for 'git bisect terms'.\\n\"\n     -+\t\t\t\t  \"Supported options are: \"\n     -+\t\t\t\t  \"--term-good|--term-old and \"\n     -+\t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n     ++\tif (option == NULL) {\n     ++\t\tprintf(_(\"Your current terms are %s for the old state\\n\"\n     ++\t\t\t \"and %s for the new state.\\n\"),\n     ++\t\t       terms->term_good, terms->term_bad);\n     ++\t\treturn 0;\n      +\t}\n     ++\tif (one_of(option, \"--term-good\", \"--term-old\", NULL))\n     ++\t\tprintf(\"%s\\n\", terms->term_good);\n     ++\telse if (one_of(option, \"--term-bad\", \"--term-new\", NULL))\n     ++\t\tprintf(\"%s\\n\", terms->term_bad);\n     ++\telse\n     ++\t\treturn error(_(\"invalid argument %s for 'git bisect terms'.\\n\"\n     ++\t\t\t       \"Supported options are: \"\n     ++\t\t\t       \"--term-good|--term-old and \"\n     ++\t\t\t       \"--term-bad|--term-new.\"), option);\n      +\n      +\treturn 0;\n      +}\n     @@ -101,7 +100,7 @@\n      +\t\tBISECT_NEXT_CHECK,\n      +\t\tBISECT_TERMS\n       \t} cmdmode = 0;\n     - \tint no_checkout = 0, res = 0;\n     + \tint no_checkout = 0, res = 0, nolog = 0;\n       \tstruct option options[] = {\n      @@\n       \t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n     @@ -111,9 +110,9 @@\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     + \t\tOPT_BOOL(0, \"no-log\", &nolog,\n      @@\n     - \tstruct bisect_terms terms;\n     + \tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\n       \n       \targc = parse_options(argc, argv, prefix, options,\n      -\t\t\t     git_bisect_helper_usage, 0);\n     @@ -128,7 +127,7 @@\n      +\tcase BISECT_TERMS:\n      +\t\tif (argc > 1)\n      +\t\t\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n     -+\t\tres = bisect_terms(&terms, argv, argc);\n     ++\t\tres = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);\n      +\t\tbreak;\n       \tdefault:\n       \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n     @@ -142,7 +141,7 @@\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\tgit bisect--helper --bisect-terms $rev || exit;;\n       \t\t*)\n       \t\t\tdie \"$(gettext \"?? what are you talking about?\")\" ;;\n       \t\tesac\n 7:  e14e913797 ! 7:  87a033b858 bisect--helper: `bisect_start` shell function partially in C\n     @@ -6,7 +6,7 @@\n          `bisect-start` subcommand to `git bisect--helper` to call it from\n          git-bisect.sh .\n      \n     -    The last part is not converted because it calls another shell function\n     +    The last part is not converted because it calls another shell function.\n          `bisect_start` shell function will be completed after the `bisect_next`\n          shell function is ported in C.\n      \n     @@ -18,12 +18,17 @@\n          Also introduce a method `bisect_append_log_quoted` to keep things short\n          and crisp.\n      \n     +    Note that we are a bit lax about command-line parsing because the helper\n     +    is not supposed to be called by the user directly (but only from the git\n     +    bisect script).\n     +\n          Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\n          Helped-by: Stephan Beyer <s-beyer@gmx.net>\n          Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n          Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n     +    Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n          Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n      \n       diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n       --- a/builtin/bisect--helper.c\n     @@ -47,10 +52,10 @@\n       \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n      @@\n       \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n     - \tN_(\"git bisect--helper --bisect-next-check [<term>] <good_term> <bad_term>\"),\n     + \tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\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     ++\t\t\t\t\t     \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n       \tNULL\n       };\n       \n     @@ -67,17 +72,15 @@\n      +\tif (!fp)\n      +\t\treturn -1;\n      +\n     -+\tif (fprintf(fp, \"git bisect start\") < 1)\n     -+\t\tgoto fail;\n     ++\tif (fprintf(fp, \"git bisect start\") < 1) {\n     ++\t\tretval = -1;\n     ++\t\tgoto finish;\n     ++\t}\n      +\n     -+\tsq_quote_argv(&orig_args, argv, 0);\n     ++\tsq_quote_argv(&orig_args, argv);\n      +\tif (fprintf(fp, \"%s\\n\", orig_args.buf) < 1)\n     -+\t\tgoto fail;\n     ++\t\tretval = -1;\n      +\n     -+\tgoto finish;\n     -+\n     -+fail:\n     -+\tretval = -1;\n      +finish:\n      +\tfclose(fp);\n      +\tstrbuf_release(&orig_args);\n     @@ -138,7 +141,7 @@\n      +\t\t\tterms->term_bad = xstrdup(arg);\n      +\t\t} else if (starts_with(arg, \"--\") &&\n      +\t\t\t !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n     -+\t\t\treturn error(_(\"unrecognised option: '%s'\"), arg);\n     ++\t\t\treturn error(_(\"unrecognized option: '%s'\"), arg);\n      +\t\t} else {\n      +\t\t\tchar *commit_id = xstrfmt(\"%s^{commit}\", arg);\n      +\t\t\tif (get_oid(commit_id, &oid) && has_double_dash)\n     @@ -157,7 +160,8 @@\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     ++\tif (revs.nr)\n     ++\t\tmust_write_terms = 1;\n      +\tfor (i = 0; i < revs.nr; i++) {\n      +\t\tif (bad_seen) {\n      +\t\t\tstring_list_append(&states, terms->term_good);\n     @@ -173,7 +177,7 @@\n      +\thead = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, &flags);\n      +\tif (!head)\n      +\t\tif (get_oid(\"HEAD\", &head_oid))\n     -+\t\t\treturn error(_(\"Bad HEAD - I need a HEAD\"));\n     ++\t\t\treturn error(_(\"bad HEAD - I need a HEAD\"));\n      +\n      +\t/*\n      +\t * Check if we are bisecting\n     @@ -188,10 +192,11 @@\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\tgoto fail;\n     ++\t\t\t\tretval = error(_(\"checking out '%s' failed.\"\n     ++\t\t\t\t\t\t \" Try 'git bisect start \"\n     ++\t\t\t\t\t\t \"<valid-branch>'.\"),\n     ++\t\t\t\t\t       start_head.buf);\n     ++\t\t\t\tgoto finish;\n      +\t\t\t}\n      +\t\t}\n      +\t} else {\n     @@ -199,7 +204,7 @@\n      +\t\tif (!get_oid(head, &head_oid) &&\n      +\t\t    !starts_with(head, \"refs/heads/\")) {\n      +\t\t\tstrbuf_reset(&start_head);\n     -+\t\t\tstrbuf_addstr(&start_head, sha1_to_hex(head_oid.hash));\n     ++\t\t\tstrbuf_addstr(&start_head, oid_to_hex(&head_oid));\n      +\t\t} else if (!get_oid(head, &head_oid) &&\n      +\t\t\t   skip_prefix(head, \"refs/heads/\", &head)) {\n      +\t\t\t/*\n     @@ -211,7 +216,7 @@\n      +\t\t\t\treturn error(_(\"won't bisect on cg-seek'ed tree\"));\n      +\t\t\tstrbuf_addstr(&start_head, head);\n      +\t\t} else {\n     -+\t\t\treturn error(_(\"Bad HEAD - strange symbolic ref\"));\n     ++\t\t\treturn error(_(\"bad HEAD - strange symbolic ref\"));\n      +\t\t}\n      +\t}\n      +\n     @@ -236,31 +241,33 @@\n      +\tif (no_checkout) {\n      +\t\tget_oid(start_head.buf, &oid);\n      +\t\tif (update_ref(NULL, \"BISECT_HEAD\", &oid, NULL, 0,\n     -+\t\t\t       UPDATE_REFS_MSG_ON_ERR))\n     -+\t\t\tgoto fail;\n     ++\t\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n     ++\t\t\tretval = -1;\n     ++\t\t\tgoto finish;\n     ++\t\t}\n      +\t}\n      +\n      +\tif (pathspec_pos < argc - 1)\n     -+\t\tsq_quote_argv(&bisect_names, argv + pathspec_pos, 0);\n     ++\t\tsq_quote_argv(&bisect_names, argv + pathspec_pos);\n      +\twrite_file(git_path_bisect_names(), \"%s\\n\", bisect_names.buf);\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\tgoto fail;\n     ++\t\t\t\t revs.items[i].string, terms, 1)) {\n     ++\t\t\tretval = -1;\n     ++\t\t\tgoto finish;\n     ++\t\t}\n      +\n     -+\tif (must_write_terms)\n     -+\t\tif (write_terms(terms->term_bad, terms->term_good))\n     -+\t\t\tgoto fail;\n     ++\tif (must_write_terms && write_terms(terms->term_bad,\n     ++\t\t\t\t\t    terms->term_good)) {\n     ++\t\tretval = -1;\n     ++\t\tgoto finish;\n     ++\t}\n      +\n      +\tretval = bisect_append_log_quoted(argv);\n      +\tif (retval)\n     -+\t\tgoto fail;\n     -+\n     -+\tgoto finish;\n     ++\t\tretval = -1;\n      +\n     -+fail:\n     -+\tretval = -1;\n      +finish:\n      +\tstring_list_clear(&revs, 0);\n      +\tstring_list_clear(&states, 0);\n     @@ -280,7 +287,7 @@\n      +\t\tBISECT_TERMS,\n      +\t\tBISECT_START\n       \t} cmdmode = 0;\n     - \tint no_checkout = 0, res = 0;\n     + \tint no_checkout = 0, res = 0, nolog = 0;\n       \tstruct option options[] = {\n      @@\n       \t\t\t N_(\"check whether bad or good terms exist\"), BISECT_NEXT_CHECK),\n     @@ -290,9 +297,9 @@\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     + \t\tOPT_BOOL(0, \"no-log\", &nolog,\n      @@\n     - \tstruct bisect_terms terms;\n     + \tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\n       \n       \targc = parse_options(argc, argv, prefix, options,\n      -\t\t\t     git_bisect_helper_usage, PARSE_OPT_KEEP_UNKNOWN);\n     @@ -303,7 +310,7 @@\n       \t\tusage_with_options(git_bisect_helper_usage, options);\n      @@\n       \t\t\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n     - \t\tres = bisect_terms(&terms, argv, argc);\n     + \t\tres = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);\n       \t\tbreak;\n      +\tcase BISECT_START:\n      +\t\tset_terms(&terms, \"bad\", \"good\");\n 8:  161bbaced1 < -:  ---------- t6030: make various test to pass GETTEXT_POISON tests\n\n-- \ngitgitgadget\n"},{"id":"366036","messageId":"7d6291d9dda2531646b2a64941338adb98f60dee.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 2/7] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:32Z","receivedAt":"2019-01-02T15:38:38Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement 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\nAdd a log_commit() helper function to write the contents of the commit message\nheader to a file which will be re-used in future parts of the code as\nwell.\n\nAlso introduce a function free_terms() to free the memory of `struct\nbisect_terms` and set_terms() to set the values of members in `struct\nbisect_terms`.\n\nHelped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c | 105 +++++++++++++++++++++++++++++++++++++--\n git-bisect.sh            |  25 ++--------\n 2 files changed, 106 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex aa6495dc84..df821be4b2 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -12,15 +12,37 @@ 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_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\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+\tN_(\"git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tchar *term_good;\n+\tchar *term_bad;\n+};\n+\n+static void free_terms(struct bisect_terms *terms)\n+{\n+\tFREE_AND_NULL(terms->term_good);\n+\tFREE_AND_NULL(terms->term_bad);\n+}\n+\n+static void set_terms(struct bisect_terms *terms, const char *bad,\n+\t\t      const char *good)\n+{\n+\tfree((void *)terms->term_good);\n+\tterms->term_good = xstrdup(good);\n+\tfree((void *)terms->term_bad);\n+\tterms->term_bad = xstrdup(bad);\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -148,6 +170,70 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static void log_commit(FILE *fp, char *fmt, const char *state,\n+\t\t       struct commit *commit)\n+{\n+\tstruct pretty_print_context pp = {0};\n+\tstruct strbuf commit_msg = STRBUF_INIT;\n+\tchar *label = xstrfmt(fmt, state);\n+\n+\tformat_commit_message(commit, \"%s\", &commit_msg, &pp);\n+\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", label, oid_to_hex(&commit->object.oid),\n+\t\tcommit_msg.buf);\n+\n+\tstrbuf_release(&commit_msg);\n+\tfree(label);\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 object_id oid;\n+\tstruct commit *commit;\n+\tFILE *fp = NULL;\n+\tint retval = 0;\n+\n+\tif (!strcmp(state, terms->term_bad)) {\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\t} else if (one_of(state, terms->term_good, \"skip\", NULL)) {\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\t} else {\n+\t\tretval = error(_(\"Bad bisect_write argument: %s\"), state);\n+\t\tgoto finish;\n+\t}\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\tretval = error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t\tgoto finish;\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, &oid, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp) {\n+\t\tretval = error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\t\tgoto finish;\n+\t}\n+\n+\tcommit = lookup_commit_reference(the_repository, &oid);\n+\tlog_commit(fp, \"%s\", state, commit);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&tag);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -155,9 +241,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n \t\tCHECK_EXPECTED_REVS,\n-\t\tBISECT_RESET\n+\t\tBISECT_RESET,\n+\t\tBISECT_WRITE\n \t} cmdmode = 0;\n-\tint no_checkout = 0;\n+\tint no_checkout = 0, res = 0, nolog = 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@@ -169,10 +256,15 @@ 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-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\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_BOOL(0, \"no-log\", &nolog,\n+\t\t\t N_(\"no log for BISECT_WRITE \")),\n \t\tOPT_END()\n \t};\n+\tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -198,8 +290,15 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc > 1)\n \t\t\treturn error(_(\"--bisect-reset requires either no argument or a commit\"));\n \t\treturn !!bisect_reset(argc ? argv[0] : NULL);\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\treturn error(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tset_terms(&terms, argv[3], argv[2]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tfree_terms(&terms);\n+\treturn !!res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex afbfbc1f8e..ebf445223c 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-- \ngitgitgadget\n\n"},{"id":"366037","messageId":"4e97a08a10b2d23d83c1d1b53b78b39fcc6af6ad.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 4/7] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:33Z","receivedAt":"2019-01-02T15:38:38Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement 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\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c | 39 ++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 36 ++++--------------------------------\n 2 files changed, 42 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex df821be4b2..02ea5a9611 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 [--no-log] <state> <revision> <good_term> <bad_term>\"),\n+\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n \tNULL\n };\n \n@@ -234,6 +235,33 @@ static int bisect_write(const char *state, const char *rev,\n \treturn retval;\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 && strcmp(cmd, terms->term_bad) &&\n+\t    strcmp(cmd, terms->term_good))\n+\t\treturn error(_(\"Invalid command: you're currently in a \"\n+\t\t\t\t\"%s/%s bisect\"), terms->term_bad,\n+\t\t\t\tterms->term_good);\n+\n+\tif (!has_term_file) {\n+\t\tif (one_of(cmd, \"bad\", \"good\", NULL)) {\n+\t\t\tset_terms(terms, \"bad\", \"good\");\n+\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n+\t\t}\n+\t\tif (one_of(cmd, \"new\", \"old\", NULL)) {\n+\t\t\tset_terms(terms, \"new\", \"old\");\n+\t\t\treturn write_terms(terms->term_bad, terms->term_good);\n+\t\t}\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@@ -242,7 +270,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_CLEAN_STATE,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_RESET,\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, nolog = 0;\n \tstruct option options[] = {\n@@ -258,6 +287,8 @@ 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, \"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_BOOL(0, \"no-log\", &nolog,\n@@ -296,6 +327,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[3], argv[2]);\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\treturn error(_(\"--check-and-set-terms requires 3 arguments\"));\n+\t\tset_terms(&terms, argv[2], argv[1]);\n+\t\tres = check_and_set_terms(&terms, argv[0]);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex ebf445223c..9e993a8187 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@@ -482,36 +484,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-- \ngitgitgadget\n\n"},{"id":"366038","messageId":"e9f400b1d6e091798d9444046cfbcb67f7afd1b3.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 5/7] bisect--helper: `bisect_next_check` shell function in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:34Z","receivedAt":"2019-01-02T15:38:39Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement `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\n`bisect_voc` shell function is no longer useful now and is replaced by\nusing a char *[] of \"new|bad\" and \"good|old\" values.\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\nHelped-by: Stephan Beyer <s-beyer@gmx.net>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c | 88 +++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 60 ++-------------------------\n 2 files changed, 91 insertions(+), 57 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 02ea5a9611..38ae825b9a 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 [--no-log] <state> <revision> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n+\tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\n \tNULL\n };\n \n@@ -44,6 +46,9 @@ static void set_terms(struct bisect_terms *terms, const char *bad,\n \tterms->term_bad = xstrdup(bad);\n }\n \n+static const char *vocab_bad = \"bad|new\";\n+static const char *vocab_good = \"good|old\";\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -262,6 +267,78 @@ 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 const char *need_bad_and_good_revision_warning =\n+\tN_(\"You need to give me at least one %s and %s revision.\\n\"\n+\t   \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\");\n+\n+static const char *need_bisect_start_warning =\n+\tN_(\"You need to start by \\\"git bisect start\\\".\\n\"\n+\t   \"You then need to give me at least one %s and %s revision.\\n\"\n+\t   \"You can use \\\"git bisect %s\\\" and \\\"git bisect %s\\\" for that.\");\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, retval = 0;\n+\tconst char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n+\tconst char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n+\n+\tif (ref_exists(bad_ref))\n+\t\tmissing_bad = 0;\n+\n+\tfor_each_glob_ref_in(mark_good, good_glob, \"refs/bisect/\",\n+\t\t\t     (void *) &missing_good);\n+\n+\tif (!missing_good && !missing_bad)\n+\t\tgoto finish;\n+\n+\tif (!current_term) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tif (missing_good && !missing_bad &&\n+\t    !strcmp(current_term, terms->term_good)) {\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\twarning(_(\"bisecting only with a %s commit\"), terms->term_bad);\n+\t\tif (!isatty(0))\n+\t\t\tgoto finish;\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\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\tretval = error(_(need_bad_and_good_revision_warning),\n+\t\t\t       vocab_bad, vocab_good, vocab_bad, vocab_good);\n+\t} else {\n+\t\tretval = error(_(need_bisect_start_warning),\n+\t\t\t       vocab_good, vocab_bad, vocab_good, vocab_bad);\n+\t}\n+\n+finish:\n+\tfree((void *) good_glob);\n+\tfree((void *) bad_ref);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -271,7 +348,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_RESET,\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, nolog = 0;\n \tstruct option options[] = {\n@@ -289,6 +367,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_BOOL(0, \"no-log\", &nolog,\n@@ -333,6 +413,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[2], argv[1]);\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\treturn error(_(\"--bisect-next-check requires 2 or 3 arguments\"));\n+\t\tset_terms(&terms, argv[1], argv[0]);\n+\t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 9e993a8187..5ef3e25621 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 \ttest -n \"$*\" || die \"$(gettext \"bisect run failed: no command provided.\")\"\n \n@@ -484,13 +439,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-- \ngitgitgadget\n\n"},{"id":"366039","messageId":"87a033b858d7e6acba2671339f6bdded03dcdc3a.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 7/7] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:36Z","receivedAt":"2019-01-02T15:38:41Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement 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\nAlso introduce a method `bisect_append_log_quoted` to keep things short\nand crisp.\n\nNote that we are a bit lax about command-line parsing because the helper\nis not supposed to be called by the user directly (but only from the git\nbisect script).\n\nHelped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>\nHelped-by: Stephan Beyer <s-beyer@gmx.net>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c | 230 ++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 132 +---------------------\n 2 files changed, 230 insertions(+), 132 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex d61edd3c91..22e669e3b1 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_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\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> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\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@@ -389,6 +394,219 @@ static int bisect_terms(struct bisect_terms *terms, const char *option)\n \treturn 0;\n }\n \n+static int bisect_append_log_quoted(const char **argv)\n+{\n+\tint retval = 0;\n+\tFILE *fp = fopen(git_path_bisect_log(), \"a\");\n+\tstruct strbuf orig_args = STRBUF_INIT;\n+\n+\tif (!fp)\n+\t\treturn -1;\n+\n+\tif (fprintf(fp, \"git bisect start\") < 1) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tsq_quote_argv(&orig_args, argv);\n+\tif (fprintf(fp, \"%s\\n\", orig_args.buf) < 1)\n+\t\tretval = -1;\n+\n+finish:\n+\tfclose(fp);\n+\tstrbuf_release(&orig_args);\n+\treturn retval;\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, retval = 0;\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 object_id head_oid;\n+\tstruct object_id oid;\n+\tconst char *head;\n+\n+\tif (is_bare_repository())\n+\t\tno_checkout = 1;\n+\n+\t/*\n+\t * Check for one bad and then some good revisions\n+\t */\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\tconst char *arg = argv[i];\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\tbreak;\n+\t\t} else if (!strcmp(arg, \"--no-checkout\")) {\n+\t\t\tno_checkout = 1;\n+\t\t} else if (!strcmp(arg, \"--term-good\") ||\n+\t\t\t !strcmp(arg, \"--term-old\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_good);\n+\t\t\tterms->term_good = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg) ||\n+\t\t\t   skip_prefix(arg, \"--term-old=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_good);\n+\t\t\tterms->term_good = xstrdup(arg);\n+\t\t} else if (!strcmp(arg, \"--term-bad\") ||\n+\t\t\t !strcmp(arg, \"--term-new\")) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_bad);\n+\t\t\tterms->term_bad = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg) ||\n+\t\t\t   skip_prefix(arg, \"--term-new=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tfree((void *) terms->term_bad);\n+\t\t\tterms->term_bad = xstrdup(arg);\n+\t\t} else if (starts_with(arg, \"--\") &&\n+\t\t\t !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n+\t\t\treturn error(_(\"unrecognized option: '%s'\"), arg);\n+\t\t} else {\n+\t\t\tchar *commit_id = xstrfmt(\"%s^{commit}\", arg);\n+\t\t\tif (get_oid(commit_id, &oid) && has_double_dash)\n+\t\t\t\tdie(_(\"'%s' does not appear to be a valid \"\n+\t\t\t\t      \"revision\"), arg);\n+\n+\t\t\tstring_list_append(&revs, oid_to_hex(&oid));\n+\t\t\tfree(commit_id);\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+\tif (revs.nr)\n+\t\tmust_write_terms = 1;\n+\tfor (i = 0; i < revs.nr; i++) {\n+\t\tif (bad_seen) {\n+\t\t\tstring_list_append(&states, terms->term_good);\n+\t\t} else {\n+\t\t\tbad_seen = 1;\n+\t\t\tstring_list_append(&states, terms->term_bad);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Verify HEAD\n+\t */\n+\thead = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, &flags);\n+\tif (!head)\n+\t\tif (get_oid(\"HEAD\", &head_oid))\n+\t\t\treturn error(_(\"bad HEAD - I need a HEAD\"));\n+\n+\t/*\n+\t * Check if we are bisecting\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+\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\tretval = error(_(\"checking out '%s' failed.\"\n+\t\t\t\t\t\t \" Try 'git bisect start \"\n+\t\t\t\t\t\t \"<valid-branch>'.\"),\n+\t\t\t\t\t       start_head.buf);\n+\t\t\t\tgoto finish;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\t/* Get the rev from where we start. */\n+\t\tif (!get_oid(head, &head_oid) &&\n+\t\t    !starts_with(head, \"refs/heads/\")) {\n+\t\t\tstrbuf_reset(&start_head);\n+\t\t\tstrbuf_addstr(&start_head, oid_to_hex(&head_oid));\n+\t\t} else if (!get_oid(head, &head_oid) &&\n+\t\t\t   skip_prefix(head, \"refs/heads/\", &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\treturn error(_(\"won't bisect on cg-seek'ed tree\"));\n+\t\t\tstrbuf_addstr(&start_head, head);\n+\t\t} else {\n+\t\t\treturn error(_(\"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+\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, NULL, 0,\n+\t\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\t\tretval = -1;\n+\t\t\tgoto finish;\n+\t\t}\n+\t}\n+\n+\tif (pathspec_pos < argc - 1)\n+\t\tsq_quote_argv(&bisect_names, argv + pathspec_pos);\n+\twrite_file(git_path_bisect_names(), \"%s\\n\", bisect_names.buf);\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\tretval = -1;\n+\t\t\tgoto finish;\n+\t\t}\n+\n+\tif (must_write_terms && write_terms(terms->term_bad,\n+\t\t\t\t\t    terms->term_good)) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tretval = bisect_append_log_quoted(argv);\n+\tif (retval)\n+\t\tretval = -1;\n+\n+finish:\n+\tstring_list_clear(&revs, 0);\n+\tstring_list_clear(&states, 0);\n+\tstrbuf_release(&start_head);\n+\tstrbuf_release(&bisect_names);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -400,7 +618,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, nolog = 0;\n \tstruct option options[] = {\n@@ -422,6 +641,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_BOOL(0, \"no-log\", &nolog,\n@@ -431,7 +652,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\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@@ -477,6 +699,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n \t\tres = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);\n \t\tbreak;\n+\tcase BISECT_START:\n+\t\tset_terms(&terms, \"bad\", \"good\");\n+\t\tres = bisect_start(&terms, no_checkout, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex bdb614e3c2..efee12b8b1 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@@ -198,23 +83,10 @@ bisect_start() {\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\" || exit\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-- \ngitgitgadget\n"},{"id":"366040","messageId":"5f24e7cef26b4b1b6c87be03e5485b182040ece1.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 3/7] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:32Z","receivedAt":"2019-01-02T15:38:42Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nis_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 8f27f3375b..310eefe9e8 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -34,22 +34,6 @@\n #include \"packfile.h\"\n #include \"repository.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@@ -1220,7 +1204,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.\"));\n \t\tdie_user_resolve(state);\n \t}\n@@ -1803,7 +1787,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 ca36b44ee0..9ff7e56b74 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1788,4 +1788,7 @@ void safe_create_dir(const char *dir, int share);\n  */\n extern int print_sha1_ellipsis(void);\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 e4fa9d84cd..ea3cf64d4c 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -690,3 +690,16 @@ int xgethostname(char *buf, size_t len)\n \t\tbuf[len - 1] = 0;\n \treturn ret;\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-- \ngitgitgadget\n\n"},{"id":"366041","messageId":"f2b1706e5be93d8481dfd99fcb4c0a705fd36784.1546443509.git.gitgitgadget@gmail.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"[PATCH v17 6/7] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-01-02T15:38:35Z","receivedAt":"2019-01-02T15:38:43Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"From: Pranit Bauva <pranit.bauva@gmail.com>\n\nReimplement 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\nAlso use error() to report \"no terms defined\" and accordingly change the\ntest in t6030.\n\nWe need to use PARSE_OPT_KEEP_UNKNOWN here to allow for parameters that\nlook like options (e.g --term-good) but should not be parsed by\ncmd_bisect__helper(). This change is safe because all other cmdmodes have\nstrict argc checks already.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\nSigned-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n---\n builtin/bisect--helper.c    | 62 +++++++++++++++++++++++++++++++++++--\n git-bisect.sh               | 35 ++-------------------\n t/t6030-bisect-porcelain.sh |  2 +-\n 3 files changed, 63 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 38ae825b9a..d61edd3c91 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 [--no-log] <state> <revision> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>\"),\n \tN_(\"git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]\"),\n+\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n \tNULL\n };\n \n@@ -339,6 +340,55 @@ static int bisect_next_check(const struct bisect_terms *terms,\n \treturn retval;\n }\n \n+static int get_terms(struct bisect_terms *terms)\n+{\n+\tstruct strbuf str = STRBUF_INIT;\n+\tFILE *fp = NULL;\n+\tint res = 0;\n+\n+\tfp = fopen(git_path_bisect_terms(), \"r\");\n+\tif (!fp) {\n+\t\tres = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tfree_terms(terms);\n+\tstrbuf_getline_lf(&str, fp);\n+\tterms->term_bad = strbuf_detach(&str, NULL);\n+\tstrbuf_getline_lf(&str, fp);\n+\tterms->term_good = strbuf_detach(&str, NULL);\n+\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&str);\n+\treturn res;\n+}\n+\n+static int bisect_terms(struct bisect_terms *terms, const char *option)\n+{\n+\tif (get_terms(terms))\n+\t\treturn error(_(\"no terms defined\"));\n+\n+\tif (option == NULL) {\n+\t\tprintf(_(\"Your current terms are %s for the old state\\n\"\n+\t\t\t \"and %s for the new state.\\n\"),\n+\t\t       terms->term_good, terms->term_bad);\n+\t\treturn 0;\n+\t}\n+\tif (one_of(option, \"--term-good\", \"--term-old\", NULL))\n+\t\tprintf(\"%s\\n\", terms->term_good);\n+\telse if (one_of(option, \"--term-bad\", \"--term-new\", NULL))\n+\t\tprintf(\"%s\\n\", terms->term_bad);\n+\telse\n+\t\treturn error(_(\"invalid argument %s for 'git bisect terms'.\\n\"\n+\t\t\t       \"Supported options are: \"\n+\t\t\t       \"--term-good|--term-old and \"\n+\t\t\t       \"--term-bad|--term-new.\"), option);\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -349,7 +399,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_RESET,\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, nolog = 0;\n \tstruct option options[] = {\n@@ -369,6 +420,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_BOOL(0, \"no-log\", &nolog,\n@@ -378,7 +431,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tstruct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };\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@@ -419,6 +472,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tset_terms(&terms, argv[1], argv[0]);\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\treturn error(_(\"--bisect-terms requires 0 or 1 argument\"));\n+\t\tres = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);\n+\t\tbreak;\n \tdefault:\n \t\treturn error(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 5ef3e25621..bdb614e3c2 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@@ -439,37 +439,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@@ -500,7 +469,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\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex f84ff941c3..55835ee4a4 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -802,7 +802,7 @@ test_expect_success 'bisect terms needs 0 or 1 argument' '\n \ttest_must_fail git bisect terms only-one &&\n \ttest_must_fail git bisect terms 1 2 &&\n \ttest_must_fail git bisect terms 2>actual &&\n-\techo \"no terms defined\" >expected &&\n+\techo \"error: no terms defined\" >expected &&\n \ttest_i18ncmp expected actual\n '\n \n-- \ngitgitgadget\n\n"},{"id":"366060","messageId":"d64492dc-4643-823b-c804-3c152c4d9090@ramsayjones.plus.com","threadId":"47045","inReplyTo":"pull.101.v17.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v17 0/7] git bisect: convert from shell to C","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2019-01-03T01:19:28Z","receivedAt":"2019-01-03T01:19:33Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 02/01/2019 15:38, Tanushree Tumane via GitGitGadget wrote:\n[snip]\n> base-commit: 7f4e64169352e03476b0ea64e7e2973669e491a2\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-101%2Ftanushree27%2Fgit-bisect_part2_fixup-v17\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-101/tanushree27/git-bisect_part2_fixup-v17\n> Pull-Request: https://github.com/gitgitgadget/git/pull/101\n\nI didn't look at the patches, only the range-diff below, and the\nonly thing I noticed was ...\n\n> \n> Range-diff vs v16:\n> \n>  1:  f1e89ba517 ! 1:  338ebdc97a bisect--helper: `bisect_reset` shell function in C\n>      @@ -16,8 +16,9 @@\n>       \n>           Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n>           Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n>      +    Mentored by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n>           Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>      -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n>      +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n>       \n>        diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>        --- a/builtin/bisect--helper.c\n>      @@ -53,8 +54,10 @@\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\treturn !printf(_(\"We are not bisecting.\\n\"));\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>      @@ -69,11 +72,11 @@\n>       +\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\treturn error(_(\"could not check out original\"\n>      ++\t\t\t\t       \" HEAD '%s'. Try 'git bisect\"\n>      ++\t\t\t\t       \"reset <commit>'.\"), branch.buf);\n\n... this 'branch.buf' will refer to the empty 'slopbuf', since\nthe call to 'strbuf_release(&branch)' now precedes this call\nto error().\n\nATB,\nRamsay Jones\n"},{"id":"366246","messageId":"CAJ6Xce1A2RtBtd0FLouAUQRqaOVtTM4z28eYf45HMO6qK-w+fQ@mail.gmail.com","threadId":"47045","inReplyTo":"d64492dc-4643-823b-c804-3c152c4d9090@ramsayjones.plus.com","subject":"Re: [PATCH v17 0/7] git bisect: convert from shell to C","fromName":"TANUSHREE TUMANE","fromEmail":"tanushreetumane@gmail.com","sentAt":"2019-01-07T09:15:45Z","receivedAt":"2019-01-07T09:15:59Z","isPatch":true,"sender":{"key":"tanushreetumane@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22275398?v=4"},"body":"Yes, you are right. I will revert this back.\n\nOn Fri, Jan 4, 2019 at 8:08 PM Ramsay Jones <ramsay@ramsayjones.plus.com> wrote:\n>\n>\n>\n> On 02/01/2019 15:38, Tanushree Tumane via GitGitGadget wrote:\n> [snip]\n> > base-commit: 7f4e64169352e03476b0ea64e7e2973669e491a2\n> > Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-101%2Ftanushree27%2Fgit-bisect_part2_fixup-v17\n> > Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-101/tanushree27/git-bisect_part2_fixup-v17\n> > Pull-Request: https://github.com/gitgitgadget/git/pull/101\n>\n> I didn't look at the patches, only the range-diff below, and the\n> only thing I noticed was ...\n>\n> >\n> > Range-diff vs v16:\n> >\n> >  1:  f1e89ba517 ! 1:  338ebdc97a bisect--helper: `bisect_reset` shell function in C\n> >      @@ -16,8 +16,9 @@\n> >\n> >           Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n> >           Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n> >      +    Mentored by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n> >           Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> >      -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> >      +    Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>\n> >\n> >        diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> >        --- a/builtin/bisect--helper.c\n> >      @@ -53,8 +54,10 @@\n> >       +       struct strbuf branch = STRBUF_INIT;\n> >       +\n> >       +       if (!commit) {\n> >      -+               if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1)\n> >      -+                       return !printf(_(\"We are not bisecting.\\n\"));\n> >      ++               if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n> >      ++                       printf(_(\"We are not bisecting.\\n\"));\n> >      ++                       return 0;\n> >      ++               }\n> >       +               strbuf_rtrim(&branch);\n> >       +       } else {\n> >       +               struct object_id oid;\n> >      @@ -69,11 +72,11 @@\n> >       +\n> >       +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n> >       +               if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n> >      -+                       error(_(\"Could not check out original HEAD '%s'. Try \"\n> >      -+                               \"'git bisect reset <commit>'.\"), branch.buf);\n> >       +                       strbuf_release(&branch);\n> >       +                       argv_array_clear(&argv);\n> >      -+                       return -1;\n> >      ++                       return error(_(\"could not check out original\"\n> >      ++                                      \" HEAD '%s'. Try 'git bisect\"\n> >      ++                                      \"reset <commit>'.\"), branch.buf);\n>\n> ... this 'branch.buf' will refer to the empty 'slopbuf', since\n> the call to 'strbuf_release(&branch)' now precedes this call\n> to error().\n>\n> ATB,\n> Ramsay Jones\n>\n"}]}