{"thread":{"id":"44299","subject":"[PATCH v15 06/27] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","startedAt":"2016-10-14T14:14:36Z","lastAt":"2017-01-01T17:41:17Z","messageCount":82,"participants":["Pranit Bauva","Junio C Hamano","Christian Couder","Matthieu Moy","Stephan Beyer"],"isPatch":true,"patchVersion":15,"patchTotal":27},"messages":[{"id":"304140","messageId":"01020157c38b1a96-b0b1eef2-f637-4840-816f-373c500b7f4d-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 06/27] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:14:36Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"is_empty_file() can help to refactor a lot of code. This will be very\nhelpful in porting \"git bisect\" to C.\n\nSuggested-by: Torsten Bögershausen <tboegi@web.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/am.c | 20 ++------------------\n cache.h      |  3 +++\n wrapper.c    | 13 +++++++++++++\n 3 files changed, 18 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 739b34d..9e1e9d6 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -30,22 +30,6 @@\n #include \"mailinfo.h\"\n \n /**\n- * Returns 1 if the file is empty or does not exist, 0 otherwise.\n- */\n-static int is_empty_file(const char *filename)\n-{\n-\tstruct stat st;\n-\n-\tif (stat(filename, &st) < 0) {\n-\t\tif (errno == ENOENT)\n-\t\t\treturn 1;\n-\t\tdie_errno(_(\"could not stat %s\"), filename);\n-\t}\n-\n-\treturn !st.st_size;\n-}\n-\n-/**\n  * Returns the length of the first line of msg.\n  */\n static int linelen(const char *msg)\n@@ -1324,7 +1308,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \t\tgoto finish;\n \t}\n \n-\tif (is_empty_file(am_path(state, \"patch\"))) {\n+\tif (is_empty_or_missing_file(am_path(state, \"patch\"))) {\n \t\tprintf_ln(_(\"Patch is empty. Was it split wrong?\"));\n \t\tdie_user_resolve(state);\n \t}\n@@ -1896,7 +1880,7 @@ static void am_run(struct am_state *state, int resume)\n \t\tresume = 0;\n \t}\n \n-\tif (!is_empty_file(am_path(state, \"rewritten\"))) {\n+\tif (!is_empty_or_missing_file(am_path(state, \"rewritten\"))) {\n \t\tassert(state->rebasing);\n \t\tcopy_notes_for_rebase(state);\n \t\trun_post_rewrite_hook(state);\ndiff --git a/cache.h b/cache.h\nindex b780a91..49f214b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1916,4 +1916,7 @@ void sleep_millisec(int millisec);\n  */\n void safe_create_dir(const char *dir, int share);\n \n+/* Return 1 if the file is empty or does not exists, 0 otherwise. */\n+extern int is_empty_or_missing_file(const char *filename);\n+\n #endif /* CACHE_H */\ndiff --git a/wrapper.c b/wrapper.c\nindex e7f1979..78f6431 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -679,3 +679,16 @@ void sleep_millisec(int millisec)\n {\n \tpoll(NULL, 0, millisec);\n }\n+\n+int is_empty_or_missing_file(const char *filename)\n+{\n+\tstruct stat st;\n+\n+\tif (stat(filename, &st) < 0) {\n+\t\tif (errno == ENOENT)\n+\t\t\treturn 1;\n+\t\tdie_errno(_(\"could not stat %s\"), filename);\n+\t}\n+\n+\treturn !st.st_size;\n+}\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304141","messageId":"01020157c38b1a86-ea6b7899-f395-4ca9-bdc5-881f548f5d0d-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 05/27] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:15Z","receivedAt":"2016-10-14T14:14:40Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Add test to explicitly check that 'git bisect reset' is working as\nexpected. This is already covered implicitly by the test suite.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n\n---\nI faced this problem while converting `bisect_clean_state` and the tests\nwhere showing breakages but it wasn't clear as to where exactly are they\nbreaking. This will patch  will help in that. Also I tested the test\ncoverage of the test suite before this patch and it covers this (I did\nthis by purposely changing names of files in git-bisect.sh and running\nthe test suite).\n---\n t/t6030-bisect-porcelain.sh | 17 +++++++++++++++++\n 1 file changed, 17 insertions(+)\n\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex 5e5370f..18e7998 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'git bisect reset cleans bisection state properly' '\n+\tgit bisect reset &&\n+\tgit bisect start &&\n+\tgit bisect good $HASH1 &&\n+\tgit bisect bad $HASH4 &&\n+\tgit bisect reset &&\n+\ttest -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_LOG\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_RUN\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_TERMS\" &&\n+\ttest_path_is_missing \"$GIT_DIR/head-name\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_HEAD\" &&\n+\ttest_path_is_missing \"$GIT_DIR/BISECT_START\"\n+'\n+\n test_done\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304142","messageId":"01020157c38b1b18-b81203b0-122f-4244-bfb2-9fac8ae71767-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 22/27] bisect--helper: `bisect_log` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:14:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_log` shell function in C and also add\n`--bisect-log` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nUsing `--bisect-log` subcommand is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and will be called by some\nother method.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 27 ++++++++++++++++++++++++++-\n git-bisect.sh            |  7 +------\n 2 files changed, 27 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 493034c..c18ca07 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -858,6 +858,23 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,\n \treturn -1;\n }\n \n+static int bisect_log(void)\n+{\n+\tint fd, status;\n+\tfd = open(git_path_bisect_log(), O_RDONLY);\n+\tif (fd < 0)\n+\t\treturn -1;\n+\n+\tstatus = copy_fd(fd, 1);\n+\tif (status) {\n+\t\tclose(fd);\n+\t\treturn -1;\n+\t}\n+\n+\tclose(fd);\n+\treturn status;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -870,7 +887,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_NEXT,\n \t\tBISECT_AUTO_NEXT,\n \t\tBISECT_AUTOSTART,\n-\t\tBISECT_STATE\n+\t\tBISECT_STATE,\n+\t\tBISECT_LOG\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -894,6 +912,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n \t\tOPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n \t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n+\t\tOPT_CMDMODE(0, \"bisect-log\", &cmdmode,\n+\t\t\t N_(\"output the contents of BISECT_LOG\"), BISECT_LOG),\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@@ -973,6 +993,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tget_terms(&terms);\n \t\tres = bisect_state(&terms, argv, argc);\n \t\tbreak;\n+\tcase BISECT_LOG:\n+\t\tif (argc > 1)\n+\t\t\tdie(_(\"--bisect-log requires 0 arguments\"));\n+\t\tres = bisect_log();\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex a9eebbb..a47e3b5 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -166,11 +166,6 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n \tdone\n }\n \n-bisect_log () {\n-\ttest -s \"$GIT_DIR/BISECT_LOG\" || die \"$(gettext \"We are not bisecting.\")\"\n-\tcat \"$GIT_DIR/BISECT_LOG\"\n-}\n-\n get_terms () {\n \tif test -s \"$GIT_DIR/BISECT_TERMS\"\n \tthen\n@@ -208,7 +203,7 @@ case \"$#\" in\n \treplay)\n \t\tbisect_replay \"$@\" ;;\n \tlog)\n-\t\tbisect_log ;;\n+\t\tgit bisect--helper --bisect-log ;;\n \trun)\n \t\tbisect_run \"$@\" ;;\n \tterms)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304143","messageId":"01020157c38b1aca-0c26fb8c-404f-4f57-afe7-7ebb552a1002-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 10/27] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:14:56Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `check_and_set_terms` shell function in C and add\n`check-and-set-terms` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh\n\nUsing `--check-and-set-terms` subcommand is a temporary measure to port\nshell function in C so as to use the existing test suite. As more\nfunctions are ported, this subcommand will be retired but its\nimplementation will be called by some other methods.\n\ncheck_and_set_terms() sets and receives two global variables namely\nTERM_GOOD and TERM_BAD in the shell script. Luckily the file BISECT_TERMS\nalso contains the value of those variables so its appropriate to evoke the\nmethod get_terms() after calling the subcommand so that it retrieves the\nvalue of TERM_GOOD and TERM_BAD from the file BISECT_TERMS. The two\nglobal variables are passed as arguments to the subcommand.\n\nAlso introduce set_terms() to copy the `term_good` and `term_bad` into\n`struct bisect_terms` and write it out to the file BISECT_TERMS.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 36 ++++--------------------------------\n 2 files changed, 48 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 3f19b68..c6c11e3 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -20,6 +20,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n+\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tNULL\n };\n \n@@ -212,6 +213,38 @@ static int bisect_write(const char *state, const char *rev,\n \treturn retval;\n }\n \n+static int 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+\treturn write_terms(terms->term_bad, terms->term_good);\n+}\n+\n+static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)\n+{\n+\tint has_term_file = !is_empty_or_missing_file(git_path_bisect_terms());\n+\n+\tif (one_of(cmd, \"skip\", \"start\", \"terms\", NULL))\n+\t\treturn 0;\n+\n+\tif (has_term_file &&\n+\t    strcmp(cmd, terms->term_bad) &&\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\treturn set_terms(terms, \"bad\", \"good\");\n+\t\tif (one_of(cmd, \"new\", \"old\", NULL))\n+\t\t\treturn set_terms(terms, \"new\", \"old\");\n+\t}\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -220,7 +253,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_CLEAN_STATE,\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n-\t\tBISECT_WRITE\n+\t\tBISECT_WRITE,\n+\t\tCHECK_AND_SET_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -236,6 +270,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n \t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n \t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n+\t\tOPT_CMDMODE(0, \"check-and-set-terms\", &cmdmode,\n+\t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -278,6 +314,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tterms.term_bad = xstrdup(argv[3]);\n \t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n \t\tbreak;\n+\tcase CHECK_AND_SET_TERMS:\n+\t\tif (argc != 3)\n+\t\t\tdie(_(\"--check-and-set-terms requires 3 arguments\"));\n+\t\tterms.term_good = xstrdup(argv[1]);\n+\t\tterms.term_bad = xstrdup(argv[2]);\n+\t\tres = check_and_set_terms(&terms, argv[0]);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex dfdec33..bdf2227 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -238,7 +238,8 @@ bisect_skip() {\n bisect_state() {\n \tbisect_autostart\n \tstate=$1\n-\tcheck_and_set_terms $state\n+\tgit bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n+\tget_terms\n \tcase \"$#,$state\" in\n \t0,*)\n \t\tdie \"Please call 'bisect_state' with at least one argument.\" ;;\n@@ -390,7 +391,8 @@ bisect_replay () {\n \t\t\tcommand=\"$bisect\"\n \t\tfi\n \t\tget_terms\n-\t\tcheck_and_set_terms \"$command\"\n+\t\tgit bisect--helper --check-and-set-terms \"$command\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n+\t\tget_terms\n \t\tcase \"$command\" in\n \t\tstart)\n \t\t\tcmd=\"bisect_start $rev\"\n@@ -480,36 +482,6 @@ get_terms () {\n \tfi\n }\n \n-check_and_set_terms () {\n-\tcmd=\"$1\"\n-\tcase \"$cmd\" in\n-\tskip|start|terms) ;;\n-\t*)\n-\t\tif test -s \"$GIT_DIR/BISECT_TERMS\" && test \"$cmd\" != \"$TERM_BAD\" && test \"$cmd\" != \"$TERM_GOOD\"\n-\t\tthen\n-\t\t\tdie \"$(eval_gettext \"Invalid command: you're currently in a \\$TERM_BAD/\\$TERM_GOOD bisect.\")\"\n-\t\tfi\n-\t\tcase \"$cmd\" in\n-\t\tbad|good)\n-\t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\t\t\tthen\n-\t\t\t\tTERM_BAD=bad\n-\t\t\t\tTERM_GOOD=good\n-\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n-\t\t\tfi\n-\t\t\t;;\n-\t\tnew|old)\n-\t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\t\t\tthen\n-\t\t\t\tTERM_BAD=new\n-\t\t\t\tTERM_GOOD=old\n-\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n-\t\t\tfi\n-\t\t\t;;\n-\t\tesac ;;\n-\tesac\n-}\n-\n bisect_voc () {\n \tcase \"$1\" in\n \tbad) echo \"bad|new\" ;;\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304144","messageId":"01020157c38b1b29-65f79716-42c6-4327-acda-8c8d0fe05471-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:14:58Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_replay` shell function in C and also add\n`--bisect-replay` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh\n\nUsing `--bisect-replay` subcommand is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and will be called by some\nother method.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            |  32 +-----------\n 2 files changed, 124 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex c18ca07..b367d8d 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -32,6 +32,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-autostart\"),\n \tN_(\"git bisect--helper --bisect-state (bad|new) [<rev>]\"),\n \tN_(\"git bisect--helper --bisect-state (good|old) [<rev>...]\"),\n+\tN_(\"git bisect--helper --bisect-replay <filename>\"),\n \tNULL\n };\n \n@@ -601,7 +602,6 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \t\t\tterms->term_good = arg;\n \t\t} else if (!strcmp(arg, \"--term-bad\") ||\n \t\t\t !strcmp(arg, \"--term-new\")) {\n-\t\t\tconst char *next_arg;\n \t\t\tif (starts_with(argv[++i], \"'\"))\n \t\t\t\tterms->term_bad = sq_dequote(xstrdup(argv[i]));\n \t\t\telse\n@@ -875,6 +875,117 @@ static int bisect_log(void)\n \treturn status;\n }\n \n+static int get_next_word(const char *line, int pos, struct strbuf *word)\n+{\n+\tint i, len = strlen(line), begin = 0;\n+\tstrbuf_reset(word);\n+\tfor (i = pos; i < len; i++) {\n+\t\tif (line[i] == ' ' && begin)\n+\t\t\treturn i + 1;\n+\n+\t\tif (!begin)\n+\t\t\tbegin = 1;\n+\t\tstrbuf_addch(word, line[i]);\n+\t}\n+\n+\treturn i;\n+}\n+\n+static int bisect_replay(struct bisect_terms *terms, const char *filename)\n+{\n+\tstruct strbuf line = STRBUF_INIT;\n+\tstruct strbuf word = STRBUF_INIT;\n+\tFILE *fp = NULL;\n+\tint res = 0;\n+\n+\tif (is_empty_or_missing_file(filename)) {\n+\t\terror(_(\"no such file with name '%s' exists\"), filename);\n+\t\tres = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tif (bisect_reset(NULL)) {\n+\t\tres = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tfp = fopen(filename, \"r\");\n+\tif (!fp) {\n+\t\tres = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\twhile (strbuf_getline(&line, fp) != EOF) {\n+\t\tint pos = 0;\n+\t\twhile (pos < line.len) {\n+\t\t\tpos = get_next_word(line.buf, pos, &word);\n+\n+\t\t\tif (!strcmp(word.buf, \"git\")) {\n+\t\t\t\tcontinue;\n+\t\t\t} else if (!strcmp(word.buf, \"git-bisect\")) {\n+\t\t\t\tcontinue;\n+\t\t\t} else if (!strcmp(word.buf, \"bisect\")) {\n+\t\t\t\tcontinue;\n+\t\t\t} else if (!strcmp(word.buf, \"#\")) {\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tget_terms(terms);\n+\t\t\tif (check_and_set_terms(terms, word.buf)) {\n+\t\t\t\tres = -1;\n+\t\t\t\tgoto finish;\n+\t\t\t}\n+\n+\t\t\tif (!strcmp(word.buf, \"start\")) {\n+\t\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\t\t\tsq_dequote_to_argv_array(line.buf+pos, &argv);\n+\t\t\t\tif (bisect_start(terms, 0, argv.argv, argv.argc)) {\n+\t\t\t\t\targv_array_clear(&argv);\n+\t\t\t\t\tres = -1;\n+\t\t\t\t\tgoto finish;\n+\t\t\t\t}\n+\t\t\t\targv_array_clear(&argv);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (one_of(word.buf, terms->term_good,\n+\t\t\t    terms->term_bad, \"skip\", NULL)) {\n+\t\t\t\tif (bisect_write(word.buf, line.buf+pos, terms, 0)) {\n+\t\t\t\t\tres = -1;\n+\t\t\t\t\tgoto finish;\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (!strcmp(word.buf, \"terms\")) {\n+\t\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\t\t\tsq_dequote_to_argv_array(line.buf+pos, &argv);\n+\t\t\t\tif (bisect_terms(terms, argv.argv, argv.argc)) {\n+\t\t\t\t\targv_array_clear(&argv);\n+\t\t\t\t\tres = -1;\n+\t\t\t\t\tgoto finish;\n+\t\t\t\t}\n+\t\t\t\targv_array_clear(&argv);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\terror(_(\"?? what are you talking about?\"));\n+\t\t\tres = -1;\n+\t\t\tgoto finish;\n+\t\t}\n+\t}\n+\tgoto finish;\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&line);\n+\tstrbuf_release(&word);\n+\tif (res)\n+\t\treturn -1;\n+\n+\treturn bisect_auto_next(terms, NULL);\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -888,7 +999,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_AUTO_NEXT,\n \t\tBISECT_AUTOSTART,\n \t\tBISECT_STATE,\n-\t\tBISECT_LOG\n+\t\tBISECT_LOG,\n+\t\tBISECT_REPLAY\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -914,6 +1026,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-log\", &cmdmode,\n \t\t\t N_(\"output the contents of BISECT_LOG\"), BISECT_LOG),\n+\t\tOPT_CMDMODE(0, \"bisect-replay\", &cmdmode,\n+\t\t\t N_(\"replay the bisection process from the given file\"), BISECT_REPLAY),\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@@ -998,6 +1112,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--bisect-log requires 0 arguments\"));\n \t\tres = bisect_log();\n \t\tbreak;\n+\tcase BISECT_REPLAY:\n+\t\tif (argc != 1)\n+\t\t\tdie(_(\"--bisect-replay requires 1 argument\"));\n+\t\tterms.term_good = \"good\";\n+\t\tterms.term_bad = \"bad\";\n+\t\tres = bisect_replay(&terms, argv[0]);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex a47e3b5..bf66ee2 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -77,36 +77,6 @@ bisect_visualize() {\n \teval '\"$@\"' --bisect -- $(cat \"$GIT_DIR/BISECT_NAMES\")\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-\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-\t\tif test \"$git\" = \"git-bisect\"\n-\t\tthen\n-\t\t\trev=\"$command\"\n-\t\t\tcommand=\"$bisect\"\n-\t\tfi\n-\t\tget_terms\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\teval \"git bisect--helper --bisect-start $rev\" ;;\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\tgit bisect--helper --bisect-terms $rev  || exit;;\n-\t\t*)\n-\t\t\tdie \"$(gettext \"?? what are you talking about?\")\" ;;\n-\t\tesac\n-\tdone <\"$file\"\n-\tgit bisect--helper --bisect-auto-next\n-}\n-\n bisect_run () {\n \tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit\n \n@@ -201,7 +171,7 @@ case \"$#\" in\n \treset)\n \t\tgit bisect--helper --bisect-reset \"$@\" ;;\n \treplay)\n-\t\tbisect_replay \"$@\" ;;\n+\t\tgit bisect--helper --bisect-replay \"$@\" ;;\n \tlog)\n \t\tgit bisect--helper --bisect-log ;;\n \trun)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304145","messageId":"01020157c38b1a82-dc1c5b57-3e93-4996-87e7-4a1d83cb5817-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 04/27] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:14:59Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_clean_state` shell function in C and add a\n`bisect-clean-state` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nUsing `--bisect-clean-state` subcommand is a measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation  will\nbe called by bisect_reset() and bisect_start().\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n bisect.c                 | 43 +++++++++++++++++++++++++++++++++++++++++++\n bisect.h                 |  2 ++\n builtin/bisect--helper.c | 14 +++++++++++++-\n git-bisect.sh            | 26 +++-----------------------\n 4 files changed, 61 insertions(+), 24 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 6f512c2..45d598d 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -430,6 +430,12 @@ static int read_bisect_refs(void)\n \n static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n+static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n+static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\n \n static void read_bisect_paths(struct argv_array *array)\n {\n@@ -1040,3 +1046,40 @@ int estimate_bisect_steps(int all)\n \n \treturn (e < 3 * x) ? n : n - 1;\n }\n+\n+static int mark_for_removal(const char *refname, const struct object_id *oid,\n+\t\t\t    int flag, void *cb_data)\n+{\n+\tstruct string_list *refs = cb_data;\n+\tchar *ref = xstrfmt(\"refs/bisect%s\", refname);\n+\tstring_list_append(refs, ref);\n+\treturn 0;\n+}\n+\n+int bisect_clean_state(void)\n+{\n+\tint result = 0;\n+\n+\t/* There may be some refs packed during bisection */\n+\tstruct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n+\tfor_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n+\tstring_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n+\tresult = delete_refs(&refs_for_removal, REF_NODEREF);\n+\trefs_for_removal.strdup_strings = 1;\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tunlink_or_warn(git_path_bisect_expected_rev());\n+\tunlink_or_warn(git_path_bisect_ancestors_ok());\n+\tunlink_or_warn(git_path_bisect_log());\n+\tunlink_or_warn(git_path_bisect_names());\n+\tunlink_or_warn(git_path_bisect_run());\n+\tunlink_or_warn(git_path_bisect_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tunlink_or_warn(git_path_head_name());\n+\t/*\n+\t * Cleanup BISECT_START last to support the --no-checkout option\n+\t * introduced in the commit 4796e823a.\n+\t */\n+\tunlink_or_warn(git_path_bisect_start());\n+\n+\treturn result;\n+}\ndiff --git a/bisect.h b/bisect.h\nindex acd12ef..0ae63d4 100644\n--- a/bisect.h\n+++ b/bisect.h\n@@ -28,4 +28,6 @@ extern int estimate_bisect_steps(int all);\n \n extern void read_bisect_terms(const char **bad, const char **good);\n \n+extern int bisect_clean_state(void);\n+\n #endif\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 65cf519..4254d61 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -5,10 +5,15 @@\n #include \"refs.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n+static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n+static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n+static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n+\tN_(\"git bisect--helper --bisect-clean-state\"),\n \tNULL\n };\n \n@@ -83,7 +88,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n-\t\tWRITE_TERMS\n+\t\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -91,6 +97,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n \t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n+\t\tOPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n+\t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -109,6 +117,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n \t\treturn write_terms(argv[0], argv[1]);\n+\tcase BISECT_CLEAN_STATE:\n+\t\tif (argc != 0)\n+\t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n+\t\treturn bisect_clean_state();\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 9ef6cb8..f1202df 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -186,7 +186,7 @@ bisect_start() {\n \t#\n \t# Get rid of any old bisect state.\n \t#\n-\tbisect_clean_state || exit\n+\tgit bisect--helper --bisect-clean-state || exit\n \n \t#\n \t# Change state.\n@@ -195,7 +195,7 @@ bisect_start() {\n \t# We have to trap this to be able to clean up using\n \t# \"bisect_clean_state\".\n \t#\n-\ttrap 'bisect_clean_state' 0\n+\ttrap 'git bisect--helper --bisect-clean-state' 0\n \ttrap 'exit 255' 1 2 3 15\n \n \t#\n@@ -430,27 +430,7 @@ bisect_reset() {\n \t\tdie \"$(eval_gettext \"Could not check out original HEAD '\\$branch'.\n Try 'git bisect reset <commit>'.\")\"\n \tfi\n-\tbisect_clean_state\n-}\n-\n-bisect_clean_state() {\n-\t# There may be some refs packed during bisection.\n-\tgit for-each-ref --format='%(refname) %(objectname)' refs/bisect/\\* |\n-\twhile read ref hash\n-\tdo\n-\t\tgit update-ref -d $ref $hash || exit\n-\tdone\n-\trm -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n-\trm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n-\trm -f \"$GIT_DIR/BISECT_LOG\" &&\n-\trm -f \"$GIT_DIR/BISECT_NAMES\" &&\n-\trm -f \"$GIT_DIR/BISECT_RUN\" &&\n-\trm -f \"$GIT_DIR/BISECT_TERMS\" &&\n-\t# Cleanup head-name if it got left by an old version of git-bisect\n-\trm -f \"$GIT_DIR/head-name\" &&\n-\tgit update-ref -d --no-deref BISECT_HEAD &&\n-\t# clean up BISECT_START last\n-\trm -f \"$GIT_DIR/BISECT_START\"\n+\tgit bisect--helper --bisect-clean-state || exit\n }\n \n bisect_replay () {\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304146","messageId":"01020157c38b1ad1-f3a59b1f-9cdb-4d91-b28e-2501facdcb45-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 09/27] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:00Z","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\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 | 94 ++++++++++++++++++++++++++++++++++++++++++++----\n git-bisect.sh            | 25 +++----------\n 2 files changed, 91 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex c542e8b..3f19b68 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -19,9 +19,15 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n+\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tconst char *term_good;\n+\tconst char *term_bad;\n+};\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -149,6 +155,63 @@ static int check_expected_revs(const char **revs, int rev_nr)\n \treturn 0;\n }\n \n+static int bisect_write(const char *state, const char *rev,\n+\t\t\tconst struct bisect_terms *terms, int nolog)\n+{\n+\tstruct strbuf tag = STRBUF_INIT;\n+\tstruct strbuf commit_name = STRBUF_INIT;\n+\tstruct object_id oid;\n+\tstruct commit *commit;\n+\tstruct pretty_print_context pp = {0};\n+\tFILE *fp = NULL;\n+\tint retval = 0;\n+\n+\tif (!strcmp(state, terms->term_bad))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\telse if (one_of(state, terms->term_good, \"skip\", NULL))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\telse {\n+\t\terror(_(\"Bad bisect_write argument: %s\"), state);\n+\t\tretval = -1;\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\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, oid.hash, 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\terror_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tcommit = lookup_commit_reference(oid.hash);\n+\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n+\t\tcommit_name.buf);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+\tgoto finish;\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstrbuf_release(&tag);\n+\tstrbuf_release(&commit_name);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -156,9 +219,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n \t\tBISECT_RESET,\n-\t\tCHECK_EXPECTED_REVS\n+\t\tCHECK_EXPECTED_REVS,\n+\t\tBISECT_WRITE\n \t} cmdmode = 0;\n-\tint no_checkout = 0;\n+\tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n@@ -170,10 +234,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n+\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n+\t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n \t};\n+\tstruct bisect_terms terms;\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -182,24 +249,37 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n \tswitch (cmdmode) {\n+\tint nolog;\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n-\t\treturn write_terms(argv[0], argv[1]);\n+\t\tres = write_terms(argv[0], argv[1]);\n+\t\tbreak;\n \tcase BISECT_CLEAN_STATE:\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n-\t\treturn bisect_clean_state();\n+\t\tres = bisect_clean_state();\n+\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n-\t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\t\tres = bisect_reset(argc ? argv[0] : NULL);\n+\t\tbreak;\n \tcase CHECK_EXPECTED_REVS:\n-\t\treturn check_expected_revs(argv, argc);\n+\t\tres = check_expected_revs(argv, argc);\n+\t\tbreak;\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n+\t\tterms.term_good = xstrdup(argv[2]);\n+\t\tterms.term_bad = xstrdup(argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\treturn res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex c3e43248..dfdec33 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -144,7 +144,7 @@ bisect_start() {\n \t\t0) state=$TERM_BAD ; bad_seen=1 ;;\n \t\t*) state=$TERM_GOOD ;;\n \t\tesac\n-\t\teval=\"$eval bisect_write '$state' '$rev' 'nolog' &&\"\n+\t\teval=\"$eval git bisect--helper --bisect-write '$state' '$rev' '$TERM_GOOD' '$TERM_BAD' 'nolog' &&\"\n \tdone\n \t#\n \t# Verify HEAD.\n@@ -220,23 +220,6 @@ bisect_start() {\n \ttrap '-' 0\n }\n \n-bisect_write() {\n-\tstate=\"$1\"\n-\trev=\"$2\"\n-\tnolog=\"$3\"\n-\tcase \"$state\" in\n-\t\t\"$TERM_BAD\")\n-\t\t\ttag=\"$state\" ;;\n-\t\t\"$TERM_GOOD\"|skip)\n-\t\t\ttag=\"$state\"-\"$rev\" ;;\n-\t\t*)\n-\t\t\tdie \"$(eval_gettext \"Bad bisect_write argument: \\$state\")\" ;;\n-\tesac\n-\tgit update-ref \"refs/bisect/$tag\" \"$rev\" || exit\n-\techo \"# $state: $(git show-branch $rev)\" >>\"$GIT_DIR/BISECT_LOG\"\n-\ttest -n \"$nolog\" || echo \"git bisect $state $rev\" >>\"$GIT_DIR/BISECT_LOG\"\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -263,7 +246,7 @@ bisect_state() {\n \t\tbisected_head=$(bisect_head)\n \t\trev=$(git rev-parse --verify \"$bisected_head\") ||\n \t\t\tdie \"$(eval_gettext \"Bad rev input: \\$bisected_head\")\"\n-\t\tbisect_write \"$state\" \"$rev\"\n+\t\tgit bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n \t\tgit bisect--helper --check-expected-revs \"$rev\" ;;\n \t2,\"$TERM_BAD\"|*,\"$TERM_GOOD\"|*,skip)\n \t\tshift\n@@ -276,7 +259,7 @@ bisect_state() {\n \t\tdone\n \t\tfor rev in $hash_list\n \t\tdo\n-\t\t\tbisect_write \"$state\" \"$rev\"\n+\t\t\tgit bisect--helper --bisect-write \"$state\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit\n \t\tdone\n \t\tgit bisect--helper --check-expected-revs $hash_list ;;\n \t*,\"$TERM_BAD\")\n@@ -413,7 +396,7 @@ bisect_replay () {\n \t\t\tcmd=\"bisect_start $rev\"\n \t\t\teval \"$cmd\" ;;\n \t\t\"$TERM_GOOD\"|\"$TERM_BAD\"|skip)\n-\t\t\tbisect_write \"$command\" \"$rev\" ;;\n+\t\t\tgit bisect--helper --bisect-write \"$command\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit;;\n \t\tterms)\n \t\t\tbisect_terms $rev ;;\n \t\t*)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304147","messageId":"01020157c38b1b3c-d866ad23-6405-4571-bc5c-aeb917a49fea-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 20/27] bisect--helper: retire `--check-expected-revs` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:02Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--check-expected-revs` subcommand is no longer used in the shell\nscript and the function `check_expected_revs()` is called from the C\nimplementation of `bisect_next()`.\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 | 6 ------\n 1 file changed, 6 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 1481c6d..d5fe35b 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -864,7 +864,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tenum {\n \t\tWRITE_TERMS = 1,\n \t\tBISECT_RESET,\n-\t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n \t\tBISECT_NEXT_CHECK,\n@@ -881,8 +880,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n-\t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n-\t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n \t\tOPT_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@@ -926,9 +923,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n \t\tres = bisect_reset(argc ? argv[0] : NULL);\n \t\tbreak;\n-\tcase CHECK_EXPECTED_REVS:\n-\t\tres = check_expected_revs(argv, argc);\n-\t\tbreak;\n \tcase BISECT_WRITE:\n \t\tif (argc != 4 && argc != 5)\n \t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304148","messageId":"01020157c38b1ad5-0f90c88e-2077-4155-94e9-7d71dbbac38f-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 12/27] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:03Z","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    | 72 +++++++++++++++++++++++++++++++++++++++++++--\n git-bisect.sh               | 35 ++--------------------\n t/t6030-bisect-porcelain.sh |  2 +-\n 3 files changed, 73 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 317d671..6a5878c 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -23,6 +23,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n+\tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n \tNULL\n };\n \n@@ -343,6 +344,65 @@ 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+\tfp = fopen(git_path_bisect_terms(), \"r\");\n+\tif (!fp) {\n+\t\tres = -1;\n+\t\tgoto finish;\n+\t}\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+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+\tconst char bisect_term_usage[] =\n+\"git bisect--helper --bisect-terms [--term-good | --term-bad | ]\"\n+\"--term-old | --term-new\";\n+\n+\tif (get_terms(terms))\n+\t\treturn error(_(\"no terms defined\"));\n+\n+\tif (argc > 1) {\n+\t\tusage(bisect_term_usage);\n+\t\treturn -1;\n+\t}\n+\n+\tif (argc == 0) {\n+\t\tprintf(_(\"Your current terms are %s for the old state\\nand \"\n+\t\t       \"%s for the new state.\\n\"), terms->term_good,\n+\t\t       terms->term_bad);\n+\t\treturn 0;\n+\t}\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tif (!strcmp(argv[i], \"--term-good\"))\n+\t\t\tprintf(\"%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\tdie(_(\"invalid argument %s for 'git bisect \"\n+\t\t\t\t  \"terms'.\\nSupported options are: \"\n+\t\t\t\t  \"--term-good|--term-old and \"\n+\t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n+\t}\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -353,7 +413,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n-\t\tBISECT_NEXT_CHECK\n+\t\tBISECT_NEXT_CHECK,\n+\t\tBISECT_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -373,6 +434,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@@ -380,7 +443,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@@ -429,6 +492,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tterms.term_bad = xstrdup(argv[1]);\n \t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n \t\tbreak;\n+\tcase BISECT_TERMS:\n+\t\tif (argc > 1)\n+\t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n+\t\tres = bisect_terms(&terms, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex fe6c9d0..d6c8b5a 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -355,7 +355,7 @@ bisect_replay () {\n \t\t\"$TERM_GOOD\"|\"$TERM_BAD\"|skip)\n \t\t\tgit bisect--helper --bisect-write \"$command\" \"$rev\" \"$TERM_GOOD\" \"$TERM_BAD\" || exit;;\n \t\tterms)\n-\t\t\tbisect_terms $rev ;;\n+\t\t\tgit bisect--helper --bisect-terms $rev  || exit;;\n \t\t*)\n \t\t\tdie \"$(gettext \"?? what are you talking about?\")\" ;;\n \t\tesac\n@@ -437,37 +437,6 @@ get_terms () {\n \tfi\n }\n \n-bisect_terms () {\n-\tget_terms\n-\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n-\tthen\n-\t\tdie \"$(gettext \"no terms defined\")\"\n-\tfi\n-\tcase \"$#\" in\n-\t0)\n-\t\tgettextln \"Your current terms are $TERM_GOOD for the old state\n-and $TERM_BAD for the new state.\"\n-\t\t;;\n-\t1)\n-\t\targ=$1\n-\t\tcase \"$arg\" in\n-\t\t\t--term-good|--term-old)\n-\t\t\t\tprintf '%s\\n' \"$TERM_GOOD\"\n-\t\t\t\t;;\n-\t\t\t--term-bad|--term-new)\n-\t\t\t\tprintf '%s\\n' \"$TERM_BAD\"\n-\t\t\t\t;;\n-\t\t\t*)\n-\t\t\t\tdie \"$(eval_gettext \"invalid argument \\$arg for 'git bisect terms'.\n-Supported options are: --term-good|--term-old and --term-bad|--term-new.\")\"\n-\t\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t*)\n-\t\tusage ;;\n-\tesac\n-}\n-\n case \"$#\" in\n 0)\n \tusage ;;\n@@ -498,7 +467,7 @@ case \"$#\" in\n \trun)\n \t\tbisect_run \"$@\" ;;\n \tterms)\n-\t\tbisect_terms \"$@\" ;;\n+\t\tgit bisect--helper --bisect-terms \"$@\" || exit;;\n \t*)\n \t\tusage ;;\n \tesac\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex 18e7998..e62e2a8 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/287\n"},{"id":"304149","messageId":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020156b73fe5b4-5dc768ab-b73b-4a21-ab92-018e2a7aa6f7-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:15Z","receivedAt":"2016-10-14T14:15:05Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"`--next-all` is meant to be used as a subcommand to support multiple\n\"operation mode\" though the current implementation does not contain any\nother subcommand along side with `--next-all` but further commits will\ninclude some more subcommands.\n\nHelped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 17 +++++++++++------\n 1 file changed, 11 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 3324229..8111c91 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -10,11 +10,11 @@ static const char * const git_bisect_helper_usage[] = {\n \n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n-\tint next_all = 0;\n+\tenum { NEXT_ALL = 1 } cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n-\t\tOPT_BOOL(0, \"next-all\", &next_all,\n-\t\t\t N_(\"perform 'git bisect next'\")),\n+\t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n+\t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -23,9 +23,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n \n-\tif (!next_all)\n+\tif (!cmdmode)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n-\t/* next-all */\n-\treturn bisect_next_all(prefix, no_checkout);\n+\tswitch (cmdmode) {\n+\tcase NEXT_ALL:\n+\t\treturn bisect_next_all(prefix, no_checkout);\n+\tdefault:\n+\t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n+\t}\n+\treturn 0;\n }\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304150","messageId":"01020157c38b1ad3-ea75ed97-2514-427e-8e57-9f10efd4e6e9-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 13/27] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:15Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_start` shell function partially in C and add\n`bisect-start` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nThe last part is not converted because it calls another shell function\n`bisect_start` shell function will be completed after the `bisect_next`\nshell function is ported in C.\n\nUsing `--bisect-start` subcommand is a temporary measure to port shell\nfunction in C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and will be called by some\nother methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 133 +----------------------------\n 2 files changed, 217 insertions(+), 133 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 6a5878c..1d3e17f 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -7,6 +7,7 @@\n #include \"argv-array.h\"\n #include \"run-command.h\"\n #include \"prompt.h\"\n+#include \"quote.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -14,6 +15,8 @@ static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\n+static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n@@ -24,6 +27,8 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n \tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n+\tN_(\"git bisect--helper --bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]\"\n+\t\t\t\t\t      \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n \tNULL\n };\n \n@@ -403,6 +408,205 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \treturn 0;\n }\n \n+static int bisect_start(struct bisect_terms *terms, int no_checkout,\n+\t\t\tconst char **argv, int argc)\n+{\n+\tint i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;\n+\tint flags, pathspec_pos, 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 strbuf orig_args = STRBUF_INIT;\n+\tconst char *head;\n+\tunsigned char sha1[20];\n+\tFILE *fp = NULL;\n+\tstruct object_id oid;\n+\n+\tif (is_bare_repository())\n+\t\tno_checkout = 1;\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\thas_double_dash = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < argc; i++) {\n+\t\tconst char *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n+\t\tconst char *arg = argv[i];\n+\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\t\thas_double_dash = 1;\n+\t\t\tbreak;\n+\t\t} else if (!strcmp(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\tterms->term_good = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_good = xstrdup(arg);\n+\t\t} else if (skip_prefix(arg, \"--term-old=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\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\tterms->term_bad = xstrdup(argv[++i]);\n+\t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_bad = xstrdup(arg);\n+\t\t} else if (skip_prefix(arg, \"--term-new=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_good = 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\tdie(_(\"unrecognised option: '%s'\"), arg);\n+\t\t} else if (get_oid(commit_id, &oid) && has_double_dash) {\n+\t\t\tdie(_(\"'%s' does not appear to be a valid revision\"), argv[i]);\n+\t\t} else {\n+\t\t\tstring_list_append(&revs, oid_to_hex(&oid));\n+\t\t}\n+\t}\n+\tpathspec_pos = i;\n+\n+\t/*\n+\t * The user ran \"git bisect start <sha1> <sha1>\", hence did not\n+\t * explicitly specify the terms, but we are already starting to\n+\t * set references named with the default terms, and won't be able\n+\t * to change afterwards.\n+\t */\n+\tmust_write_terms |= !!revs.nr;\n+\tfor (i = 0; i < revs.nr; i++) {\n+\t\tif (bad_seen) {\n+\t\t\tstring_list_append(&states, terms->term_good);\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, sha1, &flags);\n+\tif (!head)\n+\t\tif (get_sha1(\"HEAD\", sha1))\n+\t\t\tdie(_(\"Bad HEAD - I need a HEAD\"));\n+\n+\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\t/* Reset to the rev from where we started */\n+\t\tstrbuf_read_file(&start_head, git_path_bisect_start(), 0);\n+\t\tstrbuf_trim(&start_head);\n+\t\tif (!no_checkout) {\n+\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\t\targv_array_pushl(&argv, \"checkout\", start_head.buf,\n+\t\t\t\t\t \"--\", NULL);\n+\t\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\t\terror(_(\"checking out '%s' failed. Try 'git \"\n+\t\t\t\t\t\"bisect start <valid-branch>'.\"),\n+\t\t\t\t      start_head.buf);\n+\t\t\t\tretval = -1;\n+\t\t\t\tgoto finish;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tif (!get_sha1(head, sha1) &&\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(sha1));\n+\t\t} else if (!get_sha1(head, sha1) &&\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\tdie(_(\"won't bisect on cg-seek'ed tree\"));\n+\t\t\tstrbuf_addstr(&start_head, head);\n+\t\t} else {\n+\t\t\tdie(_(\"Bad HEAD - strange symbolic ref\"));\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Get rid of any old bisect state.\n+\t */\n+\tif (bisect_clean_state()) {\n+\t\treturn -1;\n+\t}\n+\t/*\n+\t * In case of mistaken revs or checkout error, or signals received,\n+\t * \"bisect_auto_next\" below may exit or misbehave.\n+\t * We have to trap this to be able to clean up using\n+\t * \"bisect_clean_state\".\n+\t */\n+\n+\t/*\n+\t * Write new start state\n+\t */\n+\twrite_file(git_path_bisect_start(), \"%s\\n\", start_head.buf);\n+\n+\tif (no_checkout) {\n+\t\tget_oid(start_head.buf, &oid);\n+\t\tif (update_ref(NULL, \"BISECT_HEAD\", oid.hash, NULL, 0,\n+\t\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\t\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+\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+\t}\n+\n+\tif (must_write_terms)\n+\t\tif (write_terms(terms->term_bad, terms->term_good)) {\n+\t\t\tretval = -1;\n+\t\t\tgoto finish;\n+\t\t}\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp)\n+\t\treturn -1;\n+\n+\tif (fprintf(fp, \"git bisect start\") < 1) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\n+\tsq_quote_argv(&orig_args, argv, 0);\n+\tif (fprintf(fp, \"%s\", orig_args.buf) < 0) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\tif (fprintf(fp, \"\\n\") < 1) {\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\tgoto finish;\n+finish:\n+\tif (fp)\n+\t\tfclose(fp);\n+\tstring_list_clear(&revs, 0);\n+\tstring_list_clear(&states, 0);\n+\tstrbuf_release(&start_head);\n+\tstrbuf_release(&bisect_names);\n+\tstrbuf_release(&orig_args);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -414,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;\n \tstruct option options[] = {\n@@ -436,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_END()\n@@ -443,7 +650,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@@ -497,6 +705,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n \t\tres = bisect_terms(&terms, argv, argc);\n \t\tbreak;\n+\tcase BISECT_START:\n+\t\tterms.term_good = \"good\";\n+\t\tterms.term_bad = \"bad\";\n+\t\tres = bisect_start(&terms, no_checkout, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex d6c8b5a..f0896b3 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -71,122 +71,7 @@ bisect_autostart() {\n }\n \n bisect_start() {\n-\t#\n-\t# Check for one bad and then some good revisions.\n-\t#\n-\thas_double_dash=0\n-\tfor arg; do\n-\t\tcase \"$arg\" in --) has_double_dash=1; break ;; esac\n-\tdone\n-\torig_args=$(git rev-parse --sq-quote \"$@\")\n-\tbad_seen=0\n-\teval=''\n-\tmust_write_terms=0\n-\trevs=''\n-\tif test \"z$(git rev-parse --is-bare-repository)\" != zfalse\n-\tthen\n-\t\tmode=--no-checkout\n-\telse\n-\t\tmode=''\n-\tfi\n-\twhile [ $# -gt 0 ]; do\n-\t\targ=\"$1\"\n-\t\tcase \"$arg\" in\n-\t\t--)\n-\t\t\tshift\n-\t\t\tbreak\n-\t\t;;\n-\t\t--no-checkout)\n-\t\t\tmode=--no-checkout\n-\t\t\tshift ;;\n-\t\t--term-good|--term-old)\n-\t\t\tshift\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_GOOD=$1\n-\t\t\tshift ;;\n-\t\t--term-good=*|--term-old=*)\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_GOOD=${1#*=}\n-\t\t\tshift ;;\n-\t\t--term-bad|--term-new)\n-\t\t\tshift\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_BAD=$1\n-\t\t\tshift ;;\n-\t\t--term-bad=*|--term-new=*)\n-\t\t\tmust_write_terms=1\n-\t\t\tTERM_BAD=${1#*=}\n-\t\t\tshift ;;\n-\t\t--*)\n-\t\t\tdie \"$(eval_gettext \"unrecognised option: '\\$arg'\")\" ;;\n-\t\t*)\n-\t\t\trev=$(git rev-parse -q --verify \"$arg^{commit}\") || {\n-\t\t\t\ttest $has_double_dash -eq 1 &&\n-\t\t\t\tdie \"$(eval_gettext \"'\\$arg' does not appear to be a valid revision\")\"\n-\t\t\t\tbreak\n-\t\t\t}\n-\t\t\trevs=\"$revs $rev\"\n-\t\t\tshift\n-\t\t\t;;\n-\t\tesac\n-\tdone\n-\n-\tfor rev in $revs\n-\tdo\n-\t\t# The user ran \"git bisect start <sha1>\n-\t\t# <sha1>\", hence did not explicitly specify\n-\t\t# the terms, but we are already starting to\n-\t\t# set references named with the default terms,\n-\t\t# and won't be able to change afterwards.\n-\t\tmust_write_terms=1\n-\n-\t\tcase $bad_seen in\n-\t\t0) state=$TERM_BAD ; bad_seen=1 ;;\n-\t\t*) state=$TERM_GOOD ;;\n-\t\tesac\n-\t\teval=\"$eval git bisect--helper --bisect-write '$state' '$rev' '$TERM_GOOD' '$TERM_BAD' 'nolog' &&\"\n-\tdone\n-\t#\n-\t# Verify HEAD.\n-\t#\n-\thead=$(GIT_DIR=\"$GIT_DIR\" git symbolic-ref -q HEAD) ||\n-\thead=$(GIT_DIR=\"$GIT_DIR\" git rev-parse --verify HEAD) ||\n-\tdie \"$(gettext \"Bad HEAD - I need a HEAD\")\"\n-\n-\t#\n-\t# Check if we are bisecting.\n-\t#\n-\tstart_head=''\n-\tif test -s \"$GIT_DIR/BISECT_START\"\n-\tthen\n-\t\t# Reset to the rev from where we started.\n-\t\tstart_head=$(cat \"$GIT_DIR/BISECT_START\")\n-\t\tif test \"z$mode\" != \"z--no-checkout\"\n-\t\tthen\n-\t\t\tgit checkout \"$start_head\" -- ||\n-\t\t\tdie \"$(eval_gettext \"Checking out '\\$start_head' failed. Try 'git bisect reset <valid-branch>'.\")\"\n-\t\tfi\n-\telse\n-\t\t# Get rev from where we start.\n-\t\tcase \"$head\" in\n-\t\trefs/heads/*|$_x40)\n-\t\t\t# This error message should only be triggered by\n-\t\t\t# cogito usage, and cogito users should understand\n-\t\t\t# it relates to cg-seek.\n-\t\t\t[ -s \"$GIT_DIR/head-name\" ] &&\n-\t\t\t\tdie \"$(gettext \"won't bisect on cg-seek'ed tree\")\"\n-\t\t\tstart_head=\"${head#refs/heads/}\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\tdie \"$(gettext \"Bad HEAD - strange symbolic ref\")\"\n-\t\t\t;;\n-\t\tesac\n-\tfi\n-\n-\t#\n-\t# Get rid of any old bisect state.\n-\t#\n-\tgit bisect--helper --bisect-clean-state || exit\n+\tgit bisect--helper --bisect-start $@ || exit\n \n \t#\n \t# Change state.\n@@ -197,24 +82,10 @@ bisect_start() {\n \t#\n \ttrap 'git bisect--helper --bisect-clean-state' 0\n \ttrap 'exit 255' 1 2 3 15\n-\n-\t#\n-\t# Write new start state.\n-\t#\n-\techo \"$start_head\" >\"$GIT_DIR/BISECT_START\" && {\n-\t\ttest \"z$mode\" != \"z--no-checkout\" ||\n-\t\tgit update-ref --no-deref BISECT_HEAD \"$start_head\"\n-\t} &&\n-\tgit rev-parse --sq-quote \"$@\" >\"$GIT_DIR/BISECT_NAMES\" &&\n-\teval \"$eval true\" &&\n-\tif test $must_write_terms -eq 1\n-\tthen\n-\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\"\n-\tfi &&\n-\techo \"git bisect start$orig_args\" >>\"$GIT_DIR/BISECT_LOG\" || exit\n \t#\n \t# Check if we can proceed to the next bisect state.\n \t#\n+\tget_terms\n \tbisect_auto_next\n \n \ttrap '-' 0\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304151","messageId":"01020157c38b1b1a-067117ef-cd0d-469b-ba80-ea1a1169f694-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 18/27] bisect--helper: `bisect_autostart` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:18Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_autostart` shell function in C and add the\nC implementation from `bisect_next()` which was previously left\nuncovered. Also add a subcommand `--bisect-autostart` to\n`git bisect--helper` be called from `bisect_state()` from\ngit-bisect.sh .\n\nUsing `--bisect-autostart` subcommand is a temporary measure to port\nshell function to C so as to use the existing test suite. As more\nfunctions are ported, this subcommand will be retired and will be called\nby `bisect_state()`.\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 | 40 ++++++++++++++++++++++++++++++++++++++++\n git-bisect.sh            | 23 +----------------------\n 2 files changed, 41 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 502bf18..1767916 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -30,6 +30,7 @@ static const char * const git_bisect_helper_usage[] = {\n \t\t\t\t\t      \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n \tN_(\"git bisect--helper --bisect-next\"),\n \tN_(\"git bisect--helper --bisect-auto-next\"),\n+\tN_(\"git bisect--helper --bisect-autostart\"),\n \tNULL\n };\n \n@@ -38,6 +39,8 @@ struct bisect_terms {\n \tconst char *term_bad;\n };\n \n+static int bisect_autostart(struct bisect_terms *terms);\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -422,6 +425,7 @@ static int bisect_next(struct bisect_terms *terms, const char *prefix)\n {\n \tint res, no_checkout;\n \n+\tbisect_autostart(terms);\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@@ -754,6 +758,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \treturn retval || bisect_auto_next(terms, NULL);\n }\n \n+static int bisect_autostart(struct bisect_terms *terms)\n+{\n+\tif (is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\tconst char *yesno;\n+\t\tconst char *argv[] = {NULL};\n+\t\tfprintf(stderr, _(\"You need to start by \\\"git bisect \"\n+\t\t\t\t  \"start\\\"\\n\"));\n+\n+\t\tif (!isatty(0))\n+\t\t\treturn 1;\n+\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(_(\"Do you want me to do it for you \"\n+\t\t\t\t     \"[Y/n]? \"), PROMPT_ECHO);\n+\t\tif (starts_with(yesno, \"n\") || starts_with(yesno, \"N\"))\n+\t\t\texit(0);\n+\n+\t\treturn bisect_start(terms, 0, argv, 0);\n+\t}\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -767,6 +797,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_START,\n \t\tBISECT_NEXT,\n \t\tBISECT_AUTO_NEXT,\n+\t\tBISECT_AUTOSTART,\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -790,6 +821,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n \t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n \t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n+\t\tOPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n+\t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\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@@ -862,6 +895,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tget_terms(&terms);\n \t\tres = bisect_auto_next(&terms, prefix);\n \t\tbreak;\n+\tcase BISECT_AUTOSTART:\n+\t\tif (argc)\n+\t\t\tdie(_(\"--bisect-autostart requires 0 arguments\"));\n+\t\tterms.term_good = \"good\";\n+\t\tterms.term_bad = \"bad\";\n+\t\tres = bisect_autostart(&terms);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex d574c44..cd56551 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -49,27 +49,6 @@ bisect_head()\n \tfi\n }\n \n-bisect_autostart() {\n-\ttest -s \"$GIT_DIR/BISECT_START\" || {\n-\t\tgettextln \"You need to start by \\\"git bisect start\\\"\" >&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 \"Do you want me to do it for you [Y/n]? \" >&2\n-\t\t\tread yesno\n-\t\t\tcase \"$yesno\" in\n-\t\t\t[Nn]*)\n-\t\t\t\texit ;;\n-\t\t\tesac\n-\t\t\tgit bisect--helper --bisect-start\n-\t\telse\n-\t\t\texit 1\n-\t\tfi\n-\t}\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -86,7 +65,7 @@ bisect_skip() {\n }\n \n bisect_state() {\n-\tbisect_autostart\n+\tgit bisect--helper --bisect-autostart\n \tstate=$1\n \tget_terms\n \tgit bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304152","messageId":"01020157c38b1b37-aedbfacb-8369-4a71-830e-a6b47ee0b0cd-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 21/27] bisect--helper: retire `--write-terms` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:19Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--write-terms` subcommand is no longer used in the shell script and\nthe function `write_terms()` is called from the C implementation of\n`set_terms()` and `bisect_start()`.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 11 +----------\n 1 file changed, 1 insertion(+), 10 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex d5fe35b..493034c 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -20,7 +20,6 @@ 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 --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n@@ -862,8 +861,7 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n-\t\tWRITE_TERMS = 1,\n-\t\tBISECT_RESET,\n+\t\tBISECT_RESET = 1,\n \t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n \t\tBISECT_NEXT_CHECK,\n@@ -876,8 +874,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n-\t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n-\t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n@@ -913,11 +909,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \n \tswitch (cmdmode) {\n \tint nolog;\n-\tcase WRITE_TERMS:\n-\t\tif (argc != 2)\n-\t\t\tdie(_(\"--write-terms requires two arguments\"));\n-\t\tres = write_terms(argv[0], argv[1]);\n-\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304153","messageId":"01020157c38b1b54-0ac61448-98b1-4c7d-bfdd-47af95f52153-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 19/27] bisect--helper: `bisect_state` & `bisect_head` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:21Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_state` shell function in C and also add a\nsubcommand `--bisect-state` to `git-bisect--helper` to call it from\ngit-bisect.sh .\n\nUsing `--bisect-state` subcommand is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and will be called by some\nother methods.\n\n`bisect_head` is called from `bisect_state` thus its not required to\nintroduce another 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 | 86 ++++++++++++++++++++++++++++++++++++++++++++++++\n git-bisect.sh            | 57 +++-----------------------------\n 2 files changed, 91 insertions(+), 52 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 1767916..1481c6d 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -31,6 +31,8 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-next\"),\n \tN_(\"git bisect--helper --bisect-auto-next\"),\n \tN_(\"git bisect--helper --bisect-autostart\"),\n+\tN_(\"git bisect--helper --bisect-state (bad|new) [<rev>]\"),\n+\tN_(\"git bisect--helper --bisect-state (good|old) [<rev>...]\"),\n \tNULL\n };\n \n@@ -784,6 +786,79 @@ static int bisect_autostart(struct bisect_terms *terms)\n \treturn 0;\n }\n \n+static char *bisect_head(void)\n+{\n+\tif (is_empty_or_missing_file(git_path_bisect_head()))\n+\t\treturn \"HEAD\";\n+\telse\n+\t\treturn \"BISECT_HEAD\";\n+}\n+\n+static int bisect_state(struct bisect_terms *terms, const char **argv,\n+\t\t\tint argc)\n+{\n+\tconst char *state = argv[0];\n+\n+\tget_terms(terms);\n+\tif (check_and_set_terms(terms, state))\n+\t\treturn -1;\n+\n+\tif (!argc)\n+\t\tdie(_(\"Please call `--bisect-state` with at least one argument\"));\n+\n+\tif (argc == 1 && one_of(state, terms->term_good,\n+\t    terms->term_bad, \"skip\", NULL)) {\n+\t\tconst char *bisected_head = xstrdup(bisect_head());\n+\t\tconst char *hex[1];\n+\t\tunsigned char sha1[20];\n+\n+\t\tif (get_sha1(bisected_head, sha1))\n+\t\t\tdie(_(\"Bad rev input: %s\"), bisected_head);\n+\t\tif (bisect_write(state, sha1_to_hex(sha1), terms, 0))\n+\t\t\treturn -1;\n+\n+\t\t*hex = xstrdup(sha1_to_hex(sha1));\n+\t\tif (check_expected_revs(hex, 1))\n+\t\t\treturn -1;\n+\t\treturn bisect_auto_next(terms, NULL);\n+\t}\n+\n+\tif ((argc == 2 && !strcmp(state, terms->term_bad)) ||\n+\t\t\tone_of(state, terms->term_good, \"skip\", NULL)) {\n+\t\tint i;\n+\t\tstruct string_list hex = STRING_LIST_INIT_DUP;\n+\n+\t\tfor (i = 1; i < argc; i++) {\n+\t\t\tunsigned char sha1[20];\n+\n+\t\t\tif (get_sha1(argv[i], sha1)) {\n+\t\t\t\tstring_list_clear(&hex, 0);\n+\t\t\t\tdie(_(\"Bad rev input: %s\"), argv[i]);\n+\t\t\t}\n+\t\t\tstring_list_append(&hex, sha1_to_hex(sha1));\n+\t\t}\n+\t\tfor (i = 0; i < hex.nr; i++) {\n+\t\t\tconst char **hex_string = (const char **) &hex.items[i].string;\n+\t\t\tif(bisect_write(state, *hex_string, terms, 0)) {\n+\t\t\t\tstring_list_clear(&hex, 0);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tif (check_expected_revs(hex_string, 1)) {\n+\t\t\t\tstring_list_clear(&hex, 0);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t\tstring_list_clear(&hex, 0);\n+\t\treturn bisect_auto_next(terms, NULL);\n+\t}\n+\n+\tif (!strcmp(state, terms->term_bad))\n+\t\tdie(_(\"'git bisect %s' can take only one argument.\"),\n+\t\t      terms->term_bad);\n+\n+\treturn -1;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -798,6 +873,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_NEXT,\n \t\tBISECT_AUTO_NEXT,\n \t\tBISECT_AUTOSTART,\n+\t\tBISECT_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -823,6 +899,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n \t\tOPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n \t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n+\t\tOPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n+\t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -902,6 +980,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tterms.term_bad = \"bad\";\n \t\tres = bisect_autostart(&terms);\n \t\tbreak;\n+\tcase BISECT_STATE:\n+\t\tif (argc == 0)\n+\t\t\tdie(_(\"--bisect-state requires at least 1 argument\"));\n+\t\tterms.term_good = \"good\";\n+\t\tterms.term_bad = \"bad\";\n+\t\tget_terms(&terms);\n+\t\tres = bisect_state(&terms, argv, argc);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex cd56551..a9eebbb 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -39,16 +39,6 @@ _x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n TERM_BAD=bad\n TERM_GOOD=good\n \n-bisect_head()\n-{\n-\tif test -f \"$GIT_DIR/BISECT_HEAD\"\n-\tthen\n-\t\techo BISECT_HEAD\n-\telse\n-\t\techo HEAD\n-\tfi\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -61,44 +51,7 @@ bisect_skip() {\n \t\tesac\n \t\tall=\"$all $revs\"\n \tdone\n-\teval bisect_state 'skip' $all\n-}\n-\n-bisect_state() {\n-\tgit bisect--helper --bisect-autostart\n-\tstate=$1\n-\tget_terms\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-\t1,\"$TERM_BAD\"|1,\"$TERM_GOOD\"|1,skip)\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\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-\t\thash_list=''\n-\t\tfor rev in \"$@\"\n-\t\tdo\n-\t\t\tsha=$(git rev-parse --verify \"$rev^{commit}\") ||\n-\t\t\t\tdie \"$(eval_gettext \"Bad rev input: \\$rev\")\"\n-\t\t\thash_list=\"$hash_list $sha\"\n-\t\tdone\n-\t\tfor rev in $hash_list\n-\t\tdo\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-\t\tdie \"$(eval_gettext \"'git bisect \\$TERM_BAD' can take only one argument.\")\" ;;\n-\t*)\n-\t\tusage ;;\n-\tesac\n-\tgit bisect--helper --bisect-auto-next || exit\n+\teval git bisect--helper --bisect-state 'skip' $all\n }\n \n bisect_visualize() {\n@@ -184,8 +137,8 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n \t\t\tstate=\"$TERM_GOOD\"\n \t\tfi\n \n-\t\t# We have to use a subshell because \"bisect_state\" can exit.\n-\t\t( bisect_state $state >\"$GIT_DIR/BISECT_RUN\" )\n+\t\t# We have to use a subshell because \"--bisect-state\" can exit.\n+\t\t( git bisect--helper --bisect-state $state >\"$GIT_DIR/BISECT_RUN\" )\n \t\tres=$?\n \n \t\tcat \"$GIT_DIR/BISECT_RUN\"\n@@ -200,7 +153,7 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n \t\tif [ $res -ne 0 ]\n \t\tthen\n \t\t\teval_gettextln \"bisect run failed:\n-'bisect_state \\$state' exited with error code \\$res\" >&2\n+'git bisect--helper --bisect-state \\$state' exited with error code \\$res\" >&2\n \t\t\texit $res\n \t\tfi\n \n@@ -241,7 +194,7 @@ case \"$#\" in\n \tstart)\n \t\tgit bisect--helper --bisect-start \"$@\" ;;\n \tbad|good|new|old|\"$TERM_BAD\"|\"$TERM_GOOD\")\n-\t\tbisect_state \"$cmd\" \"$@\" ;;\n+\t\tgit bisect--helper --bisect-state \"$cmd\" \"$@\" ;;\n \tskip)\n \t\tbisect_skip \"$@\" ;;\n \tnext)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304154","messageId":"01020157c38b1adc-d5fa6b9a-ce13-4ee9-874e-e45fac99fba6-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 14/27] t6030: no cleanup with bad merge base","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:15:24Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The bisection cleanup should be performed with bad merge base so that\nthe user can return to its original position with `git bisect reset`.\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 t/t6030-bisect-porcelain.sh | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex e62e2a8..8ac77ee 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -911,4 +911,11 @@ test_expect_success 'git bisect reset cleans bisection state properly' '\n \ttest_path_is_missing \"$GIT_DIR/BISECT_START\"\n '\n \n+test_expect_success 'check whether bisection cleanup is not done with bad merges' '\n+\tgit bisect start $HASH7 $SIDE_HASH7 &&\n+\ttest_expect_failure git bisect bad >out 2>out &&\n+\ttest_i18ngrep \"The merge base\" out &&\n+\ttest -e .git/BISECT_START\n+'\n+\n test_done\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304155","messageId":"01020157c38b1af0-5d688c2e-868d-4d8c-a8fd-9a675f7f01da-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:22:55Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `bisect_next` and the `bisect_auto_next` shell function\nin C and add the subcommands to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nAlong with this conversion of `bisect_start` has also finished and thus\nit has been fully ported to C.\n\nA lot of parts of bisect.c uses exit() and these signals are then\ntrapped in the `bisect_start` function. Since the shell script ceases\nits existence it would be necessary to convert those exit() calls to\nreturn statements so that errors can be reported.\n\nAs more and more calls are happening to the subcommands in `git\nbisect--helper`, more specifically when `bisect_start $rev` is converted to\n`git bisect--helper --bisect-start $rev` it is necessary to dequote the\narguments because of shell to C conversion.\n\nUsing `--bisect-next` and `--bisect-auto-start` subcommands is a\ntemporary measure to port shell function to C so as to use the existing\ntest suite. As more functions are ported, this subcommand will be\nretired and will be called by some other methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n bisect.c                 | 128 ++++++++++++++++++++++++--------\n builtin/bisect--helper.c | 189 ++++++++++++++++++++++++++++++++++++++++++++---\n git-bisect.sh            |  74 ++-----------------\n 3 files changed, 285 insertions(+), 106 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 45d598d..7c97e85 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -618,6 +618,12 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,\n \tstruct argv_array rev_argv = ARGV_ARRAY_INIT;\n \tint i;\n \n+\t/*\n+\t * Since the code is slowly being converted to C, there might be\n+\t * instances where the revisions were initialized before. Thus\n+\t * we first need to reset it.\n+\t */\n+\treset_revision_walk();\n \tinit_revisions(revs, prefix);\n \trevs->abbrev = 0;\n \trevs->commit_format = CMIT_FMT_UNSPECIFIED;\n@@ -638,17 +644,22 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,\n \n static void bisect_common(struct rev_info *revs)\n {\n+\t/*\n+\t * We don't want to clean the bisection state\n+\t * as we need to get back to where we started\n+\t * by using `git bisect reset`.\n+\t */\n \tif (prepare_revision_walk(revs))\n \t\tdie(\"revision walk setup failed\");\n \tif (revs->tree_objects)\n \t\tmark_edges_uninteresting(revs, NULL);\n }\n \n-static void exit_if_skipped_commits(struct commit_list *tried,\n+static int exit_if_skipped_commits(struct commit_list *tried,\n \t\t\t\t    const struct object_id *bad)\n {\n \tif (!tried)\n-\t\treturn;\n+\t\treturn 0;\n \n \tprintf(\"There are only 'skip'ped commits left to test.\\n\"\n \t       \"The first %s commit could be any of:\\n\", term_bad);\n@@ -659,7 +670,13 @@ static void exit_if_skipped_commits(struct commit_list *tried,\n \tif (bad)\n \t\tprintf(\"%s\\n\", oid_to_hex(bad));\n \tprintf(_(\"We cannot bisect more!\\n\"));\n-\texit(2);\n+\n+\t/*\n+\t * We don't want to clean the bisection state\n+\t * as we need to get back to where we started\n+\t * by using `git bisect reset`.\n+\t */\n+\treturn 2;\n }\n \n static int is_expected_rev(const struct object_id *oid)\n@@ -700,7 +717,7 @@ static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)\n \t\tint res;\n \t\tres = run_command_v_opt(argv_checkout, RUN_GIT_CMD);\n \t\tif (res)\n-\t\t\texit(res);\n+\t\t\treturn res;\n \t}\n \n \targv_show_branch[1] = bisect_rev_hex;\n@@ -729,7 +746,7 @@ static struct commit **get_bad_and_good_commits(int *rev_nr)\n \treturn rev;\n }\n \n-static void handle_bad_merge_base(void)\n+static int handle_bad_merge_base(void)\n {\n \tif (is_expected_rev(current_bad_oid)) {\n \t\tchar *bad_hex = oid_to_hex(current_bad_oid);\n@@ -750,17 +767,23 @@ static void handle_bad_merge_base(void)\n \t\t\t\t\"between %s and [%s].\\n\"),\n \t\t\t\tbad_hex, term_bad, term_good, bad_hex, good_hex);\n \t\t}\n-\t\texit(3);\n+\t\t/*\n+\t\t * We don't want to clean the bisection state\n+\t\t * as we need to get back to where we started\n+\t\t * by using `git bisect reset`.\n+\t\t */\n+\t\treturn 3;\n \t}\n \n \tfprintf(stderr, _(\"Some %s revs are not ancestor of the %s rev.\\n\"\n \t\t\"git bisect cannot work properly in this case.\\n\"\n \t\t\"Maybe you mistook %s and %s revs?\\n\"),\n \t\tterm_good, term_bad, term_good, term_bad);\n-\texit(1);\n+\tbisect_clean_state();\n+\treturn 1;\n }\n \n-static void handle_skipped_merge_base(const unsigned char *mb)\n+static int handle_skipped_merge_base(const unsigned char *mb)\n {\n \tchar *mb_hex = sha1_to_hex(mb);\n \tchar *bad_hex = oid_to_hex(current_bad_oid);\n@@ -773,21 +796,22 @@ static void handle_skipped_merge_base(const unsigned char *mb)\n \t\t\"We continue anyway.\"),\n \t\tbad_hex, good_hex, term_bad, mb_hex, bad_hex);\n \tfree(good_hex);\n+\treturn 0;\n }\n \n /*\n  * \"check_merge_bases\" checks that merge bases are not \"bad\" (or \"new\").\n  *\n  * - If one is \"bad\" (or \"new\"), it means the user assumed something wrong\n- * and we must exit with a non 0 error code.\n+ * and we must return error with a non 0 error code.\n  * - If one is \"good\" (or \"old\"), that's good, we have nothing to do.\n  * - If one is \"skipped\", we can't know but we should warn.\n  * - If we don't know, we should check it out and ask the user to test.\n  */\n-static void check_merge_bases(int no_checkout)\n+static int check_merge_bases(int no_checkout)\n {\n \tstruct commit_list *result;\n-\tint rev_nr;\n+\tint rev_nr, res = 0;\n \tstruct commit **rev = get_bad_and_good_commits(&rev_nr);\n \n \tresult = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);\n@@ -795,19 +819,30 @@ static void check_merge_bases(int no_checkout)\n \tfor (; result; result = result->next) {\n \t\tconst unsigned char *mb = result->item->object.oid.hash;\n \t\tif (!hashcmp(mb, current_bad_oid->hash)) {\n-\t\t\thandle_bad_merge_base();\n+\t\t\tres = handle_bad_merge_base();\n+\t\t\tbreak;\n \t\t} else if (0 <= sha1_array_lookup(&good_revs, mb)) {\n \t\t\tcontinue;\n \t\t} else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {\n-\t\t\thandle_skipped_merge_base(mb);\n+\t\t\tres = handle_skipped_merge_base(mb);\n+\t\t\tbreak;\n \t\t} else {\n \t\t\tprintf(_(\"Bisecting: a merge base must be tested\\n\"));\n-\t\t\texit(bisect_checkout(mb, no_checkout));\n+\t\t\tres = bisect_checkout(mb, no_checkout);\n+\t\t\t/*\n+\t\t\t * We don't want to clean the bisection state\n+\t\t\t * as we need to get back to where we started\n+\t\t\t * by using `git bisect reset`.\n+\t\t\t */\n+\t\t\tif (!res)\n+\t\t\t\texit(0);\n+\t\t\tbreak;\n \t\t}\n \t}\n \n \tfree(rev);\n \tfree_commit_list(result);\n+\treturn res;\n }\n \n static int check_ancestors(const char *prefix)\n@@ -843,16 +878,21 @@ static int check_ancestors(const char *prefix)\n  *\n  * If that's not the case, we need to check the merge bases.\n  * If a merge base must be tested by the user, its source code will be\n- * checked out to be tested by the user and we will exit.\n+ * checked out to be tested by the user and we will return.\n  */\n-static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n+static int check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n {\n \tchar *filename = git_pathdup(\"BISECT_ANCESTORS_OK\");\n \tstruct stat st;\n-\tint fd;\n+\tint fd, res = 0;\n \n+\t/*\n+\t * We don't want to clean the bisection state\n+\t * as we need to get back to where we started\n+\t * by using `git bisect reset`.\n+\t */\n \tif (!current_bad_oid)\n-\t\tdie(_(\"a %s revision is needed\"), term_bad);\n+\t\terror(_(\"a %s revision is needed\"), term_bad);\n \n \t/* Check if file BISECT_ANCESTORS_OK exists. */\n \tif (!stat(filename, &st) && S_ISREG(st.st_mode))\n@@ -864,7 +904,10 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n \n \t/* Check if all good revs are ancestor of the bad rev. */\n \tif (check_ancestors(prefix))\n-\t\tcheck_merge_bases(no_checkout);\n+\t\tres = check_merge_bases(no_checkout);\n+\n+\tif (res)\n+\t\tgoto done;\n \n \t/* Create file BISECT_ANCESTORS_OK. */\n \tfd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);\n@@ -873,8 +916,11 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n \t\t\t      filename);\n \telse\n \t\tclose(fd);\n+\n+\tgoto done;\n  done:\n \tfree(filename);\n+\treturn res;\n }\n \n /*\n@@ -933,7 +979,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good)\n }\n \n /*\n- * We use the convention that exiting with an exit code 10 means that\n+ * We use the convention to return with an return code 10 means that\n  * the bisection process finished successfully.\n  * In this case the calling shell script should exit 0.\n  *\n@@ -944,7 +990,7 @@ int bisect_next_all(const char *prefix, int no_checkout)\n {\n \tstruct rev_info revs;\n \tstruct commit_list *tried;\n-\tint reaches = 0, all = 0, nr, steps;\n+\tint reaches = 0, all = 0, nr, steps, res;\n \tconst unsigned char *bisect_rev;\n \tchar steps_msg[32];\n \n@@ -952,7 +998,9 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \tif (read_bisect_refs())\n \t\tdie(_(\"reading bisect refs failed\"));\n \n-\tcheck_good_are_ancestors_of_bad(prefix, no_checkout);\n+\tres = check_good_are_ancestors_of_bad(prefix, no_checkout);\n+\tif (res)\n+\t\treturn res;\n \n \tbisect_rev_setup(&revs, prefix, \"%s\", \"^%s\", 1);\n \trevs.limited = 1;\n@@ -964,34 +1012,52 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \trevs.commits = managed_skipped(revs.commits, &tried);\n \n \tif (!revs.commits) {\n+\t\tint res;\n \t\t/*\n-\t\t * We should exit here only if the \"bad\"\n+\t\t * We should return error here only if the \"bad\"\n \t\t * commit is also a \"skip\" commit.\n \t\t */\n-\t\texit_if_skipped_commits(tried, NULL);\n+\t\tres = exit_if_skipped_commits(tried, NULL);\n+\t\tif (res)\n+\t\t\treturn res;\n \n \t\tprintf(_(\"%s was both %s and %s\\n\"),\n \t\t       oid_to_hex(current_bad_oid),\n \t\t       term_good,\n \t\t       term_bad);\n-\t\texit(1);\n+\n+\t\t/*\n+\t\t * We don't want to clean the bisection state\n+\t\t * as we need to get back to where we started\n+\t\t * by using `git bisect reset`.\n+\t\t */\n+\t\treturn 1;\n \t}\n \n \tif (!all) {\n \t\tfprintf(stderr, _(\"No testable commit found.\\n\"\n \t\t\t\"Maybe you started with bad path parameters?\\n\"));\n-\t\texit(4);\n+\n+\t\t/*\n+\t\t * We don't want to clean the bisection state\n+\t\t * as we need to get back to where we started\n+\t\t * by using `git bisect reset`.\n+\t\t */\n+\t\treturn 4;\n \t}\n \n \tbisect_rev = revs.commits->item->object.oid.hash;\n \n \tif (!hashcmp(bisect_rev, current_bad_oid->hash)) {\n-\t\texit_if_skipped_commits(tried, current_bad_oid);\n+\t\tres = exit_if_skipped_commits(tried, current_bad_oid);\n+\t\tif (res)\n+\t\t\treturn res;\n+\n \t\tprintf(\"%s is the first %s commit\\n\", sha1_to_hex(bisect_rev),\n \t\t\tterm_bad);\n \t\tshow_diff_tree(prefix, revs.commits->item);\n \t\t/* This means the bisection process succeeded. */\n-\t\texit(10);\n+\t\treturn 10;\n \t}\n \n \tnr = all - reaches - 1;\n@@ -1005,7 +1071,11 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \t\t  \"Bisecting: %d revisions left to test after this %s\\n\",\n \t\t  nr), nr, steps_msg);\n \n-\treturn bisect_checkout(bisect_rev, no_checkout);\n+\tres = bisect_checkout(bisect_rev, no_checkout);\n+\tif (res)\n+\t\tbisect_clean_state();\n+\n+\treturn res;\n }\n \n static inline int log2i(int n)\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 1d3e17f..fcd7574 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -8,6 +8,7 @@\n #include \"run-command.h\"\n #include \"prompt.h\"\n #include \"quote.h\"\n+#include \"revision.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@@ -29,6 +30,8 @@ static const char * const git_bisect_helper_usage[] = {\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+\tN_(\"git bisect--helper --bisect-next\"),\n+\tN_(\"git bisect--helper --bisect-auto-next\"),\n \tNULL\n };\n \n@@ -408,6 +411,136 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n \treturn 0;\n }\n \n+static int register_good_ref(const char *refname,\n+\t\t\t     const struct object_id *oid, int flags,\n+\t\t\t     void *cb_data)\n+{\n+\tstruct string_list *good_refs = cb_data;\n+\tstring_list_append(good_refs, oid_to_hex(oid));\n+\treturn 0;\n+}\n+\n+static int bisect_next(struct bisect_terms *terms, const char *prefix)\n+{\n+\tint res, no_checkout;\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+\tif (bisect_next_check(terms, terms->term_good))\n+\t\treturn -1;\n+\n+\tno_checkout = !is_empty_or_missing_file(git_path_bisect_head());\n+\n+\t/* Perform all bisection computation, display and checkout */\n+\tres = bisect_next_all(prefix , no_checkout);\n+\n+\tif (res == 10) {\n+\t\tFILE *fp = NULL;\n+\t\tunsigned char sha1[20];\n+\t\tstruct commit *commit;\n+\t\tstruct pretty_print_context pp = {0};\n+\t\tstruct strbuf commit_name = STRBUF_INIT;\n+\t\tchar *bad_ref = xstrfmt(\"refs/bisect/%s\",\n+\t\t\t\t\t      terms->term_bad);\n+\t\tint retval = 0;\n+\n+\t\tread_ref(bad_ref, sha1);\n+\t\tcommit = lookup_commit_reference(sha1);\n+\t\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n+\t\tfp = fopen(git_path_bisect_log(), \"a\");\n+\t\tif (!fp) {\n+\t\t\tretval = -1;\n+\t\t\tgoto finish_10;\n+\t\t}\n+\t\tif (fprintf(fp, \"# first %s commit: [%s] %s\\n\",\n+\t\t\t    terms->term_bad, sha1_to_hex(sha1),\n+\t\t\t    commit_name.buf) < 1){\n+\t\t\tretval = -1;\n+\t\t\tgoto finish_10;\n+\t\t}\n+\t\tgoto finish_10;\n+\tfinish_10:\n+\t\tif (fp)\n+\t\t\tfclose(fp);\n+\t\tstrbuf_release(&commit_name);\n+\t\tfree(bad_ref);\n+\t\treturn retval;\n+\t}\n+\telse if (res == 2) {\n+\t\tFILE *fp = NULL;\n+\t\tstruct rev_info revs;\n+\t\tstruct argv_array rev_argv = ARGV_ARRAY_INIT;\n+\t\tstruct string_list good_revs = STRING_LIST_INIT_DUP;\n+\t\tstruct pretty_print_context pp = {0};\n+\t\tstruct commit *commit;\n+\t\tchar *term_good = xstrfmt(\"%s-*\", terms->term_good);\n+\t\tint i, retval = 0;\n+\n+\t\tfp = fopen(git_path_bisect_log(), \"a\");\n+\t\tif (!fp) {\n+\t\t\tretval = -1;\n+\t\t\tgoto finish_2;\n+\t\t}\n+\t\tif (fprintf(fp, \"# only skipped commits left to test\\n\") < 1) {\n+\t\t\tretval = -1;\n+\t\t\tgoto finish_2;\n+\t\t}\n+\t\tfor_each_glob_ref_in(register_good_ref, term_good,\n+\t\t\t\t     \"refs/bisect/\", (void *) &good_revs);\n+\n+\t\targv_array_pushl(&rev_argv, \"skipped_commits\", \"refs/bisect/bad\", \"--not\", NULL);\n+\t\tfor (i = 0; i < good_revs.nr; i++)\n+\t\t\targv_array_push(&rev_argv, good_revs.items[i].string);\n+\n+\t\t/* It is important to reset the flags used by revision walks\n+\t\t * as the previous call to bisect_next_all() in turn\n+\t\t * setups a revision walk.\n+\t\t */\n+\t\treset_revision_walk();\n+\t\tinit_revisions(&revs, NULL);\n+\t\trev_argv.argc = setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL);\n+\t\targv_array_clear(&rev_argv);\n+\t\tstring_list_clear(&good_revs, 0);\n+\t\tif (prepare_revision_walk(&revs))\n+\t\t\tdie(_(\"revision walk setup failed\\n\"));\n+\n+\t\twhile ((commit = get_revision(&revs)) != NULL) {\n+\t\t\tstruct strbuf commit_name = STRBUF_INIT;\n+\t\t\tformat_commit_message(commit, \"%s\",\n+\t\t\t\t\t      &commit_name, &pp);\n+\t\t\tfprintf(fp, \"# possible first %s commit: \"\n+\t\t\t\t    \"[%s] %s\\n\", terms->term_bad,\n+\t\t\t\t    oid_to_hex(&commit->object.oid),\n+\t\t\t\t    commit_name.buf);\n+\t\t\tstrbuf_release(&commit_name);\n+\t\t}\n+\t\tgoto finish_2;\n+\tfinish_2:\n+\t\tif (fp)\n+\t\t\tfclose(fp);\n+\t\tstring_list_clear(&good_revs, 0);\n+\t\targv_array_clear(&rev_argv);\n+\t\tfree(term_good);\n+\t\tif (retval)\n+\t\t\treturn retval;\n+\t\telse\n+\t\t\treturn res;\n+\t}\n+\treturn res;\n+}\n+\n+static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)\n+{\n+\tif (!bisect_next_check(terms, NULL))\n+\t\treturn bisect_next(terms, prefix);\n+\n+\treturn 0;\n+}\n+\n static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \t\t\tconst char **argv, int argc)\n {\n@@ -427,15 +560,24 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \t\tno_checkout = 1;\n \n \tfor (i = 0; i < argc; i++) {\n-\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\tconst char *arg;\n+\t\tif (starts_with(argv[i], \"'\"))\n+\t\t\targ = sq_dequote(xstrdup(argv[i]));\n+\t\telse\n+\t\t\targ = argv[i];\n+\t\tif (!strcmp(arg, \"--\")) {\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 *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n-\t\tconst char *arg = argv[i];\n+\t\tconst char *arg, *commit_id;\n+\t\tif (starts_with(argv[i], \"'\"))\n+\t\t\targ = sq_dequote(xstrdup(argv[i]));\n+\t\telse\n+\t\t\targ = argv[i];\n+\t\tcommit_id = xstrfmt(\"%s^{commit}\", arg);\n \t\tif (!strcmp(argv[i], \"--\")) {\n \t\t\thas_double_dash = 1;\n \t\t\tbreak;\n@@ -443,24 +585,31 @@ static int bisect_start(struct bisect_terms *terms, int 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\tif (starts_with(argv[++i], \"'\"))\n+\t\t\t\tterms->term_good = sq_dequote(xstrdup(argv[i]));\n+\t\t\telse\n+\t\t\t\tterms->term_good = xstrdup(argv[i]);\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_good = xstrdup(argv[++i]);\n \t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_good = xstrdup(arg);\n+\t\t\tterms->term_good = arg;\n \t\t} else if (skip_prefix(arg, \"--term-old=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_good = xstrdup(arg);\n+\t\t\tterms->term_good = arg;\n \t\t} else if (!strcmp(arg, \"--term-bad\") ||\n \t\t\t !strcmp(arg, \"--term-new\")) {\n+\t\t\tconst char *next_arg;\n+\t\t\tif (starts_with(argv[++i], \"'\"))\n+\t\t\t\tterms->term_bad = sq_dequote(xstrdup(argv[i]));\n+\t\t\telse\n+\t\t\t\tterms->term_bad = xstrdup(argv[i]);\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_bad = xstrdup(argv[++i]);\n \t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_bad = xstrdup(arg);\n+\t\t\tterms->term_bad = arg;\n \t\t} else if (skip_prefix(arg, \"--term-new=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n-\t\t\tterms->term_good = xstrdup(arg);\n+\t\t\tterms->term_good = arg;\n \t\t} else if (starts_with(arg, \"--\") &&\n \t\t\t !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n \t\t\tdie(_(\"unrecognised option: '%s'\"), arg);\n@@ -604,7 +753,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \tstrbuf_release(&start_head);\n \tstrbuf_release(&bisect_names);\n \tstrbuf_release(&orig_args);\n-\treturn retval;\n+\treturn retval || bisect_auto_next(terms, NULL);\n }\n \n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n@@ -619,7 +768,9 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tCHECK_AND_SET_TERMS,\n \t\tBISECT_NEXT_CHECK,\n \t\tBISECT_TERMS,\n-\t\tBISECT_START\n+\t\tBISECT_START,\n+\t\tBISECT_NEXT,\n+\t\tBISECT_AUTO_NEXT,\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -643,6 +794,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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_CMDMODE(0, \"bisect-next\", &cmdmode,\n+\t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n+\t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n+\t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\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@@ -710,6 +865,18 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tterms.term_bad = \"bad\";\n \t\tres = bisect_start(&terms, no_checkout, argv, argc);\n \t\tbreak;\n+\tcase BISECT_NEXT:\n+\t\tif (argc)\n+\t\t\tdie(_(\"--bisect-next requires 0 arguments\"));\n+\t\tget_terms(&terms);\n+\t\tres = bisect_next(&terms, prefix);\n+\t\tbreak;\n+\tcase BISECT_AUTO_NEXT:\n+\t\tif (argc)\n+\t\t\tdie(_(\"--bisect-auto-next requires 0 arguments\"));\n+\t\tget_terms(&terms);\n+\t\tres = bisect_auto_next(&terms, prefix);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex f0896b3..d574c44 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -63,34 +63,13 @@ bisect_autostart() {\n \t\t\t[Nn]*)\n \t\t\t\texit ;;\n \t\t\tesac\n-\t\t\tbisect_start\n+\t\t\tgit bisect--helper --bisect-start\n \t\telse\n \t\t\texit 1\n \t\tfi\n \t}\n }\n \n-bisect_start() {\n-\tgit bisect--helper --bisect-start $@ || exit\n-\n-\t#\n-\t# Change state.\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-\ttrap 'git bisect--helper --bisect-clean-state' 0\n-\ttrap 'exit 255' 1 2 3 15\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-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -109,6 +88,7 @@ bisect_skip() {\n bisect_state() {\n \tbisect_autostart\n \tstate=$1\n+\tget_terms\n \tgit bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n \tget_terms\n \tcase \"$#,$state\" in\n@@ -139,45 +119,7 @@ bisect_state() {\n \t*)\n \t\tusage ;;\n \tesac\n-\tbisect_auto_next\n-}\n-\n-bisect_auto_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-\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-\tres=$?\n-\n-\t# Check if we should exit because bisection is finished\n-\tif test $res -eq 10\n-\tthen\n-\t\tbad_rev=$(git show-ref --hash --verify refs/bisect/$TERM_BAD)\n-\t\tbad_commit=$(git show-branch $bad_rev)\n-\t\techo \"# first $TERM_BAD commit: $bad_commit\" >>\"$GIT_DIR/BISECT_LOG\"\n-\t\texit 0\n-\telif test $res -eq 2\n-\tthen\n-\t\techo \"# only skipped commits left to test\" >>\"$GIT_DIR/BISECT_LOG\"\n-\t\tgood_revs=$(git for-each-ref --format=\"%(objectname)\" \"refs/bisect/$TERM_GOOD-*\")\n-\t\tfor skipped in $(git rev-list refs/bisect/$TERM_BAD --not $good_revs)\n-\t\tdo\n-\t\t\tskipped_commit=$(git show-branch $skipped)\n-\t\t\techo \"# possible first $TERM_BAD commit: $skipped_commit\" >>\"$GIT_DIR/BISECT_LOG\"\n-\t\tdone\n-\t\texit $res\n-\tfi\n-\n-\t# Check for an error in the bisection process\n-\ttest $res -ne 0 && exit $res\n-\n-\treturn 0\n+\tgit bisect--helper --bisect-auto-next || exit\n }\n \n bisect_visualize() {\n@@ -221,8 +163,7 @@ bisect_replay () {\n \t\tget_terms\n \t\tcase \"$command\" in\n \t\tstart)\n-\t\t\tcmd=\"bisect_start $rev\"\n-\t\t\teval \"$cmd\" ;;\n+\t\t\teval \"git bisect--helper --bisect-start $rev\" ;;\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@@ -231,7 +172,7 @@ bisect_replay () {\n \t\t\tdie \"$(gettext \"?? what are you talking about?\")\" ;;\n \t\tesac\n \tdone <\"$file\"\n-\tbisect_auto_next\n+\tgit bisect--helper --bisect-auto-next\n }\n \n bisect_run () {\n@@ -319,14 +260,15 @@ case \"$#\" in\n \thelp)\n \t\tgit bisect -h ;;\n \tstart)\n-\t\tbisect_start \"$@\" ;;\n+\t\tgit bisect--helper --bisect-start \"$@\" ;;\n \tbad|good|new|old|\"$TERM_BAD\"|\"$TERM_GOOD\")\n \t\tbisect_state \"$cmd\" \"$@\" ;;\n \tskip)\n \t\tbisect_skip \"$@\" ;;\n \tnext)\n \t\t# Not sure we want \"next\" at the UI level anymore.\n-\t\tbisect_next \"$@\" ;;\n+\t\tget_terms\n+\t\tgit bisect--helper --bisect-next \"$@\" || exit ;;\n \tvisualize|view)\n \t\tbisect_visualize \"$@\" ;;\n \treset)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304156","messageId":"01020157c38b1aa0-0c1fed14-e058-4621-9958-973113d7e45f-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 07/27] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:24:32Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\nsubcommand to `git bisect--helper` to call it from git-bisect.sh .\n\nUsing `bisect_reset` subcommand is a temporary measure to port shell\nfunctions to C so as to use the existing test suite. As more functions\nare ported, this subcommand would be retired but its implementation will\nbe called by some other method.\n\nNote: --bisect-clean-state subcommand has not been retired as there are\nstill a function namely `bisect_start()` which still uses this\nsubcommand.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++--------------------------\n 2 files changed, 49 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 4254d61..d84ba86 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,17 +3,22 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n+#include \"argv-array.h\"\n+#include \"run-command.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n+static GIT_PATH_FUNC(git_path_bisect_head, \"BISECT_HEAD\")\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n+\tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tNULL\n };\n \n@@ -84,12 +89,47 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\n }\n \n+static int bisect_reset(const char *commit)\n+{\n+\tstruct strbuf branch = STRBUF_INIT;\n+\n+\tif (!commit) {\n+\t\tif (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n+\t\t\tprintf(\"We are not bisecting.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tunsigned char sha1[20];\n+\t\tif (get_sha1_committish(commit, sha1))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addstr(&branch, commit);\n+\t}\n+\n+\tif (!file_exists(git_path_bisect_head())) {\n+\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\targv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n+\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\terror(_(\"Could not check out original HEAD '%s'. Try \"\n+\t\t\t\t\"'git bisect reset <commit>'.\"), branch.buf);\n+\t\t\tstrbuf_release(&branch);\n+\t\t\targv_array_clear(&argv);\n+\t\t\treturn -1;\n+\t\t}\n+\t\targv_array_clear(&argv);\n+\t}\n+\n+\tstrbuf_release(&branch);\n+\treturn bisect_clean_state();\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n-\t\tBISECT_CLEAN_STATE\n+\t\tBISECT_CLEAN_STATE,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -99,6 +139,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n \t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n+\t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n+\t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -121,6 +163,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n \t\treturn bisect_clean_state();\n+\tcase BISECT_RESET:\n+\t\tif (argc > 1)\n+\t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n+\t\treturn bisect_reset(argc ? argv[0] : NULL);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex f1202df..442397b 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -409,35 +409,11 @@ bisect_visualize() {\n \teval '\"$@\"' --bisect -- $(cat \"$GIT_DIR/BISECT_NAMES\")\n }\n \n-bisect_reset() {\n-\ttest -s \"$GIT_DIR/BISECT_START\" || {\n-\t\tgettextln \"We are not bisecting.\"\n-\t\treturn\n-\t}\n-\tcase \"$#\" in\n-\t0) branch=$(cat \"$GIT_DIR/BISECT_START\") ;;\n-\t1) git rev-parse --quiet --verify \"$1^{commit}\" >/dev/null || {\n-\t\t\tinvalid=\"$1\"\n-\t\t\tdie \"$(eval_gettext \"'\\$invalid' is not a valid commit\")\"\n-\t\t}\n-\t\tbranch=\"$1\" ;;\n-\t*)\n-\t\tusage ;;\n-\tesac\n-\n-\tif ! test -f \"$GIT_DIR/BISECT_HEAD\" && ! git checkout \"$branch\" --\n-\tthen\n-\t\tdie \"$(eval_gettext \"Could not check out original HEAD '\\$branch'.\n-Try 'git bisect reset <commit>'.\")\"\n-\tfi\n-\tgit bisect--helper --bisect-clean-state || exit\n-}\n-\n bisect_replay () {\n \tfile=\"$1\"\n \ttest \"$#\" -eq 1 || die \"$(gettext \"No logfile given\")\"\n \ttest -r \"$file\" || die \"$(eval_gettext \"cannot read \\$file for replaying\")\"\n-\tbisect_reset\n+\tgit bisect--helper --bisect-reset || exit\n \twhile read git bisect command rev\n \tdo\n \t\ttest \"$git $bisect\" = \"git bisect\" || test \"$git\" = \"git-bisect\" || continue\n@@ -627,7 +603,7 @@ case \"$#\" in\n \tvisualize|view)\n \t\tbisect_visualize \"$@\" ;;\n \treset)\n-\t\tbisect_reset \"$@\" ;;\n+\t\tgit bisect--helper --bisect-reset \"$@\" ;;\n \treplay)\n \t\tbisect_replay \"$@\" ;;\n \tlog)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304157","messageId":"01020157c38b1af1-4c6ed428-4d97-4186-bd5a-4b3b433a05dc-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 17/27] bisect--helper: retire `--next-all` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:27:28Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--next-all` subcommand is no longer used in the shell script and\nthe function `bisect_next_all()` is called from the C implementation of\n`bisect_next()`.\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 | 8 +-------\n 1 file changed, 1 insertion(+), 7 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 45d9336..502bf18 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -20,7 +20,6 @@ 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 \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n@@ -758,8 +757,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\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\tWRITE_TERMS = 1,\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n@@ -772,8 +770,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t} cmdmode = 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 \t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n@@ -809,8 +805,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \n \tswitch (cmdmode) {\n \tint nolog;\n-\tcase NEXT_ALL:\n-\t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304158","messageId":"01020157c38b1b49-f17ea9d4-32d8-47da-bdcf-833bd7a9093d-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 24/27] bisect--helper: retire `--bisect-write` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:29:25Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--bisect-write` subcommand is no longer used in the shell script\nand the function `bisect_write()` is called from the C implementation.\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 | 13 -------------\n 1 file changed, 13 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex b367d8d..7f676e2 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -21,7 +21,6 @@ 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 --bisect-reset [<commit>]\"),\n-\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n \tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n@@ -990,7 +989,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tBISECT_RESET = 1,\n-\t\tBISECT_WRITE,\n \t\tCHECK_AND_SET_TERMS,\n \t\tBISECT_NEXT_CHECK,\n \t\tBISECT_TERMS,\n@@ -1006,8 +1004,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\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_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@@ -1042,20 +1038,11 @@ 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 BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n \t\tres = bisect_reset(argc ? argv[0] : NULL);\n \t\tbreak;\n-\tcase BISECT_WRITE:\n-\t\tif (argc != 4 && argc != 5)\n-\t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n-\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n-\t\tterms.term_good = xstrdup(argv[2]);\n-\t\tterms.term_bad = xstrdup(argv[3]);\n-\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n-\t\tbreak;\n \tcase CHECK_AND_SET_TERMS:\n \t\tif (argc != 3)\n \t\t\tdie(_(\"--check-and-set-terms requires 3 arguments\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304159","messageId":"01020157c38b1a84-d3b8c27a-aeb6-4cfd-8b9f-1db291331b2f-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 03/27] bisect--helper: `write_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:15Z","receivedAt":"2016-10-14T14:30:31Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `write_terms` shell function in C and add a `write-terms`\nsubcommand to `git bisect--helper` to call it from git-bisect.sh . Also\nremove the subcommand `--check-term-format` as it can now be called from\ninside the function write_terms() C implementation.\n\nAlso `|| exit` is added when calling write-terms subcommand from\ngit-bisect.sh so as to exit whenever there is an error.\n\nUsing `--write-terms` subcommand is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired and its implementation will\nbe called by some other method.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 36 +++++++++++++++++++++++++++++-------\n git-bisect.sh            | 22 +++++++---------------\n 2 files changed, 36 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex a47f1f2..65cf519 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,9 +4,11 @@\n #include \"bisect.h\"\n #include \"refs.h\"\n \n+static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n+\n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n-\tN_(\"git bisect--helper --check-term-format <term> <orig_term>\"),\n+\tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tNULL\n };\n \n@@ -57,18 +59,38 @@ static int check_term_format(const char *term, const char *orig_term)\n \treturn 0;\n }\n \n+static int write_terms(const char *bad, const char *good)\n+{\n+\tFILE *fp = NULL;\n+\tint res;\n+\n+\tif (!strcmp(bad, good))\n+\t\treturn error(_(\"please use two different terms\"));\n+\n+\tif (check_term_format(bad, \"bad\") || check_term_format(good, \"good\"))\n+\t\treturn -1;\n+\n+\tfp = fopen(git_path_bisect_terms(), \"w\");\n+\tif (!fp)\n+\t\treturn error_errno(_(\"could not open the file BISECT_TERMS\"));\n+\n+\tres = fprintf(fp, \"%s\\n%s\\n\", bad, good);\n+\tres |= fclose(fp);\n+\treturn (res < 0) ? -1 : 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n-\t\tCHECK_TERM_FMT\n+\t\tWRITE_TERMS\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n-\t\tOPT_CMDMODE(0, \"check-term-format\", &cmdmode,\n-\t\t\t N_(\"check format of the term\"), CHECK_TERM_FMT),\n+\t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n+\t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -83,10 +105,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tswitch (cmdmode) {\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n-\tcase CHECK_TERM_FMT:\n+\tcase WRITE_TERMS:\n \t\tif (argc != 2)\n-\t\t\tdie(_(\"--check-term-format requires two arguments\"));\n-\t\treturn check_term_format(argv[0], argv[1]);\n+\t\t\tdie(_(\"--write-terms requires two arguments\"));\n+\t\treturn write_terms(argv[0], argv[1]);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex a727c59..9ef6cb8 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -209,7 +209,7 @@ bisect_start() {\n \teval \"$eval true\" &&\n \tif test $must_write_terms -eq 1\n \tthen\n-\t\twrite_terms \"$TERM_BAD\" \"$TERM_GOOD\"\n+\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\"\n \tfi &&\n \techo \"git bisect start$orig_args\" >>\"$GIT_DIR/BISECT_LOG\" || exit\n \t#\n@@ -557,18 +557,6 @@ get_terms () {\n \tfi\n }\n \n-write_terms () {\n-\tTERM_BAD=$1\n-\tTERM_GOOD=$2\n-\tif test \"$TERM_BAD\" = \"$TERM_GOOD\"\n-\tthen\n-\t\tdie \"$(gettext \"please use two different terms\")\"\n-\tfi\n-\tgit bisect--helper --check-term-format \"$TERM_BAD\" bad || exit\n-\tgit bisect--helper --check-term-format \"$TERM_GOOD\" good || exit\n-\tprintf '%s\\n%s\\n' \"$TERM_BAD\" \"$TERM_GOOD\" >\"$GIT_DIR/BISECT_TERMS\"\n-}\n-\n check_and_set_terms () {\n \tcmd=\"$1\"\n \tcase \"$cmd\" in\n@@ -582,13 +570,17 @@ check_and_set_terms () {\n \t\tbad|good)\n \t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n \t\t\tthen\n-\t\t\t\twrite_terms bad good\n+\t\t\t\tTERM_BAD=bad\n+\t\t\t\tTERM_GOOD=good\n+\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n \t\t\tfi\n \t\t\t;;\n \t\tnew|old)\n \t\t\tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n \t\t\tthen\n-\t\t\t\twrite_terms new old\n+\t\t\t\tTERM_BAD=new\n+\t\t\t\tTERM_GOOD=old\n+\t\t\t\tgit bisect--helper --write-terms \"$TERM_BAD\" \"$TERM_GOOD\" || exit\n \t\t\tfi\n \t\t\t;;\n \t\tesac ;;\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304160","messageId":"01020157c38b1a74-ad2bcaff-0c92-4af4-9aa0-72d98f4945fc-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 02/27] bisect: rewrite `check_term_format` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:15Z","receivedAt":"2016-10-14T14:30:34Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement the `check_term_format` shell function in C and add\na `--check-term-format` subcommand to `git bisect--helper` to call it\nfrom git-bisect.sh\n\nUsing `--check-term-format` subcommand is a temporary measure to port\nshell function to C so as to use the existing test suite. As more\nfunctions are ported, this subcommand will be retired and its\nimplementation will be called by some other method/subcommand. For\neg. In conversion of write_terms() of git-bisect.sh, the subcommand will\nbe removed and instead check_term_format() will be called in its C\nimplementation while a new subcommand will be introduced for write_terms().\n\nHelped-by: Johannes Schindelein <Johannes.Schindelein@gmx.de>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 31 ++-----------------------\n 2 files changed, 61 insertions(+), 30 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 8111c91..a47f1f2 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -2,19 +2,73 @@\n #include \"cache.h\"\n #include \"parse-options.h\"\n #include \"bisect.h\"\n+#include \"refs.h\"\n \n static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --next-all [--no-checkout]\"),\n+\tN_(\"git bisect--helper --check-term-format <term> <orig_term>\"),\n \tNULL\n };\n \n+/*\n+ * Check whether the string `term` belongs to the set of strings\n+ * included in the variable arguments.\n+ */\n+LAST_ARG_MUST_BE_NULL\n+static int one_of(const char *term, ...)\n+{\n+\tint res = 0;\n+\tva_list matches;\n+\tconst char *match;\n+\n+\tva_start(matches, term);\n+\twhile (!res && (match = va_arg(matches, const char *)))\n+\t\tres = !strcmp(term, match);\n+\tva_end(matches);\n+\n+\treturn res;\n+}\n+\n+static int check_term_format(const char *term, const char *orig_term)\n+{\n+\tint res;\n+\tchar *new_term = xstrfmt(\"refs/bisect/%s\", term);\n+\n+\tres = check_refname_format(new_term, 0);\n+\tfree(new_term);\n+\n+\tif (res)\n+\t\treturn error(_(\"'%s' is not a valid term\"), term);\n+\n+\tif (one_of(term, \"help\", \"start\", \"skip\", \"next\", \"reset\",\n+\t\t\t\"visualize\", \"replay\", \"log\", \"run\", NULL))\n+\t\treturn error(_(\"can't use the builtin command '%s' as a term\"), term);\n+\n+\t/*\n+\t * In theory, nothing prevents swapping completely good and bad,\n+\t * but this situation could be confusing and hasn't been tested\n+\t * enough. Forbid it for now.\n+\t */\n+\n+\tif ((strcmp(orig_term, \"bad\") && one_of(term, \"bad\", \"new\", NULL)) ||\n+\t\t (strcmp(orig_term, \"good\") && one_of(term, \"good\", \"old\", NULL)))\n+\t\treturn error(_(\"can't change the meaning of the term '%s'\"), term);\n+\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n-\tenum { NEXT_ALL = 1 } cmdmode = 0;\n+\tenum {\n+\t\tNEXT_ALL = 1,\n+\t\tCHECK_TERM_FMT\n+\t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n+\t\tOPT_CMDMODE(0, \"check-term-format\", &cmdmode,\n+\t\t\t N_(\"check format of the term\"), CHECK_TERM_FMT),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -29,6 +83,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tswitch (cmdmode) {\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n+\tcase CHECK_TERM_FMT:\n+\t\tif (argc != 2)\n+\t\t\tdie(_(\"--check-term-format requires two arguments\"));\n+\t\treturn check_term_format(argv[0], argv[1]);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex ae3cb01..a727c59 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -564,38 +564,11 @@ write_terms () {\n \tthen\n \t\tdie \"$(gettext \"please use two different terms\")\"\n \tfi\n-\tcheck_term_format \"$TERM_BAD\" bad\n-\tcheck_term_format \"$TERM_GOOD\" good\n+\tgit bisect--helper --check-term-format \"$TERM_BAD\" bad || exit\n+\tgit bisect--helper --check-term-format \"$TERM_GOOD\" good || exit\n \tprintf '%s\\n%s\\n' \"$TERM_BAD\" \"$TERM_GOOD\" >\"$GIT_DIR/BISECT_TERMS\"\n }\n \n-check_term_format () {\n-\tterm=$1\n-\tgit check-ref-format refs/bisect/\"$term\" ||\n-\tdie \"$(eval_gettext \"'\\$term' is not a valid term\")\"\n-\tcase \"$term\" in\n-\thelp|start|terms|skip|next|reset|visualize|replay|log|run)\n-\t\tdie \"$(eval_gettext \"can't use the builtin command '\\$term' as a term\")\"\n-\t\t;;\n-\tbad|new)\n-\t\tif test \"$2\" != bad\n-\t\tthen\n-\t\t\t# In theory, nothing prevents swapping\n-\t\t\t# completely good and bad, but this situation\n-\t\t\t# could be confusing and hasn't been tested\n-\t\t\t# enough. Forbid it for now.\n-\t\t\tdie \"$(eval_gettext \"can't change the meaning of term '\\$term'\")\"\n-\t\tfi\n-\t\t;;\n-\tgood|old)\n-\t\tif test \"$2\" != good\n-\t\tthen\n-\t\t\tdie \"$(eval_gettext \"can't change the meaning of term '\\$term'\")\"\n-\t\tfi\n-\t\t;;\n-\tesac\n-}\n-\n check_and_set_terms () {\n \tcmd=\"$1\"\n \tcase \"$cmd\" in\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304161","messageId":"01020157c38b1b47-1ec438cb-2643-4e6c-b010-b7585429f948-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 26/27] bisect--helper: retire `--bisect-auto-next` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:30:42Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--bisect-auto-next` subcommand is no longer used in the shell\nscript and the function `bisect_auto_next` is called from the C\nimplementation.\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 | 10 ----------\n 1 file changed, 10 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 8653fde..d6c2efc 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -27,7 +27,6 @@ static const char * const git_bisect_helper_usage[] = {\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 \tN_(\"git bisect--helper --bisect-next\"),\n-\tN_(\"git bisect--helper --bisect-auto-next\"),\n \tN_(\"git bisect--helper --bisect-state (bad|new) [<rev>]\"),\n \tN_(\"git bisect--helper --bisect-state (good|old) [<rev>...]\"),\n \tN_(\"git bisect--helper --bisect-replay <filename>\"),\n@@ -993,7 +992,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_TERMS,\n \t\tBISECT_START,\n \t\tBISECT_NEXT,\n-\t\tBISECT_AUTO_NEXT,\n \t\tBISECT_STATE,\n \t\tBISECT_LOG,\n \t\tBISECT_REPLAY\n@@ -1012,8 +1010,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"start the bisect session\"), BISECT_START),\n \t\tOPT_CMDMODE(0, \"bisect-next\", &cmdmode,\n \t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n-\t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n-\t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n \t\tOPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n \t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-log\", &cmdmode,\n@@ -1069,12 +1065,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tget_terms(&terms);\n \t\tres = bisect_next(&terms, prefix);\n \t\tbreak;\n-\tcase BISECT_AUTO_NEXT:\n-\t\tif (argc)\n-\t\t\tdie(_(\"--bisect-auto-next requires 0 arguments\"));\n-\t\tget_terms(&terms);\n-\t\tres = bisect_auto_next(&terms, prefix);\n-\t\tbreak;\n \tcase BISECT_STATE:\n \t\tif (argc == 0)\n \t\t\tdie(_(\"--bisect-state requires at least 1 argument\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304162","messageId":"01020157c38b1aed-b292f336-2675-46d4-a270-4ba46a722def-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 16/27] bisect--helper: retire `--bisect-clean-state` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:31:09Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `bisect-clean-state` subcommand is no longer used in the shell\nscript while the C code uses `bisect_clean_state()` thus remove the\nsubcommand.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 9 ---------\n 1 file changed, 9 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex fcd7574..45d9336 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -22,7 +22,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\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> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n@@ -761,7 +760,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n-\t\tBISECT_CLEAN_STATE,\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n@@ -778,8 +776,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n \t\tOPT_CMDMODE(0, \"write-terms\", &cmdmode,\n \t\t\t N_(\"write the terms to .git/BISECT_TERMS\"), WRITE_TERMS),\n-\t\tOPT_CMDMODE(0, \"bisect-clean-state\", &cmdmode,\n-\t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n@@ -820,11 +816,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n \t\tres = write_terms(argv[0], argv[1]);\n \t\tbreak;\n-\tcase BISECT_CLEAN_STATE:\n-\t\tif (argc != 0)\n-\t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n-\t\tres = bisect_clean_state();\n-\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304165","messageId":"01020157c38b1ab6-bda8420e-9a63-47d7-9b99-47465b6333d9-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T14:50:54Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `is_expected_rev` & `check_expected_revs` shell function in\nC and add a `--check-expected-revs` subcommand to `git bisect--helper` to\ncall it from git-bisect.sh .\n\nUsing `--check-expected-revs` subcommand is a temporary measure to port\nshell functions to C so as to use the existing test suite. As more\nfunctions are ported, this subcommand would be retired but its\nimplementation will be called by some other method.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 33 ++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 20 ++------------------\n 2 files changed, 34 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex d84ba86..c542e8b 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static int is_expected_rev(const char *expected_hex)\n+{\n+\tstruct strbuf actual_hex = STRBUF_INIT;\n+\tint res = 0;\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {\n+\t\tstrbuf_trim(&actual_hex);\n+\t\tres = !strcmp(actual_hex.buf, expected_hex);\n+\t}\n+\tstrbuf_release(&actual_hex);\n+\treturn res;\n+}\n+\n+static int check_expected_revs(const char **revs, int rev_nr)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < rev_nr; i++) {\n+\t\tif (!is_expected_rev(revs[i])) {\n+\t\t\tunlink_or_warn(git_path_bisect_ancestors_ok());\n+\t\t\tunlink_or_warn(git_path_bisect_expected_rev());\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n \t\tBISECT_CLEAN_STATE,\n-\t\tBISECT_RESET\n+\t\tBISECT_RESET,\n+\t\tCHECK_EXPECTED_REVS\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -141,6 +168,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"cleanup the bisection state\"), BISECT_CLEAN_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-reset\", &cmdmode,\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n+\t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n+\t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -167,6 +196,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n \t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\tcase CHECK_EXPECTED_REVS:\n+\t\treturn check_expected_revs(argv, argc);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 442397b..c3e43248 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -237,22 +237,6 @@ bisect_write() {\n \ttest -n \"$nolog\" || echo \"git bisect $state $rev\" >>\"$GIT_DIR/BISECT_LOG\"\n }\n \n-is_expected_rev() {\n-\ttest -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n-\ttest \"$1\" = $(cat \"$GIT_DIR/BISECT_EXPECTED_REV\")\n-}\n-\n-check_expected_revs() {\n-\tfor _rev in \"$@\"; do\n-\t\tif ! is_expected_rev \"$_rev\"\n-\t\tthen\n-\t\t\trm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\"\n-\t\t\trm -f \"$GIT_DIR/BISECT_EXPECTED_REV\"\n-\t\t\treturn\n-\t\tfi\n-\tdone\n-}\n-\n bisect_skip() {\n \tall=''\n \tfor arg in \"$@\"\n@@ -280,7 +264,7 @@ bisect_state() {\n \t\trev=$(git rev-parse --verify \"$bisected_head\") ||\n \t\t\tdie \"$(eval_gettext \"Bad rev input: \\$bisected_head\")\"\n \t\tbisect_write \"$state\" \"$rev\"\n-\t\tcheck_expected_revs \"$rev\" ;;\n+\t\tgit bisect--helper --check-expected-revs \"$rev\" ;;\n \t2,\"$TERM_BAD\"|*,\"$TERM_GOOD\"|*,skip)\n \t\tshift\n \t\thash_list=''\n@@ -294,7 +278,7 @@ bisect_state() {\n \t\tdo\n \t\t\tbisect_write \"$state\" \"$rev\"\n \t\tdone\n-\t\tcheck_expected_revs $hash_list ;;\n+\t\tgit bisect--helper --check-expected-revs $hash_list ;;\n \t*,\"$TERM_BAD\")\n \t\tdie \"$(eval_gettext \"'git bisect \\$TERM_BAD' can take only one argument.\")\" ;;\n \t*)\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304166","messageId":"01020157c38b1b50-74ee305b-1121-4c0f-b827-30d115d0bf02-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 25/27] bisect--helper: retire `--bisect-autostart` subcommand","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T15:08:26Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The `--bisect-autostart` subcommand is no longer used in the shell\nscript and the function `bisect_autostart()` is called from the C\nimplementation.\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 | 11 -----------\n 1 file changed, 11 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 7f676e2..8653fde 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -28,7 +28,6 @@ static const char * const git_bisect_helper_usage[] = {\n \t\t\t\t\t      \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n \tN_(\"git bisect--helper --bisect-next\"),\n \tN_(\"git bisect--helper --bisect-auto-next\"),\n-\tN_(\"git bisect--helper --bisect-autostart\"),\n \tN_(\"git bisect--helper --bisect-state (bad|new) [<rev>]\"),\n \tN_(\"git bisect--helper --bisect-state (good|old) [<rev>...]\"),\n \tN_(\"git bisect--helper --bisect-replay <filename>\"),\n@@ -995,7 +994,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_START,\n \t\tBISECT_NEXT,\n \t\tBISECT_AUTO_NEXT,\n-\t\tBISECT_AUTOSTART,\n \t\tBISECT_STATE,\n \t\tBISECT_LOG,\n \t\tBISECT_REPLAY\n@@ -1016,8 +1014,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n \t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n \t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n-\t\tOPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n-\t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n \t\tOPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n \t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n \t\tOPT_CMDMODE(0, \"bisect-log\", &cmdmode,\n@@ -1079,13 +1075,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tget_terms(&terms);\n \t\tres = bisect_auto_next(&terms, prefix);\n \t\tbreak;\n-\tcase BISECT_AUTOSTART:\n-\t\tif (argc)\n-\t\t\tdie(_(\"--bisect-autostart requires 0 arguments\"));\n-\t\tterms.term_good = \"good\";\n-\t\tterms.term_bad = \"bad\";\n-\t\tres = bisect_autostart(&terms);\n-\t\tbreak;\n \tcase BISECT_STATE:\n \t\tif (argc == 0)\n \t\t\tdie(_(\"--bisect-state requires at least 1 argument\"));\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304167","messageId":"CAFZEwPOjK25m84BgTF7AL72DL_K1dHf7OrYoX=_vky9r3GayNw@mail.gmail.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T15:12:43Z","receivedAt":"2016-10-14T15:12:49Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey everyone,\n\nIt took me some time to get to the next version as I was a bit\npreoccupied with my assignments and exams. The diff between the v14[1]\nand v15[2] can be found here[3] because gmail web client will wrap the\nlines. Thanks Junio for the reviews in v14. I have tried to solves\nevery issue raised in the previous round.\n\nThe major changes in this series are:\n * Use the char * instead of struct strbuf in struct bisect_terms.\n * Use goto mechanism for error handling.\n * Use get_sha1_committish() instead of just get_oid() because there\nis also ^{commit} at the end of the call from shell.\n * Use skip_prefix() where ever required.\n * Use return error() instead of die() where ever possible.\n * Restructure a part in bisect_start() to make it more readable.\n * Change the comments in bisect.c to use return instead of exit\nbecause the code does it.\n * Introduce a test to check for cleanups in after bad merge base to\nmake the patch 15/28 more understood.\n * Also keeping comments in bisect.c to show at which places there\nwould be cleanups and where not.\n * Restructure bisect_replay() and get_next_word().\n\n\n[1]: http://public-inbox.org/git/01020156b73fe5b4-5dc768ab-b73b-4a21-ab92-018e2a7aa6f7-000000@eu-west-1.amazonses.com/T/#m7c26060fcf95abbd19f93742d7317eef87b915a1\n[2]: http://public-inbox.org/git/01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com/T/#u\n[3]: http://paste.ubuntu.com/23323581/\n\nRegards,\nPranit Bauva\n"},{"id":"304171","messageId":"01020157c38b1adb-ab4c90ed-d084-40b5-a037-f62c76e52ec4-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 11/27] bisect--helper: `bisect_next_check` & bisect_voc shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T16:11:09Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Reimplement `bisect_next_check` shell function in C and add\n`bisect-next-check` subcommand to `git bisect--helper` to call it from\ngit-bisect.sh .\n\nAlso reimplement `bisect_voc` shell function in C and call it from\n`bisect_next_check` implementation in C.\n\nUsing `--bisect-next-check` is a temporary measure to port shell\nfunction to C so as to use the existing test suite. As more functions\nare ported, this subcommand will be retired but its implementation will\nbe called by some other methods.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            |  60 ++------------------------\n 2 files changed, 113 insertions(+), 57 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex c6c11e3..317d671 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -6,6 +6,7 @@\n #include \"dir.h\"\n #include \"argv-array.h\"\n #include \"run-command.h\"\n+#include \"prompt.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -21,6 +22,7 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n+\tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n \tNULL\n };\n \n@@ -245,6 +247,102 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)\n \treturn 0;\n }\n \n+static int mark_good(const char *refname, const struct object_id *oid,\n+\t\t     int flag, void *cb_data)\n+{\n+\tint *m_good = (int *)cb_data;\n+\t*m_good = 0;\n+\treturn 1;\n+}\n+\n+static char *bisect_voc(char *revision_type)\n+{\n+\tif (!strcmp(revision_type, \"bad\"))\n+\t\treturn \"bad|new\";\n+\tif (!strcmp(revision_type, \"good\"))\n+\t\treturn \"good|old\";\n+\n+\treturn NULL;\n+}\n+\n+static int bisect_next_check(const struct bisect_terms *terms,\n+\t\t\t     const char *current_term)\n+{\n+\tint missing_good = 1, missing_bad = 1, retval = 0;\n+\tchar *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n+\tchar *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n+\tchar *bad_syn, *good_syn;\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 && 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\tretval = -1;\n+\t\t\tgoto finish;\n+\t\t}\n+\n+\t\tgoto finish;\n+\t}\n+\tbad_syn = xstrdup(bisect_voc(\"bad\"));\n+\tgood_syn = xstrdup(bisect_voc(\"good\"));\n+\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n+\t\terror(_(\"You need to give me at least one %s and \"\n+\t\t\t\"%s revision. You can use \\\"git bisect %s\\\" \"\n+\t\t\t\"and \\\"git bisect %s\\\" for that. \\n\"),\n+\t\t\tbad_syn, good_syn, bad_syn, good_syn);\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\telse {\n+\t\terror(_(\"You need to start by \\\"git bisect start\\\". You \"\n+\t\t\t\"then need to give me at least one %s and %s \"\n+\t\t\t\"revision. You can use \\\"git bisect %s\\\" and \"\n+\t\t\t\"\\\"git bisect %s\\\" for that.\\n\"),\n+\t\t\tgood_syn, bad_syn, bad_syn, good_syn);\n+\t\tretval = -1;\n+\t\tgoto finish;\n+\t}\n+\tgoto finish;\n+finish:\n+\tif (!bad_ref)\n+\t\tfree(bad_ref);\n+\tif (!good_glob)\n+\t\tfree(good_glob);\n+\tif (!bad_syn)\n+\t\tfree(bad_syn);\n+\tif (!good_syn)\n+\t\tfree(good_syn);\n+\treturn retval;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -254,7 +352,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tBISECT_RESET,\n \t\tCHECK_EXPECTED_REVS,\n \t\tBISECT_WRITE,\n-\t\tCHECK_AND_SET_TERMS\n+\t\tCHECK_AND_SET_TERMS,\n+\t\tBISECT_NEXT_CHECK\n \t} cmdmode = 0;\n \tint no_checkout = 0, res = 0;\n \tstruct option options[] = {\n@@ -272,6 +371,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_CMDMODE(0, \"check-and-set-terms\", &cmdmode,\n \t\t\t N_(\"check and set terms in a bisection state\"), CHECK_AND_SET_TERMS),\n+\t\tOPT_CMDMODE(0, \"bisect-next-check\", &cmdmode,\n+\t\t\t N_(\"check whether bad or good terms exist\"), BISECT_NEXT_CHECK),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n@@ -321,6 +422,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tterms.term_bad = xstrdup(argv[2]);\n \t\tres = check_and_set_terms(&terms, argv[0]);\n \t\tbreak;\n+\tcase BISECT_NEXT_CHECK:\n+\t\tif (argc != 2 && argc != 3)\n+\t\t\tdie(_(\"--bisect-next-check requires 2 or 3 arguments\"));\n+\t\tterms.term_good = xstrdup(argv[0]);\n+\t\tterms.term_bad = xstrdup(argv[1]);\n+\t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex bdf2227..fe6c9d0 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -271,59 +271,14 @@ bisect_state() {\n \tbisect_auto_next\n }\n \n-bisect_next_check() {\n-\tmissing_good= missing_bad=\n-\tgit show-ref -q --verify refs/bisect/$TERM_BAD || missing_bad=t\n-\ttest -n \"$(git for-each-ref \"refs/bisect/$TERM_GOOD-*\")\" || missing_good=t\n-\n-\tcase \"$missing_good,$missing_bad,$1\" in\n-\t,,*)\n-\t\t: have both $TERM_GOOD and $TERM_BAD - ok\n-\t\t;;\n-\t*,)\n-\t\t# do not have both but not asked to fail - just report.\n-\t\tfalse\n-\t\t;;\n-\tt,,\"$TERM_GOOD\")\n-\t\t# have bad (or new) but not good (or old).  we could bisect although\n-\t\t# this is less optimum.\n-\t\teval_gettextln \"Warning: bisecting only with a \\$TERM_BAD commit.\" >&2\n-\t\tif test -t 0\n-\t\tthen\n-\t\t\t# TRANSLATORS: Make sure to include [Y] and [n] in your\n-\t\t\t# translation. The program will only accept English input\n-\t\t\t# at this point.\n-\t\t\tgettext \"Are you sure [Y/n]? \" >&2\n-\t\t\tread yesno\n-\t\t\tcase \"$yesno\" in [Nn]*) exit 1 ;; esac\n-\t\tfi\n-\t\t: bisect without $TERM_GOOD...\n-\t\t;;\n-\t*)\n-\t\tbad_syn=$(bisect_voc bad)\n-\t\tgood_syn=$(bisect_voc good)\n-\t\tif test -s \"$GIT_DIR/BISECT_START\"\n-\t\tthen\n-\n-\t\t\teval_gettextln \"You need to give me at least one \\$bad_syn and one \\$good_syn revision.\n-(You can use \\\"git bisect \\$bad_syn\\\" and \\\"git bisect \\$good_syn\\\" for that.)\" >&2\n-\t\telse\n-\t\t\teval_gettextln \"You need to start by \\\"git bisect start\\\".\n-You then need to give me at least one \\$good_syn and one \\$bad_syn revision.\n-(You can use \\\"git bisect \\$bad_syn\\\" and \\\"git bisect \\$good_syn\\\" for that.)\" >&2\n-\t\tfi\n-\t\texit 1 ;;\n-\tesac\n-}\n-\n bisect_auto_next() {\n-\tbisect_next_check && bisect_next || :\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD && bisect_next || :\n }\n \n bisect_next() {\n \tcase \"$#\" in 0) ;; *) usage ;; esac\n \tbisect_autostart\n-\tbisect_next_check $TERM_GOOD\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit\n \n \t# Perform all bisection computation, display and checkout\n \tgit bisect--helper --next-all $(test -f \"$GIT_DIR/BISECT_HEAD\" && echo --no-checkout)\n@@ -355,7 +310,7 @@ bisect_next() {\n }\n \n bisect_visualize() {\n-\tbisect_next_check fail\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit\n \n \tif test $# = 0\n \tthen\n@@ -409,7 +364,7 @@ bisect_replay () {\n }\n \n bisect_run () {\n-\tbisect_next_check fail\n+\tgit bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit\n \n \twhile true\n \tdo\n@@ -482,13 +437,6 @@ get_terms () {\n \tfi\n }\n \n-bisect_voc () {\n-\tcase \"$1\" in\n-\tbad) echo \"bad|new\" ;;\n-\tgood) echo \"good|old\" ;;\n-\tesac\n-}\n-\n bisect_terms () {\n \tget_terms\n \tif ! test -s \"$GIT_DIR/BISECT_TERMS\"\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304172","messageId":"01020157c38b1b58-947a88c6-2da5-4b64-8802-94127516cb6b-000000@eu-west-1.amazonses.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"[PATCH v15 27/27] bisect--helper: remove the dequote in bisect_start()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-14T14:14:16Z","receivedAt":"2016-10-14T16:34:52Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Dequoting the arguments was introduced in 25b48b5c to port the function\n`bisect_next()` but after the `bisect_replay()` porting, the dequoting\nis carried out itself when it passes the arguments to `bisect_start()`\nin a simpler way thus dequoting again isn't required. So remove the\nextra \"deqouting\" code introduced by the commit 25b48b5c.\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 | 26 ++++++--------------------\n 1 file changed, 6 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex d6c2efc..8cd6527 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -561,24 +561,16 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \t\tno_checkout = 1;\n \n \tfor (i = 0; i < argc; i++) {\n-\t\tconst char *arg;\n-\t\tif (starts_with(argv[i], \"'\"))\n-\t\t\targ = sq_dequote(xstrdup(argv[i]));\n-\t\telse\n-\t\t\targ = argv[i];\n-\t\tif (!strcmp(arg, \"--\")) {\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, *commit_id;\n-\t\tif (starts_with(argv[i], \"'\"))\n-\t\t\targ = sq_dequote(xstrdup(argv[i]));\n-\t\telse\n-\t\t\targ = argv[i];\n-\t\tcommit_id = xstrfmt(\"%s^{commit}\", arg);\n+\t\tconst char  *commit_id;\n+\t\tconst char *arg = argv[i];\n+\t\tcommit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n \t\tif (!strcmp(argv[i], \"--\")) {\n \t\t\thas_double_dash = 1;\n \t\t\tbreak;\n@@ -586,11 +578,8 @@ static int bisect_start(struct bisect_terms *terms, int 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\tif (starts_with(argv[++i], \"'\"))\n-\t\t\t\tterms->term_good = sq_dequote(xstrdup(argv[i]));\n-\t\t\telse\n-\t\t\t\tterms->term_good = xstrdup(argv[i]);\n \t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_good = xstrdup(argv[++i]);\n \t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n \t\t\tterms->term_good = arg;\n@@ -599,10 +588,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n \t\t\tterms->term_good = arg;\n \t\t} else if (!strcmp(arg, \"--term-bad\") ||\n \t\t\t !strcmp(arg, \"--term-new\")) {\n-\t\t\tif (starts_with(argv[++i], \"'\"))\n-\t\t\t\tterms->term_bad = sq_dequote(xstrdup(argv[i]));\n-\t\t\telse\n-\t\t\t\tterms->term_bad = xstrdup(argv[i]);\n+\t\t\tterms->term_bad = xstrdup(argv[++i]);\n \t\t\tmust_write_terms = 1;\n \t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg)) {\n \t\t\tmust_write_terms = 1;\n\n--\nhttps://github.com/git/git/pull/287\n"},{"id":"304203","messageId":"xmqqr37iy5bw.fsf@gitster.mtv.corp.google.com","threadId":"44299","inReplyTo":"01020157c38b1adc-d5fa6b9a-ce13-4ee9-874e-e45fac99fba6-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 14/27] t6030: no cleanup with bad merge base","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-14T21:43:31Z","receivedAt":"2016-10-16T00:34:02Z","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> +test_expect_success 'check whether bisection cleanup is not done with bad merges' '\n> +\tgit bisect start $HASH7 $SIDE_HASH7 &&\n> +\ttest_expect_failure git bisect bad >out 2>out &&\n\nI think you meant \"test_must_fail\" here.\n\n> +\ttest_i18ngrep \"The merge base\" out &&\n> +\ttest -e .git/BISECT_START\n> +'\n> +\n>  test_done\n>\n> --\n> https://github.com/git/git/pull/287\n"},{"id":"304222","messageId":"CAFZEwPMjJ90k1BwK+Bc2Ca9LXzscvs2c2BuX347N+XyREDG98Q@mail.gmail.com","threadId":"44299","inReplyTo":"xmqqr37iy5bw.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 14/27] t6030: no cleanup with bad merge base","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-10-15T08:46:26Z","receivedAt":"2016-10-16T00:34:37Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Junio,\n\nOn Sat, Oct 15, 2016 at 3:13 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Pranit Bauva <pranit.bauva@gmail.com> writes:\n>\n>> +test_expect_success 'check whether bisection cleanup is not done with bad merges' '\n>> +     git bisect start $HASH7 $SIDE_HASH7 &&\n>> +     test_expect_failure git bisect bad >out 2>out &&\n>\n> I think you meant \"test_must_fail\" here.\n\nOh yes! Thanks for pointing it out. I see that you have already\nsubmitted a patch to catch this mistake which was previously ignored.\nThanks!\n\nRegards,\nPranit Bauva\n"},{"id":"304969","messageId":"xmqqvawd7mnr.fsf@gitster.mtv.corp.google.com","threadId":"44299","inReplyTo":"01020157c38b19e0-81123fa5-5d9d-4f64-8f1b-ff336e83ebe4-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-27T16:59:52Z","receivedAt":"2016-10-27T17:00:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Cc'ed those who touched either \"git-bisect.sh\" or \"builtin/bisect-helper.c\"\nin our relatively recent past.\n\nDoes any of you (and others on the list) have time and inclination\nto review this series?\n\nThanks.\n"},{"id":"304986","messageId":"CAP8UFD3Er7AWO8-bwXbsGr05eoBUEgPcmiS53n-PT19e9h+7sg@mail.gmail.com","threadId":"44299","inReplyTo":"xmqqvawd7mnr.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-10-27T20:14:44Z","receivedAt":"2016-10-27T20:14:50Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Thu, Oct 27, 2016 at 6:59 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Cc'ed those who touched either \"git-bisect.sh\" or \"builtin/bisect-helper.c\"\n> in our relatively recent past.\n>\n> Does any of you (and others on the list) have time and inclination\n> to review this series?\n\nAs part of my mentoring Pranit for the GSoC I already took a look at\nthose patches some months ago on GitHub.\n\nI could take another look at them but my eyes will not be fresh\nanymore, so I don know if it will be valuable.\n"},{"id":"305042","messageId":"vpqtwbxgge1.fsf@anie.imag.fr","threadId":"44299","inReplyTo":"xmqqvawd7mnr.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2016-10-28T06:02:46Z","receivedAt":"2016-10-28T06:03:02Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Cc'ed those who touched either \"git-bisect.sh\" or \"builtin/bisect-helper.c\"\n> in our relatively recent past.\n>\n> Does any of you (and others on the list) have time and inclination\n> to review this series?\n\nUnfortunately, I have essentially zero-bandwidth to do that in the near\nfuture :-(.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"305923","messageId":"61aacd44-cb6a-2bbb-7fb4-933e2505040d@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1a74-ad2bcaff-0c92-4af4-9aa0-72d98f4945fc-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 02/27] bisect: rewrite `check_term_format` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-14T22:20:54Z","receivedAt":"2016-11-14T22:21:04Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nI saw in the recent \"What's cooking\" mail that this is still waiting\nfor review, so I thought I could interfere and help reviewing it from a\nnon-git-developer point of view.\nBut only two commits for today. The first one seems fine. The second\none makes me write this mail ;-)\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> +static int check_term_format(const char *term, const char *orig_term)\n> +{\n[...]\n> +\tif (one_of(term, \"help\", \"start\", \"skip\", \"next\", \"reset\",\n> +\t\t\t\"visualize\", \"replay\", \"log\", \"run\", NULL))\n[... vs ...]\n> -check_term_format () {\n> -\tterm=$1\n> -\tgit check-ref-format refs/bisect/\"$term\" ||\n> -\tdie \"$(eval_gettext \"'\\$term' is not a valid term\")\"\n> -\tcase \"$term\" in\n> -\thelp|start|terms|skip|next|reset|visualize|replay|log|run)\n\nIs there a reasons why \"terms\" has been dropped from the list?\n\nBest\nStephan\n"},{"id":"305936","messageId":"CAFZEwPM9RSTGN54dzaw9gO9iZmsYjJ_d1SjUD4EzSDDbmh-XuA@mail.gmail.com","threadId":"44299","inReplyTo":"61aacd44-cb6a-2bbb-7fb4-933e2505040d@gmx.net","subject":"Re: [PATCH v15 02/27] bisect: rewrite `check_term_format` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-11-15T05:16:47Z","receivedAt":"2016-11-15T05:42:38Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Tue, Nov 15, 2016 at 3:50 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> I saw in the recent \"What's cooking\" mail that this is still waiting\n> for review, so I thought I could interfere and help reviewing it from a\n> non-git-developer point of view.\n> But only two commits for today. The first one seems fine. The second\n> one makes me write this mail ;-)\n\nThanks a lot!\n\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> +static int check_term_format(const char *term, const char *orig_term)\n>> +{\n> [...]\n>> +     if (one_of(term, \"help\", \"start\", \"skip\", \"next\", \"reset\",\n>> +                     \"visualize\", \"replay\", \"log\", \"run\", NULL))\n> [... vs ...]\n>> -check_term_format () {\n>> -     term=$1\n>> -     git check-ref-format refs/bisect/\"$term\" ||\n>> -     die \"$(eval_gettext \"'\\$term' is not a valid term\")\"\n>> -     case \"$term\" in\n>> -     help|start|terms|skip|next|reset|visualize|replay|log|run)\n>\n> Is there a reasons why \"terms\" has been dropped from the list?\n\nIt is a mistake. I will rectify.. Thanks!\n\nRegards,\nPranit Bauva\n"},{"id":"305985","messageId":"13aa642a-2272-c5b8-4a30-382ab5e73b98@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1a82-dc1c5b57-3e93-4996-87e7-4a1d83cb5817-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 04/27] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-15T21:09:11Z","receivedAt":"2016-11-15T21:09:21Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/bisect.c b/bisect.c\n> index 6f512c2..45d598d 100644\n> --- a/bisect.c\n> +++ b/bisect.c\n> @@ -1040,3 +1046,40 @@ int estimate_bisect_steps(int all)\n>  \n>  \treturn (e < 3 * x) ? n : n - 1;\n>  }\n> +\n> +static int mark_for_removal(const char *refname, const struct object_id *oid,\n> +\t\t\t    int flag, void *cb_data)\n> +{\n> +\tstruct string_list *refs = cb_data;\n> +\tchar *ref = xstrfmt(\"refs/bisect%s\", refname);\n> +\tstring_list_append(refs, ref);\n> +\treturn 0;\n> +}\n> +\n> +int bisect_clean_state(void)\n> +{\n> +\tint result = 0;\n> +\n> +\t/* There may be some refs packed during bisection */\n> +\tstruct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n> +\tfor_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n> +\tstring_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n> +\tresult = delete_refs(&refs_for_removal, REF_NODEREF);\n> +\trefs_for_removal.strdup_strings = 1;\n> +\tstring_list_clear(&refs_for_removal, 0);\n\nDoes it have advantages to populate a list (with duplicated strings),\nhand it to delete_refs(), and clear the list (and strings), instead of\njust doing a single delete_ref() (or whatever name the singular function\nhas) in the callback?\nI am only seeing the disadvantage: a list with duped strings.\n\n> +\tunlink_or_warn(git_path_bisect_expected_rev());\n[...]\n> +\tunlink_or_warn(git_path_bisect_start());\n\nComparing it with the original shell code (which uses \"rm -f\"), I was\nwondering a little after reading the function name unlink_or_warn()\nhere... Looking it up helped: despite its name, unlink_or_warn() is\nreally the function you have to use here ;D\n\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 65cf519..4254d61 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -5,10 +5,15 @@\n>  #include \"refs.h\"\n>  \n>  static GIT_PATH_FUNC(git_path_bisect_terms, \"BISECT_TERMS\")\n> +static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n> +static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, \"BISECT_ANCESTORS_OK\")\n> +static GIT_PATH_FUNC(git_path_bisect_log, \"BISECT_LOG\")\n> +static GIT_PATH_FUNC(git_path_bisect_start, \"BISECT_START\")\n\nThis is perhaps a non-issue, but you do not need any of these new path\nfunctions in *this* patch. I think nobody really cares, though, because\nyou will need them later.\n\nCheers\nStephan\n"},{"id":"305986","messageId":"xmqq37istoay.fsf@gitster.mtv.corp.google.com","threadId":"44299","inReplyTo":"13aa642a-2272-c5b8-4a30-382ab5e73b98@gmx.net","subject":"Re: [PATCH v15 04/27] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-11-15T21:40:05Z","receivedAt":"2016-11-15T21:40:14Z","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>> +int bisect_clean_state(void)\n>> +{\n>> +\tint result = 0;\n>> +\n>> +\t/* There may be some refs packed during bisection */\n>> +\tstruct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n>> +\tfor_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n>> +\tstring_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n>> +\tresult = delete_refs(&refs_for_removal, REF_NODEREF);\n>> +\trefs_for_removal.strdup_strings = 1;\n>> +\tstring_list_clear(&refs_for_removal, 0);\n>\n> Does it have advantages to populate a list (with duplicated strings),\n> hand it to delete_refs(), and clear the list (and strings), instead of\n> just doing a single delete_ref() (or whatever name the singular function\n> has) in the callback?\n\nDepending on ref backends, removing multiple refs may be a lot more\nefficient than calling a single ref removal for the same set of\nrefs, and the comment upfront I think hints that the code was\nwritten in the way exactly with that in mind.  Removing N refs from\na packed refs file will involve a loop that runs N times, each\niteration loading the file, locating an entry among possibly 100s of\nrefs to remove, and then rewriting the file.\n\nBesides, it is bad taste to delete each individual item being\niterated over in an interator in general, isn't it?\n\n"},{"id":"305987","messageId":"20ffa616-765d-ef73-4133-977561105eff@gmx.net","threadId":"44299","inReplyTo":"xmqqvawd7mnr.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-15T21:40:31Z","receivedAt":"2016-11-15T21:40:46Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/27/2016 06:59 PM, Junio C Hamano wrote:\n> Does any of you (and others on the list) have time and inclination\n> to review this series?\n\nMe, currently. ;)\nBesides the things I'm mentioning in respective patch e-mails, I wonder\nwhy several bisect--helper commands are prefixed by \"bisect\"; I'm\ntalking about:\n\n\tgit bisect--helper --bisect-clean-state\n\tgit bisect--helper --bisect-reset\n\tgit bisect--helper --bisect-write\n\tgit bisect--helper --bisect-check-and-set-terms\n\tgit bisect--helper --bisect-next-check\n\tgit bisect--helper --bisect-terms\n\tgit bisect--helper --bisect-start\n\tetc.\n\ninstead of\n\n\tgit bisect--helper --clean-state\n\tgit bisect--helper --reset\n\tgit bisect--helper --write\n\tgit bisect--helper --check-and-set-terms\n\tgit bisect--helper --next-check\n\tgit bisect--helper --terms\n\tgit bisect--helper --start\n\tetc.\n\nWell, I know *why* they have these names: because the shell function\nnames are simply reused. But I don't know why these prefixes are kept in\nthe bisect--helper command options. On the other hand, these command\nnames are not exposed to the user and may hence not be that important.(?)\n\n~Stephan\n"},{"id":"305988","messageId":"827c5f88-dcdd-2fa0-5461-77f29be87783@gmx.net","threadId":"44299","inReplyTo":"xmqq37istoay.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 04/27] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-15T21:53:42Z","receivedAt":"2016-11-15T21:53:55Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On 11/15/2016 10:40 PM, Junio C Hamano wrote:\n> Stephan Beyer <s-beyer@gmx.net> writes:\n> \n>>> +int bisect_clean_state(void)\n>>> +{\n>>> +\tint result = 0;\n>>> +\n>>> +\t/* There may be some refs packed during bisection */\n>>> +\tstruct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n>>> +\tfor_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n>>> +\tstring_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n>>> +\tresult = delete_refs(&refs_for_removal, REF_NODEREF);\n>>> +\trefs_for_removal.strdup_strings = 1;\n>>> +\tstring_list_clear(&refs_for_removal, 0);\n>>\n>> Does it have advantages to populate a list (with duplicated strings),\n>> hand it to delete_refs(), and clear the list (and strings), instead of\n>> just doing a single delete_ref() (or whatever name the singular function\n>> has) in the callback?\n> \n> Depending on ref backends, removing multiple refs may be a lot more\n> efficient than calling a single ref removal for the same set of\n> refs, and the comment upfront I think hints that the code was\n> written in the way exactly with that in mind.  Removing N refs from\n> a packed refs file will involve a loop that runs N times, each\n> iteration loading the file, locating an entry among possibly 100s of\n> refs to remove, and then rewriting the file.\n\nGreat, that's the reply I wanted to hear (and that I've considered but\nwasn't sure of) ;)\n[I did not want to dig into the sources and check if delete_refs() does\nsomething smarter than invoking delete_ref() on each item of the list.]\n\n~Stephan\n"},{"id":"306011","messageId":"098cb39e-3c92-df56-1dc9-c529df817262@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1ad3-ea75ed97-2514-427e-8e57-9f10efd4e6e9-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 13/27] bisect--helper: `bisect_start` shell function partially in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-15T23:19:34Z","receivedAt":"2016-11-15T23:19:43Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 6a5878c..1d3e17f 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -24,6 +27,8 @@ static const char * const git_bisect_helper_usage[] = {\n>  \tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n>  \tN_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n>  \tN_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n> +\tN_(\"git bisect--helper --bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]\"\n> +\t\t\t\t\t      \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n\nTypo: \"--bisect start\" with space instead of \"-\"\n\n> @@ -403,6 +408,205 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>  \treturn 0;\n>  }\n>  \n> +static int bisect_start(struct bisect_terms *terms, int no_checkout,\n> +\t\t\tconst char **argv, int argc)\n> +{\n> +\tint i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;\n> +\tint flags, pathspec_pos, 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 strbuf orig_args = STRBUF_INIT;\n> +\tconst char *head;\n> +\tunsigned char sha1[20];\n> +\tFILE *fp = NULL;\n> +\tstruct object_id oid;\n> +\n> +\tif (is_bare_repository())\n> +\t\tno_checkout = 1;\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tif (!strcmp(argv[i], \"--\")) {\n> +\t\t\thas_double_dash = 1;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tconst char *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n> +\t\tconst char *arg = argv[i];\n> +\t\tif (!strcmp(argv[i], \"--\")) {\n> +\t\t\thas_double_dash = 1;\n\nThis is without effect since has_double_dash is already set to 1 by the\nloop above. I think you can remove this line.\n\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\tterms->term_good = xstrdup(argv[++i]);\n> +\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n> +\t\t\tmust_write_terms = 1;\n> +\t\t\tterms->term_good = xstrdup(arg);\n> +\t\t} else if (skip_prefix(arg, \"--term-old=\", &arg)) {\n> +\t\t\tmust_write_terms = 1;\n> +\t\t\tterms->term_good = xstrdup(arg);\n\nI think you can join the last two branches:\n\n+\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg) ||\n+\t\t           skip_prefix(arg, \"--term-old=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_good = xstrdup(arg);\n\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\tterms->term_bad = xstrdup(argv[++i]);\n> +\t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg)) {\n> +\t\t\tmust_write_terms = 1;\n> +\t\t\tterms->term_bad = xstrdup(arg);\n> +\t\t} else if (skip_prefix(arg, \"--term-new=\", &arg)) {\n> +\t\t\tmust_write_terms = 1;\n> +\t\t\tterms->term_good = xstrdup(arg);\n\nThis has to be terms->term_bad = ...\n\nAlso, you can join the last two branches, again, ie,\n\n+\t\t} else if (skip_prefix(arg, \"--term-bad=\", &arg) ||\n+\t\t           skip_prefix(arg, \"--term-new=\", &arg)) {\n+\t\t\tmust_write_terms = 1;\n+\t\t\tterms->term_bad = xstrdup(arg);\n\n> +\t\t} else if (starts_with(arg, \"--\") &&\n> +\t\t\t !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n> +\t\t\tdie(_(\"unrecognised option: '%s'\"), arg);\n[...]\n> +\t/*\n> +\t * Verify HEAD\n> +\t */\n> +\thead = resolve_ref_unsafe(\"HEAD\", 0, sha1, &flags);\n> +\tif (!head)\n> +\t\tif (get_sha1(\"HEAD\", sha1))\n> +\t\t\tdie(_(\"Bad HEAD - I need a HEAD\"));\n> +\n> +\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n\nYou were so eager to re-use the comments from the shell script, but you\nforgot the \"Check if we are bisecting.\" comment above this line ;-)\n\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> +\tif (must_write_terms)\n> +\t\tif (write_terms(terms->term_bad, terms->term_good)) {\n> +\t\t\tretval = -1;\n> +\t\t\tgoto finish;\n> +\t\t}\n> +\n\nbisect_start() is a pretty big function.\nI think it can easily be decomposed in some smaller parts, for example,\nthe following lines ...\n\n> +\tfp = fopen(git_path_bisect_log(), \"a\");\n> +\tif (!fp)\n> +\t\treturn -1;\n> +\n> +\tif (fprintf(fp, \"git bisect start\") < 1) {\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n> +\n> +\tsq_quote_argv(&orig_args, argv, 0);\n> +\tif (fprintf(fp, \"%s\", orig_args.buf) < 0) {\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n> +\tif (fprintf(fp, \"\\n\") < 1) {\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n\n... could be in a function like\n\nstatic int bisect_append_log(const char **argv)\n{\n\tFILE *fp = fopen(git_path_bisect_log(), \"a\");\n\tstruct strbuf orig_args = STRBUF_INIT;\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, 0);\n\tif (fprintf(fp, \"%s\", orig_args.buf) < 0 ||\n\t    fprintf(fp, \"\\n\") < 1) {\n\t\tretval = -1;\n\t\tgoto finish;\n\t}\n\nfinish:\n\tif (fp)\n\t\tfclose(fp);\n\tstrbuf_release(&orig_args);\n\n\treturn retval;\n}\n\nand then simply call\n\n\tretval = bisect_append_log(argv);\n\nin bisect_start()... (This is totally untested.)\n\nIf you do not want that for some reason, you should at least fix\n\n> +\tif (!fp)\n> +\t\treturn -1;\n\nto retval = 1; goto finish; such that the other lists and strings are\nreleased.\n\n> +\tgoto finish;\n> +finish:\n\nThe \"goto finish\" right above the \"finish\" label is unnecessary.\n\n> +\tif (fp)\n> +\t\tfclose(fp);\n> +\tstring_list_clear(&revs, 0);\n> +\tstring_list_clear(&states, 0);\n> +\tstrbuf_release(&start_head);\n> +\tstrbuf_release(&bisect_names);\n> +\tstrbuf_release(&orig_args);\n> +\treturn retval;\n> +}\n> +\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n>  \tenum {\n\nBy the way, there are two spaghetti-ish ways to get rid of the\n\n\tretval = -1;\n\tgoto finish;\n\nline pair:\n\n\tgoto fail;\n\nand below the \"return retval;\" add\n\nfail:\n\tretval = -1;\n\tgoto finish;\n\nand you can feel the touch of His Noodly Appendage. *scnr*\n\nThe other way is to keep the \"goto finish\" I deemed unnecessary (right\nabove the label), and expand it to:\n\n\tgoto finish;\nfail:\n\tretval = -1;\nfinish:\n\t...\n\nCheers\n  Stephan\n"},{"id":"306024","messageId":"xmqqpolws2ez.fsf@gitster.mtv.corp.google.com","threadId":"44299","inReplyTo":"20ffa616-765d-ef73-4133-977561105eff@gmx.net","subject":"Re: [PATCH v15 01/27] bisect--helper: use OPT_CMDMODE instead of OPT_BOOL","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-11-16T00:18:12Z","receivedAt":"2016-11-16T00:18:19Z","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> Besides the things I'm mentioning in respective patch e-mails, I wonder\n> why several bisect--helper commands are prefixed by \"bisect\"; I'm\n> talking about:\n>\n> \tgit bisect--helper --bisect-clean-state\n>...\n> \tgit bisect--helper --bisect-start\n> \tetc.\n>\n> instead of\n>\n> \tgit bisect--helper --clean-state\n>...\n> \tgit bisect--helper --start\n> \tetc.\n>\n> Well, I know *why* they have these names: because the shell function\n> names are simply reused. But I don't know why these prefixes are kept in\n> the bisect--helper command options. On the other hand, these command\n> names are not exposed to the user and may hence not be that important.(?)\n\nThat's a good point ;-) \n\nThese are not intended to be end-user entry points, so names that\nare bit longer than necessary does not bother me too much.\nHopefully the longer-term endgame would be not to need a separate\n\"bisect-helper\" binary at all but to have a \"git bisect\" binary\nmaking these requests as subroutine calls, and at that point, the\nnames of the functions would want to have \"bisect\" prefix.\n"},{"id":"306059","messageId":"CAFZEwPMrC=7wJtUO+G3dcESPOJisFsrZ0_F6oKE8eDVGfBEVpg@mail.gmail.com","threadId":"44299","inReplyTo":"xmqq37istoay.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v15 04/27] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-11-16T16:49:28Z","receivedAt":"2016-11-16T16:49:36Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Junio,\n\nOn Wed, Nov 16, 2016 at 3:10 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Stephan Beyer <s-beyer@gmx.net> writes:\n>\n> >> +int bisect_clean_state(void)\n> >> +{\n> >> +    int result = 0;\n> >> +\n> >> +    /* There may be some refs packed during bisection */\n> >> +    struct string_list refs_for_removal = STRING_LIST_INIT_NODUP;\n> >> +    for_each_ref_in(\"refs/bisect\", mark_for_removal, (void *) &refs_for_removal);\n> >> +    string_list_append(&refs_for_removal, xstrdup(\"BISECT_HEAD\"));\n> >> +    result = delete_refs(&refs_for_removal, REF_NODEREF);\n> >> +    refs_for_removal.strdup_strings = 1;\n> >> +    string_list_clear(&refs_for_removal, 0);\n> >\n> > Does it have advantages to populate a list (with duplicated strings),\n> > hand it to delete_refs(), and clear the list (and strings), instead of\n> > just doing a single delete_ref() (or whatever name the singular function\n> > has) in the callback?\n>\n> Depending on ref backends, removing multiple refs may be a lot more\n> efficient than calling a single ref removal for the same set of\n> refs, and the comment upfront I think hints that the code was\n> written in the way exactly with that in mind.  Removing N refs from\n> a packed refs file will involve a loop that runs N times, each\n> iteration loading the file, locating an entry among possibly 100s of\n> refs to remove, and then rewriting the file.\n>\n> Besides, it is bad taste to delete each individual item being\n> iterated over in an interator in general, isn't it?\n>\n\nNot just that, deleting a ref inside for_each*() is illegal because it\nbuilds some kind of index and that is spoiled if anything is deleted\nin between. Thus it gives a seg fault. See this[1]. I did the same\nmistake when making this patch and I was confused about that was\nhappening but then Michael Haggerty pointed this out[2].\n\n[1]: https://github.com/git/git/blob/v2.11.0-rc1/refs.h#L183-L191\n[2]: http://public-inbox.org/git/574D122F.7080608@alum.mit.edu/\n\nRegards,\nPranit Bauva\n"},{"id":"306062","messageId":"CAFZEwPOswSePNWn=X-sPf08nGMcKp8m_VkeNdqHfWxsEqu7z7A@mail.gmail.com","threadId":"44299","inReplyTo":"098cb39e-3c92-df56-1dc9-c529df817262@gmx.net","subject":"Re: [PATCH v15 13/27] bisect--helper: `bisect_start` shell function partially in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-11-16T17:09:35Z","receivedAt":"2016-11-16T17:09:44Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Wed, Nov 16, 2016 at 4:49 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 6a5878c..1d3e17f 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -24,6 +27,8 @@ static const char * const git_bisect_helper_usage[] = {\n>>       N_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n>>       N_(\"git bisect--helper --bisect-next-check [<term>] <TERM_GOOD> <TERM_BAD\"),\n>>       N_(\"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]\"),\n>> +     N_(\"git bisect--helper --bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]\"\n>> +                                           \"[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]\"),\n>\n> Typo: \"--bisect start\" with space instead of \"-\"\n>\n>> @@ -403,6 +408,205 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>>       return 0;\n>>  }\n>>\n>> +static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>> +                     const char **argv, int argc)\n>> +{\n>> +     int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;\n>> +     int flags, pathspec_pos, retval = 0;\n>> +     struct string_list revs = STRING_LIST_INIT_DUP;\n>> +     struct string_list states = STRING_LIST_INIT_DUP;\n>> +     struct strbuf start_head = STRBUF_INIT;\n>> +     struct strbuf bisect_names = STRBUF_INIT;\n>> +     struct strbuf orig_args = STRBUF_INIT;\n>> +     const char *head;\n>> +     unsigned char sha1[20];\n>> +     FILE *fp = NULL;\n>> +     struct object_id oid;\n>> +\n>> +     if (is_bare_repository())\n>> +             no_checkout = 1;\n>> +\n>> +     for (i = 0; i < argc; i++) {\n>> +             if (!strcmp(argv[i], \"--\")) {\n>> +                     has_double_dash = 1;\n>> +                     break;\n>> +             }\n>> +     }\n>> +\n>> +     for (i = 0; i < argc; i++) {\n>> +             const char *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n>> +             const char *arg = argv[i];\n>> +             if (!strcmp(argv[i], \"--\")) {\n>> +                     has_double_dash = 1;\n>\n> This is without effect since has_double_dash is already set to 1 by the\n> loop above. I think you can remove this line.\n\nTrue. I will remove this line.\n\n>> +                     break;\n>> +             } else if (!strcmp(arg, \"--no-checkout\")) {\n>> +                     no_checkout = 1;\n>> +             } else if (!strcmp(arg, \"--term-good\") ||\n>> +                      !strcmp(arg, \"--term-old\")) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_good = xstrdup(argv[++i]);\n>> +             } else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_good = xstrdup(arg);\n>> +             } else if (skip_prefix(arg, \"--term-old=\", &arg)) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_good = xstrdup(arg);\n>\n> I think you can join the last two branches:\n>\n> +               } else if (skip_prefix(arg, \"--term-good=\", &arg) ||\n> +                          skip_prefix(arg, \"--term-old=\", &arg)) {\n> +                       must_write_terms = 1;\n> +                       terms->term_good = xstrdup(arg);\n>\n>> +             } else if (!strcmp(arg, \"--term-bad\") ||\n>> +                      !strcmp(arg, \"--term-new\")) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_bad = xstrdup(argv[++i]);\n>> +             } else if (skip_prefix(arg, \"--term-bad=\", &arg)) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_bad = xstrdup(arg);\n>> +             } else if (skip_prefix(arg, \"--term-new=\", &arg)) {\n>> +                     must_write_terms = 1;\n>> +                     terms->term_good = xstrdup(arg);\n>\n> This has to be terms->term_bad = ...\n\nMy bad.\n\n> Also, you can join the last two branches, again, ie,\n\nSure!\n\n> +               } else if (skip_prefix(arg, \"--term-bad=\", &arg) ||\n> +                          skip_prefix(arg, \"--term-new=\", &arg)) {\n> +                       must_write_terms = 1;\n> +                       terms->term_bad = xstrdup(arg);\n>\n>> +             } else if (starts_with(arg, \"--\") &&\n>> +                      !one_of(arg, \"--term-good\", \"--term-bad\", NULL)) {\n>> +                     die(_(\"unrecognised option: '%s'\"), arg);\n> [...]\n>> +     /*\n>> +      * Verify HEAD\n>> +      */\n>> +     head = resolve_ref_unsafe(\"HEAD\", 0, sha1, &flags);\n>> +     if (!head)\n>> +             if (get_sha1(\"HEAD\", sha1))\n>> +                     die(_(\"Bad HEAD - I need a HEAD\"));\n>> +\n>> +     if (!is_empty_or_missing_file(git_path_bisect_start())) {\n>\n> You were so eager to re-use the comments from the shell script, but you\n> forgot the \"Check if we are bisecting.\" comment above this line ;-)\n\nI will add it back again.\n\n>> +             /* Reset to the rev from where we started */\n>> +             strbuf_read_file(&start_head, git_path_bisect_start(), 0);\n>> +             strbuf_trim(&start_head);\n>> +             if (!no_checkout) {\n>> +                     struct argv_array argv = ARGV_ARRAY_INIT;\n> [...]\n>> +     if (must_write_terms)\n>> +             if (write_terms(terms->term_bad, terms->term_good)) {\n>> +                     retval = -1;\n>> +                     goto finish;\n>> +             }\n>> +\n>\n> bisect_start() is a pretty big function.\n> I think it can easily be decomposed in some smaller parts, for example,\n> the following lines ...\n>\n>> +     fp = fopen(git_path_bisect_log(), \"a\");\n>> +     if (!fp)\n>> +             return -1;\n>> +\n>> +     if (fprintf(fp, \"git bisect start\") < 1) {\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>> +\n>> +     sq_quote_argv(&orig_args, argv, 0);\n>> +     if (fprintf(fp, \"%s\", orig_args.buf) < 0) {\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>> +     if (fprintf(fp, \"\\n\") < 1) {\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>\n> ... could be in a function like\n>\n> static int bisect_append_log(const char **argv)\n> {\n>         FILE *fp = fopen(git_path_bisect_log(), \"a\");\n>         struct strbuf orig_args = STRBUF_INIT;\n>         if (!fp)\n>                 return -1;\n>\n>         if (fprintf(fp, \"git bisect start\") < 1) {\n>                 retval = -1;\n>                 goto finish;\n>         }\n>\n>         sq_quote_argv(&orig_args, argv, 0);\n>         if (fprintf(fp, \"%s\", orig_args.buf) < 0 ||\n>             fprintf(fp, \"\\n\") < 1) {\n>                 retval = -1;\n>                 goto finish;\n>         }\n>\n> finish:\n>         if (fp)\n>                 fclose(fp);\n>         strbuf_release(&orig_args);\n>\n>         return retval;\n> }\n>\n> and then simply call\n>\n>         retval = bisect_append_log(argv);\n>\n> in bisect_start()... (This is totally untested.)\n\nI think this would be a better choice. Thanks!\n\n> If you do not want that for some reason, you should at least fix\n>\n>> +     if (!fp)\n>> +             return -1;\n>\n> to retval = 1; goto finish; such that the other lists and strings are\n> released.\n>\n>> +     goto finish;\n>> +finish:\n>\n> The \"goto finish\" right above the \"finish\" label is unnecessary.\n>\n>> +     if (fp)\n>> +             fclose(fp);\n>> +     string_list_clear(&revs, 0);\n>> +     string_list_clear(&states, 0);\n>> +     strbuf_release(&start_head);\n>> +     strbuf_release(&bisect_names);\n>> +     strbuf_release(&orig_args);\n>> +     return retval;\n>> +}\n>> +\n>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>  {\n>>       enum {\n>\n> By the way, there are two spaghetti-ish ways to get rid of the\n>\n>         retval = -1;\n>         goto finish;\n>\n> line pair:\n>\n>         goto fail;\n>\n> and below the \"return retval;\" add\n>\n> fail:\n>         retval = -1;\n>         goto finish;\n>\n> and you can feel the touch of His Noodly Appendage. *scnr*\n\nNice little trick.\n\n> The other way is to keep the \"goto finish\" I deemed unnecessary (right\n> above the label), and expand it to:\n>\n>         goto finish;\n> fail:\n>         retval = -1;\n> finish:\n>         ...\n\n\nRegards,\nPranit Bauva\n"},{"id":"306086","messageId":"1190e37e-d54a-7dbf-412d-8dff90ca677a@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1aa0-0c1fed14-e058-4621-9958-973113d7e45f-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 07/27] bisect--helper: `bisect_reset` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-16T23:23:31Z","receivedAt":"2016-11-16T23:23:40Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 4254d61..d84ba86 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -84,12 +89,47 @@ static int write_terms(const char *bad, const char *good)\n>  \treturn (res < 0) ? -1 : 0;\n>  }\n>  \n> +static int bisect_reset(const char *commit)\n> +{\n> +\tstruct strbuf branch = STRBUF_INIT;\n> +\n> +\tif (!commit) {\n> +\t\tif (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n> +\t\t\tprintf(\"We are not bisecting.\\n\");\n\nI think this string should be marked for translation.\n\n> +\t\t\treturn 0;\n> +\t\t}\n> +\t\tstrbuf_rtrim(&branch);\n[...]\n> @@ -121,6 +163,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tif (argc != 0)\n>  \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n>  \t\treturn bisect_clean_state();\n> +\tcase BISECT_RESET:\n> +\t\tif (argc > 1)\n> +\t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n\nThis error message is imho a little unspecific (but this might not be an\nissue because bisect--helper commands are not really exposed to the\nuser). Maybe \"--bisect-reset requires either no argument or a commit.\"?\n\n> +\t\treturn bisect_reset(argc ? argv[0] : NULL);\n>  \tdefault:\n>  \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n>  \t}\n\n~Stephan\n"},{"id":"306091","messageId":"a4c7fec8-0e84-eb53-ca22-c369ce3facfa@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1ab6-bda8420e-9a63-47d7-9b99-47465b6333d9-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-16T23:47:22Z","receivedAt":"2016-11-16T23:47:31Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index d84ba86..c542e8b 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n>  \treturn bisect_clean_state();\n>  }\n>  \n> +static int is_expected_rev(const char *expected_hex)\n> +{\n> +\tstruct strbuf actual_hex = STRBUF_INIT;\n> +\tint res = 0;\n> +\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {\n> +\t\tstrbuf_trim(&actual_hex);\n> +\t\tres = !strcmp(actual_hex.buf, expected_hex);\n> +\t}\n> +\tstrbuf_release(&actual_hex);\n> +\treturn res;\n> +}\n\nI am not sure it does what it should.\n\nI would expect the following behavior from this function:\n - file does not exist (or is \"broken\") => return 0\n - actual_hex != expected_hex => return 0\n - otherwise return 1\n\nIf I am not wrong, the code does the following instead:\n - file does not exist (or is \"broken\") => return 0\n - actual_hex != expected_hex => return 1\n - otherwise => return 0\n\n> +static int check_expected_revs(const char **revs, int rev_nr)\n> +{\n> +\tint i;\n> +\n> +\tfor (i = 0; i < rev_nr; i++) {\n> +\t\tif (!is_expected_rev(revs[i])) {\n> +\t\t\tunlink_or_warn(git_path_bisect_ancestors_ok());\n> +\t\t\tunlink_or_warn(git_path_bisect_expected_rev());\n> +\t\t\treturn 0;\n> +\t\t}\n> +\t}\n> +\treturn 0;\n> +}\n\nHere I am not sure what the function *should* do. However, I see that it\nbasically mimics the behavior of the shell function (assuming\nis_expected_rev() is implemented correctly).\n\nI don't understand why the return value is int and not void. To avoid a\n\"return 0;\" line when calling this function?\n\n> @@ -167,6 +196,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tif (argc > 1)\n>  \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n>  \t\treturn bisect_reset(argc ? argv[0] : NULL);\n> +\tcase CHECK_EXPECTED_REVS:\n> +\t\treturn check_expected_revs(argv, argc);\n\nI note that you check the correct number of arguments for some\nsubcommands and you do not check it for some other subcommands like this\none. (I don't care, I just want to mention it.)\n\n>  \tdefault:\n>  \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n>  \t}\n\n~Stephan\n"},{"id":"306098","messageId":"CAFZEwPNtSAKut3t0n-WxZyoV=xuf9-s7XJO9gvGQWVsL3vTouw@mail.gmail.com","threadId":"44299","inReplyTo":"1190e37e-d54a-7dbf-412d-8dff90ca677a@gmx.net","subject":"Re: [PATCH v15 07/27] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-11-17T03:56:39Z","receivedAt":"2016-11-17T03:56:46Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Thu, Nov 17, 2016 at 4:53 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 4254d61..d84ba86 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -84,12 +89,47 @@ static int write_terms(const char *bad, const char *good)\n>>       return (res < 0) ? -1 : 0;\n>>  }\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>> +                     printf(\"We are not bisecting.\\n\");\n>\n> I think this string should be marked for translation.\n\nTrue. Thanks!\n\n>> +                     return 0;\n>> +             }\n>> +             strbuf_rtrim(&branch);\n> [...]\n>> @@ -121,6 +163,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               if (argc != 0)\n>>                       die(_(\"--bisect-clean-state requires no arguments\"));\n>>               return bisect_clean_state();\n>> +     case BISECT_RESET:\n>> +             if (argc > 1)\n>> +                     die(_(\"--bisect-reset requires either zero or one arguments\"));\n>\n> This error message is imho a little unspecific (but this might not be an\n> issue because bisect--helper commands are not really exposed to the\n> user). Maybe \"--bisect-reset requires either no argument or a commit.\"?\n\nThat sounds good.\n\n>> +             return bisect_reset(argc ? argv[0] : NULL);\n>>       default:\n>>               die(\"BUG: unknown subcommand '%d'\", cmdmode);\n>>       }\n\nRegards,\nPranit Bauva\n"},{"id":"306101","messageId":"ceb2c50b-0ca7-115d-eb0e-316389569e36@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1ad1-f3a59b1f-9cdb-4d91-b28e-2501facdcb45-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 09/27] bisect--helper: `bisect_write` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-17T09:40:03Z","receivedAt":"2016-11-17T09:40:14Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nI've only got some minors to mention here ;)\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index c542e8b..3f19b68 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -19,9 +19,15 @@ static const char * const git_bisect_helper_usage[] = {\n>  \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n>  \tN_(\"git bisect--helper --bisect-clean-state\"),\n>  \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n> +\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n>  \tNULL\n>  };\n\nI wouldn't write \"<TERM_GOOD <TERM_BAD>\" in capital letters. I'd use\nsomething like \"<good_term> <bad_term>\" as you have used for\n--write-terms. Note that \"git bisect --help\" uses \"<term-old>\n<term-new>\" in that context.\n\n> @@ -149,6 +155,63 @@ static int check_expected_revs(const char **revs, int rev_nr)\n>  \treturn 0;\n>  }\n>  \n> +static int bisect_write(const char *state, const char *rev,\n> +\t\t\tconst struct bisect_terms *terms, int nolog)\n> +{\n> +\tstruct strbuf tag = STRBUF_INIT;\n> +\tstruct strbuf commit_name = STRBUF_INIT;\n> +\tstruct object_id oid;\n> +\tstruct commit *commit;\n> +\tstruct pretty_print_context pp = {0};\n> +\tFILE *fp = NULL;\n> +\tint retval = 0;\n> +\n> +\tif (!strcmp(state, terms->term_bad))\n> +\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n> +\telse if (one_of(state, terms->term_good, \"skip\", NULL))\n> +\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n> +\telse {\n> +\t\terror(_(\"Bad bisect_write argument: %s\"), state);\n> +\t\tretval = -1;\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\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n> +\n> +\tif (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n> +\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n\nI'd like to mention that the \"goto fail;\" trick could apply in this\nfunction, too.\n\n> @@ -156,9 +219,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tWRITE_TERMS,\n>  \t\tBISECT_CLEAN_STATE,\n>  \t\tBISECT_RESET,\n> -\t\tCHECK_EXPECTED_REVS\n> +\t\tCHECK_EXPECTED_REVS,\n> +\t\tBISECT_WRITE\n>  \t} cmdmode = 0;\n> -\tint no_checkout = 0;\n> +\tint no_checkout = 0, res = 0;\n\nWhy do you do this \"direct return\" -> \"set res and return res\" transition?\nYou don't need it in this patch, you do not need it in the subsequent\npatches (you always set \"res\" exactly once after the initialization),\nand you don't need cleanup code in this function.\n\n>  \tstruct option options[] = {\n>  \t\tOPT_CMDMODE(0, \"next-all\", &cmdmode,\n>  \t\t\t N_(\"perform 'git bisect next'\"), NEXT_ALL),\n> @@ -170,10 +234,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n>  \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n>  \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n> +\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n> +\t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n\nThat info text is confusing, especially considering that there is a\n\"nolog\" option. I think the action of bisect-write is two-fold: (1)\nupdate the refs, (2) log.\n\n> @@ -182,24 +249,37 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tusage_with_options(git_bisect_helper_usage, options);\n>  \n>  \tswitch (cmdmode) {\n> +\tint nolog;\n>  \tcase NEXT_ALL:\n>  \t\treturn bisect_next_all(prefix, no_checkout);\n>  \tcase WRITE_TERMS:\n>  \t\tif (argc != 2)\n>  \t\t\tdie(_(\"--write-terms requires two arguments\"));\n> -\t\treturn write_terms(argv[0], argv[1]);\n> +\t\tres = write_terms(argv[0], argv[1]);\n> +\t\tbreak;\n\nAs indicated above, I think the direct \"return ...;\" is cleaner.\n\n\n~Stephan\n"},{"id":"306122","messageId":"b7691fac-9642-f87d-f23f-5175b5ead05b@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1aca-0c26fb8c-404f-4f57-afe7-7ebb552a1002-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 10/27] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-17T20:25:05Z","receivedAt":"2016-11-17T20:25:16Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 3f19b68..c6c11e3 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -20,6 +20,7 @@ static const char * const git_bisect_helper_usage[] = {\n>  \tN_(\"git bisect--helper --bisect-clean-state\"),\n>  \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n>  \tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n> +\tN_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n\nHere's the same as in the previous patch... I'd not use\nTERM_GOOD/TERM_BAD in capitals.\n\n>  \tNULL\n>  };\n>  \n> @@ -212,6 +213,38 @@ static int bisect_write(const char *state, const char *rev,\n>  \treturn retval;\n>  }\n>  \n> +static int 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> +\treturn write_terms(terms->term_bad, terms->term_good);\n\nAt this stage of the patch series I am wondering why you are setting\n\"terms\" here, but I guess you'll need it later.\n\nHowever, you are leaking memory here. Something like\n\n\tfree(terms->term_good);\n\tfree(terms->term_bad);\n\tterms->term_good = xstrdup(good);\n\tterms->term_bad = xstrdup(bad);\n\nshould be safe (because you've always used xstrdup() for the terms\nmembers before). Or am I overseeing something?\n\n> @@ -278,6 +314,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tterms.term_bad = xstrdup(argv[3]);\n>  \t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n>  \t\tbreak;\n> +\tcase CHECK_AND_SET_TERMS:\n> +\t\tif (argc != 3)\n> +\t\t\tdie(_(\"--check-and-set-terms requires 3 arguments\"));\n> +\t\tterms.term_good = xstrdup(argv[1]);\n> +\t\tterms.term_bad = xstrdup(argv[2]);\n> +\t\tres = check_and_set_terms(&terms, argv[0]);\n> +\t\tbreak;\n\nHa! When I reviewed the last patch, I asked you why you changed the code\nfrom returning directly from each subcommand to setting res; break; and\nthen return res at the bottom of the function.\n\nNow I see why this was useful. The two members of \"terms\" are again\nleaking memory: you are allocating memory by using xstrdup() but you are\nnot freeing it.\n(That also applies to the last patch.)\n\nCheers,\nStephan\n"},{"id":"306123","messageId":"b78a4cbf-86ed-938e-1d41-6c48e0df981e@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1adb-ab4c90ed-d084-40b5-a037-f62c76e52ec4-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 11/27] bisect--helper: `bisect_next_check` & bisect_voc shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-17T20:59:47Z","receivedAt":"2016-11-17T20:59:55Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> Also reimplement `bisect_voc` shell function in C and call it from\n> `bisect_next_check` implementation in C.\n\nPlease don't! ;D\n\n> +static char *bisect_voc(char *revision_type)\n> +{\n> +\tif (!strcmp(revision_type, \"bad\"))\n> +\t\treturn \"bad|new\";\n> +\tif (!strcmp(revision_type, \"good\"))\n> +\t\treturn \"good|old\";\n> +\n> +\treturn NULL;\n> +}\n\nWhy not simply use something like this:\n\nstatic const char *voc[] = {\n\t\"bad|new\",\n\t\"good|old\",\n};\n\nThen...\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> +\tchar *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n> +\tchar *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n> +\tchar *bad_syn, *good_syn;\n\n...you don't need bad_syn and good_syn...\n\n> +\tbad_syn = xstrdup(bisect_voc(\"bad\"));\n> +\tgood_syn = xstrdup(bisect_voc(\"good\"));\n\n...and hence not these two lines...\n\n> +\tif (!is_empty_or_missing_file(git_path_bisect_start())) {\n> +\t\terror(_(\"You need to give me at least one %s and \"\n> +\t\t\t\"%s revision. You can use \\\"git bisect %s\\\" \"\n> +\t\t\t\"and \\\"git bisect %s\\\" for that. \\n\"),\n> +\t\t\tbad_syn, good_syn, bad_syn, good_syn);\n\n...and write\n\t\t\tvoc[0], voc[1], voc[0], voc[1]);\ninstead...\n\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n> +\telse {\n> +\t\terror(_(\"You need to start by \\\"git bisect start\\\". You \"\n> +\t\t\t\"then need to give me at least one %s and %s \"\n> +\t\t\t\"revision. You can use \\\"git bisect %s\\\" and \"\n> +\t\t\t\"\\\"git bisect %s\\\" for that.\\n\"),\n> +\t\t\tgood_syn, bad_syn, bad_syn, good_syn);\n\n...and here\n\t\t\tvoc[1], voc[0], voc[0], voc[1]);\n...\n\n> +\t\tretval = -1;\n> +\t\tgoto finish;\n> +\t}\n> +\tgoto finish;\n> +finish:\n> +\tif (!bad_ref)\n> +\t\tfree(bad_ref);\n> +\tif (!good_glob)\n> +\t\tfree(good_glob);\n> +\tif (!bad_syn)\n> +\t\tfree(bad_syn);\n> +\tif (!good_syn)\n> +\t\tfree(good_syn);\n\n...and you can remove the 4 lines above.\n\n> +\treturn retval;\n> +}\n\nBesides that, there are again some things that I've already mentioned\nand that can be applied here, too, for example, not capitalizing\nTERM_GOOD and TERM_BAD, the goto fail simplification, the terms memory leak.\n\nCheers\nStephan\n"},{"id":"306124","messageId":"b54f7f46-a3c0-3334-24fa-e8d1e7d8f653@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1ad5-0f90c88e-2077-4155-94e9-7d71dbbac38f-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 12/27] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-17T21:32:07Z","receivedAt":"2016-11-17T21:32:32Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 317d671..6a5878c 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> +\tconst char bisect_term_usage[] =\n> +\"git bisect--helper --bisect-terms [--term-good | --term-bad | ]\"\n> +\"--term-old | --term-new\";\n\nThree things:\n\n(1) Is that indentation intentional?\n\n(2) You have a \"]\" at the end of the first part of the string instead of\nthe end of the second part.\n\n(3) After the correction, bisect_term_usage and\ngit_bisect_helper_usage[7] are the same strings. I don't recommend to\nuse git_bisect_helper_usage[7] instead because keeping the index\nup-to-date is a maintenance hell. (At the end of your patch series it is\na 3 instead of a 7.) However, if - for whatever reason - the usage of\nbisect--helper --bisect-terms changes, you always have to sync the two\nstrings which is also nasty....\n\n> +\n> +\tif (get_terms(terms))\n> +\t\treturn error(_(\"no terms defined\"));\n> +\n> +\tif (argc > 1) {\n> +\t\tusage(bisect_term_usage);\n> +\t\treturn -1;\n> +\t}\n\n...and since you only use it once, why not simply do something like\n\nreturn error(_(\"--bisect-term requires exactly one argument\"));\n\nand drop the definition of bisect_term_usage.\n\n> +\n> +\tif (argc == 0) {\n> +\t\tprintf(_(\"Your current terms are %s for the old state\\nand \"\n> +\t\t       \"%s for the new state.\\n\"), terms->term_good,\n> +\t\t       terms->term_bad);\n\nVery minor: It improves the readability if you'd split the string after\nthe \\n and put the \"and \"in the next line.\n\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tif (!strcmp(argv[i], \"--term-good\"))\n> +\t\t\tprintf(\"%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\tdie(_(\"invalid argument %s for 'git bisect \"\n> +\t\t\t\t  \"terms'.\\nSupported options are: \"\n> +\t\t\t\t  \"--term-good|--term-old and \"\n> +\t\t\t\t  \"--term-bad|--term-new.\"), argv[i]);\n\nHm, \"return error(...)\" and \"die(...)\" seems to be quasi-equivalent in\nthis case. Because I am always looking from a library perspective, I'd\nprefer \"return error(...)\".\n\n> @@ -429,6 +492,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tterms.term_bad = xstrdup(argv[1]);\n>  \t\tres = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n>  \t\tbreak;\n> +\tcase BISECT_TERMS:\n> +\t\tif (argc > 1)\n> +\t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n> +\t\tres = bisect_terms(&terms, argv, argc);\n> +\t\tbreak;\n\nAlso here: \"terms\" is leaking...\n\n~Stephan\n"},{"id":"306125","messageId":"c49a6151-0827-cae5-0569-8f05515be0f9@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1b18-b81203b0-122f-4244-bfb2-9fac8ae71767-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 22/27] bisect--helper: `bisect_log` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-17T21:47:29Z","receivedAt":"2016-11-17T21:47:39Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 493034c..c18ca07 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -858,6 +858,23 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,\n>  \treturn -1;\n>  }\n>  \n> +static int bisect_log(void)\n> +{\n> +\tint fd, status;\n> +\tfd = open(git_path_bisect_log(), O_RDONLY);\n> +\tif (fd < 0)\n> +\t\treturn -1;\n> +\n> +\tstatus = copy_fd(fd, 1);\n\nPerhaps\n\n\tstatus = copy_fd(fd, STDOUT_FILENO);\n\n> +\tif (status) {\n> +\t\tclose(fd);\n> +\t\treturn -1;\n> +\t}\n> +\n> +\tclose(fd);\n> +\treturn status;\n> +}\n\nThat's weird.\nEither get rid of the if() and actually use status:\n\n\tstatus = copy_fd(fd, STDOUT_FILENO);\n\n\tclose(fd);\n\treturn status ? -1 : 0;\n\nor get rid of status and use the if:\n\n\tif (copy_fd(fd, STDOUT_FILENO)) {\n\t\tclose(fd);\n\t\treturn -1;\n\t}\n\n\tclose(fd);\n\treturn 0;\n\nI'd recommend the shorter variant ;)\n\n~Stephan\n"},{"id":"306202","messageId":"52f6241f-e584-d830-ca66-084dc509c7fe@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1ad3-ea75ed97-2514-427e-8e57-9f10efd4e6e9-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 13/27] bisect--helper: `bisect_start` shell function partially in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-20T20:01:27Z","receivedAt":"2016-11-20T20:01:37Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 6a5878c..1d3e17f 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -403,6 +408,205 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>  \treturn 0;\n>  }\n>  \n> +static int bisect_start(struct bisect_terms *terms, int no_checkout,\n> +\t\t\tconst char **argv, int argc)\n> +{\n> +\tint i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;\n> +\tint flags, pathspec_pos, 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 strbuf orig_args = STRBUF_INIT;\n> +\tconst char *head;\n> +\tunsigned char sha1[20];\n> +\tFILE *fp = NULL;\n> +\tstruct object_id oid;\n> +\n> +\tif (is_bare_repository())\n> +\t\tno_checkout = 1;\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tif (!strcmp(argv[i], \"--\")) {\n> +\t\t\thas_double_dash = 1;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\n> +\tfor (i = 0; i < argc; i++) {\n> +\t\tconst char *commit_id = xstrfmt(\"%s^{commit}\", argv[i]);\n> +\t\tconst char *arg = argv[i];\n> +\t\tif (!strcmp(argv[i], \"--\")) {\n> +\t\t\thas_double_dash = 1;\n> +\t\t\tbreak;\n> +\t\t} else if (!strcmp(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\tterms->term_good = xstrdup(argv[++i]);\n\nAll these xstrdup() for the terms here and below will leak memory.\n\nI recommend to use xstrdup() also at (*) below, and use\nfree(terms->term_good) above this line (and for every occurrence below,\nof course).\n\n> +\t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n> +\t\t\tmust_write_terms = 1;\n> +\t\t\tterms->term_good = xstrdup(arg);\n[...]\n> @@ -497,6 +705,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\t\tdie(_(\"--bisect-terms requires 0 or 1 argument\"));\n>  \t\tres = bisect_terms(&terms, argv, argc);\n>  \t\tbreak;\n> +\tcase BISECT_START:\n> +\t\tterms.term_good = \"good\";\n> +\t\tterms.term_bad = \"bad\";\n\nHere is (*): use xstrdup(\"good\") etc.\n\nAnd then, as already mentioned for another patch, free(terms.*) below.\n\n\n\nI personally am a friend of small functions and would prefer something\nlike as follows...  (This is a comment about several patches of your\nseries, not only this one.)\n\nFirst, replace the current set_terms() by\n\nstatic void set_terms(struct bisect_terms *terms, const char *bad,\n                                                 const char *good)\n{\n\tterms->term_good = xstrdup(good);\n\tterms->term_bad = xstrdup(bad);\n}\n\nie, without calling write_terms(...).\nAnd then replace the *current* set_terms() calls by set_terms(...);\nwrite_terms(...); calls.\n\nSecond, add\n\nstatic void get_default_terms(struct bisect_terms *terms)\n{\n\tset_terms(terms, \"bad\", \"good\");\n}\n\nand use this instead of the two lines quoted above (and all its other\noccurrences).\n\nThird, use the new set_terms() everywhere instead of settings terms\nmembers directly (with the exception of get_terms()).\n\nThis sounds like a safer variant (with respect to leaks and handling\nthem) to me than doing it the current way.\n\n~Stephan\n"},{"id":"306203","messageId":"8bd0682f-e35e-a50e-24a9-fd3a53454ed4@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1af0-5d688c2e-868d-4d8c-a8fd-9a675f7f01da-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-20T20:01:34Z","receivedAt":"2016-11-20T20:01:42Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nthis one is hard to review because you do two or three commits in one here.\nI think the first commit should be the exit()->return conversion, the\nsecond commit is next and autonext, and the third commit is the pretty\ntrivial bisect_start commit ;) However, you did it this way and it's\nalways a hassle to split commit, so I don't really care...\n\nHowever, I was reviewing this superficially, to be honest. This mail\nskips the next and autonext part.\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/bisect.c b/bisect.c\n> index 45d598d..7c97e85 100644\n> --- a/bisect.c\n> +++ b/bisect.c\n> @@ -843,16 +878,21 @@ static int check_ancestors(const char *prefix)\n>   *\n>   * If that's not the case, we need to check the merge bases.\n>   * If a merge base must be tested by the user, its source code will be\n> - * checked out to be tested by the user and we will exit.\n> + * checked out to be tested by the user and we will return.\n>   */\n> -static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n> +static int check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n>  {\n>  \tchar *filename = git_pathdup(\"BISECT_ANCESTORS_OK\");\n>  \tstruct stat st;\n> -\tint fd;\n> +\tint fd, res = 0;\n>  \n> +\t/*\n> +\t * We don't want to clean the bisection state\n> +\t * as we need to get back to where we started\n> +\t * by using `git bisect reset`.\n> +\t */\n>  \tif (!current_bad_oid)\n> -\t\tdie(_(\"a %s revision is needed\"), term_bad);\n> +\t\terror(_(\"a %s revision is needed\"), term_bad);\n\nOnly error() or return error()?\n\n> @@ -873,8 +916,11 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n>  \t\t\t      filename);\n>  \telse\n>  \t\tclose(fd);\n> +\n> +\tgoto done;\n>   done:\n\nI never understand why you do this. In case of adding a \"fail\" label\n(and fail code like \"res = -1;\") between \"goto done\" and \"done:\", it's\nfine... but without one this is just a nop.\n\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 1d3e17f..fcd7574 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -427,15 +560,24 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>  \t\tno_checkout = 1;\n>  \n>  \tfor (i = 0; i < argc; i++) {\n> -\t\tif (!strcmp(argv[i], \"--\")) {\n> +\t\tconst char *arg;\n> +\t\tif (starts_with(argv[i], \"'\"))\n> +\t\t\targ = sq_dequote(xstrdup(argv[i]));\n> +\t\telse\n> +\t\t\targ = argv[i];\n\nOne is xstrdup'ed, one is not, so there'll be a leak somewhere, and it's\nan inconsistent leak... I guess it's a bad idea to do it this way ;)\n(Also below.)\n\n> @@ -443,24 +585,31 @@ static int bisect_start(struct bisect_terms *terms, int 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\tif (starts_with(argv[++i], \"'\"))\n> +\t\t\t\tterms->term_good = sq_dequote(xstrdup(argv[i]));\n> +\t\t\telse\n> +\t\t\t\tterms->term_good = xstrdup(argv[i]);\n>  \t\t\tmust_write_terms = 1;\n> -\t\t\tterms->term_good = xstrdup(argv[++i]);\n>  \t\t} else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n>  \t\t\tmust_write_terms = 1;\n> -\t\t\tterms->term_good = xstrdup(arg);\n> +\t\t\tterms->term_good = arg;\n\nNo ;) (See my other comments (to other patches) for the \"terms\" leaks.)\n\n[This repeats several times below.]\n\n> diff --git a/git-bisect.sh b/git-bisect.sh\n> index f0896b3..d574c44 100755\n> --- a/git-bisect.sh\n> +++ b/git-bisect.sh\n> @@ -109,6 +88,7 @@ bisect_skip() {\n>  bisect_state() {\n>  \tbisect_autostart\n>  \tstate=$1\n> +\tget_terms\n>  \tgit bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n>  \tget_terms\n>  \tcase \"$#,$state\" in\n\nI can't say if this change is right or wrong. It looks right, but: How\ndoes this relate to the other changes? Is this the right patch for it?\n\n~Stephan\n"},{"id":"306204","messageId":"723476f6-2c8c-38df-1771-9a525196d9de@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1b1a-067117ef-cd0d-469b-ba80-ea1a1169f694-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 18/27] bisect--helper: `bisect_autostart` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-20T20:15:00Z","receivedAt":"2016-11-20T20:15:10Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 502bf18..1767916 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -422,6 +425,7 @@ static int bisect_next(...)\n>  {\n>  \tint res, no_checkout;\n>\n> +\tbisect_autostart(terms);\n\nYou are not checking for return values here. (The shell code simply\nexited if there is no tty, but you don't.)\n\n> @@ -754,6 +758,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>  \treturn retval || bisect_auto_next(terms, NULL);\n>  }\n>  \n> +static int bisect_autostart(struct bisect_terms *terms)\n> +{\n> +\tif (is_empty_or_missing_file(git_path_bisect_start())) {\n> +\t\tconst char *yesno;\n> +\t\tconst char *argv[] = {NULL};\n> +\t\tfprintf(stderr, _(\"You need to start by \\\"git bisect \"\n> +\t\t\t\t  \"start\\\"\\n\"));\n> +\n> +\t\tif (!isatty(0))\n\nisatty(STDIN_FILENO)?\n\n> +\t\t\treturn 1;\n> +\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\nTypo \"THe\"\n\n> +\t\t * at this point.\n> +\t\t */\n\nTaking \"at this point\" into consideration, I think the Y and n can be\neasily translated now that it is in C. I guess, by using...\n\n> +\t\tyesno = git_prompt(_(\"Do you want me to do it for you \"\n> +\t\t\t\t     \"[Y/n]? \"), PROMPT_ECHO);\n> +\t\tif (starts_with(yesno, \"n\") || starts_with(yesno, \"N\"))\n\n... starts_with(yesno, _(\"n\")) || starts_with(yesno, _(\"N\"))\nhere (but not sure). However, this would be an extra patch on top of\nthis series.\n\n> +\t\t\texit(0);\n\nShouldn't this also be \"return 1;\"? Saying \"no\" is the same outcome as\nnot having a tty to ask for yes or no.\n\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n>  \tenum {\n> @@ -790,6 +821,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n>  \t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n>  \t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n> +\t\tOPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n> +\t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n\nThe word \"is\" is missing.\n\n~Stephan\n"},{"id":"306206","messageId":"de42ba9d-af15-6d77-5c97-4136b7aad149@gmx.net","threadId":"44299","inReplyTo":"52f6241f-e584-d830-ca66-084dc509c7fe@gmx.net","subject":"Re: [PATCH v15 13/27] bisect--helper: `bisect_start` shell function partially in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-20T20:19:55Z","receivedAt":"2016-11-20T20:20:03Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On 11/20/2016 09:01 PM, Stephan Beyer wrote:\n> First, replace the current set_terms() by\n> \n> static void set_terms(struct bisect_terms *terms, const char *bad,\n>                                                  const char *good)\n> {\n> \tterms->term_good = xstrdup(good);\n> \tterms->term_bad = xstrdup(bad);\n> }\n> \n> ie, without calling write_terms(...).\n\nI did not want to confuse you here but I forgot to mention that there\nshould also be freeing code, i.e. initialize your terms to NULL in the\nbeginning of cmd_builtin__helper, and always free them if it is not\nnull. This freeing code could also be in an extra function free_terms()\nand you call it in set_terms() and for cleanup in the end.\n"},{"id":"306255","messageId":"06402c8a-14a4-3d70-8d98-659cfe9f1aa2@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1af0-5d688c2e-868d-4d8c-a8fd-9a675f7f01da-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-21T21:35:24Z","receivedAt":"2016-11-21T21:35:43Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nin this mail I review the \"second part\" of your patch: the transition of\nbisect_next and bisect_auto_next to C.\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 1d3e17f..fcd7574 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -408,6 +411,136 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>  \treturn 0;\n>  }\n>  \n> +static int register_good_ref(const char *refname,\n> +\t\t\t     const struct object_id *oid, int flags,\n> +\t\t\t     void *cb_data)\n> +{\n> +\tstruct string_list *good_refs = cb_data;\n> +\tstring_list_append(good_refs, oid_to_hex(oid));\n> +\treturn 0;\n> +}\n> +\n> +static int bisect_next(struct bisect_terms *terms, const char *prefix)\n> +{\n> +\tint res, no_checkout;\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\nThe comment above makes no sense here, or does it?\n\n> +\tif (bisect_next_check(terms, terms->term_good))\n> +\t\treturn -1;\n> +\n> +\tno_checkout = !is_empty_or_missing_file(git_path_bisect_head());\n> +\n> +\t/* Perform all bisection computation, display and checkout */\n> +\tres = bisect_next_all(prefix , no_checkout);\n\nStyle: there is a space left of the comma.\n\n> +\n> +\tif (res == 10) {\n> +\t\tFILE *fp = NULL;\n> +\t\tunsigned char sha1[20];\n> +\t\tstruct commit *commit;\n> +\t\tstruct pretty_print_context pp = {0};\n> +\t\tstruct strbuf commit_name = STRBUF_INIT;\n> +\t\tchar *bad_ref = xstrfmt(\"refs/bisect/%s\",\n> +\t\t\t\t\t      terms->term_bad);\n> +\t\tint retval = 0;\n> +\n> +\t\tread_ref(bad_ref, sha1);\n> +\t\tcommit = lookup_commit_reference(sha1);\n> +\t\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n> +\t\tfp = fopen(git_path_bisect_log(), \"a\");\n> +\t\tif (!fp) {\n> +\t\t\tretval = -1;\n> +\t\t\tgoto finish_10;\n> +\t\t}\n> +\t\tif (fprintf(fp, \"# first %s commit: [%s] %s\\n\",\n> +\t\t\t    terms->term_bad, sha1_to_hex(sha1),\n> +\t\t\t    commit_name.buf) < 1){\n> +\t\t\tretval = -1;\n> +\t\t\tgoto finish_10;\n> +\t\t}\n> +\t\tgoto finish_10;\n> +\tfinish_10:\n> +\t\tif (fp)\n> +\t\t\tfclose(fp);\n> +\t\tstrbuf_release(&commit_name);\n> +\t\tfree(bad_ref);\n> +\t\treturn retval;\n> +\t}\n> +\telse if (res == 2) {\n> +\t\tFILE *fp = NULL;\n> +\t\tstruct rev_info revs;\n> +\t\tstruct argv_array rev_argv = ARGV_ARRAY_INIT;\n> +\t\tstruct string_list good_revs = STRING_LIST_INIT_DUP;\n> +\t\tstruct pretty_print_context pp = {0};\n> +\t\tstruct commit *commit;\n> +\t\tchar *term_good = xstrfmt(\"%s-*\", terms->term_good);\n> +\t\tint i, retval = 0;\n> +\n> +\t\tfp = fopen(git_path_bisect_log(), \"a\");\n> +\t\tif (!fp) {\n> +\t\t\tretval = -1;\n> +\t\t\tgoto finish_2;\n> +\t\t}\n> +\t\tif (fprintf(fp, \"# only skipped commits left to test\\n\") < 1) {\n> +\t\t\tretval = -1;\n> +\t\t\tgoto finish_2;\n> +\t\t}\n> +\t\tfor_each_glob_ref_in(register_good_ref, term_good,\n> +\t\t\t\t     \"refs/bisect/\", (void *) &good_revs);\n> +\n> +\t\targv_array_pushl(&rev_argv, \"skipped_commits\", \"refs/bisect/bad\", \"--not\", NULL);\n> +\t\tfor (i = 0; i < good_revs.nr; i++)\n> +\t\t\targv_array_push(&rev_argv, good_revs.items[i].string);\n> +\n> +\t\t/* It is important to reset the flags used by revision walks\n> +\t\t * as the previous call to bisect_next_all() in turn\n> +\t\t * setups a revision walk.\n> +\t\t */\n> +\t\treset_revision_walk();\n> +\t\tinit_revisions(&revs, NULL);\n> +\t\trev_argv.argc = setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL);\n> +\t\targv_array_clear(&rev_argv);\n> +\t\tstring_list_clear(&good_revs, 0);\n> +\t\tif (prepare_revision_walk(&revs))\n> +\t\t\tdie(_(\"revision walk setup failed\\n\"));\n> +\n> +\t\twhile ((commit = get_revision(&revs)) != NULL) {\n> +\t\t\tstruct strbuf commit_name = STRBUF_INIT;\n> +\t\t\tformat_commit_message(commit, \"%s\",\n> +\t\t\t\t\t      &commit_name, &pp);\n> +\t\t\tfprintf(fp, \"# possible first %s commit: \"\n> +\t\t\t\t    \"[%s] %s\\n\", terms->term_bad,\n> +\t\t\t\t    oid_to_hex(&commit->object.oid),\n> +\t\t\t\t    commit_name.buf);\n> +\t\t\tstrbuf_release(&commit_name);\n> +\t\t}\n> +\t\tgoto finish_2;\n> +\tfinish_2:\n> +\t\tif (fp)\n> +\t\t\tfclose(fp);\n> +\t\tstring_list_clear(&good_revs, 0);\n> +\t\targv_array_clear(&rev_argv);\n> +\t\tfree(term_good);\n> +\t\tif (retval)\n> +\t\t\treturn retval;\n> +\t\telse\n> +\t\t\treturn res;\n> +\t}\n> +\treturn res;\n> +}\n\nIt would be much nicer if you put the (res == 10) branch and the\n(res == 2) branch into separate functions and just call them.\nThen you also won't need ugly label naming like finish_10 or finish_2.\nI'd also (again) recommend to use goto fail instead of setting retval to\n-1 separately each time.\n\nI'd also recommend to use a separate function to append to the bisect\nlog file. There is a lot of duplicated opening, checking, closing code;\nIIRC such a function would also already be handy for some of the\nprevious patches.\n\n> +\n> +static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)\n> +{\n> +\tif (!bisect_next_check(terms, NULL))\n> +\t\treturn bisect_next(terms, prefix);\n> +\n> +\treturn 0;\n> +}\n\nHmm, the handling of the return values is a little confusing. However,\nif I understand the sh source correctly, it always returns success, no\nmatter if bisect_next failed or not. I do not know if you had something\nspecial in mind here.\n\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n> @@ -643,6 +794,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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_CMDMODE(0, \"bisect-next\", &cmdmode,\n> +\t\t\t N_(\"find the next bisection commit\"), BISECT_NEXT),\n> +\t\tOPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n> +\t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n\nThe next bisection *state* is found?\n\n> diff --git a/git-bisect.sh b/git-bisect.sh\n> index f0896b3..d574c44 100755\n> --- a/git-bisect.sh\n> +++ b/git-bisect.sh\n> @@ -139,45 +119,7 @@ bisect_state() {\n>  \t*)\n>  \t\tusage ;;\n>  \tesac\n> -\tbisect_auto_next\n[...deleted lines...]\n> +\tgit bisect--helper --bisect-auto-next || exit\n\nWhy is the \"|| exit\" necessary?\n\n> @@ -319,14 +260,15 @@ case \"$#\" in\n>  \thelp)\n>  \t\tgit bisect -h ;;\n>  \tstart)\n> -\t\tbisect_start \"$@\" ;;\n> +\t\tgit bisect--helper --bisect-start \"$@\" ;;\n>  \tbad|good|new|old|\"$TERM_BAD\"|\"$TERM_GOOD\")\n>  \t\tbisect_state \"$cmd\" \"$@\" ;;\n>  \tskip)\n>  \t\tbisect_skip \"$@\" ;;\n>  \tnext)\n>  \t\t# Not sure we want \"next\" at the UI level anymore.\n> -\t\tbisect_next \"$@\" ;;\n> +\t\tget_terms\n> +\t\tgit bisect--helper --bisect-next \"$@\" || exit ;;\n\nWhy is the \"|| exit\" necessary? ;)\n\n\nFurthermore:\nWhere is the bisect_autostart call from bisect_next() sh source gone?\nWas it not necessary?\n\n~Stephan\n"},{"id":"306271","messageId":"0cc22155-2b3f-b69c-9ed4-2b1c55e40eee@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1b54-0ac61448-98b1-4c7d-bfdd-47af95f52153-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 19/27] bisect--helper: `bisect_state` & `bisect_head` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-22T00:12:24Z","receivedAt":"2016-11-22T00:12:33Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> Reimplement the `bisect_state` shell function in C and also add a\n> subcommand `--bisect-state` to `git-bisect--helper` to call it from\n> git-bisect.sh .\n> \n> Using `--bisect-state` subcommand 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 and will be called by some\n> other methods.\n> \n> `bisect_head` is called from `bisect_state` thus its not required to\n> introduce another subcommand.\n\nMissing comma before \"thus\", and \"it is\" (or \"it's\") instead of \"its\" :)\n\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index 1767916..1481c6d 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -784,6 +786,79 @@ static int bisect_autostart(struct bisect_terms *terms)\n>  \treturn 0;\n>  }\n>  \n> +static char *bisect_head(void)\n> +{\n> +\tif (is_empty_or_missing_file(git_path_bisect_head()))\n> +\t\treturn \"HEAD\";\n> +\telse\n> +\t\treturn \"BISECT_HEAD\";\n> +}\n\nThis is very shellish.\nIn C I'd expect something like\n\nstatic int bisect_head_sha1(unsigned char *sha)\n{\n\tint res;\n\tif (is_empty_or_missing_file(git_path_bisect_head()))\n\t\tres = get_sha1(\"HEAD\", sha);\n\telse\n\t\tres = get_sha1(\"BISECT_HEAD\", sha);\n\n\tif (res)\n\t\treturn error(_(\"Could not find BISECT_HEAD or HEAD.\"));\n\n\treturn 0;\n}\n\n> +\n> +static int bisect_state(struct bisect_terms *terms, const char **argv,\n> +\t\t\tint argc)\n> +{\n> +\tconst char *state = argv[0];\n> +\n> +\tget_terms(terms);\n> +\tif (check_and_set_terms(terms, state))\n> +\t\treturn -1;\n> +\n> +\tif (!argc)\n> +\t\tdie(_(\"Please call `--bisect-state` with at least one argument\"));\n\nI think this check should move to cmd_bisect__helper. There are also the\nother argument number checks.\n\n> +\n> +\tif (argc == 1 && one_of(state, terms->term_good,\n> +\t    terms->term_bad, \"skip\", NULL)) {\n> +\t\tconst char *bisected_head = xstrdup(bisect_head());\n> +\t\tconst char *hex[1];\n\nMaybe:\n\t\tconst char *hex;\n\n> +\t\tunsigned char sha1[20];\n> +\n> +\t\tif (get_sha1(bisected_head, sha1))\n> +\t\t\tdie(_(\"Bad rev input: %s\"), bisected_head);\n\nAnd instead of...\n\n> +\t\tif (bisect_write(state, sha1_to_hex(sha1), terms, 0))\n> +\t\t\treturn -1;\n> +\n> +\t\t*hex = xstrdup(sha1_to_hex(sha1));\n> +\t\tif (check_expected_revs(hex, 1))\n> +\t\t\treturn -1;\n\n... simply:\n\n\t\thex = xstrdup(sha1_to_hex(sha1));\n\t\tif (set_state(terms, state, hex)) {\n\t\t\tfree(hex);\n\t\t\treturn -1;\n\t\t}\n\t\tfree(hex);\n\nwhere:\n\nstatic int set_state(struct bisect_terms *terms, const char *state,\n                                                 const char *hex)\n{\n\tif (bisect_write(state, hex, terms, 0))\n\t\treturn -1;\n\tif (check_expected_revs(&hex, 1))\n\t\treturn -1;\n\treturn 0;\n}\n\n> +\t\treturn bisect_auto_next(terms, NULL);\n> +\t}\n> +\n> +\tif ((argc == 2 && !strcmp(state, terms->term_bad)) ||\n> +\t\t\tone_of(state, terms->term_good, \"skip\", NULL)) {\n> +\t\tint i;\n> +\t\tstruct string_list hex = STRING_LIST_INIT_DUP;\n> +\n> +\t\tfor (i = 1; i < argc; i++) {\n> +\t\t\tunsigned char sha1[20];\n> +\n> +\t\t\tif (get_sha1(argv[i], sha1)) {\n> +\t\t\t\tstring_list_clear(&hex, 0);\n> +\t\t\t\tdie(_(\"Bad rev input: %s\"), argv[i]);\n> +\t\t\t}\n> +\t\t\tstring_list_append(&hex, sha1_to_hex(sha1));\n> +\t\t}\n> +\t\tfor (i = 0; i < hex.nr; i++) {\n\n... And replace this:\n\n> +\t\t\tconst char **hex_string = (const char **) &hex.items[i].string;\n> +\t\t\tif(bisect_write(state, *hex_string, terms, 0)) {\n> +\t\t\t\tstring_list_clear(&hex, 0);\n> +\t\t\t\treturn -1;\n> +\t\t\t}\n> +\t\t\tif (check_expected_revs(hex_string, 1)) {\n> +\t\t\t\tstring_list_clear(&hex, 0);\n> +\t\t\t\treturn -1;\n> +\t\t\t}\n\nby:\n\n\t\t\tconst char *hex_str = hex.items[i].string;\n\t\t\tif (set_state(terms, state, hex_string)) {\n\t\t\t\tstring_list_clear(&hex, 0);\n\t\t\t\treturn -1;\n\t\t\t}\n\n> +\t\t}\n> +\t\tstring_list_clear(&hex, 0);\n> +\t\treturn bisect_auto_next(terms, NULL);\n> +\t}\n> +\n> +\tif (!strcmp(state, terms->term_bad))\n> +\t\tdie(_(\"'git bisect %s' can take only one argument.\"),\n> +\t\t      terms->term_bad);\n> +\n> +\treturn -1;\n> +}\n> +\n>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  {\n>  \tenum {\n> @@ -823,6 +899,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\t\t N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>  \t\tOPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n>  \t\t\t N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n> +\t\tOPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n> +\t\t\t N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n\n\"mark the state of the given revs\"\n\nNote that rev != ref\n\n> @@ -902,6 +980,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>  \t\tterms.term_bad = \"bad\";\n>  \t\tres = bisect_autostart(&terms);\n>  \t\tbreak;\n> +\tcase BISECT_STATE:\n> +\t\tif (argc == 0)\n> +\t\t\tdie(_(\"--bisect-state requires at least 1 argument\"));\n\n\"at least one revision\"\n\n> diff --git a/git-bisect.sh b/git-bisect.sh\n> index cd56551..a9eebbb 100755\n> --- a/git-bisect.sh\n> +++ b/git-bisect.sh\n> @@ -61,44 +51,7 @@ bisect_skip() {\n>  \t\tesac\n>  \t\tall=\"$all $revs\"\n>  \tdone\n> -\teval bisect_state 'skip' $all\n[...deleted lines...]\n> +\teval git bisect--helper --bisect-state 'skip' $all\n\nI think you don't need \"eval\" here any longer.\n\n> @@ -184,8 +137,8 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n>  \t\t\tstate=\"$TERM_GOOD\"\n>  \t\tfi\n>  \n> -\t\t# We have to use a subshell because \"bisect_state\" can exit.\n> -\t\t( bisect_state $state >\"$GIT_DIR/BISECT_RUN\" )\n> +\t\t# We have to use a subshell because \"--bisect-state\" can exit.\n> +\t\t( git bisect--helper --bisect-state $state >\"$GIT_DIR/BISECT_RUN\" )\n\nThe new comment is funny, but you don't need a subshell here any longer.\n\n~Stephan\n"},{"id":"306275","messageId":"1816d5b4-a4c1-7c97-09ff-b11001501423@gmx.net","threadId":"44299","inReplyTo":"01020157c38b1b29-65f79716-42c6-4327-acda-8c8d0fe05471-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-11-22T00:49:46Z","receivedAt":"2016-11-22T00:50:05Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Okay Pranit,\n\nthis is the last patch for me to review in this series.\n\nNow that I have a coarse overview of what you did, I have the general\nremark that imho the \"terms\" variable should simply be global instead of\nbeing passed around all the time.\n\nI also had some other remarks but I forgot them... maybe they come to my\nmind again when I see patch series v16.\n\nI also want to remark again that I am not a Git developer and only\nreviewed this because of my interest in git-bisect. So some of my\nsuggestions might conflict with other beliefs here. For example, I\nconsider it very bad style to leak memory... but Git is rather written\nas a scripting tool than a genuine library, so perhaps many people here\ndo not care about it as long as it works...\n\nOn 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> index c18ca07..b367d8d 100644\n> --- a/builtin/bisect--helper.c\n> +++ b/builtin/bisect--helper.c\n> @@ -601,7 +602,6 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>  \t\t\tterms->term_good = arg;\n>  \t\t} else if (!strcmp(arg, \"--term-bad\") ||\n>  \t\t\t !strcmp(arg, \"--term-new\")) {\n> -\t\t\tconst char *next_arg;\n\nThis should already have been removed in patch 15/27, not here.\n\n> @@ -875,6 +875,117 @@ static int bisect_log(void)\n>  \treturn status;\n>  }\n>  \n> +static int get_next_word(const char *line, int pos, struct strbuf *word)\n> +{\n> +\tint i, len = strlen(line), begin = 0;\n> +\tstrbuf_reset(word);\n> +\tfor (i = pos; i < len; i++) {\n> +\t\tif (line[i] == ' ' && begin)\n> +\t\t\treturn i + 1;\n> +\n> +\t\tif (!begin)\n> +\t\t\tbegin = 1;\n> +\t\tstrbuf_addch(word, line[i]);\n> +\t}\n> +\n> +\treturn i;\n> +}\n> +\n> +static int bisect_replay(struct bisect_terms *terms, const char *filename)\n> +{\n> +\tstruct strbuf line = STRBUF_INIT;\n> +\tstruct strbuf word = STRBUF_INIT;\n> +\tFILE *fp = NULL;\n\n(The initialization is not necessary here.)\n\n> +\tint res = 0;\n> +\n> +\tif (is_empty_or_missing_file(filename)) {\n> +\t\terror(_(\"no such file with name '%s' exists\"), filename);\n\nThe error message is misleading if the file exists but is empty.\nMaybe something like \"cannot read file '%s' for replaying\"?\n\n> +\t\tres = -1;\n> +\t\tgoto finish;\n\n\t\tgoto fail;\n:D\n\n> +\t}\n> +\n> +\tif (bisect_reset(NULL)) {\n> +\t\tres = -1;\n> +\t\tgoto finish;\n\n\t\tgoto fail;\n\n> +\t}\n> +\n> +\tfp = fopen(filename, \"r\");\n> +\tif (!fp) {\n> +\t\tres = -1;\n> +\t\tgoto finish;\n\n\t\tgoto fail;\n\n> +\t}\n> +\n> +\twhile (strbuf_getline(&line, fp) != EOF) {\n> +\t\tint pos = 0;\n> +\t\twhile (pos < line.len) {\n> +\t\t\tpos = get_next_word(line.buf, pos, &word);\n> +\n> +\t\t\tif (!strcmp(word.buf, \"git\")) {\n> +\t\t\t\tcontinue;\n> +\t\t\t} else if (!strcmp(word.buf, \"git-bisect\")) {\n> +\t\t\t\tcontinue;\n> +\t\t\t} else if (!strcmp(word.buf, \"bisect\")) {\n> +\t\t\t\tcontinue;\n> +\t\t\t} else if (!strcmp(word.buf, \"#\")) {\n> +\t\t\t\tbreak;\n\nMaybe it is more robust to check whether word.buf begins with #\n\n> +\t\t\t}\n> +\n> +\t\t\tget_terms(terms);\n> +\t\t\tif (check_and_set_terms(terms, word.buf)) {\n> +\t\t\t\tres = -1;\n> +\t\t\t\tgoto finish;\n\n\t\t\t\tgoto fail;\n\n> +\t\t\t}\n> +\n> +\t\t\tif (!strcmp(word.buf, \"start\")) {\n> +\t\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n> +\t\t\t\tsq_dequote_to_argv_array(line.buf+pos, &argv);\n> +\t\t\t\tif (bisect_start(terms, 0, argv.argv, argv.argc)) {\n> +\t\t\t\t\targv_array_clear(&argv);\n> +\t\t\t\t\tres = -1;\n> +\t\t\t\t\tgoto finish;\n\n\t\t\t\t\tgoto fail;\n\n> +\t\t\t\t}\n> +\t\t\t\targv_array_clear(&argv);\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\n> +\t\t\tif (one_of(word.buf, terms->term_good,\n> +\t\t\t    terms->term_bad, \"skip\", NULL)) {\n> +\t\t\t\tif (bisect_write(word.buf, line.buf+pos, terms, 0)) {\n> +\t\t\t\t\tres = -1;\n> +\t\t\t\t\tgoto finish;\n\n\t\t\t\t\tgoto fail;\n\n> +\t\t\t\t}\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\n> +\t\t\tif (!strcmp(word.buf, \"terms\")) {\n> +\t\t\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n> +\t\t\t\tsq_dequote_to_argv_array(line.buf+pos, &argv);\n> +\t\t\t\tif (bisect_terms(terms, argv.argv, argv.argc)) {\n> +\t\t\t\t\targv_array_clear(&argv);\n> +\t\t\t\t\tres = -1;\n> +\t\t\t\t\tgoto finish;\n\n\t\t\t\t\tgoto fail;\n\n> +\t\t\t\t}\n> +\t\t\t\targv_array_clear(&argv);\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\n> +\t\t\terror(_(\"?? what are you talking about?\"));\n\nI know this string is taken from the original source. However, even\nsomething like error(_(\"Replay file contains rubbish (\\\"%s\\\")\"),\nword.buf) is more informative.\n\n> +\t\t\tres = -1;\n> +\t\t\tgoto finish;\n\n\t\t\tgoto fail;\n\n> +\t\t}\n> +\t}\n> +\tgoto finish;\n\n+fail:\n+\tres = -1;\n\nI just wanted to make finally clear what I was referring to by the\n\"goto fail\" trick. :D\n\nAlso I think the readability could be improved by extracting the body of\nthe outer while loop into an extra function replay_line(). Then most of\nmy suggested \"goto fail;\" lines simply become \"return -1;\" :)\n\n> @@ -998,6 +1112,13 @@ int cmd_bisect__helper(...)\n>   \t\t\tdie(_(\"--bisect-log requires 0 arguments\"));\n>   \t\tres = bisect_log();\n>   \t\tbreak;\n> +\tcase BISECT_REPLAY:\n> +\t\tif (argc != 1)\n> +\t\t\tdie(_(\"--bisect-replay requires 1 argument\"));\n\nI'd keep the (already translated) string from the original source:\n\"No logfile given\"\n\n\nCheers,\n  Stephan\n"},{"id":"307035","messageId":"CAFZEwPPXPPHi8KiEGS9ggzNHDCGhuqMgH9Z8-Pf9GLshg8+LPA@mail.gmail.com","threadId":"44299","inReplyTo":"b78a4cbf-86ed-938e-1d41-6c48e0df981e@gmx.net","subject":"Re: [PATCH v15 11/27] bisect--helper: `bisect_next_check` & bisect_voc shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T18:39:35Z","receivedAt":"2016-12-06T18:39:41Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nSorry for the late replies. My end semester exams just got over.\n\nOn Fri, Nov 18, 2016 at 2:29 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>\n> Hi Pranit,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n> > Also reimplement `bisect_voc` shell function in C and call it from\n> > `bisect_next_check` implementation in C.\n>\n> Please don't! ;D\n>\n> > +static char *bisect_voc(char *revision_type)\n> > +{\n> > +     if (!strcmp(revision_type, \"bad\"))\n> > +             return \"bad|new\";\n> > +     if (!strcmp(revision_type, \"good\"))\n> > +             return \"good|old\";\n> > +\n> > +     return NULL;\n> > +}\n>\n> Why not simply use something like this:\n>\n> static const char *voc[] = {\n>         \"bad|new\",\n>         \"good|old\",\n> };\n>\n> Then...\n\nThis probably seems a good idea.\n\n> > +static int bisect_next_check(const struct bisect_terms *terms,\n> > +                          const char *current_term)\n> > +{\n> > +     int missing_good = 1, missing_bad = 1, retval = 0;\n> > +     char *bad_ref = xstrfmt(\"refs/bisect/%s\", terms->term_bad);\n> > +     char *good_glob = xstrfmt(\"%s-*\", terms->term_good);\n> > +     char *bad_syn, *good_syn;\n>\n> ...you don't need bad_syn and good_syn...\n>\n> > +     bad_syn = xstrdup(bisect_voc(\"bad\"));\n> > +     good_syn = xstrdup(bisect_voc(\"good\"));\n>\n> ...and hence not these two lines...\n>\n> > +     if (!is_empty_or_missing_file(git_path_bisect_start())) {\n> > +             error(_(\"You need to give me at least one %s and \"\n> > +                     \"%s revision. You can use \\\"git bisect %s\\\" \"\n> > +                     \"and \\\"git bisect %s\\\" for that. \\n\"),\n> > +                     bad_syn, good_syn, bad_syn, good_syn);\n>\n> ...and write\n>                         voc[0], voc[1], voc[0], voc[1]);\n> instead...\n>\n> > +             retval = -1;\n> > +             goto finish;\n> > +     }\n> > +     else {\n> > +             error(_(\"You need to start by \\\"git bisect start\\\". You \"\n> > +                     \"then need to give me at least one %s and %s \"\n> > +                     \"revision. You can use \\\"git bisect %s\\\" and \"\n> > +                     \"\\\"git bisect %s\\\" for that.\\n\"),\n> > +                     good_syn, bad_syn, bad_syn, good_syn);\n>\n> ...and here\n>                         voc[1], voc[0], voc[0], voc[1]);\n> ...\n>\n> > +             retval = -1;\n> > +             goto finish;\n> > +     }\n> > +     goto finish;\n> > +finish:\n> > +     if (!bad_ref)\n> > +             free(bad_ref);\n> > +     if (!good_glob)\n> > +             free(good_glob);\n> > +     if (!bad_syn)\n> > +             free(bad_syn);\n> > +     if (!good_syn)\n> > +             free(good_syn);\n>\n> ...and you can remove the 4 lines above.\n>\n> > +     return retval;\n> > +}\n>\n> Besides that, there are again some things that I've already mentioned\n> and that can be applied here, too, for example, not capitalizing\n> TERM_GOOD and TERM_BAD, the goto fail simplification, the terms memory leak.\n\nYour suggestion simplifies things, I will use that.\n\nRegards,\nPranit Bauva\n"},{"id":"307039","messageId":"CAFZEwPOZhO=sXLVwh03C8QN0uVXBUfb=xZ-JS003tgCNLgVOjg@mail.gmail.com","threadId":"44299","inReplyTo":"a4c7fec8-0e84-eb53-ca22-c369ce3facfa@gmx.net","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T19:33:22Z","receivedAt":"2016-12-06T19:33:34Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Thu, Nov 17, 2016 at 5:17 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index d84ba86..c542e8b 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n>>       return bisect_clean_state();\n>>  }\n>>\n>> +static int is_expected_rev(const char *expected_hex)\n>> +{\n>> +     struct strbuf actual_hex = STRBUF_INIT;\n>> +     int res = 0;\n>> +     if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {\n>> +             strbuf_trim(&actual_hex);\n>> +             res = !strcmp(actual_hex.buf, expected_hex);\n>> +     }\n>> +     strbuf_release(&actual_hex);\n>> +     return res;\n>> +}\n>\n> I am not sure it does what it should.\n>\n> I would expect the following behavior from this function:\n>  - file does not exist (or is \"broken\") => return 0\n>  - actual_hex != expected_hex => return 0\n>  - otherwise return 1\n>\n> If I am not wrong, the code does the following instead:\n>  - file does not exist (or is \"broken\") => return 0\n>  - actual_hex != expected_hex => return 1\n>  - otherwise => return 0\n\nYeah, you are right. I should update this. Thanks for pointing it out.\n\n>> +static int check_expected_revs(const char **revs, int rev_nr)\n>> +{\n>> +     int i;\n>> +\n>> +     for (i = 0; i < rev_nr; i++) {\n>> +             if (!is_expected_rev(revs[i])) {\n>> +                     unlink_or_warn(git_path_bisect_ancestors_ok());\n>> +                     unlink_or_warn(git_path_bisect_expected_rev());\n>> +                     return 0;\n>> +             }\n>> +     }\n>> +     return 0;\n>> +}\n>\n> Here I am not sure what the function *should* do. However, I see that it\n> basically mimics the behavior of the shell function (assuming\n> is_expected_rev() is implemented correctly).\n>\n> I don't understand why the return value is int and not void. To avoid a\n> \"return 0;\" line when calling this function?\n\nInitially I thought I would be using the return value but now I\nrealize that it is meaningless to do so. Using void seems better. :)\n\n>> @@ -167,6 +196,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               if (argc > 1)\n>>                       die(_(\"--bisect-reset requires either zero or one arguments\"));\n>>               return bisect_reset(argc ? argv[0] : NULL);\n>> +     case CHECK_EXPECTED_REVS:\n>> +             return check_expected_revs(argv, argc);\n>\n> I note that you check the correct number of arguments for some\n> subcommands and you do not check it for some other subcommands like this\n> one. (I don't care, I just want to mention it.)\n\nHere we should be able to accept any number of arguments. I think it\nwould be good to add a non-zero check though just to maintain the\nuniformity. Though this is something programmer needs to be careful\nabout rather than the user.\n\n>>       default:\n>>               die(\"BUG: unknown subcommand '%d'\", cmdmode);\n>>       }\n>\n> ~Stephan\n\nRegards,\nPranit Bauva\n"},{"id":"307040","messageId":"CAFZEwPPMb+1SzadRyhyjnz1U=wKN+2eaMr2xd3Aq6TU1wwicgQ@mail.gmail.com","threadId":"44299","inReplyTo":"723476f6-2c8c-38df-1771-9a525196d9de@gmx.net","subject":"Re: [PATCH v15 18/27] bisect--helper: `bisect_autostart` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T19:47:30Z","receivedAt":"2016-12-06T19:47:44Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Mon, Nov 21, 2016 at 1:45 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 502bf18..1767916 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -422,6 +425,7 @@ static int bisect_next(...)\n>>  {\n>>       int res, no_checkout;\n>>\n>> +     bisect_autostart(terms);\n>\n> You are not checking for return values here. (The shell code simply\n> exited if there is no tty, but you don't.)\n\nTrue. I didn't notice it carefully. Thanks for pointing it out.\n\n>> @@ -754,6 +758,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>>       return retval || bisect_auto_next(terms, NULL);\n>>  }\n>>\n>> +static int bisect_autostart(struct bisect_terms *terms)\n>> +{\n>> +     if (is_empty_or_missing_file(git_path_bisect_start())) {\n>> +             const char *yesno;\n>> +             const char *argv[] = {NULL};\n>> +             fprintf(stderr, _(\"You need to start by \\\"git bisect \"\n>> +                               \"start\\\"\\n\"));\n>> +\n>> +             if (!isatty(0))\n>\n> isatty(STDIN_FILENO)?\n\nSeems better.\n\n>> +                     return 1;\n>> +\n>> +             /*\n>> +              * TRANSLATORS: Make sure to include [Y] and [n] in your\n>> +              * translation. THe program will only accept English input\n>\n> Typo \"THe\"\n\nSure.\n\n>> +              * at this point.\n>> +              */\n>\n> Taking \"at this point\" into consideration, I think the Y and n can be\n> easily translated now that it is in C. I guess, by using...\n>\n>> +             yesno = git_prompt(_(\"Do you want me to do it for you \"\n>> +                                  \"[Y/n]? \"), PROMPT_ECHO);\n>> +             if (starts_with(yesno, \"n\") || starts_with(yesno, \"N\"))\n>\n> ... starts_with(yesno, _(\"n\")) || starts_with(yesno, _(\"N\"))\n> here (but not sure). However, this would be an extra patch on top of\n> this series.\n\nCan add it as an extra patch. Thanks for informing.\n\n>> +                     exit(0);\n>\n> Shouldn't this also be \"return 1;\"? Saying \"no\" is the same outcome as\n> not having a tty to ask for yes or no.\n\nYes.\n\n>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>  {\n>>       enum {\n>> @@ -790,6 +821,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>                        N_(\"find the next bisection commit\"), BISECT_NEXT),\n>>               OPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n>>                        N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>> +             OPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n>> +                      N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n>\n> The word \"is\" is missing.\n\nSure. Thanks for going through these patches very carefully.\n\nRegards,\nPranit Bauva\n"},{"id":"307052","messageId":"CAFZEwPNZCSGzeabHMH6wihz-51OUMMtnBMsffwJJVm9G8Fn=tw@mail.gmail.com","threadId":"44299","inReplyTo":"b54f7f46-a3c0-3334-24fa-e8d1e7d8f653@gmx.net","subject":"Re: [PATCH v15 12/27] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T21:14:10Z","receivedAt":"2016-12-06T21:28:58Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Fri, Nov 18, 2016 at 3:02 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 317d671..6a5878c 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>> +     const char bisect_term_usage[] =\n>> +\"git bisect--helper --bisect-terms [--term-good | --term-bad | ]\"\n>> +\"--term-old | --term-new\";\n>\n> Three things:\n>\n> (1) Is that indentation intentional?\n\nYes it was intentional but now I cannot recollect why. I think it was\nbecause I found something similar. Nevertheless, I will fix this\nindentation/\n\n> (2) You have a \"]\" at the end of the first part of the string instead of\n> the end of the second part.\n\nThis should be corrected.\n\n> (3) After the correction, bisect_term_usage and\n> git_bisect_helper_usage[7] are the same strings. I don't recommend to\n> use git_bisect_helper_usage[7] instead because keeping the index\n> up-to-date is a maintenance hell. (At the end of your patch series it is\n> a 3 instead of a 7.) However, if - for whatever reason - the usage of\n> bisect--helper --bisect-terms changes, you always have to sync the two\n> strings which is also nasty....\n>\n>> +\n>> +     if (get_terms(terms))\n>> +             return error(_(\"no terms defined\"));\n>> +\n>> +     if (argc > 1) {\n>> +             usage(bisect_term_usage);\n>> +             return -1;\n>> +     }\n>\n> ...and since you only use it once, why not simply do something like\n>\n> return error(_(\"--bisect-term requires exactly one argument\"));\n>\n> and drop the definition of bisect_term_usage.\n\nSure that would be better.\n\n>> +\n>> +     if (argc == 0) {\n>> +             printf(_(\"Your current terms are %s for the old state\\nand \"\n>> +                    \"%s for the new state.\\n\"), terms->term_good,\n>> +                    terms->term_bad);\n>\n> Very minor: It improves the readability if you'd split the string after\n> the \\n and put the \"and \"in the next line.\n\nAh. This is because of the message. If I do the other way, then it\nwon't match the output in one of the tests in t/t6030 thus, I am\nkeeping it that way in order to avoid modifying the file t/t6030.\n\n>> +             return 0;\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>> +             else\n>> +                     die(_(\"invalid argument %s for 'git bisect \"\n>> +                               \"terms'.\\nSupported options are: \"\n>> +                               \"--term-good|--term-old and \"\n>> +                               \"--term-bad|--term-new.\"), argv[i]);\n>\n> Hm, \"return error(...)\" and \"die(...)\" seems to be quasi-equivalent in\n> this case. Because I am always looking from a library perspective, I'd\n> prefer \"return error(...)\".\n\nI should use return error()\n\n>> @@ -429,6 +492,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               terms.term_bad = xstrdup(argv[1]);\n>>               res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);\n>>               break;\n>> +     case BISECT_TERMS:\n>> +             if (argc > 1)\n>> +                     die(_(\"--bisect-terms requires 0 or 1 argument\"));\n>> +             res = bisect_terms(&terms, argv, argc);\n>> +             break;\n>\n> Also here: \"terms\" is leaking...\n\nWill have to free it.\n\n> ~Stephan\n"},{"id":"307053","messageId":"CAFZEwPN_6HVWzdk46kKyU7vOzd1rhxzCo7JR45ucsVrhwDWEGw@mail.gmail.com","threadId":"44299","inReplyTo":"ceb2c50b-0ca7-115d-eb0e-316389569e36@gmx.net","subject":"Re: [PATCH v15 09/27] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T21:32:54Z","receivedAt":"2016-12-06T21:33:00Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Thu, Nov 17, 2016 at 3:10 PM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> I've only got some minors to mention here ;)\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index c542e8b..3f19b68 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -19,9 +19,15 @@ static const char * const git_bisect_helper_usage[] = {\n>>       N_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n>>       N_(\"git bisect--helper --bisect-clean-state\"),\n>>       N_(\"git bisect--helper --bisect-reset [<commit>]\"),\n>> +     N_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n>>       NULL\n>>  };\n>\n> I wouldn't write \"<TERM_GOOD <TERM_BAD>\" in capital letters. I'd use\n> something like \"<good_term> <bad_term>\" as you have used for\n> --write-terms. Note that \"git bisect --help\" uses \"<term-old>\n> <term-new>\" in that context.\n\nKeeping it in small does give less strain to the eye ;)\n\n>> @@ -149,6 +155,63 @@ static int check_expected_revs(const char **revs, int rev_nr)\n>>       return 0;\n>>  }\n>>\n>> +static int bisect_write(const char *state, const char *rev,\n>> +                     const struct bisect_terms *terms, int nolog)\n>> +{\n>> +     struct strbuf tag = STRBUF_INIT;\n>> +     struct strbuf commit_name = STRBUF_INIT;\n>> +     struct object_id oid;\n>> +     struct commit *commit;\n>> +     struct pretty_print_context pp = {0};\n>> +     FILE *fp = NULL;\n>> +     int retval = 0;\n>> +\n>> +     if (!strcmp(state, terms->term_bad))\n>> +             strbuf_addf(&tag, \"refs/bisect/%s\", state);\n>> +     else if (one_of(state, terms->term_good, \"skip\", NULL))\n>> +             strbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n>> +     else {\n>> +             error(_(\"Bad bisect_write argument: %s\"), state);\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>> +\n>> +     if (get_oid(rev, &oid)) {\n>> +             error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>> +\n>> +     if (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n>> +                    UPDATE_REFS_MSG_ON_ERR)) {\n>> +             retval = -1;\n>> +             goto finish;\n>> +     }\n>\n> I'd like to mention that the \"goto fail;\" trick could apply in this\n> function, too.\n\nSure!\n\n>> @@ -156,9 +219,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               WRITE_TERMS,\n>>               BISECT_CLEAN_STATE,\n>>               BISECT_RESET,\n>> -             CHECK_EXPECTED_REVS\n>> +             CHECK_EXPECTED_REVS,\n>> +             BISECT_WRITE\n>>       } cmdmode = 0;\n>> -     int no_checkout = 0;\n>> +     int no_checkout = 0, res = 0;\n>\n> Why do you do this \"direct return\" -> \"set res and return res\" transition?\n> You don't need it in this patch, you do not need it in the subsequent\n> patches (you always set \"res\" exactly once after the initialization),\n> and you don't need cleanup code in this function.\n\nInitially I was using strbuf but then I switched to const char *\naccording to Junio's suggestion. It seems that in this version I have\nforgot to free the terms.\n\n>>       struct option options[] = {\n>>               OPT_CMDMODE(0, \"next-all\", &cmdmode,\n>>                        N_(\"perform 'git bisect next'\"), NEXT_ALL),\n>> @@ -170,10 +234,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>                        N_(\"reset the bisection state\"), BISECT_RESET),\n>>               OPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n>>                        N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n>> +             OPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n>> +                      N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n>\n> That info text is confusing, especially considering that there is a\n> \"nolog\" option. I think the action of bisect-write is two-fold: (1)\n> update the refs, (2) log.\n\nI agree that it is confusing. I couldn't find a better way to describe\nit and since this would be gone after the whole conversion, I didn't\nbother putting more efforts there.\n\nRegards,\nPranit Bauva\n"},{"id":"307078","messageId":"CAFZEwPPTnfOYsL8OB5x5n9cm2s+chMwg=xo459kVnFV9bB+5Hw@mail.gmail.com","threadId":"44299","inReplyTo":"0cc22155-2b3f-b69c-9ed4-2b1c55e40eee@gmx.net","subject":"Re: [PATCH v15 19/27] bisect--helper: `bisect_state` & `bisect_head` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T22:40:42Z","receivedAt":"2016-12-06T22:40:48Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Tue, Nov 22, 2016 at 5:42 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> Reimplement the `bisect_state` shell function in C and also add a\n>> subcommand `--bisect-state` to `git-bisect--helper` to call it from\n>> git-bisect.sh .\n>>\n>> Using `--bisect-state` subcommand 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 and will be called by some\n>> other methods.\n>>\n>> `bisect_head` is called from `bisect_state` thus its not required to\n>> introduce another subcommand.\n>\n> Missing comma before \"thus\", and \"it is\" (or \"it's\") instead of \"its\" :)\n\nSure, will fix.\n\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 1767916..1481c6d 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -784,6 +786,79 @@ static int bisect_autostart(struct bisect_terms *terms)\n>>       return 0;\n>>  }\n>>\n>> +static char *bisect_head(void)\n>> +{\n>> +     if (is_empty_or_missing_file(git_path_bisect_head()))\n>> +             return \"HEAD\";\n>> +     else\n>> +             return \"BISECT_HEAD\";\n>> +}\n>\n> This is very shellish.\n> In C I'd expect something like\n>\n> static int bisect_head_sha1(unsigned char *sha)\n> {\n>         int res;\n>         if (is_empty_or_missing_file(git_path_bisect_head()))\n>                 res = get_sha1(\"HEAD\", sha);\n>         else\n>                 res = get_sha1(\"BISECT_HEAD\", sha);\n>\n>         if (res)\n>                 return error(_(\"Could not find BISECT_HEAD or HEAD.\"));\n>\n>         return 0;\n> }\n>\n>> +\n>> +static int bisect_state(struct bisect_terms *terms, const char **argv,\n>> +                     int argc)\n>> +{\n>> +     const char *state = argv[0];\n>> +\n>> +     get_terms(terms);\n>> +     if (check_and_set_terms(terms, state))\n>> +             return -1;\n>> +\n>> +     if (!argc)\n>> +             die(_(\"Please call `--bisect-state` with at least one argument\"));\n>\n> I think this check should move to cmd_bisect__helper. There are also the\n> other argument number checks.\n\nNot really. After the whole conversion, the cmdmode will cease to\nexists while bisect_state will be called directly, thus it is\nimportant to check it here.\n\n>> +\n>> +     if (argc == 1 && one_of(state, terms->term_good,\n>> +         terms->term_bad, \"skip\", NULL)) {\n>> +             const char *bisected_head = xstrdup(bisect_head());\n>> +             const char *hex[1];\n>\n> Maybe:\n>                 const char *hex;\n>\n>> +             unsigned char sha1[20];\n>> +\n>> +             if (get_sha1(bisected_head, sha1))\n>> +                     die(_(\"Bad rev input: %s\"), bisected_head);\n>\n> And instead of...\n>\n>> +             if (bisect_write(state, sha1_to_hex(sha1), terms, 0))\n>> +                     return -1;\n>> +\n>> +             *hex = xstrdup(sha1_to_hex(sha1));\n>> +             if (check_expected_revs(hex, 1))\n>> +                     return -1;\n>\n> ... simply:\n>\n>                 hex = xstrdup(sha1_to_hex(sha1));\n>                 if (set_state(terms, state, hex)) {\n>                         free(hex);\n>                         return -1;\n>                 }\n>                 free(hex);\n>\n> where:\n\nYes I am planning to convert all places with hex rather than the sha1\nbut not yet, maybe in an another patch series because currently a lot\nof things revolve around sha1 and changing its behaviour wouldn't\nreally be a part of a porting patch series.\n\n> static int set_state(struct bisect_terms *terms, const char *state,\n>                                                  const char *hex)\n> {\n>         if (bisect_write(state, hex, terms, 0))\n>                 return -1;\n>         if (check_expected_revs(&hex, 1))\n>                 return -1;\n>         return 0;\n> }\n>\n>> +             return bisect_auto_next(terms, NULL);\n>> +     }\n>> +\n>> +     if ((argc == 2 && !strcmp(state, terms->term_bad)) ||\n>> +                     one_of(state, terms->term_good, \"skip\", NULL)) {\n>> +             int i;\n>> +             struct string_list hex = STRING_LIST_INIT_DUP;\n>> +\n>> +             for (i = 1; i < argc; i++) {\n>> +                     unsigned char sha1[20];\n>> +\n>> +                     if (get_sha1(argv[i], sha1)) {\n>> +                             string_list_clear(&hex, 0);\n>> +                             die(_(\"Bad rev input: %s\"), argv[i]);\n>> +                     }\n>> +                     string_list_append(&hex, sha1_to_hex(sha1));\n>> +             }\n>> +             for (i = 0; i < hex.nr; i++) {\n>\n> ... And replace this:\n>\n>> +                     const char **hex_string = (const char **) &hex.items[i].string;\n>> +                     if(bisect_write(state, *hex_string, terms, 0)) {\n>> +                             string_list_clear(&hex, 0);\n>> +                             return -1;\n>> +                     }\n>> +                     if (check_expected_revs(hex_string, 1)) {\n>> +                             string_list_clear(&hex, 0);\n>> +                             return -1;\n>> +                     }\n>\n> by:\n>\n>                         const char *hex_str = hex.items[i].string;\n>                         if (set_state(terms, state, hex_string)) {\n>                                 string_list_clear(&hex, 0);\n>                                 return -1;\n>                         }\n>\n>> +             }\n>> +             string_list_clear(&hex, 0);\n>> +             return bisect_auto_next(terms, NULL);\n>> +     }\n>> +\n>> +     if (!strcmp(state, terms->term_bad))\n>> +             die(_(\"'git bisect %s' can take only one argument.\"),\n>> +                   terms->term_bad);\n>> +\n>> +     return -1;\n>> +}\n>> +\n>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>  {\n>>       enum {\n>> @@ -823,6 +899,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>                        N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>>               OPT_CMDMODE(0, \"bisect-autostart\", &cmdmode,\n>>                        N_(\"start the bisection if BISECT_START empty or missing\"), BISECT_AUTOSTART),\n>> +             OPT_CMDMODE(0, \"bisect-state\", &cmdmode,\n>> +                      N_(\"mark the state of ref (or refs)\"), BISECT_STATE),\n>\n> \"mark the state of the given revs\"\n>\n> Note that rev != ref\n\nMight have been a typo. Will fix.\n\n>> @@ -902,6 +980,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               terms.term_bad = \"bad\";\n>>               res = bisect_autostart(&terms);\n>>               break;\n>> +     case BISECT_STATE:\n>> +             if (argc == 0)\n>> +                     die(_(\"--bisect-state requires at least 1 argument\"));\n>\n> \"at least one revision\"\n\nOkay, that would make it more specific.\n\n>> diff --git a/git-bisect.sh b/git-bisect.sh\n>> index cd56551..a9eebbb 100755\n>> --- a/git-bisect.sh\n>> +++ b/git-bisect.sh\n>> @@ -61,44 +51,7 @@ bisect_skip() {\n>>               esac\n>>               all=\"$all $revs\"\n>>       done\n>> -     eval bisect_state 'skip' $all\n> [...deleted lines...]\n>> +     eval git bisect--helper --bisect-state 'skip' $all\n>\n> I think you don't need \"eval\" here any longer.\n\nYes, I wouldn't\n\n>> @@ -184,8 +137,8 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n>>                       state=\"$TERM_GOOD\"\n>>               fi\n>>\n>> -             # We have to use a subshell because \"bisect_state\" can exit.\n>> -             ( bisect_state $state >\"$GIT_DIR/BISECT_RUN\" )\n>> +             # We have to use a subshell because \"--bisect-state\" can exit.\n>> +             ( git bisect--helper --bisect-state $state >\"$GIT_DIR/BISECT_RUN\" )\n\nTrue, but right now I didn't want to modify that part of the source\ncode to remove the comment. I will remove the comment all together\nwhen I port bisect_run()\n\nRegards,\nPranit Bauva\n"},{"id":"307079","messageId":"CAFZEwPMW5jD=bJy25qb36PfCazy=2=C10aDh-CL+ijhbkePZkA@mail.gmail.com","threadId":"44299","inReplyTo":"c49a6151-0827-cae5-0569-8f05515be0f9@gmx.net","subject":"Re: [PATCH v15 22/27] bisect--helper: `bisect_log` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T22:42:09Z","receivedAt":"2016-12-06T22:43:13Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Fri, Nov 18, 2016 at 3:17 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 493034c..c18ca07 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -858,6 +858,23 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,\n>>       return -1;\n>>  }\n>>\n>> +static int bisect_log(void)\n>> +{\n>> +     int fd, status;\n>> +     fd = open(git_path_bisect_log(), O_RDONLY);\n>> +     if (fd < 0)\n>> +             return -1;\n>> +\n>> +     status = copy_fd(fd, 1);\n>\n> Perhaps\n>\n>         status = copy_fd(fd, STDOUT_FILENO);\n\nSure!\n\n>> +     if (status) {\n>> +             close(fd);\n>> +             return -1;\n>> +     }\n>> +\n>> +     close(fd);\n>> +     return status;\n>> +}\n>\n> That's weird.\n> Either get rid of the if() and actually use status:\n>\n>         status = copy_fd(fd, STDOUT_FILENO);\n>\n>         close(fd);\n>         return status ? -1 : 0;\n\nThis one seems better!\n"},{"id":"307080","messageId":"CAFZEwPNctpM3KAsYK587aJvokE2FzyTvMoCJ_ztO3ijpUiMcwg@mail.gmail.com","threadId":"44299","inReplyTo":"b7691fac-9642-f87d-f23f-5175b5ead05b@gmx.net","subject":"Re: [PATCH v15 10/27] bisect--helper: `check_and_set_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T22:43:30Z","receivedAt":"2016-12-06T22:43:35Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Fri, Nov 18, 2016 at 1:55 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 3f19b68..c6c11e3 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>>       N_(\"git bisect--helper --bisect-clean-state\"),\n>>       N_(\"git bisect--helper --bisect-reset [<commit>]\"),\n>>       N_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n>> +     N_(\"git bisect--helper --bisect-check-and-set-terms <command> <TERM_GOOD> <TERM_BAD>\"),\n>\n> Here's the same as in the previous patch... I'd not use\n> TERM_GOOD/TERM_BAD in capitals.\n\nSure.\n\n>>       NULL\n>>  };\n>>\n>> @@ -212,6 +213,38 @@ static int bisect_write(const char *state, const char *rev,\n>>       return retval;\n>>  }\n>>\n>> +static int set_terms(struct bisect_terms *terms, const char *bad,\n>> +                  const char *good)\n>> +{\n>> +     terms->term_good = xstrdup(good);\n>> +     terms->term_bad = xstrdup(bad);\n>> +     return write_terms(terms->term_bad, terms->term_good);\n>\n> At this stage of the patch series I am wondering why you are setting\n> \"terms\" here, but I guess you'll need it later.\n>\n> However, you are leaking memory here. Something like\n>\n>         free(terms->term_good);\n>         free(terms->term_bad);\n>         terms->term_good = xstrdup(good);\n>         terms->term_bad = xstrdup(bad);\n>\n> should be safe (because you've always used xstrdup() for the terms\n> members before). Or am I overseeing something?\n\nYeah it is safe.\n\n>> @@ -278,6 +314,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>               terms.term_bad = xstrdup(argv[3]);\n>>               res = bisect_write(argv[0], argv[1], &terms, nolog);\n>>               break;\n>> +     case CHECK_AND_SET_TERMS:\n>> +             if (argc != 3)\n>> +                     die(_(\"--check-and-set-terms requires 3 arguments\"));\n>> +             terms.term_good = xstrdup(argv[1]);\n>> +             terms.term_bad = xstrdup(argv[2]);\n>> +             res = check_and_set_terms(&terms, argv[0]);\n>> +             break;\n>\n> Ha! When I reviewed the last patch, I asked you why you changed the code\n> from returning directly from each subcommand to setting res; break; and\n> then return res at the bottom of the function.\n>\n> Now I see why this was useful. The two members of \"terms\" are again\n> leaking memory: you are allocating memory by using xstrdup() but you are\n> not freeing it.\n\nI will take care about freeing the memory.\n\nRegards,\nPranit Bauva\n"},{"id":"307081","messageId":"CAFZEwPNmB7rYvUTPy6dvfqfbUsjDeEcteLBBH5Wk-G_suE+YTw@mail.gmail.com","threadId":"44299","inReplyTo":"1816d5b4-a4c1-7c97-09ff-b11001501423@gmx.net","subject":"Re: [PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-06T23:02:13Z","receivedAt":"2016-12-06T23:02:21Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Tue, Nov 22, 2016 at 6:19 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Okay Pranit,\n>\n> this is the last patch for me to review in this series.\n>\n> Now that I have a coarse overview of what you did, I have the general\n> remark that imho the \"terms\" variable should simply be global instead of\n> being passed around all the time.\n\nIn a personal conversation with my mentors, we thought it is the best\nfit to keep it in a struct and pass it around so that it is easier in\nlibification.\n\n> I also had some other remarks but I forgot them... maybe they come to my\n> mind again when I see patch series v16.\n>\n> I also want to remark again that I am not a Git developer and only\n> reviewed this because of my interest in git-bisect. So some of my\n> suggestions might conflict with other beliefs here. For example, I\n> consider it very bad style to leak memory... but Git is rather written\n> as a scripting tool than a genuine library, so perhaps many people here\n> do not care about it as long as it works...\n\nThanks for taking out your time to review my series extremely\ncarefully. I will try to post a v16 next week probably.\n\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index c18ca07..b367d8d 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -601,7 +602,6 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>>                       terms->term_good = arg;\n>>               } else if (!strcmp(arg, \"--term-bad\") ||\n>>                        !strcmp(arg, \"--term-new\")) {\n>> -                     const char *next_arg;\n>\n> This should already have been removed in patch 15/27, not here.\n>\n>> @@ -875,6 +875,117 @@ static int bisect_log(void)\n>>       return status;\n>>  }\n>>\n>> +static int get_next_word(const char *line, int pos, struct strbuf *word)\n>> +{\n>> +     int i, len = strlen(line), begin = 0;\n>> +     strbuf_reset(word);\n>> +     for (i = pos; i < len; i++) {\n>> +             if (line[i] == ' ' && begin)\n>> +                     return i + 1;\n>> +\n>> +             if (!begin)\n>> +                     begin = 1;\n>> +             strbuf_addch(word, line[i]);\n>> +     }\n>> +\n>> +     return i;\n>> +}\n>> +\n>> +static int bisect_replay(struct bisect_terms *terms, const char *filename)\n>> +{\n>> +     struct strbuf line = STRBUF_INIT;\n>> +     struct strbuf word = STRBUF_INIT;\n>> +     FILE *fp = NULL;\n>\n> (The initialization is not necessary here.)\n\nUm. I think it is. Otherwise if it goes to the finish block before you\ntry to operate on fp, it will cause a seg fault.\n\n>> +     int res = 0;\n>> +\n>> +     if (is_empty_or_missing_file(filename)) {\n>> +             error(_(\"no such file with name '%s' exists\"), filename);\n>\n> The error message is misleading if the file exists but is empty.\n> Maybe something like \"cannot read file '%s' for replaying\"?\n\nOkay will change.\n\n>> +             res = -1;\n>> +             goto finish;\n>\n>                 goto fail;\n> :D\n>\n>> +     }\n>> +\n>> +     if (bisect_reset(NULL)) {\n>> +             res = -1;\n>> +             goto finish;\n>\n>                 goto fail;\n>\n>> +     }\n>> +\n>> +     fp = fopen(filename, \"r\");\n>> +     if (!fp) {\n>> +             res = -1;\n>> +             goto finish;\n>\n>                 goto fail;\n>\n>> +     }\n>> +\n>> +     while (strbuf_getline(&line, fp) != EOF) {\n>> +             int pos = 0;\n>> +             while (pos < line.len) {\n>> +                     pos = get_next_word(line.buf, pos, &word);\n>> +\n>> +                     if (!strcmp(word.buf, \"git\")) {\n>> +                             continue;\n>> +                     } else if (!strcmp(word.buf, \"git-bisect\")) {\n>> +                             continue;\n>> +                     } else if (!strcmp(word.buf, \"bisect\")) {\n>> +                             continue;\n>> +                     } else if (!strcmp(word.buf, \"#\")) {\n>> +                             break;\n>\n> Maybe it is more robust to check whether word.buf begins with #\n\nAssuming that you meant \"# \", yes.\n\n>> +                     }\n>> +\n>> +                     get_terms(terms);\n>> +                     if (check_and_set_terms(terms, word.buf)) {\n>> +                             res = -1;\n>> +                             goto finish;\n>\n>                                 goto fail;\n>\n>> +                     }\n>> +\n>> +                     if (!strcmp(word.buf, \"start\")) {\n>> +                             struct argv_array argv = ARGV_ARRAY_INIT;\n>> +                             sq_dequote_to_argv_array(line.buf+pos, &argv);\n>> +                             if (bisect_start(terms, 0, argv.argv, argv.argc)) {\n>> +                                     argv_array_clear(&argv);\n>> +                                     res = -1;\n>> +                                     goto finish;\n>\n>                                         goto fail;\n>\n>> +                             }\n>> +                             argv_array_clear(&argv);\n>> +                             break;\n>> +                     }\n>> +\n>> +                     if (one_of(word.buf, terms->term_good,\n>> +                         terms->term_bad, \"skip\", NULL)) {\n>> +                             if (bisect_write(word.buf, line.buf+pos, terms, 0)) {\n>> +                                     res = -1;\n>> +                                     goto finish;\n>\n>                                         goto fail;\n>\n>> +                             }\n>> +                             break;\n>> +                     }\n>> +\n>> +                     if (!strcmp(word.buf, \"terms\")) {\n>> +                             struct argv_array argv = ARGV_ARRAY_INIT;\n>> +                             sq_dequote_to_argv_array(line.buf+pos, &argv);\n>> +                             if (bisect_terms(terms, argv.argv, argv.argc)) {\n>> +                                     argv_array_clear(&argv);\n>> +                                     res = -1;\n>> +                                     goto finish;\n>\n>                                         goto fail;\n>\n>> +                             }\n>> +                             argv_array_clear(&argv);\n>> +                             break;\n>> +                     }\n>> +\n>> +                     error(_(\"?? what are you talking about?\"));\n>\n> I know this string is taken from the original source. However, even\n> something like error(_(\"Replay file contains rubbish (\\\"%s\\\")\"),\n> word.buf) is more informative.\n\nOkay will change.\n\n>> +                     res = -1;\n>> +                     goto finish;\n>\n>                         goto fail;\n>\n>> +             }\n>> +     }\n>> +     goto finish;\n>\n> +fail:\n> +       res = -1;\n>\n> I just wanted to make finally clear what I was referring to by the\n> \"goto fail\" trick. :D\n\nI got it. Will update accordingly.\n\n> Also I think the readability could be improved by extracting the body of\n> the outer while loop into an extra function replay_line(). Then most of\n> my suggested \"goto fail;\" lines simply become \"return -1;\" :)\n>\n>> @@ -998,6 +1112,13 @@ int cmd_bisect__helper(...)\n>>                       die(_(\"--bisect-log requires 0 arguments\"));\n>>               res = bisect_log();\n>>               break;\n>> +     case BISECT_REPLAY:\n>> +             if (argc != 1)\n>> +                     die(_(\"--bisect-replay requires 1 argument\"));\n>\n> I'd keep the (already translated) string from the original source:\n> \"No logfile given\"\n\nSure\n\nRegards.\nPranit Bauva\n"},{"id":"307082","messageId":"a492fb63-3642-1f97-4668-a927352169f9@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPNZCSGzeabHMH6wihz-51OUMMtnBMsffwJJVm9G8Fn=tw@mail.gmail.com","subject":"Re: [PATCH v15 12/27] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-06T23:05:46Z","receivedAt":"2016-12-06T23:05:54Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hey Pranit,\n\nOn 12/06/2016 10:14 PM, Pranit Bauva wrote:\n>>> +\n>>> +     if (argc == 0) {\n>>> +             printf(_(\"Your current terms are %s for the old state\\nand \"\n>>> +                    \"%s for the new state.\\n\"), terms->term_good,\n>>> +                    terms->term_bad);\n>>\n>> Very minor: It improves the readability if you'd split the string after\n>> the \\n and put the \"and \"in the next line.\n> \n> Ah. This is because of the message. If I do the other way, then it\n> won't match the output in one of the tests in t/t6030 thus, I am\n> keeping it that way in order to avoid modifying the file t/t6030.\n\nI think I was unclear here. I was referring to the coding/layouting\nstyle, not to the string. I mean like writing:\n\n\tprintf(_(\"Your current terms are %s for the old state\\n\"\n\t         \"and \"%s for the new state.\\n\"),\n\t       terms->term_good, terms->term_bad);\n\nThe string fed to _() is the same, but it is split in a different (imho\nmore readable) way: after the \"\\n\", not after the \"and \".\n\n\n>>> +                     die(_(\"invalid argument %s for 'git bisect \"\n>>> +                               \"terms'.\\nSupported options are: \"\n>>> +                               \"--term-good|--term-old and \"\n>>> +                               \"--term-bad|--term-new.\"), argv[i]);\n>>\n>> Hm, \"return error(...)\" and \"die(...)\" seems to be quasi-equivalent in\n>> this case. Because I am always looking from a library perspective, I'd\n>> prefer \"return error(...)\".\n> \n> I should use return error()\n\nWhen you reroll your patches, please also check if you always put _()\naround your error()s ;) (Hmmm... On the other hand, it might be arguable\nif translations are useful for errors that only occur when people hack\ngit-bisect or use the bisect--helper directly... This makes me feel like\nall those errors should be prefixed by some \"BUG: \" marker since the\nordinary user only sees them when there is a bug. But I don't feel in\nthe position to decide or recommend such a thing, so it's just a thought.)\n\n~Stephan\n"},{"id":"307083","messageId":"9da43af2-bd34-5cb6-66d5-01db6f27cdde@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPNmB7rYvUTPy6dvfqfbUsjDeEcteLBBH5Wk-G_suE+YTw@mail.gmail.com","subject":"Re: [PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-06T23:20:35Z","receivedAt":"2016-12-06T23:20:44Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hey Pranit,\n\nOn 12/07/2016 12:02 AM, Pranit Bauva wrote:\n>>> +static int bisect_replay(struct bisect_terms *terms, const char *filename)\n>>> +{\n>>> +     struct strbuf line = STRBUF_INIT;\n>>> +     struct strbuf word = STRBUF_INIT;\n>>> +     FILE *fp = NULL;\n>>\n>> (The initialization is not necessary here.)\n> \n> Um. I think it is. Otherwise if it goes to the finish block before you\n> try to operate on fp, it will cause a seg fault.\n\nYou are right, thanks!\n\n>>> +     while (strbuf_getline(&line, fp) != EOF) {\n>>> +             int pos = 0;\n>>> +             while (pos < line.len) {\n>>> +                     pos = get_next_word(line.buf, pos, &word);\n>>> +\n>>> +                     if (!strcmp(word.buf, \"git\")) {\n>>> +                             continue;\n>>> +                     } else if (!strcmp(word.buf, \"git-bisect\")) {\n>>> +                             continue;\n>>> +                     } else if (!strcmp(word.buf, \"bisect\")) {\n>>> +                             continue;\n>>> +                     } else if (!strcmp(word.buf, \"#\")) {\n>>> +                             break;\n>>\n>> Maybe it is more robust to check whether word.buf begins with #\n> \n> Assuming that you meant \"# \", yes.\n\nNo, if I get it right \"# \" can never occur because the word.buf never\ncontains a space.\nWhat I meant was that you are currently ignoring everything after a\n\"# \", so comments like\n\n# foo\n\nare ignored.\nHowever, imagine a user changes the file by hand (he probably should not\ndo it but, hey, it's git: unixy, hacky ... and he thinks he knows what\nhe does) and then we have in the file something like\n\n#foo\n\nwhich makes perfectly sense when you are used to programming languages\nwith # as comment-till-eol marker. The problem is that your current code\ndoes expect \"#\" as a single word and would hence not recognize #foo as a\ncomment.\n\nI hope I made it clear why I suggested to test if the word *begins* with\n\"#\" (not \"# \").\n\n~Stephan\n"},{"id":"307084","messageId":"58ab6600-5ac2-9e7d-7cf0-452db40d5f6b@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPNmB7rYvUTPy6dvfqfbUsjDeEcteLBBH5Wk-G_suE+YTw@mail.gmail.com","subject":"Re: [PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-06T23:40:25Z","receivedAt":"2016-12-06T23:40:37Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit and Christian and Lars ;)\n\nOn 12/07/2016 12:02 AM, Pranit Bauva wrote:\n> On Tue, Nov 22, 2016 at 6:19 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>> Okay Pranit,\n>>\n>> this is the last patch for me to review in this series.\n>>\n>> Now that I have a coarse overview of what you did, I have the general\n>> remark that imho the \"terms\" variable should simply be global instead of\n>> being passed around all the time.\n> \n> In a personal conversation with my mentors, we thought it is the best\n> fit to keep it in a struct and pass it around so that it is easier in\n> libification.\n\nI guess you had that conversation at the beginning of the project and I\nthink that at that stage I would have recommended it that way, too.\n\nHowever, looking at the v15 bisect--helper.c, it looks like it is rather\na pain to do it that way. I mean, you use the terms like they were\nglobal variables: you initialize them in cmd_bisect__helper() and then\nyou always pass them around; you update them \"globally\", never using\nrestricted scope, never ever use a second instantiation besides the one\nof cmd_bisect__helper(). These are all signs that *in the current code*\nusing (static) global variables is the better way (making the code simpler).\n\nThe libification argument may be worth considering, though. I am not\nsure if there is really a use-case where you need two different\ninstantiations of the terms, *except* if the lib allows bisecting with\ndifferent terms at the same time (in different repos, of course). Is the\nlib \"aware\" of such use-cases like doing stuff in different repos at the\nsame time? If that's the case, not using global variables is the right\nthing to do. In any other case I can imagine, I'd suggest to use global\nvariables.\n\n~Stephan\n"},{"id":"307088","messageId":"14b9ba3a-4568-2e4b-0b1a-f0ee75a7c677@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPPTnfOYsL8OB5x5n9cm2s+chMwg=xo459kVnFV9bB+5Hw@mail.gmail.com","subject":"Re: [PATCH v15 19/27] bisect--helper: `bisect_state` & `bisect_head` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-06T23:54:19Z","receivedAt":"2016-12-06T23:54:28Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 12/06/2016 11:40 PM, Pranit Bauva wrote:\n> On Tue, Nov 22, 2016 at 5:42 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>>> +static int bisect_state(struct bisect_terms *terms, const char **argv,\n>>> +                     int argc)\n>>> +{\n>>> +     const char *state = argv[0];\n>>> +\n>>> +     get_terms(terms);\n>>> +     if (check_and_set_terms(terms, state))\n>>> +             return -1;\n>>> +\n>>> +     if (!argc)\n>>> +             die(_(\"Please call `--bisect-state` with at least one argument\"));\n>>\n>> I think this check should move to cmd_bisect__helper. There are also the\n>> other argument number checks.\n> \n> Not really. After the whole conversion, the cmdmode will cease to\n> exists while bisect_state will be called directly, thus it is\n> important to check it here.\n\nOkay, that's a point.\nIn that case, you should probably use \"return error()\" again and the\nmessage (mentioning \"--bisect-state\") does not make sense when\n--bisect-state ceases to exist.\n\n>>> +\n>>> +     if (argc == 1 && one_of(state, terms->term_good,\n>>> +         terms->term_bad, \"skip\", NULL)) {\n>>> +             const char *bisected_head = xstrdup(bisect_head());\n>>> +             const char *hex[1];\n>>\n>> Maybe:\n>>                 const char *hex;\n>>\n>>> +             unsigned char sha1[20];\n>>> +\n>>> +             if (get_sha1(bisected_head, sha1))\n>>> +                     die(_(\"Bad rev input: %s\"), bisected_head);\n>>\n>> And instead of...\n>>\n>>> +             if (bisect_write(state, sha1_to_hex(sha1), terms, 0))\n>>> +                     return -1;\n>>> +\n>>> +             *hex = xstrdup(sha1_to_hex(sha1));\n>>> +             if (check_expected_revs(hex, 1))\n>>> +                     return -1;\n>>\n>> ... simply:\n>>\n>>                 hex = xstrdup(sha1_to_hex(sha1));\n>>                 if (set_state(terms, state, hex)) {\n>>                         free(hex);\n>>                         return -1;\n>>                 }\n>>                 free(hex);\n>>\n>> where:\n> \n> Yes I am planning to convert all places with hex rather than the sha1\n> but not yet, maybe in an another patch series because currently a lot\n> of things revolve around sha1 and changing its behaviour wouldn't\n> really be a part of a porting patch series.\n\nI was not suggesting a change of behavior, I was suggesting a simple\nhelper function set_state() to get rid of code duplication above and\nsome lines below:\n\n>> ... And replace this:\n>>\n>>> +                     const char **hex_string = (const char **) &hex.items[i].string;\n>>> +                     if(bisect_write(state, *hex_string, terms, 0)) {\n>>> +                             string_list_clear(&hex, 0);\n>>> +                             return -1;\n>>> +                     }\n>>> +                     if (check_expected_revs(hex_string, 1)) {\n>>> +                             string_list_clear(&hex, 0);\n>>> +                             return -1;\n>>> +                     }\n>>\n>> by:\n>>\n>>                         const char *hex_str = hex.items[i].string;\n>>                         if (set_state(terms, state, hex_string)) {\n>>                                 string_list_clear(&hex, 0);\n>>                                 return -1;\n>>                         }\n\nSee?\n\n>>> @@ -184,8 +137,8 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n>>>                       state=\"$TERM_GOOD\"\n>>>               fi\n>>>\n>>> -             # We have to use a subshell because \"bisect_state\" can exit.\n>>> -             ( bisect_state $state >\"$GIT_DIR/BISECT_RUN\" )\n>>> +             # We have to use a subshell because \"--bisect-state\" can exit.\n>>> +             ( git bisect--helper --bisect-state $state >\"$GIT_DIR/BISECT_RUN\" )\n>>\n>> The new comment is funny, but you don't need a subshell here any\n>> longer.\n> \n> True, but right now I didn't want to modify that part of the source\n> code to remove the comment. I will remove the comment all together\n> when I port bisect_run()\nFor most of the patches, I was commenting on the current state, not on\nthe big picture.\n\nStill I think that it is better to remove the comment and the subshell\ninstead of making the comment weird (\"yes the builtin can exit, but why\ndo we need a subshell?\" vs \"yes the shell function calls exit, so we\nneed a subshell because we do not want to exit this shell script\")\n\n~Stephan\n"},{"id":"307109","messageId":"CAFZEwPOyw+OQ=umqmjqvSVtXvDKiC5ic-BTbHhT160rh5VWz1w@mail.gmail.com","threadId":"44299","inReplyTo":"a492fb63-3642-1f97-4668-a927352169f9@gmx.net","subject":"Re: [PATCH v15 12/27] bisect--helper: `get_terms` & `bisect_terms` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-07T12:06:24Z","receivedAt":"2016-12-07T12:06:29Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Wed, Dec 7, 2016 at 4:35 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hey Pranit,\n>\n> On 12/06/2016 10:14 PM, Pranit Bauva wrote:\n>>>> +\n>>>> +     if (argc == 0) {\n>>>> +             printf(_(\"Your current terms are %s for the old state\\nand \"\n>>>> +                    \"%s for the new state.\\n\"), terms->term_good,\n>>>> +                    terms->term_bad);\n>>>\n>>> Very minor: It improves the readability if you'd split the string after\n>>> the \\n and put the \"and \"in the next line.\n>>\n>> Ah. This is because of the message. If I do the other way, then it\n>> won't match the output in one of the tests in t/t6030 thus, I am\n>> keeping it that way in order to avoid modifying the file t/t6030.\n>\n> I think I was unclear here. I was referring to the coding/layouting\n> style, not to the string. I mean like writing:\n>\n>         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> The string fed to _() is the same, but it is split in a different (imho\n> more readable) way: after the \"\\n\", not after the \"and \".\n\nThanks for clearing it out. This seems a sensible change.\n\n>>>> +                     die(_(\"invalid argument %s for 'git bisect \"\n>>>> +                               \"terms'.\\nSupported options are: \"\n>>>> +                               \"--term-good|--term-old and \"\n>>>> +                               \"--term-bad|--term-new.\"), argv[i]);\n>>>\n>>> Hm, \"return error(...)\" and \"die(...)\" seems to be quasi-equivalent in\n>>> this case. Because I am always looking from a library perspective, I'd\n>>> prefer \"return error(...)\".\n>>\n>> I should use return error()\n>\n> When you reroll your patches, please also check if you always put _()\n> around your error()s ;) (Hmmm... On the other hand, it might be arguable\n> if translations are useful for errors that only occur when people hack\n> git-bisect or use the bisect--helper directly... This makes me feel like\n> all those errors should be prefixed by some \"BUG: \" marker since the\n> ordinary user only sees them when there is a bug. But I don't feel in\n> the position to decide or recommend such a thing, so it's just a thought.)\n\nIt is seems a good change, I will do it. Let other's comment on what\nthey think in the next re-roll.\n\nRegards,\nPranit Bauva\n"},{"id":"307112","messageId":"CAP8UFD2tw_DdYbYgv1uA8+2NiQc8JSvfxgd6Tw_JpKENOE06Gw@mail.gmail.com","threadId":"44299","inReplyTo":"58ab6600-5ac2-9e7d-7cf0-452db40d5f6b@gmx.net","subject":"Re: [PATCH v15 23/27] bisect--helper: `bisect_replay` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-12-07T13:15:28Z","receivedAt":"2016-12-07T13:22:44Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Hi Stephan,\n\nOn Wed, Dec 7, 2016 at 12:40 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit and Christian and Lars ;)\n>\n> On 12/07/2016 12:02 AM, Pranit Bauva wrote:\n>> On Tue, Nov 22, 2016 at 6:19 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>>>\n>>> Now that I have a coarse overview of what you did, I have the general\n>>> remark that imho the \"terms\" variable should simply be global instead of\n>>> being passed around all the time.\n>>\n>> In a personal conversation with my mentors, we thought it is the best\n>> fit to keep it in a struct and pass it around so that it is easier in\n>> libification.\n>\n> I guess you had that conversation at the beginning of the project and I\n> think that at that stage I would have recommended it that way, too.\n>\n> However, looking at the v15 bisect--helper.c, it looks like it is rather\n> a pain to do it that way. I mean, you use the terms like they were\n> global variables: you initialize them in cmd_bisect__helper() and then\n> you always pass them around; you update them \"globally\", never using\n> restricted scope, never ever use a second instantiation besides the one\n> of cmd_bisect__helper(). These are all signs that *in the current code*\n> using (static) global variables is the better way (making the code simpler).\n>\n> The libification argument may be worth considering, though. I am not\n> sure if there is really a use-case where you need two different\n> instantiations of the terms, *except* if the lib allows bisecting with\n> different terms at the same time (in different repos, of course). Is the\n> lib \"aware\" of such use-cases like doing stuff in different repos at the\n> same time? If that's the case, not using global variables is the right\n> thing to do. In any other case I can imagine, I'd suggest to use global\n> variables.\n\nYeah, I wanted to avoid global variables when there is no very good\nreason for them to avoid possible libification work later.\nAnd I don't think passing one parameter around to many functions is a\nbig burden.\n\nThanks for your reviews,\nChristian.\n"},{"id":"307219","messageId":"CAFZEwPMeEwUQivPjFqw+RPqsAp6u6LPAqtHbZ9bQYNecDw98kg@mail.gmail.com","threadId":"44299","inReplyTo":"14b9ba3a-4568-2e4b-0b1a-f0ee75a7c677@gmx.net","subject":"Re: [PATCH v15 19/27] bisect--helper: `bisect_state` & `bisect_head` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-08T06:43:49Z","receivedAt":"2016-12-08T06:43:58Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Wed, Dec 7, 2016 at 5:24 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit,\n>\n> On 12/06/2016 11:40 PM, Pranit Bauva wrote:\n>> On Tue, Nov 22, 2016 at 5:42 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>>> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>>>> +static int bisect_state(struct bisect_terms *terms, const char **argv,\n>>>> +                     int argc)\n>>>> +{\n>>>> +     const char *state = argv[0];\n>>>> +\n>>>> +     get_terms(terms);\n>>>> +     if (check_and_set_terms(terms, state))\n>>>> +             return -1;\n>>>> +\n>>>> +     if (!argc)\n>>>> +             die(_(\"Please call `--bisect-state` with at least one argument\"));\n>>>\n>>> I think this check should move to cmd_bisect__helper. There are also the\n>>> other argument number checks.\n>>\n>> Not really. After the whole conversion, the cmdmode will cease to\n>> exists while bisect_state will be called directly, thus it is\n>> important to check it here.\n>\n> Okay, that's a point.\n> In that case, you should probably use \"return error()\" again and the\n> message (mentioning \"--bisect-state\") does not make sense when\n> --bisect-state ceases to exist.\n\nTrue. Will change accordingly.\n\n>>>> +\n>>>> +     if (argc == 1 && one_of(state, terms->term_good,\n>>>> +         terms->term_bad, \"skip\", NULL)) {\n>>>> +             const char *bisected_head = xstrdup(bisect_head());\n>>>> +             const char *hex[1];\n>>>\n>>> Maybe:\n>>>                 const char *hex;\n>>>\n>>>> +             unsigned char sha1[20];\n>>>> +\n>>>> +             if (get_sha1(bisected_head, sha1))\n>>>> +                     die(_(\"Bad rev input: %s\"), bisected_head);\n>>>\n>>> And instead of...\n>>>\n>>>> +             if (bisect_write(state, sha1_to_hex(sha1), terms, 0))\n>>>> +                     return -1;\n>>>> +\n>>>> +             *hex = xstrdup(sha1_to_hex(sha1));\n>>>> +             if (check_expected_revs(hex, 1))\n>>>> +                     return -1;\n>>>\n>>> ... simply:\n>>>\n>>>                 hex = xstrdup(sha1_to_hex(sha1));\n>>>                 if (set_state(terms, state, hex)) {\n>>>                         free(hex);\n>>>                         return -1;\n>>>                 }\n>>>                 free(hex);\n>>>\n>>> where:\n>>\n>> Yes I am planning to convert all places with hex rather than the sha1\n>> but not yet, maybe in an another patch series because currently a lot\n>> of things revolve around sha1 and changing its behaviour wouldn't\n>> really be a part of a porting patch series.\n>\n> I was not suggesting a change of behavior, I was suggesting a simple\n> helper function set_state() to get rid of code duplication above and\n> some lines below:\n>\n>>> ... And replace this:\n>>>\n>>>> +                     const char **hex_string = (const char **) &hex.items[i].string;\n>>>> +                     if(bisect_write(state, *hex_string, terms, 0)) {\n>>>> +                             string_list_clear(&hex, 0);\n>>>> +                             return -1;\n>>>> +                     }\n>>>> +                     if (check_expected_revs(hex_string, 1)) {\n>>>> +                             string_list_clear(&hex, 0);\n>>>> +                             return -1;\n>>>> +                     }\n>>>\n>>> by:\n>>>\n>>>                         const char *hex_str = hex.items[i].string;\n>>>                         if (set_state(terms, state, hex_string)) {\n>>>                                 string_list_clear(&hex, 0);\n>>>                                 return -1;\n>>>                         }\n>\n> See?\n\nI can do this change of using set_state() keeping aside the sha1 to\nhex and such change.\n\n>>>> @@ -184,8 +137,8 @@ exit code \\$res from '\\$command' is < 0 or >= 128\" >&2\n>>>>                       state=\"$TERM_GOOD\"\n>>>>               fi\n>>>>\n>>>> -             # We have to use a subshell because \"bisect_state\" can exit.\n>>>> -             ( bisect_state $state >\"$GIT_DIR/BISECT_RUN\" )\n>>>> +             # We have to use a subshell because \"--bisect-state\" can exit.\n>>>> +             ( git bisect--helper --bisect-state $state >\"$GIT_DIR/BISECT_RUN\" )\n>>>\n>>> The new comment is funny, but you don't need a subshell here any\n>>> longer.\n>>\n>> True, but right now I didn't want to modify that part of the source\n>> code to remove the comment. I will remove the comment all together\n>> when I port bisect_run()\n> For most of the patches, I was commenting on the current state, not on\n> the big picture.\n>\n> Still I think that it is better to remove the comment and the subshell\n> instead of making the comment weird (\"yes the builtin can exit, but why\n> do we need a subshell?\" vs \"yes the shell function calls exit, so we\n> need a subshell because we do not want to exit this shell script\")\n\nSure I will remove the comment.\n\nRegards,\nPranit Bauva\n"},{"id":"307901","messageId":"CAFZEwPO2WgBjOnmvu1VOiz3PMYYx2mxircCWk+BWxmuunC=VQA@mail.gmail.com","threadId":"44299","inReplyTo":"CAFZEwPOZhO=sXLVwh03C8QN0uVXBUfb=xZ-JS003tgCNLgVOjg@mail.gmail.com","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-16T19:00:33Z","receivedAt":"2016-12-16T19:01:19Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Wed, Dec 7, 2016 at 1:03 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n\n>> I don't understand why the return value is int and not void. To avoid a\n>> \"return 0;\" line when calling this function?\n>\n> Initially I thought I would be using the return value but now I\n> realize that it is meaningless to do so. Using void seems better. :)\n\nI just recollected when I was creating the next iteration of this\nseries that I will need that int.\n\n>>> +     case CHECK_EXPECTED_REVS:\n>>> +             return check_expected_revs(argv, argc);\n\nSee this.\n\nRegards,\nPranit Bauva\n"},{"id":"307915","messageId":"CAFZEwPMwviof5jNvQnxFZYdw324XpbLSQ9mzEQjrCW-K4A+GCA@mail.gmail.com","threadId":"44299","inReplyTo":"a4c7fec8-0e84-eb53-ca22-c369ce3facfa@gmx.net","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-16T19:35:05Z","receivedAt":"2016-12-16T19:35:13Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Thu, Nov 17, 2016 at 5:17 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi,\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index d84ba86..c542e8b 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n>>       return bisect_clean_state();\n>>  }\n>>\n>> +static int is_expected_rev(const char *expected_hex)\n>> +{\n>> +     struct strbuf actual_hex = STRBUF_INIT;\n>> +     int res = 0;\n>> +     if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {\n>> +             strbuf_trim(&actual_hex);\n>> +             res = !strcmp(actual_hex.buf, expected_hex);\n>> +     }\n>> +     strbuf_release(&actual_hex);\n>> +     return res;\n>> +}\n>\n> I am not sure it does what it should.\n>\n> I would expect the following behavior from this function:\n>  - file does not exist (or is \"broken\") => return 0\n>  - actual_hex != expected_hex => return 0\n>  - otherwise return 1\n>\n> If I am not wrong, the code does the following instead:\n>  - file does not exist (or is \"broken\") => return 0\n>  - actual_hex != expected_hex => return 1\n>  - otherwise => return 0\n\nIt seems that I didn't carefully see what the shell code is (or\napparently did a mistake in understanding it ;)). I think the C\nversion does exactly what the shell version does. Can you confirm it\nonce again, please?\n\nRegards,\nPranit Bauva\n"},{"id":"307983","messageId":"22624028-b22d-5e4f-7101-c97e6e3e853c@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPO2WgBjOnmvu1VOiz3PMYYx2mxircCWk+BWxmuunC=VQA@mail.gmail.com","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-17T19:42:41Z","receivedAt":"2016-12-17T19:42:52Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 12/16/2016 08:00 PM, Pranit Bauva wrote:\n> On Wed, Dec 7, 2016 at 1:03 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> I don't understand why the return value is int and not void. To avoid a\n>>> \"return 0;\" line when calling this function?\n>>\n>> Initially I thought I would be using the return value but now I\n>> realize that it is meaningless to do so. Using void seems better. :)\n> \n> I just recollected when I was creating the next iteration of this\n> series that I will need that int.\n> \n>>>> +     case CHECK_EXPECTED_REVS:\n>>>> +             return check_expected_revs(argv, argc);\n> \n> See this.\n\nThis does not show that you need the \"int\", it just shows that you use\nthe return value of the function. But this return value is (in the\noriginal shell code as well as in your v15) always 0. That is a sign\nthat the \"void\" return value makes more sense. Of course, then the line\nabove must be changed to\n\n+     case CHECK_EXPECTED_REVS:\n+             check_expected_revs(argv, argc);\n+             return 0;\n\nBy the way, it also seems that the original function name\n\"check_expected_revs\" was not the best choice (because the function\nalways returns 0, but the \"check\" implies that some semantically true or\nfalse is returned).\nOn the other hand, it might also be useful (I cannot tell) to return\ndifferent values in check_expected_revs() — to signal the caller that\nsomething changed or something did not change — but then ignore the\nreturn value.\n\nBest\n  Stephan\n"},{"id":"307985","messageId":"6a8aef40-9ae9-7e7a-12b1-b28039fc6554@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPMwviof5jNvQnxFZYdw324XpbLSQ9mzEQjrCW-K4A+GCA@mail.gmail.com","subject":"Re: [PATCH v15 08/27] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2016-12-17T19:55:31Z","receivedAt":"2016-12-17T19:55:42Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 12/16/2016 08:35 PM, Pranit Bauva wrote:\n> On Thu, Nov 17, 2016 at 5:17 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>> index d84ba86..c542e8b 100644\n>>> --- a/builtin/bisect--helper.c\n>>> +++ b/builtin/bisect--helper.c\n>>> @@ -123,13 +123,40 @@ static int bisect_reset(const char *commit)\n>>>       return bisect_clean_state();\n>>>  }\n>>>\n>>> +static int is_expected_rev(const char *expected_hex)\n>>> +{\n>>> +     struct strbuf actual_hex = STRBUF_INIT;\n>>> +     int res = 0;\n>>> +     if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {\n>>> +             strbuf_trim(&actual_hex);\n>>> +             res = !strcmp(actual_hex.buf, expected_hex);\n>>> +     }\n>>> +     strbuf_release(&actual_hex);\n>>> +     return res;\n>>> +}\n>>\n>> I am not sure it does what it should.\n>>\n>> I would expect the following behavior from this function:\n>>  - file does not exist (or is \"broken\") => return 0\n>>  - actual_hex != expected_hex => return 0\n>>  - otherwise return 1\n>>\n>> If I am not wrong, the code does the following instead:\n>>  - file does not exist (or is \"broken\") => return 0\n>>  - actual_hex != expected_hex => return 1\n>>  - otherwise => return 0\n> \n> It seems that I didn't carefully see what the shell code is (or\n> apparently did a mistake in understanding it ;)). I think the C\n> version does exactly what the shell version does. Can you confirm it\n> once again, please?\n\nI check again...\n\nThe shell code does the following:\n - file does not exist or is not a regular file => return false\n - actual_hex != expected_hex => return false\n - otherwise => return true\n\n(false means a value != 0, true means 0)\n\nYour code does the following:\n - file cannot be read or is broken => return 0\n - actual_hex != expected_hex => return 0\n - otherwise => return 1\n\nSo you are very right, it seems I had a weird thinko (I probably missed\nthe \"!\" in front of strcmp or something) :)\n\nSorry for bothering,\n  Stephan\n"},{"id":"308548","messageId":"CAFZEwPMbT+BZ=eDxW1xkgH-Nrd=AMm1vGejLKmQ5wdM84TVnmQ@mail.gmail.com","threadId":"44299","inReplyTo":"8bd0682f-e35e-a50e-24a9-fd3a53454ed4@gmx.net","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-31T10:23:12Z","receivedAt":"2016-12-31T10:23:20Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nExtremely sorry I just forgot to reply to this email before. I was\npreparing from the next iteration when I saw this.\n\nOn Mon, Nov 21, 2016 at 1:31 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit,\n>\n> this one is hard to review because you do two or three commits in one here.\n> I think the first commit should be the exit()->return conversion, the\n> second commit is next and autonext, and the third commit is the pretty\n> trivial bisect_start commit ;) However, you did it this way and it's\n> always a hassle to split commit, so I don't really care...\n\nI had confusion about how to split the commits, but then I then\ndecided to dump it all together so that it compiles (I was finding it\ndifficult to split into meaningful parts which also compiled).\n\n> However, I was reviewing this superficially, to be honest. This mail\n> skips the next and autonext part.\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/bisect.c b/bisect.c\n>> index 45d598d..7c97e85 100644\n>> --- a/bisect.c\n>> +++ b/bisect.c\n>> @@ -843,16 +878,21 @@ static int check_ancestors(const char *prefix)\n>>   *\n>>   * If that's not the case, we need to check the merge bases.\n>>   * If a merge base must be tested by the user, its source code will be\n>> - * checked out to be tested by the user and we will exit.\n>> + * checked out to be tested by the user and we will return.\n>>   */\n>> -static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n>> +static int check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n>>  {\n>>       char *filename = git_pathdup(\"BISECT_ANCESTORS_OK\");\n>>       struct stat st;\n>> -     int fd;\n>> +     int fd, res = 0;\n>>\n>> +     /*\n>> +      * We don't want to clean the bisection state\n>> +      * as we need to get back to where we started\n>> +      * by using `git bisect reset`.\n>> +      */\n>>       if (!current_bad_oid)\n>> -             die(_(\"a %s revision is needed\"), term_bad);\n>> +             error(_(\"a %s revision is needed\"), term_bad);\n>\n> Only error() or return error()?\n\nIt should be return error(). Thanks for pointing it out! :)\n\n>> @@ -873,8 +916,11 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)\n>>                             filename);\n>>       else\n>>               close(fd);\n>> +\n>> +     goto done;\n>>   done:\n>\n> I never understand why you do this. In case of adding a \"fail\" label\n> (and fail code like \"res = -1;\") between \"goto done\" and \"done:\", it's\n> fine... but without one this is just a nop.\n\nI will just remove that line.\n\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 1d3e17f..fcd7574 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -427,15 +560,24 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>>               no_checkout = 1;\n>>\n>>       for (i = 0; i < argc; i++) {\n>> -             if (!strcmp(argv[i], \"--\")) {\n>> +             const char *arg;\n>> +             if (starts_with(argv[i], \"'\"))\n>> +                     arg = sq_dequote(xstrdup(argv[i]));\n>> +             else\n>> +                     arg = argv[i];\n>\n> One is xstrdup'ed, one is not, so there'll be a leak somewhere, and it's\n> an inconsistent leak... I guess it's a bad idea to do it this way ;)\n> (Also below.)\n\nYes. I will use xstrdup() and it does leak.\n\n>> @@ -443,24 +585,31 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,\n>>                       no_checkout = 1;\n>>               } else if (!strcmp(arg, \"--term-good\") ||\n>>                        !strcmp(arg, \"--term-old\")) {\n>> +                     if (starts_with(argv[++i], \"'\"))\n>> +                             terms->term_good = sq_dequote(xstrdup(argv[i]));\n>> +                     else\n>> +                             terms->term_good = xstrdup(argv[i]);\n>>                       must_write_terms = 1;\n>> -                     terms->term_good = xstrdup(argv[++i]);\n>>               } else if (skip_prefix(arg, \"--term-good=\", &arg)) {\n>>                       must_write_terms = 1;\n>> -                     terms->term_good = xstrdup(arg);\n>> +                     terms->term_good = arg;\n>\n> No ;) (See my other comments (to other patches) for the \"terms\" leaks.)\n\nYes I have addressed this issue.\n\n> [This repeats several times below.]\n>\n>> diff --git a/git-bisect.sh b/git-bisect.sh\n>> index f0896b3..d574c44 100755\n>> --- a/git-bisect.sh\n>> +++ b/git-bisect.sh\n>> @@ -109,6 +88,7 @@ bisect_skip() {\n>>  bisect_state() {\n>>       bisect_autostart\n>>       state=$1\n>> +     get_terms\n>>       git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit\n>>       get_terms\n>>       case \"$#,$state\" in\n>\n> I can't say if this change is right or wrong. It looks right, but: How\n> does this relate to the other changes? Is this the right patch for it?\n\nThis line is because of the following:\n\n * TERM_BAD and TERM_GOOD are global but in the coming patch they\nwould be removed as global variables.\n\n * To compensate for that, I will write out the state of TERM_BAD and\nTERM_GOOD every time it is updated in the file BISECT_TERMS.\n\n * So we will be reading it from there.\n\n * It is quite possible that this is completely redundant as for now\nbut I really don't care to check for each case because I have removed\nthe shell function bisect_state() afterwards and then this line won't\ncreate a problem there because we are using `struct bisect_terms`\nthere.\n"},{"id":"308549","messageId":"CAFZEwPPtF5P5nGp+=btHtwNm1unTJ7qo1khJHCqLvNn1=RYAUQ@mail.gmail.com","threadId":"44299","inReplyTo":"06402c8a-14a4-3d70-8d98-659cfe9f1aa2@gmx.net","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-12-31T10:43:10Z","receivedAt":"2016-12-31T10:43:20Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Tue, Nov 22, 2016 at 3:05 AM, Stephan Beyer <s-beyer@gmx.net> wrote:\n> Hi Pranit,\n>\n> in this mail I review the \"second part\" of your patch: the transition of\n> bisect_next and bisect_auto_next to C.\n>\n> On 10/14/2016 04:14 PM, Pranit Bauva wrote:\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> index 1d3e17f..fcd7574 100644\n>> --- a/builtin/bisect--helper.c\n>> +++ b/builtin/bisect--helper.c\n>> @@ -408,6 +411,136 @@ static int bisect_terms(struct bisect_terms *terms, const char **argv, int argc)\n>>       return 0;\n>>  }\n>>\n>> +static int register_good_ref(const char *refname,\n>> +                          const struct object_id *oid, int flags,\n>> +                          void *cb_data)\n>> +{\n>> +     struct string_list *good_refs = cb_data;\n>> +     string_list_append(good_refs, oid_to_hex(oid));\n>> +     return 0;\n>> +}\n>> +\n>> +static int bisect_next(struct bisect_terms *terms, const char *prefix)\n>> +{\n>> +     int res, no_checkout;\n>> +\n>> +     /*\n>> +      * In case of mistaken revs or checkout error, or signals received,\n>> +      * \"bisect_auto_next\" below may exit or misbehave.\n>> +      * We have to trap this to be able to clean up using\n>> +      * \"bisect_clean_state\".\n>> +      */\n>\n> The comment above makes no sense here, or does it?\n\nNo it doesn't right now. I had this initally because I was trying to\nkeep bisect_clean_state() call inside this function but then I\nrealized it should be placed elsewhere. I will remove this.\n\n>> +     if (bisect_next_check(terms, terms->term_good))\n>> +             return -1;\n>> +\n>> +     no_checkout = !is_empty_or_missing_file(git_path_bisect_head());\n>> +\n>> +     /* Perform all bisection computation, display and checkout */\n>> +     res = bisect_next_all(prefix , no_checkout);\n>\n> Style: there is a space left of the comma.\n\nNice catch! ;) I have gone through this patch so many times, yet I\nhave forgot to notice this.\n\n>> +\n>> +     if (res == 10) {\n>> +             FILE *fp = NULL;\n>> +             unsigned char sha1[20];\n>> +             struct commit *commit;\n>> +             struct pretty_print_context pp = {0};\n>> +             struct strbuf commit_name = STRBUF_INIT;\n>> +             char *bad_ref = xstrfmt(\"refs/bisect/%s\",\n>> +                                           terms->term_bad);\n>> +             int retval = 0;\n>> +\n>> +             read_ref(bad_ref, sha1);\n>> +             commit = lookup_commit_reference(sha1);\n>> +             format_commit_message(commit, \"%s\", &commit_name, &pp);\n>> +             fp = fopen(git_path_bisect_log(), \"a\");\n>> +             if (!fp) {\n>> +                     retval = -1;\n>> +                     goto finish_10;\n>> +             }\n>> +             if (fprintf(fp, \"# first %s commit: [%s] %s\\n\",\n>> +                         terms->term_bad, sha1_to_hex(sha1),\n>> +                         commit_name.buf) < 1){\n>> +                     retval = -1;\n>> +                     goto finish_10;\n>> +             }\n>> +             goto finish_10;\n>> +     finish_10:\n>> +             if (fp)\n>> +                     fclose(fp);\n>> +             strbuf_release(&commit_name);\n>> +             free(bad_ref);\n>> +             return retval;\n>> +     }\n>> +     else if (res == 2) {\n>> +             FILE *fp = NULL;\n>> +             struct rev_info revs;\n>> +             struct argv_array rev_argv = ARGV_ARRAY_INIT;\n>> +             struct string_list good_revs = STRING_LIST_INIT_DUP;\n>> +             struct pretty_print_context pp = {0};\n>> +             struct commit *commit;\n>> +             char *term_good = xstrfmt(\"%s-*\", terms->term_good);\n>> +             int i, retval = 0;\n>> +\n>> +             fp = fopen(git_path_bisect_log(), \"a\");\n>> +             if (!fp) {\n>> +                     retval = -1;\n>> +                     goto finish_2;\n>> +             }\n>> +             if (fprintf(fp, \"# only skipped commits left to test\\n\") < 1) {\n>> +                     retval = -1;\n>> +                     goto finish_2;\n>> +             }\n>> +             for_each_glob_ref_in(register_good_ref, term_good,\n>> +                                  \"refs/bisect/\", (void *) &good_revs);\n>> +\n>> +             argv_array_pushl(&rev_argv, \"skipped_commits\", \"refs/bisect/bad\", \"--not\", NULL);\n>> +             for (i = 0; i < good_revs.nr; i++)\n>> +                     argv_array_push(&rev_argv, good_revs.items[i].string);\n>> +\n>> +             /* It is important to reset the flags used by revision walks\n>> +              * as the previous call to bisect_next_all() in turn\n>> +              * setups a revision walk.\n>> +              */\n>> +             reset_revision_walk();\n>> +             init_revisions(&revs, NULL);\n>> +             rev_argv.argc = setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL);\n>> +             argv_array_clear(&rev_argv);\n>> +             string_list_clear(&good_revs, 0);\n>> +             if (prepare_revision_walk(&revs))\n>> +                     die(_(\"revision walk setup failed\\n\"));\n>> +\n>> +             while ((commit = get_revision(&revs)) != NULL) {\n>> +                     struct strbuf commit_name = STRBUF_INIT;\n>> +                     format_commit_message(commit, \"%s\",\n>> +                                           &commit_name, &pp);\n>> +                     fprintf(fp, \"# possible first %s commit: \"\n>> +                                 \"[%s] %s\\n\", terms->term_bad,\n>> +                                 oid_to_hex(&commit->object.oid),\n>> +                                 commit_name.buf);\n>> +                     strbuf_release(&commit_name);\n>> +             }\n>> +             goto finish_2;\n>> +     finish_2:\n>> +             if (fp)\n>> +                     fclose(fp);\n>> +             string_list_clear(&good_revs, 0);\n>> +             argv_array_clear(&rev_argv);\n>> +             free(term_good);\n>> +             if (retval)\n>> +                     return retval;\n>> +             else\n>> +                     return res;\n>> +     }\n>> +     return res;\n>> +}\n>\n> It would be much nicer if you put the (res == 10) branch and the\n> (res == 2) branch into separate functions and just call them.\n> Then you also won't need ugly label naming like finish_10 or finish_2.\n> I'd also (again) recommend to use goto fail instead of setting retval to\n> -1 separately each time.\n\nYes, that seems a better way to go! Thanks! :)\n\n> I'd also recommend to use a separate function to append to the bisect\n> log file. There is a lot of duplicated opening, checking, closing code;\n> IIRC such a function would also already be handy for some of the\n> previous patches.\n\nTrue. I have made that function. Will reuse it here. Thanks! :)\n\n>> +\n>> +static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)\n>> +{\n>> +     if (!bisect_next_check(terms, NULL))\n>> +             return bisect_next(terms, prefix);\n>> +\n>> +     return 0;\n>> +}\n>\n> Hmm, the handling of the return values is a little confusing. However,\n> if I understand the sh source correctly, it always returns success, no\n> matter if bisect_next failed or not. I do not know if you had something\n> special in mind here.\n\nUmm. Shell code used to die() and thus exit with an error code. Thus\nit is important to return the exit code. Handling return values was\n*very confusing* for me too while writing this commit ;) A lot of\nbehaviour is changed in this commit regarding return values.\n\n>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>> @@ -643,6 +794,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>                        N_(\"print out the bisect terms\"), BISECT_TERMS),\n>>               OPT_CMDMODE(0, \"bisect-start\", &cmdmode,\n>>                        N_(\"start the bisect session\"), BISECT_START),\n>> +             OPT_CMDMODE(0, \"bisect-next\", &cmdmode,\n>> +                      N_(\"find the next bisection commit\"), BISECT_NEXT),\n>> +             OPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n>> +                      N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>\n> The next bisection *state* is found?\n\ncheckout is more appropriate. I don't remember why I used \"find\".\n\n>> diff --git a/git-bisect.sh b/git-bisect.sh\n>> index f0896b3..d574c44 100755\n>> --- a/git-bisect.sh\n>> +++ b/git-bisect.sh\n>> @@ -139,45 +119,7 @@ bisect_state() {\n>>       *)\n>>               usage ;;\n>>       esac\n>> -     bisect_auto_next\n> [...deleted lines...]\n>> +     git bisect--helper --bisect-auto-next || exit\n>\n> Why is the \"|| exit\" necessary?\n\nSince it returning exit code, we need to quit, see earlier comment.\nEarlier in shell script we used die() but now we are using return\nerror() thus we need to make it exit here too.\n\n>> @@ -319,14 +260,15 @@ case \"$#\" in\n>>       help)\n>>               git bisect -h ;;\n>>       start)\n>> -             bisect_start \"$@\" ;;\n>> +             git bisect--helper --bisect-start \"$@\" ;;\n>>       bad|good|new|old|\"$TERM_BAD\"|\"$TERM_GOOD\")\n>>               bisect_state \"$cmd\" \"$@\" ;;\n>>       skip)\n>>               bisect_skip \"$@\" ;;\n>>       next)\n>>               # Not sure we want \"next\" at the UI level anymore.\n>> -             bisect_next \"$@\" ;;\n>> +             get_terms\n>> +             git bisect--helper --bisect-next \"$@\" || exit ;;\n>\n> Why is the \"|| exit\" necessary? ;)\n\nSame as before.\n\n>\n> Furthermore:\n> Where is the bisect_autostart call from bisect_next() sh source gone?\n> Was it not necessary?\n\nIt is necessary, but I couldn't just incorporate it in one commit. The\nfunctions are called in a circular fashion. Thus I skipped\nbisect_autostart() as for now but then when I managed to port\nbisect_autostart(), I called that function from this.\n\nRegards,\nPranit Bauva\n"},{"id":"308580","messageId":"cdf41dcc-bdc5-a3a7-8d39-8b85e01cda85@gmx.net","threadId":"44299","inReplyTo":"CAFZEwPPtF5P5nGp+=btHtwNm1unTJ7qo1khJHCqLvNn1=RYAUQ@mail.gmail.com","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2017-01-01T16:27:51Z","receivedAt":"2017-01-01T16:28:04Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi Pranit,\n\nOn 12/31/2016 11:43 AM, Pranit Bauva wrote:\n>>> +\n>>> +static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)\n>>> +{\n>>> +     if (!bisect_next_check(terms, NULL))\n>>> +             return bisect_next(terms, prefix);\n>>> +\n>>> +     return 0;\n>>> +}\n>>\n>> Hmm, the handling of the return values is a little confusing. However,\n>> if I understand the sh source correctly, it always returns success, no\n>> matter if bisect_next failed or not. I do not know if you had something\n>> special in mind here.\n> \n> Umm. Shell code used to die() and thus exit with an error code.\n\nThe invoked bisect_next shell code called \"exit\", right... you had to\nreplace this by passing return values. I get it. Thank you!\n\n>>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>> @@ -643,6 +794,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>>                        N_(\"print out the bisect terms\"), BISECT_TERMS),\n>>>               OPT_CMDMODE(0, \"bisect-start\", &cmdmode,\n>>>                        N_(\"start the bisect session\"), BISECT_START),\n>>> +             OPT_CMDMODE(0, \"bisect-next\", &cmdmode,\n>>> +                      N_(\"find the next bisection commit\"), BISECT_NEXT),\n>>> +             OPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n>>> +                      N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>>\n>> The next bisection *state* is found?\n> \n> checkout is more appropriate. I don't remember why I used \"find\".\n\n\"checkout the next bisection commit\" maybe?\n\nThanks,\n  Stephan\n"},{"id":"308582","messageId":"CAFZEwPN1yFjSxGjHP6BmF8huaVuiipGfWxdFy4fc1hapxd+qCA@mail.gmail.com","threadId":"44299","inReplyTo":"cdf41dcc-bdc5-a3a7-8d39-8b85e01cda85@gmx.net","subject":"Re: [PATCH v15 15/27] bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2017-01-01T17:41:09Z","receivedAt":"2017-01-01T17:41:17Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Stephan,\n\nOn Sun, Jan 1, 2017 at 9:57 PM, Stephan Beyer <s-beyer@gmx.net> wrote:\n>>>>  int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>>> @@ -643,6 +794,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>>>>                        N_(\"print out the bisect terms\"), BISECT_TERMS),\n>>>>               OPT_CMDMODE(0, \"bisect-start\", &cmdmode,\n>>>>                        N_(\"start the bisect session\"), BISECT_START),\n>>>> +             OPT_CMDMODE(0, \"bisect-next\", &cmdmode,\n>>>> +                      N_(\"find the next bisection commit\"), BISECT_NEXT),\n>>>> +             OPT_CMDMODE(0, \"bisect-auto-next\", &cmdmode,\n>>>> +                      N_(\"verify the next bisection state then find the next bisection state\"), BISECT_AUTO_NEXT),\n>>>\n>>> The next bisection *state* is found?\n>>\n>> checkout is more appropriate. I don't remember why I used \"find\".\n>\n> \"checkout the next bisection commit\" maybe?\n\nSeems better. Thanks!\n\nRegards,\nPranit Bauva\n"}]}