{"thread":{"id":"42559","subject":"[PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","startedAt":"2016-06-07T20:54:51Z","lastAt":"2016-07-11T19:19:49Z","messageCount":75,"participants":["Pranit Bauva","Eric Sunshine","Torsten Bögershausen","Christian Couder","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"288638","messageId":"20160607205454.22576-1-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":null,"subject":"[PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-07T20:54:51Z","receivedAt":"2016-06-07T20:54:51Z","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 and will be called by\nbisect_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 builtin/bisect--helper.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 26 +++----------------------\n 2 files changed, 51 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 91027b0..ad39181 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,12 +3,21 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_write_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_names, \"BISECT_NAMES\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -78,11 +87,43 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\n }\n \n+int mark_for_removal(const char *refname, const struct object_id *oid,\n+\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+\tstruct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n+\tfor_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n+\tstring_list_append(&refs_for_removal, \"BISECT_HEAD\");\n+\tresult |= delete_refs(&refs_for_removal);\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tremove_path(git_path_bisect_expected_rev());\n+\tremove_path(git_path_bisect_ancestors_ok());\n+\tremove_path(git_path_bisect_log());\n+\tremove_path(git_path_bisect_names());\n+\tremove_path(git_path_bisect_run());\n+\tremove_path(git_path_bisect_write_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tremove_path(git_path_head_name());\n+\t/* Cleanup BISECT_START last */\n+\tremove_path(git_path_bisect_start());\n+\n+\treturn result;\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\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -90,6 +131,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@@ -108,6 +151,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 cd39bd0..bbc57d2 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -187,7 +187,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@@ -196,7 +196,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-- \n2.8.3\n"},{"id":"288639","messageId":"20160607205454.22576-2-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"[PATCH 2/4] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-07T20:54:52Z","receivedAt":"2016-06-07T20:54:52Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"This is not an improvement in the test coverage but it helps in making\nit explicit as to what exactly would be the error as other tests are\nfocussed on testing other things.\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\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\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 e74662b..1fb5ad9 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+\t! test -s \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n+\t! test -s \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n+\t! test -s \"$GIT_DIR/BISECT_LOG\" &&\n+\t! test -s \"$GIT_DIR/BISECT_RUN\" &&\n+\t! test -s \"$GIT_DIR/BISECT_TERMS\" &&\n+\t! test -s \"$GIT_DIR/head-name\" &&\n+\t! test -s \"$GIT_DIR/BISECT_HEAD\" &&\n+\t! test -s \"$GIT_DIR/BISECT_START\"\n+'\n+\n test_done\n-- \n2.8.3\n"},{"id":"288640","messageId":"20160607205454.22576-3-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"[PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-07T20:54:53Z","receivedAt":"2016-06-07T20:54:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"At times we require to see if the file is empty and get the size of the\nfile. By using stat we can get the file size without actually having to\nopen the file to check for its contents.\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 dir.c | 8 ++++++++\n dir.h | 7 +++++++\n 2 files changed, 15 insertions(+)\n\ndiff --git a/dir.c b/dir.c\nindex 6172b34..eaee718 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2036,6 +2036,14 @@ int file_exists(const char *f)\n \treturn lstat(f, &sb) == 0;\n }\n \n+ssize_t file_size(const char *filename)\n+{\n+\tstruct stat st;\n+\tif (stat(filename, &st) < 0)\n+\t\treturn -1;\n+\treturn xsize_t(st.st_size);\n+}\n+\n static int cmp_icase(char a, char b)\n {\n \tif (a == b)\ndiff --git a/dir.h b/dir.h\nindex bfde698..aa9d276 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -248,6 +248,13 @@ extern void clear_exclude_list(struct exclude_list *el);\n extern void clear_directory(struct dir_struct *dir);\n extern int file_exists(const char *);\n \n+/*\n+ * Return the size of the file `filename`. It returns -1 if error\n+ * occurred, 0 if file is empty and a positive number denoting the size\n+ * of the file.\n+ */\n+extern ssize_t file_size(const char *);\n+\n extern int is_inside_dir(const char *dir);\n extern int dir_inside_of(const char *subdir, const char *dir);\n \n-- \n2.8.3\n"},{"id":"288641","messageId":"20160607205454.22576-4-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"[PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-07T20:54:54Z","receivedAt":"2016-06-07T20:54:54Z","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 and will be called by some\nother 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 | 51 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++------------------------\n 2 files changed, 52 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex ad39181..4153e8a 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,6 +4,8 @@\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_write_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -13,11 +15,13 @@ static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -118,12 +122,51 @@ int bisect_clean_state(void)\n \treturn result;\n }\n \n+int bisect_reset(const char *commit)\n+{\n+\tstruct strbuf branch = STRBUF_INIT;\n+\tint status = 0;\n+\n+\tif (file_size(git_path_bisect_start()) < 1) {\n+\t\tprintf(\"We are not bisecting.\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tif (!commit) {\n+\t\tstrbuf_read_file(&branch, git_path_bisect_start(), 0);\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tstruct object_id oid;\n+\t\tif (get_oid(commit, &oid))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addf(&branch, \"%s\", 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\tstatus = run_command_v_opt(argv.argv, RUN_GIT_CMD);\n+\t\targv_array_clear(&argv);\n+\t}\n+\n+\tif (status) {\n+\t\terror(_(\"Could not check out original HEAD '%s'. \"\n+\t\t\t\t\"Try 'git bisect reset <commit>'.\"), branch.buf);\n+\t\tstrbuf_release(&branch);\n+\t\treturn -1;\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@@ -133,6 +176,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@@ -155,6 +200,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 bbc57d2..18580b7 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-- \n2.8.3\n"},{"id":"288662","messageId":"CAPig+cTqk0d60Omsm12RXF2uzoxoPjbqHj7V8Y=6Uu+fH5b43Q@mail.gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-07T22:31:02Z","receivedAt":"2016-06-07T22:31:02Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `bisect_clean_state` shell function in C and add a\n> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh .\n> [...]\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> @@ -78,11 +87,43 @@ static int write_terms(const char *bad, const char *good)\n> +int mark_for_removal(const char *refname, const struct object_id *oid,\n> +                      int flag, void *cb_data)\n> +{\n> +       struct string_list *refs = cb_data;\n> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n\nHere you're allocating a string...\n\n> +       string_list_append(refs, ref);\n> +       return 0;\n> +}\n> +\n> +int bisect_clean_state(void)\n> +{\n> +       int result = 0;\n> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n\n...and the allocated string gets inserted into a string_list which\nitself duplicates the string (STRING_LIST_INIT_DUP), so this is\nleaking the string you created with xstrfmt(), isn't it?\n\n> +       string_list_append(&refs_for_removal, \"BISECT_HEAD\");\n> +       result |= delete_refs(&refs_for_removal);\n\nNot sure I understand the point of using |= here rather than merely =\nsince this is the only place 'result' is assigned in this function.\n\n> +       string_list_clear(&refs_for_removal, 0);\n> +       remove_path(git_path_bisect_expected_rev());\n> +       remove_path(git_path_bisect_ancestors_ok());\n> +       remove_path(git_path_bisect_log());\n> +       remove_path(git_path_bisect_names());\n> +       remove_path(git_path_bisect_run());\n> +       remove_path(git_path_bisect_write_terms());\n> +       /* Cleanup head-name if it got left by an old version of git-bisect */\n> +       remove_path(git_path_head_name());\n> +       /* Cleanup BISECT_START last */\n> +       remove_path(git_path_bisect_start());\n\nThe BISECT_START comment merely repeats what the code itself already\nsays. I realize that you merely copied this from the shell code, but\nit isn't helpful in its current form. Much more helpful would be to\nexplain *why* this needs to be done last. Perhaps the commit message\nof the commit which introduced the comment originally would give a\nclue (I haven't checked).\n\n> +       return result;\n> +}\n> diff --git a/git-bisect.sh b/git-bisect.sh\n> @@ -430,27 +430,7 @@ bisect_reset() {\n> -bisect_clean_state() {\n> -       # There may be some refs packed during bisection.\n\nThis comment doesn't seem to be reproduced in the C version. Should it\nbe? Is it no longer relevant in the C version? What does it mean\nexactly?\n\n> -       git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\\* |\n> -       while read ref hash\n> -       do\n> -               git update-ref -d $ref $hash || exit\n> -       done\n> -       rm -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n> -       rm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n> -       rm -f \"$GIT_DIR/BISECT_LOG\" &&\n> -       rm -f \"$GIT_DIR/BISECT_NAMES\" &&\n> -       rm -f \"$GIT_DIR/BISECT_RUN\" &&\n> -       rm -f \"$GIT_DIR/BISECT_TERMS\" &&\n> -       # Cleanup head-name if it got left by an old version of git-bisect\n> -       rm -f \"$GIT_DIR/head-name\" &&\n> -       git update-ref -d --no-deref BISECT_HEAD &&\n> -       # clean up BISECT_START last\n> -       rm -f \"$GIT_DIR/BISECT_START\"\n> +       git bisect--helper --bisect-clean-state || exit\n>  }\n"},{"id":"288671","messageId":"CAPig+cRxGAR8s_Yn7EmCs0zQe2=F7RnhSw+0mtiZOfJtFkD_FQ@mail.gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-2-pranit.bauva@gmail.com","subject":"Re: [PATCH 2/4] t6030: explicitly test for bisection cleanup","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-07T23:21:12Z","receivedAt":"2016-06-07T23:21:12Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> This is not an improvement in the test coverage but it helps in making\n> it explicit as to what exactly would be the error as other tests are\n> focussed on testing other things.\n\nIt's not clear why you consider this as *not* improving test coverage.\n\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\n> @@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n> +test_expect_success 'git bisect reset cleans bisection state properly' '\n> +       git bisect reset &&\n> +       git bisect start &&\n> +       git bisect good $HASH1 &&\n> +       git bisect bad $HASH4 &&\n> +       git bisect reset &&\n> +       test -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n\nI wonder if this would be more easily read as:\n\n    git for-each-ref \"refs/bisect/*\" >actual &&\n    test_must_be_empty actual &&\n\n> +       ! test -s \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_LOG\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_RUN\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_TERMS\" &&\n> +       ! test -s \"$GIT_DIR/head-name\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_HEAD\" &&\n> +       ! test -s \"$GIT_DIR/BISECT_START\"\n\nIs it the intention that these should verify that the files don't\nexist? Maybe use test_path_is_missing() instead?\n\n> +'\n> +\n>  test_done\n"},{"id":"288676","messageId":"CAPig+cSsgmu6dHDrqHybKMJiQ9bi29TqnJWq78=1r+pLyDR1kw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTqk0d60Omsm12RXF2uzoxoPjbqHj7V8Y=6Uu+fH5b43Q@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T01:51:42Z","receivedAt":"2016-06-08T01:51:42Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jun 7, 2016 at 6:31 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> +int bisect_clean_state(void)\n>> +{\n\nI forgot to mention that this and other functions should be 'static'.\n\n>> +       int result = 0;\n>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n"},{"id":"288681","messageId":"CAPig+cTgnp3tm_S7ybDBiGfesw9mh3J4_OtEV7timnsgL0AGjA@mail.gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-3-pranit.bauva@gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T07:37:47Z","receivedAt":"2016-06-08T07:37:47Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> dir: introduce file_size() to check the size of file\n>\n> At times we require to see if the file is empty and get the size of the\n> file. By using stat we can get the file size without actually having to\n> open the file to check for its contents.\n\nThe sole caller of this function in patch 4/4 does so only to check if\nthe file exists; it doesn't even care about the file's size, thus\nneither this function nor this patch seem justified and probably ought\nto be dropped unless some better and stronger justification can be\nshown.\n\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/dir.c b/dir.c\n> @@ -2036,6 +2036,14 @@ int file_exists(const char *f)\n> +ssize_t file_size(const char *filename)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st) < 0)\n> +               return -1;\n> +       return xsize_t(st.st_size);\n> +}\n> +\n> diff --git a/dir.h b/dir.h\n> @@ -248,6 +248,13 @@ extern void clear_exclude_list(struct exclude_list *el);\n> +/*\n> + * Return the size of the file `filename`. It returns -1 if error\n> + * occurred, 0 if file is empty and a positive number denoting the size\n> + * of the file.\n> + */\n> +extern ssize_t file_size(const char *);\n"},{"id":"288682","messageId":"CAFZEwPMJbKAOdffWs7QedB+4j32LaBZeV1iGpUuGntMjXeN3hg@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTqk0d60Omsm12RXF2uzoxoPjbqHj7V8Y=6Uu+fH5b43Q@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T07:46:22Z","receivedAt":"2016-06-08T07:46:22Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `bisect_clean_state` shell function in C and add a\n>> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n>> git-bisect.sh .\n>> [...]\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -78,11 +87,43 @@ static int write_terms(const char *bad, const char *good)\n>> +int mark_for_removal(const char *refname, const struct object_id *oid,\n>> +                      int flag, void *cb_data)\n>> +{\n>> +       struct string_list *refs = cb_data;\n>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>\n> Here you're allocating a string...\n>\n>> +       string_list_append(refs, ref);\n>> +       return 0;\n>> +}\n>> +\n>> +int bisect_clean_state(void)\n>> +{\n>> +       int result = 0;\n>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>\n> ...and the allocated string gets inserted into a string_list which\n> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n> leaking the string you created with xstrfmt(), isn't it?\n\nYes nice catch. I would prefer using the string_list with\nSTRING_LIST_INIT_DUP and free the ref.\n\n>> +       string_list_append(&refs_for_removal, \"BISECT_HEAD\");\n>> +       result |= delete_refs(&refs_for_removal);\n>\n> Not sure I understand the point of using |= here rather than merely =\n> since this is the only place 'result' is assigned in this function.\n\nIn some initial iterations I assigned value of result before so used\n|=. Then I realized it isn't necessary, so removed it. Forgot to\nremove |=. Will do it!\n\n>> +       string_list_clear(&refs_for_removal, 0);\n>> +       remove_path(git_path_bisect_expected_rev());\n>> +       remove_path(git_path_bisect_ancestors_ok());\n>> +       remove_path(git_path_bisect_log());\n>> +       remove_path(git_path_bisect_names());\n>> +       remove_path(git_path_bisect_run());\n>> +       remove_path(git_path_bisect_write_terms());\n>> +       /* Cleanup head-name if it got left by an old version of git-bisect */\n>> +       remove_path(git_path_head_name());\n>> +       /* Cleanup BISECT_START last */\n>> +       remove_path(git_path_bisect_start());\n>\n> The BISECT_START comment merely repeats what the code itself already\n> says. I realize that you merely copied this from the shell code, but\n> it isn't helpful in its current form. Much more helpful would be to\n> explain *why* this needs to be done last. Perhaps the commit message\n> of the commit which introduced the comment originally would give a\n> clue (I haven't checked).\n\nThe commit(4796e823a) by Jon Seymour (4 Aug, 2011) explains this. I am\nnot sure how I would frame the sentence as that commit introduces a\nconcept whose by-product is the comment. I do want to include it in\nthe commit message otherwise it would be passed on as \"you have to do\nit but no one knows why\".\n\n>> +       return result;\n>> +}\n>> diff --git a/git-bisect.sh b/git-bisect.sh\n>> @@ -430,27 +430,7 @@ bisect_reset() {\n>> -bisect_clean_state() {\n>> -       # There may be some refs packed during bisection.\n>\n> This comment doesn't seem to be reproduced in the C version. Should it\n> be? Is it no longer relevant in the C version? What does it mean\n> exactly?\n\ngit-bisect itself never packs refs on its own. But there is a\npossibility that the user might have packed the refs in the bisection\nstate. This was introduced by Christian ( 15 Nov, 2007) in commit\n947a604b01.\n\n>> -       git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\\* |\n>> -       while read ref hash\n>> -       do\n>> -               git update-ref -d $ref $hash || exit\n>> -       done\n>> -       rm -f \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n>> -       rm -f \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n>> -       rm -f \"$GIT_DIR/BISECT_LOG\" &&\n>> -       rm -f \"$GIT_DIR/BISECT_NAMES\" &&\n>> -       rm -f \"$GIT_DIR/BISECT_RUN\" &&\n>> -       rm -f \"$GIT_DIR/BISECT_TERMS\" &&\n>> -       # Cleanup head-name if it got left by an old version of git-bisect\n>> -       rm -f \"$GIT_DIR/head-name\" &&\n>> -       git update-ref -d --no-deref BISECT_HEAD &&\n>> -       # clean up BISECT_START last\n>> -       rm -f \"$GIT_DIR/BISECT_START\"\n>> +       git bisect--helper --bisect-clean-state || exit\n>>  }\n\nI will also include static in function declaration. Thanks!\n\nRegards,\nPranit Bauva\n"},{"id":"288683","messageId":"CAFZEwPPWMdOahMP4f0=Lm_n+ZmEtGHg=zHaZAyQjSf9oL8X2ew@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTgnp3tm_S7ybDBiGfesw9mh3J4_OtEV7timnsgL0AGjA@mail.gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T07:57:56Z","receivedAt":"2016-06-08T07:57:56Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 1:07 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> dir: introduce file_size() to check the size of file\n>>\n>> At times we require to see if the file is empty and get the size of the\n>> file. By using stat we can get the file size without actually having to\n>> open the file to check for its contents.\n>\n> The sole caller of this function in patch 4/4 does so only to check if\n> the file exists; it doesn't even care about the file's size, thus\n> neither this function nor this patch seem justified and probably ought\n> to be dropped unless some better and stronger justification can be\n> shown.\n\nUmm, actually there is a subtle difference between file_exists() and\nfile_size(). file_exists() *only* checks whether the file exists or\nnot while file_size() can also be used to check whether the file is\nempty or not also see the implementation of both of them which shows\nthe difference. In fact it doesn't care at all about the file size.\nNow there are a lot of instances in shell scripts where there are\nquite some differences with -f and -s and some places *do care* about\nthis subtle difference. For eg. in bisect_reset() we test whether the\nfile .git/BISECT_START has some contents in it. But I guess I can add\nsome more justification in the commit message. What do you think?\n\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/dir.c b/dir.c\n>> @@ -2036,6 +2036,14 @@ int file_exists(const char *f)\n>> +ssize_t file_size(const char *filename)\n>> +{\n>> +       struct stat st;\n>> +       if (stat(filename, &st) < 0)\n>> +               return -1;\n>> +       return xsize_t(st.st_size);\n>> +}\n>> +\n>> diff --git a/dir.h b/dir.h\n>> @@ -248,6 +248,13 @@ extern void clear_exclude_list(struct exclude_list *el);\n>> +/*\n>> + * Return the size of the file `filename`. It returns -1 if error\n>> + * occurred, 0 if file is empty and a positive number denoting the size\n>> + * of the file.\n>> + */\n>> +extern ssize_t file_size(const char *);\n\nRegards,\nPranit Bauva\n"},{"id":"288684","messageId":"CAPig+cSsMg5HznWGiUsngpHskSDMNhauvVw5jvaJTtEtJBw+ew@mail.gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-4-pranit.bauva@gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T07:59:35Z","receivedAt":"2016-06-08T07:59:35Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n>\n> Using `bisect_reset` subcommand is a temporary measure to port shell\n> functions to C so as to use the existing test suite. As more functions\n> are ported, this subcommand would be retired and will be called by some\n> other method.\n>\n> Note: --bisect-clean-state subcommand has not been retired as there are\n> still a function namely `bisect_start()` which still uses this\n> subcommand.\n>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> @@ -118,12 +122,51 @@ int bisect_clean_state(void)\n> +int bisect_reset(const char *commit)\n\ns/^/static/\n\n> +{\n> +       struct strbuf branch = STRBUF_INIT;\n> +       int status = 0;\n> +\n> +       if (file_size(git_path_bisect_start()) < 1) {\n\nThis doesn't even care about the size of the file, only if it\nencountered an error while stat()'ing it. Why not just use\nfile_exists() instead (which you already use elsewhere in this\nfunction)? Alternately, if you're trying to be faithful to the shell\ncode, then you *do* need to check that the file has non-zero size\nbefore issuing the \"not bisecting\" diagnostic, so:\n\n    if (file_size(git_path_bisect_start()) <= 0)\n        printf(\"... not bisecting ...\");\n\nA different approach would be to invoke strbuf_read_file()\nunconditionally, rather than performing this separate check. If\nstrbuf_read_file() returns -1, then the file didn't exist or couldn't\nbe read; if it returns 0, then the file has no content:\n\n    if (strbuf_read_file(&branch, ..., 0) <= 0)\n        printf(\"... not bisecting ...\");\n\n> +               printf(\"We are not bisecting.\\n\");\n> +               return 0;\n> +       }\n> +\n> +       if (!commit) {\n> +               strbuf_read_file(&branch, git_path_bisect_start(), 0);\n\nShouldn't you be checking the return value of strbuf_read_file()?\n\n> +               strbuf_rtrim(&branch);\n> +       } else {\n> +               struct object_id oid;\n> +               if (get_oid(commit, &oid))\n> +                       return error(_(\"'%s' is not a valid commit\"), commit);\n> +               strbuf_addf(&branch, \"%s\", commit);\n> +       }\n> +\n> +       if (!file_exists(git_path_bisect_head())) {\n> +               struct argv_array argv = ARGV_ARRAY_INIT;\n> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n> +               status = run_command_v_opt(argv.argv, RUN_GIT_CMD);\n> +               argv_array_clear(&argv);\n> +       }\n> +\n> +       if (status) {\n\nWhat's the purpose of having this 'status' conditional outside of the\nabove !file_exists() conditional, which is the only place that\n'status' gets assigned. Likewise, 'status' itself could be declared\nwithin the scope of that conditional block.\n\n> +               error(_(\"Could not check out original HEAD '%s'. \"\n> +                               \"Try 'git bisect reset <commit>'.\"), branch.buf);\n> +               strbuf_release(&branch);\n> +               return -1;\n> +       }\n> +\n> +       strbuf_release(&branch);\n> +       return bisect_clean_state();\n> +}\n"},{"id":"288685","messageId":"CAPig+cTiqRAnhBx6eCifdOmES1uD3piPYgsRHNMVFCO07W1nTg@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPMJbKAOdffWs7QedB+4j32LaBZeV1iGpUuGntMjXeN3hg@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T08:02:42Z","receivedAt":"2016-06-08T08:02:42Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 3:46 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> +       struct string_list *refs = cb_data;\n>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>\n>> Here you're allocating a string...\n>>\n>>> +       string_list_append(refs, ref);\n>>> +       return 0;\n>>> +}\n>>> +\n>>> +int bisect_clean_state(void)\n>>> +{\n>>> +       int result = 0;\n>>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>>\n>> ...and the allocated string gets inserted into a string_list which\n>> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n>> leaking the string you created with xstrfmt(), isn't it?\n>\n> Yes nice catch. I would prefer using the string_list with\n> STRING_LIST_INIT_DUP and free the ref.\n\nThat's unnecessarily wasteful. Better would be to to use STRING_LIST_INIT_NODUP.\n"},{"id":"288686","messageId":"CAFZEwPMpa1BHTP5BEqBHpYiab9G32tVXvLTZ95xhVeOcObCCBg@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cRxGAR8s_Yn7EmCs0zQe2=F7RnhSw+0mtiZOfJtFkD_FQ@mail.gmail.com","subject":"Re: [PATCH 2/4] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T08:07:24Z","receivedAt":"2016-06-08T08:07:24Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 4:51 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> This is not an improvement in the test coverage but it helps in making\n>> it explicit as to what exactly would be the error as other tests are\n>> focussed on testing other things.\n>\n> It's not clear why you consider this as *not* improving test coverage.\n\nMy mistake as I forgot to include a comment in this patch. I did it in\nthe previous patch[1]. I manually changed the file names and saw that\nthere were a couple of tests failing in each case.\n\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\n>> @@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n>> +test_expect_success 'git bisect reset cleans bisection state properly' '\n>> +       git bisect reset &&\n>> +       git bisect start &&\n>> +       git bisect good $HASH1 &&\n>> +       git bisect bad $HASH4 &&\n>> +       git bisect reset &&\n>> +       test -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n>\n> I wonder if this would be more easily read as:\n>\n>     git for-each-ref \"refs/bisect/*\" >actual &&\n>     test_must_be_empty actual &&\n\nI just tried to imitate what the test t6030 previously had (a lot of\noccurrences). Should I still change it to your specified format?\nShould I also change the others as a side cleanup \"while I am at it\"?\n\n>> +       ! test -s \"$GIT_DIR/BISECT_EXPECTED_REV\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_ANCESTORS_OK\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_LOG\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_RUN\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_TERMS\" &&\n>> +       ! test -s \"$GIT_DIR/head-name\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_HEAD\" &&\n>> +       ! test -s \"$GIT_DIR/BISECT_START\"\n>\n> Is it the intention that these should verify that the files don't\n> exist? Maybe use test_path_is_missing() instead?\n\nTrue. In fact it would be much more appropriate to use\ntest_path_is_missing() as we are using remove_path() and thus there\nshouldn't even exist a file with file size != 0. Thanks!\n\n>> +'\n>> +\n>>  test_done\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/294520\n\n\nRegards,\nPranit Bauva\n"},{"id":"288687","messageId":"CAFZEwPMWRcvaspsKRMegKbtzCKgXohoeGF36L-fCk0DcyvrWPQ@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTiqRAnhBx6eCifdOmES1uD3piPYgsRHNMVFCO07W1nTg@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T08:09:03Z","receivedAt":"2016-06-08T08:09:03Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 1:32 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 8, 2016 at 3:46 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> On Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> +       struct string_list *refs = cb_data;\n>>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>>\n>>> Here you're allocating a string...\n>>>\n>>>> +       string_list_append(refs, ref);\n>>>> +       return 0;\n>>>> +}\n>>>> +\n>>>> +int bisect_clean_state(void)\n>>>> +{\n>>>> +       int result = 0;\n>>>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>>>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>>>\n>>> ...and the allocated string gets inserted into a string_list which\n>>> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n>>> leaking the string you created with xstrfmt(), isn't it?\n>>\n>> Yes nice catch. I would prefer using the string_list with\n>> STRING_LIST_INIT_DUP and free the ref.\n>\n> That's unnecessarily wasteful. Better would be to to use STRING_LIST_INIT_NODUP.\n\nSure I will try it out!\n\nRegards,\nPranit Bauva\n"},{"id":"288689","messageId":"CAPig+cR8+ekOv3xuj1Nn9ftA5smHG78wdFp1Xnfz_qyrstKRqw@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPPWMdOahMP4f0=Lm_n+ZmEtGHg=zHaZAyQjSf9oL8X2ew@mail.gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T08:13:15Z","receivedAt":"2016-06-08T08:13:15Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 3:57 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 1:07 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> dir: introduce file_size() to check the size of file\n>>>\n>>> At times we require to see if the file is empty and get the size of the\n>>> file. By using stat we can get the file size without actually having to\n>>> open the file to check for its contents.\n>>\n>> The sole caller of this function in patch 4/4 does so only to check if\n>> the file exists; it doesn't even care about the file's size, thus\n>> neither this function nor this patch seem justified and probably ought\n>> to be dropped unless some better and stronger justification can be\n>> shown.\n>\n> Umm, actually there is a subtle difference between file_exists() and\n> file_size(). file_exists() *only* checks whether the file exists or\n> not while file_size() can also be used to check whether the file is\n> empty or not also see the implementation of both of them which shows\n> the difference. In fact it doesn't care at all about the file size.\n> Now there are a lot of instances in shell scripts where there are\n> quite some differences with -f and -s and some places *do care* about\n> this subtle difference. For eg. in bisect_reset() we test whether the\n> file .git/BISECT_START has some contents in it. But I guess I can add\n> some more justification in the commit message. What do you think?\n\nSee my review of patch 4/4 which points out that C bisect_reset() does\n*not* presently care about the file size, which is probably a bug\nsince that doesn't match the behavior of the shell code it's replacing\n(which does care that the file is not empty).\n\nI think this would be clearer if you instead added a function to\nbisect--helper.c which operates at a semantically higher level than\nwhat you have here (and drop this file_size() function). Specifically,\nadd a function which tells you precisely what you want to know:\nwhether the file exists and has non-zero size. For instance, in\nbisect--helper.c:\n\n    static int file_empty_or_missing(const char *path)\n    {\n        struct stat st;\n        return stat(...) < 0 || st.st_size == 0;\n    }\n\nOr, if you have more cases where you want to know that it exists with\nnon-zero size, then name it file_non_empty() and reverse the sense of\nthe return value.\n"},{"id":"288691","messageId":"5757D49A.304@web.de","threadId":"42559","inReplyTo":"CAFZEwPPWMdOahMP4f0=Lm_n+ZmEtGHg=zHaZAyQjSf9oL8X2ew@mail.gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2016-06-08T08:17:30Z","receivedAt":"2016-06-08T08:17:30Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 06/08/2016 09:57 AM, Pranit Bauva wrote:\n> Hey Eric,\n>\n> On Wed, Jun 8, 2016 at 1:07 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> dir: introduce file_size() to check the size of file\n>>>\n>>> At times we require to see if the file is empty and get the size of the\n>>> file. By using stat we can get the file size without actually having to\n>>> open the file to check for its contents.\n>> The sole caller of this function in patch 4/4 does so only to check if\n>> the file exists; it doesn't even care about the file's size, thus\n>> neither this function nor this patch seem justified and probably ought\n>> to be dropped unless some better and stronger justification can be\n>> shown.\n> Umm, actually there is a subtle difference between file_exists() and\n> file_size(). file_exists() *only* checks whether the file exists or\n> not while file_size() can also be used to check whether the file is\n> empty or not also see the implementation of both of them which shows\n> the difference. In fact it doesn't care at all about the file size.\n> Now there are a lot of instances in shell scripts where there are\n> quite some differences with -f and -s and some places *do care* about\n> this subtle difference. For eg. in bisect_reset() we test whether the\n> file .git/BISECT_START has some contents in it. But I guess I can add\n> some more justification in the commit message. What do you think?\n>\n>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>> ---\n>>> diff --git a/dir.c b/dir.c\n>>> @@ -2036,6 +2036,14 @@ int file_exists(const char *f)\n>>> +ssize_t file_size(const char *filename)\n>>> +{\n>>> +       struct stat st;\n>>> +       if (stat(filename, &st) < 0)\n>>> +               return -1;\n>>> +       return xsize_t(st.st_size);\n>>> +}\n>>> +\n>>> diff --git a/dir.h b/dir.h\n>>> @@ -248,6 +248,13 @@ extern void clear_exclude_list(struct exclude_list *el);\n>>> +/*\n>>> + * Return the size of the file `filename`. It returns -1 if error\n>>> + * occurred, 0 if file is empty and a positive number denoting the size\n>>> + * of the file.\n>>> + */\n>>> +extern ssize_t file_size(const char *);\n>\nSo what I understand, you want something like this:\n\n+ssize_t file_size_not_zero(const char *filename)\n+{\n+       struct stat st;\n+       if (stat(filename, &st) < 0)\n+               return -1;\n+       return !!st.st_size);\n+}\n"},{"id":"288690","messageId":"CAPig+cSVmA0xbs8AFzeOno15=-rsjd_bGGBt_h9ujRp2g+-d0A@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPMpa1BHTP5BEqBHpYiab9G32tVXvLTZ95xhVeOcObCCBg@mail.gmail.com","subject":"Re: [PATCH 2/4] t6030: explicitly test for bisection cleanup","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T08:17:38Z","receivedAt":"2016-06-08T08:17:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 4:07 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 4:51 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\n>>> @@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n>>> +test_expect_success 'git bisect reset cleans bisection state properly' '\n>>> +       git bisect reset &&\n>>> +       git bisect start &&\n>>> +       git bisect good $HASH1 &&\n>>> +       git bisect bad $HASH4 &&\n>>> +       git bisect reset &&\n>>> +       test -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n>>\n>> I wonder if this would be more easily read as:\n>>\n>>     git for-each-ref \"refs/bisect/*\" >actual &&\n>>     test_must_be_empty actual &&\n>\n> I just tried to imitate what the test t6030 previously had (a lot of\n> occurrences). Should I still change it to your specified format?\n> Should I also change the others as a side cleanup \"while I am at it\"?\n\nNo, if the 'test -z \"$(...)\"' is already used heavily in that script,\njust stick with it. As for a side cleanup, perhaps if you have time\nlater on, but don't let it derail your project timeline. It's not that\nimportant.\n"},{"id":"288697","messageId":"CAP8UFD0Q7WnKpoY76w5Lqr4P6fCo4KboiwfrZ-L+q+h5Lhysjw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTiqRAnhBx6eCifdOmES1uD3piPYgsRHNMVFCO07W1nTg@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-08T09:41:15Z","receivedAt":"2016-06-08T09:41:15Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jun 8, 2016 at 10:02 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 8, 2016 at 3:46 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> On Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> +       struct string_list *refs = cb_data;\n>>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>>\n>>> Here you're allocating a string...\n>>>\n>>>> +       string_list_append(refs, ref);\n>>>> +       return 0;\n>>>> +}\n>>>> +\n>>>> +int bisect_clean_state(void)\n>>>> +{\n>>>> +       int result = 0;\n>>>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>>>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>>>\n>>> ...and the allocated string gets inserted into a string_list which\n>>> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n>>> leaking the string you created with xstrfmt(), isn't it?\n>>\n>> Yes nice catch. I would prefer using the string_list with\n>> STRING_LIST_INIT_DUP and free the ref.\n>\n> That's unnecessarily wasteful. Better would be to to use STRING_LIST_INIT_NODUP.\n\nIn this case it is not possible to append \"BISECT_HEAD\" to\n'refs_for_removal' before calling delete_refs() like this:\n\n+       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *)\n&refs_for_removal);\n+       string_list_append(&refs_for_removal, \"BISECT_HEAD\");\n+       result = delete_refs(&refs_for_removal);\n+       string_list_clear(&refs_for_removal, 0);\n\nAnd I think it's better to delete all the refs in the same call to\ndelete_refs().\n"},{"id":"288699","messageId":"CAP8UFD2nfcMu7Gmh=asyu+WZh5X2UjhyYSC2Sbp-qsQVjEULcw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cSsMg5HznWGiUsngpHskSDMNhauvVw5jvaJTtEtJBw+ew@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-08T09:51:30Z","receivedAt":"2016-06-08T09:51:30Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jun 8, 2016 at 9:59 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n>> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n>>\n>> Using `bisect_reset` subcommand is a temporary measure to port shell\n>> functions to C so as to use the existing test suite. As more functions\n>> are ported, this subcommand would be retired and will be called by some\n>> other method.\n>>\n>> Note: --bisect-clean-state subcommand has not been retired as there are\n>> still a function namely `bisect_start()` which still uses this\n>> subcommand.\n>>\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -118,12 +122,51 @@ int bisect_clean_state(void)\n>> +int bisect_reset(const char *commit)\n>\n> s/^/static/\n>\n>> +{\n>> +       struct strbuf branch = STRBUF_INIT;\n>> +       int status = 0;\n>> +\n>> +       if (file_size(git_path_bisect_start()) < 1) {\n>\n> This doesn't even care about the size of the file, only if it\n> encountered an error while stat()'ing it. Why not just use\n> file_exists() instead (which you already use elsewhere in this\n> function)? Alternately, if you're trying to be faithful to the shell\n> code, then you *do* need to check that the file has non-zero size\n> before issuing the \"not bisecting\" diagnostic, so:\n>\n>     if ()\n>         printf(\"... not bisecting ...\");\n\nAs file_size() returns an integer, there is no difference between\n\"file_size(git_path_bisect_start()) <= 0\" and\n\"file_size(git_path_bisect_start()) < 1\".\nOr am I missing something?\n"},{"id":"288698","messageId":"CAP8UFD21gzXm3_yCHezA04zo+XFpF9TaGcMUm7y4FVK8RtekaQ@mail.gmail.com","threadId":"42559","inReplyTo":"CAP8UFD2nfcMu7Gmh=asyu+WZh5X2UjhyYSC2Sbp-qsQVjEULcw@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-08T09:53:04Z","receivedAt":"2016-06-08T09:53:04Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jun 8, 2016 at 11:51 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 9:59 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n>>> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n>>>\n>>> Using `bisect_reset` subcommand is a temporary measure to port shell\n>>> functions to C so as to use the existing test suite. As more functions\n>>> are ported, this subcommand would be retired and will be called by some\n>>> other method.\n>>>\n>>> Note: --bisect-clean-state subcommand has not been retired as there are\n>>> still a function namely `bisect_start()` which still uses this\n>>> subcommand.\n>>>\n>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>> ---\n>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>> @@ -118,12 +122,51 @@ int bisect_clean_state(void)\n>>> +int bisect_reset(const char *commit)\n>>\n>> s/^/static/\n>>\n>>> +{\n>>> +       struct strbuf branch = STRBUF_INIT;\n>>> +       int status = 0;\n>>> +\n>>> +       if (file_size(git_path_bisect_start()) < 1) {\n>>\n>> This doesn't even care about the size of the file, only if it\n>> encountered an error while stat()'ing it. Why not just use\n>> file_exists() instead (which you already use elsewhere in this\n>> function)? Alternately, if you're trying to be faithful to the shell\n>> code, then you *do* need to check that the file has non-zero size\n>> before issuing the \"not bisecting\" diagnostic, so:\n>>\n>>     if ()\n\nOoops this was:\n\n>>     if (file_size(git_path_bisect_start()) <= 0)\n\nbut I made a copy paste mistake, sorry.\n\n>>         printf(\"... not bisecting ...\");\n>\n> As file_size() returns an integer, there is no difference between\n> \"file_size(git_path_bisect_start()) <= 0\" and\n> \"file_size(git_path_bisect_start()) < 1\".\n> Or am I missing something?\n"},{"id":"288701","messageId":"CAP8UFD0PBDnn0MV0+vUJkS-Smazi6x0cfq4EJot8fDpG4RqH1g@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cR8+ekOv3xuj1Nn9ftA5smHG78wdFp1Xnfz_qyrstKRqw@mail.gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-08T10:03:26Z","receivedAt":"2016-06-08T10:03:26Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jun 8, 2016 at 10:13 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>\n> I think this would be clearer if you instead added a function to\n> bisect--helper.c which operates at a semantically higher level than\n> what you have here (and drop this file_size() function). Specifically,\n> add a function which tells you precisely what you want to know:\n> whether the file exists and has non-zero size. For instance, in\n> bisect--helper.c:\n>\n>     static int file_empty_or_missing(const char *path)\n>     {\n>         struct stat st;\n>         return stat(...) < 0 || st.st_size == 0;\n>     }\n>\n> Or, if you have more cases where you want to know that it exists with\n> non-zero size, then name it file_non_empty() and reverse the sense of\n> the return value.\n\nAfter a quick grep it seemed to me that there are a few places were we\nstat a file just to get its size, so I suggested the file_size()\nbecause it could help refactor other parts of the code.\n"},{"id":"288702","messageId":"CAFZEwPM7ir+HnsG_L8M0PauSSxBJe8HvAmVYHthXEKAxmpA26Q@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cSVmA0xbs8AFzeOno15=-rsjd_bGGBt_h9ujRp2g+-d0A@mail.gmail.com","subject":"Re: [PATCH 2/4] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T10:20:16Z","receivedAt":"2016-06-08T10:20:16Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 1:47 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 8, 2016 at 4:07 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> On Wed, Jun 8, 2016 at 4:51 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\n>>>> @@ -894,4 +894,21 @@ test_expect_success 'bisect start takes options and revs in any order' '\n>>>> +test_expect_success 'git bisect reset cleans bisection state properly' '\n>>>> +       git bisect reset &&\n>>>> +       git bisect start &&\n>>>> +       git bisect good $HASH1 &&\n>>>> +       git bisect bad $HASH4 &&\n>>>> +       git bisect reset &&\n>>>> +       test -z \"$(git for-each-ref \"refs/bisect/*\")\" &&\n>>>\n>>> I wonder if this would be more easily read as:\n>>>\n>>>     git for-each-ref \"refs/bisect/*\" >actual &&\n>>>     test_must_be_empty actual &&\n>>\n>> I just tried to imitate what the test t6030 previously had (a lot of\n>> occurrences). Should I still change it to your specified format?\n>> Should I also change the others as a side cleanup \"while I am at it\"?\n>\n> No, if the 'test -z \"$(...)\"' is already used heavily in that script,\n> just stick with it. As for a side cleanup, perhaps if you have time\n> later on, but don't let it derail your project timeline. It's not that\n> important.\n\nSure! I can mark it as \"to be cleaned up after GSoC\"\n\nRegards,\nPranit Bauva\n"},{"id":"288715","messageId":"CAFZEwPMiyHqFa0+Z1EAfwG4APcCjJ+1qBeSHjyuOhc6QMb3hLA@mail.gmail.com","threadId":"42559","inReplyTo":"5757D49A.304@web.de","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T13:08:00Z","receivedAt":"2016-06-08T13:08:00Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Torsten,\n\nOn Wed, Jun 8, 2016 at 1:47 PM, Torsten Bögershausen <tboegi@web.de> wrote:\n> On 06/08/2016 09:57 AM, Pranit Bauva wrote:\n>>\n>> Hey Eric,\n>>\n>> On Wed, Jun 8, 2016 at 1:07 PM, Eric Sunshine <sunshine@sunshineco.com>\n>> wrote:\n>>>\n>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com>\n>>> wrote:\n>>>>\n>>>> dir: introduce file_size() to check the size of file\n>>>>\n>>>> At times we require to see if the file is empty and get the size of the\n>>>> file. By using stat we can get the file size without actually having to\n>>>> open the file to check for its contents.\n>>>\n>>> The sole caller of this function in patch 4/4 does so only to check if\n>>> the file exists; it doesn't even care about the file's size, thus\n>>> neither this function nor this patch seem justified and probably ought\n>>> to be dropped unless some better and stronger justification can be\n>>> shown.\n>>\n>> Umm, actually there is a subtle difference between file_exists() and\n>> file_size(). file_exists() *only* checks whether the file exists or\n>> not while file_size() can also be used to check whether the file is\n>> empty or not also see the implementation of both of them which shows\n>> the difference. In fact it doesn't care at all about the file size.\n>> Now there are a lot of instances in shell scripts where there are\n>> quite some differences with -f and -s and some places *do care* about\n>> this subtle difference. For eg. in bisect_reset() we test whether the\n>> file .git/BISECT_START has some contents in it. But I guess I can add\n>> some more justification in the commit message. What do you think?\n>>\n>>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>>> ---\n>>>> diff --git a/dir.c b/dir.c\n>>>> @@ -2036,6 +2036,14 @@ int file_exists(const char *f)\n>>>> +ssize_t file_size(const char *filename)\n>>>> +{\n>>>> +       struct stat st;\n>>>> +       if (stat(filename, &st) < 0)\n>>>> +               return -1;\n>>>> +       return xsize_t(st.st_size);\n>>>> +}\n>>>> +\n>>>> diff --git a/dir.h b/dir.h\n>>>> @@ -248,6 +248,13 @@ extern void clear_exclude_list(struct exclude_list\n>>>> *el);\n>>>> +/*\n>>>> + * Return the size of the file `filename`. It returns -1 if error\n>>>> + * occurred, 0 if file is empty and a positive number denoting the size\n>>>> + * of the file.\n>>>> + */\n>>>> +extern ssize_t file_size(const char *);\n>>\n>>\n> So what I understand, you want something like this:\n>\n> +ssize_t file_size_not_zero(const char *filename)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st) < 0)\n> +               return -1;\n> +       return !!st.st_size);\n> +}\n\nFor the purpose of bisect_reset(), Yes. BTW a similar function exist\nin builtin/am.c with the name is_empty_file(). But as Christian points\nout file_size() could help to refactor other parts of code.\n\nRegards,\nPranit Bauva\n"},{"id":"288718","messageId":"CAFZEwPPC3WZR4dMphgZWK7UomAXEok-J8ZXvFR22+xDrFP=hEg@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cSsMg5HznWGiUsngpHskSDMNhauvVw5jvaJTtEtJBw+ew@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T13:20:52Z","receivedAt":"2016-06-08T13:20:52Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 1:29 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n>> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n>>\n>> Using `bisect_reset` subcommand is a temporary measure to port shell\n>> functions to C so as to use the existing test suite. As more functions\n>> are ported, this subcommand would be retired and will be called by some\n>> other method.\n>>\n>> Note: --bisect-clean-state subcommand has not been retired as there are\n>> still a function namely `bisect_start()` which still uses this\n>> subcommand.\n>>\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -118,12 +122,51 @@ int bisect_clean_state(void)\n>> +int bisect_reset(const char *commit)\n>\n> s/^/static/\n>\n>> +{\n>> +       struct strbuf branch = STRBUF_INIT;\n>> +       int status = 0;\n>> +\n>> +       if (file_size(git_path_bisect_start()) < 1) {\n>\n> This doesn't even care about the size of the file, only if it\n> encountered an error while stat()'ing it. Why not just use\n> file_exists() instead (which you already use elsewhere in this\n> function)? Alternately, if you're trying to be faithful to the shell\n> code, then you *do* need to check that the file has non-zero size\n> before issuing the \"not bisecting\" diagnostic, so:\n>\n>     if (file_size(git_path_bisect_start()) <= 0)\n>         printf(\"... not bisecting ...\");\n\nUmm, I think that for all x belonging to integers,\n            x <= 0    <=>      x < 1\n\n> A different approach would be to invoke strbuf_read_file()\n> unconditionally, rather than performing this separate check. If\n> strbuf_read_file() returns -1, then the file didn't exist or couldn't\n> be read; if it returns 0, then the file has no content:\n\nstrbuf_read_file() opens the file and then reads its contents. Well\nthis much of computation isn't really required. By using stat we can\nget the file size without actually reading the file. Are there any\nbenefits which I have missed of using strbuf_read_file() over stat() ?\n\n>     if (strbuf_read_file(&branch, ..., 0) <= 0)\n>         printf(\"... not bisecting ...\");\n>\n>> +               printf(\"We are not bisecting.\\n\");\n>> +               return 0;\n>> +       }\n>> +\n>> +       if (!commit) {\n>> +               strbuf_read_file(&branch, git_path_bisect_start(), 0);\n>\n> Shouldn't you be checking the return value of strbuf_read_file()?\n\nThe shell script didn't report any error but I guess this doesn't have\nto continue. Its probably better to add error handling code while\nrewriting.\n\n>> +               strbuf_rtrim(&branch);\n>> +       } else {\n>> +               struct object_id oid;\n>> +               if (get_oid(commit, &oid))\n>> +                       return error(_(\"'%s' is not a valid commit\"), commit);\n>> +               strbuf_addf(&branch, \"%s\", commit);\n>> +       }\n>> +\n>> +       if (!file_exists(git_path_bisect_head())) {\n>> +               struct argv_array argv = ARGV_ARRAY_INIT;\n>> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n>> +               status = run_command_v_opt(argv.argv, RUN_GIT_CMD);\n>> +               argv_array_clear(&argv);\n>> +       }\n>> +\n>> +       if (status) {\n>\n> What's the purpose of having this 'status' conditional outside of the\n> above !file_exists() conditional, which is the only place that\n> 'status' gets assigned. Likewise, 'status' itself could be declared\n> within the scope of that conditional block.\n\nI wanted to avoid nesting. In a few other parts of the code also,\nnesting is avoided as much as possible.\n\n>> +               error(_(\"Could not check out original HEAD '%s'. \"\n>> +                               \"Try 'git bisect reset <commit>'.\"), branch.buf);\n>> +               strbuf_release(&branch);\n>> +               return -1;\n>> +       }\n>> +\n>> +       strbuf_release(&branch);\n>> +       return bisect_clean_state();\n>> +}\n\nRegards,\nPranit Bauva\n"},{"id":"288740","messageId":"CAPig+cSWJjS6X=Bmet0bWQmWV9kQJS9_qGMM7hu+Rj+7_Ctf=w@mail.gmail.com","threadId":"42559","inReplyTo":"CAP8UFD2nfcMu7Gmh=asyu+WZh5X2UjhyYSC2Sbp-qsQVjEULcw@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T17:50:33Z","receivedAt":"2016-06-08T17:50:33Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 5:51 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 9:59 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> +       if (file_size(git_path_bisect_start()) < 1) {\n>>\n>> This doesn't even care about the size of the file, only if it\n>> encountered an error while stat()'ing it. Why not just use\n>> file_exists() instead (which you already use elsewhere in this\n>> function)? Alternately, if you're trying to be faithful to the shell\n>> code, then you *do* need to check that the file has non-zero size\n>> before issuing the \"not bisecting\" diagnostic, so:\n>>\n>>     if ()\n>>         printf(\"... not bisecting ...\");\n>\n> As file_size() returns an integer, there is no difference between\n> \"file_size(git_path_bisect_start()) <= 0\" and\n> \"file_size(git_path_bisect_start()) < 1\".\n> Or am I missing something?\n\nNo, you're right. I misread the code as:\n\n    file_size(...) < 0\n\nrather than what it really says:\n\n    file_size(...) < 1\n\nSorry for the noise.\n\nThat it was so easy to misread the code, however, may be a good\nargument for making a more special-purpose function, such as\nfile_empty_or_missing() (or file_not_empty()) as suggested in the\npatch 3/4 thread.\n"},{"id":"288744","messageId":"CAPig+cQpBcy+Sdhv7EXorJFZsYvH=ikh0PqGF1YShQEcPjMn_Q@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPPC3WZR4dMphgZWK7UomAXEok-J8ZXvFR22+xDrFP=hEg@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T17:53:11Z","receivedAt":"2016-06-08T17:53:11Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 9:20 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 1:29 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> +       if (!file_exists(git_path_bisect_head())) {\n>>> +               struct argv_array argv = ARGV_ARRAY_INIT;\n>>> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n>>> +               status = run_command_v_opt(argv.argv, RUN_GIT_CMD);\n>>> +               argv_array_clear(&argv);\n>>> +       }\n>>> +\n>>> +       if (status) {\n>>\n>> What's the purpose of having this 'status' conditional outside of the\n>> above !file_exists() conditional, which is the only place that\n>> 'status' gets assigned. Likewise, 'status' itself could be declared\n>> within the scope of that conditional block.\n>\n> I wanted to avoid nesting. In a few other parts of the code also,\n> nesting is avoided as much as possible.\n\nI figured as much, but I'm not sure that that is such a good idea in\nthis case since it makes the code more difficult to reason about. To\nwit: as a reader of the code, I spent extra time trying to figure why\nit was structured this way and if 'status' is assigned or accessed in\nsome other non-obvious way.\n"},{"id":"288742","messageId":"CAPig+cQ5z+-59BCjPXNaSQWkSyTt56yAnRo49Lba6_wjkWRp-w@mail.gmail.com","threadId":"42559","inReplyTo":"CAP8UFD0Q7WnKpoY76w5Lqr4P6fCo4KboiwfrZ-L+q+h5Lhysjw@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-08T17:59:09Z","receivedAt":"2016-06-08T17:59:09Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 8, 2016 at 5:41 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Wed, Jun 8, 2016 at 10:02 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Wed, Jun 8, 2016 at 3:46 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> On Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>>> +       struct string_list *refs = cb_data;\n>>>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>>>\n>>>> Here you're allocating a string...\n>>>>\n>>>>> +       string_list_append(refs, ref);\n>>>>> +       return 0;\n>>>>> +}\n>>>>> +\n>>>>> +int bisect_clean_state(void)\n>>>>> +{\n>>>>> +       int result = 0;\n>>>>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>>>>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>>>>\n>>>> ...and the allocated string gets inserted into a string_list which\n>>>> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n>>>> leaking the string you created with xstrfmt(), isn't it?\n>>>\n>>> Yes nice catch. I would prefer using the string_list with\n>>> STRING_LIST_INIT_DUP and free the ref.\n>>\n>> That's unnecessarily wasteful. Better would be to to use STRING_LIST_INIT_NODUP.\n>\n> In this case it is not possible to append \"BISECT_HEAD\" to\n> 'refs_for_removal' before calling delete_refs() like this:\n>\n> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *)\n> &refs_for_removal);\n> +       string_list_append(&refs_for_removal, \"BISECT_HEAD\");\n> +       result = delete_refs(&refs_for_removal);\n> +       string_list_clear(&refs_for_removal, 0);\n>\n> And I think it's better to delete all the refs in the same call to\n> delete_refs().\n\nstring_list_append(&..., xstrdup(\"BISECT_HEAD\"));\n\nperhaps?\n"},{"id":"288745","messageId":"CAFZEwPMs+O7r8HKZ0bVxPtT2kNWmmJi0wruR1au_C527M+Ne-g@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cQpBcy+Sdhv7EXorJFZsYvH=ikh0PqGF1YShQEcPjMn_Q@mail.gmail.com","subject":"Re: [PATCH 4/4] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T18:04:06Z","receivedAt":"2016-06-08T18:04:06Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 11:23 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 8, 2016 at 9:20 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> On Wed, Jun 8, 2016 at 1:29 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> +       if (!file_exists(git_path_bisect_head())) {\n>>>> +               struct argv_array argv = ARGV_ARRAY_INIT;\n>>>> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n>>>> +               status = run_command_v_opt(argv.argv, RUN_GIT_CMD);\n>>>> +               argv_array_clear(&argv);\n>>>> +       }\n>>>> +\n>>>> +       if (status) {\n>>>\n>>> What's the purpose of having this 'status' conditional outside of the\n>>> above !file_exists() conditional, which is the only place that\n>>> 'status' gets assigned. Likewise, 'status' itself could be declared\n>>> within the scope of that conditional block.\n>>\n>> I wanted to avoid nesting. In a few other parts of the code also,\n>> nesting is avoided as much as possible.\n>\n> I figured as much, but I'm not sure that that is such a good idea in\n> this case since it makes the code more difficult to reason about. To\n> wit: as a reader of the code, I spent extra time trying to figure why\n> it was structured this way and if 'status' is assigned or accessed in\n> some other non-obvious way.\n\nI can put status inside the if() .\n\nRegards,\nPranit Bauva\n"},{"id":"288743","messageId":"CAFZEwPO+E7zzPoBnEbfZtW1RfXWzTbzAGzE_WXW8BNfhTb+urw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cQ5z+-59BCjPXNaSQWkSyTt56yAnRo49Lba6_wjkWRp-w@mail.gmail.com","subject":"Re: [PATCH 1/4] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-08T18:04:58Z","receivedAt":"2016-06-08T18:04:58Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 8, 2016 at 11:29 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 8, 2016 at 5:41 AM, Christian Couder\n> <christian.couder@gmail.com> wrote:\n>> On Wed, Jun 8, 2016 at 10:02 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Wed, Jun 8, 2016 at 3:46 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> On Wed, Jun 8, 2016 at 4:01 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>>>> On Tue, Jun 7, 2016 at 4:54 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>>>> +       struct string_list *refs = cb_data;\n>>>>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>>>>\n>>>>> Here you're allocating a string...\n>>>>>\n>>>>>> +       string_list_append(refs, ref);\n>>>>>> +       return 0;\n>>>>>> +}\n>>>>>> +\n>>>>>> +int bisect_clean_state(void)\n>>>>>> +{\n>>>>>> +       int result = 0;\n>>>>>> +       struct string_list refs_for_removal = STRING_LIST_INIT_DUP;\n>>>>>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *) &refs_for_removal);\n>>>>>\n>>>>> ...and the allocated string gets inserted into a string_list which\n>>>>> itself duplicates the string (STRING_LIST_INIT_DUP), so this is\n>>>>> leaking the string you created with xstrfmt(), isn't it?\n>>>>\n>>>> Yes nice catch. I would prefer using the string_list with\n>>>> STRING_LIST_INIT_DUP and free the ref.\n>>>\n>>> That's unnecessarily wasteful. Better would be to to use STRING_LIST_INIT_NODUP.\n>>\n>> In this case it is not possible to append \"BISECT_HEAD\" to\n>> 'refs_for_removal' before calling delete_refs() like this:\n>>\n>> +       for_each_ref_in(\"refs/bisect/\", mark_for_removal, (void *)\n>> &refs_for_removal);\n>> +       string_list_append(&refs_for_removal, \"BISECT_HEAD\");\n>> +       result = delete_refs(&refs_for_removal);\n>> +       string_list_clear(&refs_for_removal, 0);\n>>\n>> And I think it's better to delete all the refs in the same call to\n>> delete_refs().\n>\n> string_list_append(&..., xstrdup(\"BISECT_HEAD\"));\n>\n> perhaps?\n\nSeems reasonable!\n\nRegards,\nPranit Bauva\n"},{"id":"289026","messageId":"3db60187-4b44-85b2-f714-f836e3c3bc6e@web.de","threadId":"42559","inReplyTo":"CAFZEwPMiyHqFa0+Z1EAfwG4APcCjJ+1qBeSHjyuOhc6QMb3hLA@mail.gmail.com","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2016-06-12T10:44:38Z","receivedAt":"2016-06-16T02:19:52Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":">> So what I understand, you want something like this:\n>>\n>> +ssize_t file_size_not_zero(const char *filename)\n>> +{\n>> +       struct stat st;\n>> +       if (stat(filename, &st) < 0)\n>> +               return -1;\n>> +       return !!st.st_size);\n>> +}\n> \n> For the purpose of bisect_reset(), Yes. BTW a similar function exist\n> in builtin/am.c with the name is_empty_file(). But as Christian points\n> out file_size() could help to refactor other parts of code.\n> \n\nPlease allow one or more late comments:\nIf is_empty_file() does what you need, then it can be moved into wrapper.c\nand simply be re-used in your code.\n\nIf you want to introduce a new function, that can be used for other refactoring,\nthen the whole thing would ideally go into a single commit,\nor into a single series.\nThat may probably be out of the scope for your current efforts ?\n\nWhat really makes me concern is the mixture of signed - and unsigned:\nssize_t file_size(const char *filename)\n+{\n+       struct stat st;\n+       if (stat(filename, &st) < 0)\n+               return -1;\n+       return xsize_t(st.st_size);\n+}\n\nTo my understanding a file size is either 0, or a positive integer.\nReturning -1 is of course impossible with a positive integer.\n\nSo either the function is changed like this:\n\nint file_size(const char *filename, size_t *len)\n+{\n+       struct stat st;\n+       if (stat(filename, &st) < 0)\n+               return -1;\n+       *len = xsize_t(st.st_size);\n+       return 0;\n+}\n\nOr, if that works for you:\n\nsize_t file_size(const char *filename)\n+{\n+       struct stat st;\n+       if (stat(filename, &st) < 0)\n+               return 0;\n+       return xsize_t(st.st_size);\n+}\n\nOr, more git-ish:\n\nsize_t file_size(const char *filename)\n+{\n+       struct stat st;\n+       if (stat(filename, &st))\n+               return 0;\n+       return xsize_t(st.st_size);\n+}\n\n(And then builtin/am.c  can be changed to use the new function.\n\n \n"},{"id":"289080","messageId":"CAFZEwPMXptc33bdvrFXiY9OD4S0aXT0-rKo9W5QKkYmrV-pFag@mail.gmail.com","threadId":"42559","inReplyTo":"3db60187-4b44-85b2-f714-f836e3c3bc6e@web.de","subject":"Re: [PATCH 3/4] dir: introduce file_size() to check the size of file","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-13T06:21:44Z","receivedAt":"2016-06-16T02:19:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Torsten,\n\nOn Sun, Jun 12, 2016 at 4:14 PM, Torsten Bögershausen <tboegi@web.de> wrote:\n>>> So what I understand, you want something like this:\n>>>\n>>> +ssize_t file_size_not_zero(const char *filename)\n>>> +{\n>>> +       struct stat st;\n>>> +       if (stat(filename, &st) < 0)\n>>> +               return -1;\n>>> +       return !!st.st_size);\n>>> +}\n>>\n>> For the purpose of bisect_reset(), Yes. BTW a similar function exist\n>> in builtin/am.c with the name is_empty_file(). But as Christian points\n>> out file_size() could help to refactor other parts of code.\n>>\n>\n> Please allow one or more late comments:\n\nThat's perfectly fine.\n\n> If is_empty_file() does what you need, then it can be moved into wrapper.c\n> and simply be re-used in your code.\n\nThanks for informing. I was unaware about the use of wrapper.c\n\n> If you want to introduce a new function, that can be used for other refactoring,\n> then the whole thing would ideally go into a single commit,\n> or into a single series.\n> That may probably be out of the scope for your current efforts ?\n\nOn re-thinking, I think introducing file_size() is out of the scope\nfor the current efforts and I will stick to is_empty_file(). Will move\nit to wrapper.c and then use it in my code. I am not sure but I think\na few other parts could also use is_empty_file(). I will check on that\nprobably after GSoC as a cleanup.\n\n> What really makes me concern is the mixture of signed - and unsigned:\n> ssize_t file_size(const char *filename)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st) < 0)\n> +               return -1;\n> +       return xsize_t(st.st_size);\n> +}\n>\n> To my understanding a file size is either 0, or a positive integer.\n> Returning -1 is of course impossible with a positive integer.\n\nTrue.\n\n> So either the function is changed like this:\n>\n> int file_size(const char *filename, size_t *len)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st) < 0)\n> +               return -1;\n> +       *len = xsize_t(st.st_size);\n> +       return 0;\n> +}\n>\n> Or, if that works for you:\n>\n> size_t file_size(const char *filename)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st) < 0)\n> +               return 0;\n> +       return xsize_t(st.st_size);\n> +}\n>\n> Or, more git-ish:\n>\n> size_t file_size(const char *filename)\n> +{\n> +       struct stat st;\n> +       if (stat(filename, &st))\n> +               return 0;\n> +       return xsize_t(st.st_size);\n> +}\n>\n> (And then builtin/am.c  can be changed to use the new function.\n\nI think I will just skip file_size() for now.\n\nThanks for your comments!\n\nRegards,\nPranit Bauva\n"},{"id":"289293","messageId":"20160615140026.10519-1-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"[PATCH v2 0/6] convert various shell functions in git-bisect to C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:20Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"A previous version is available here[1].\n\nChanges wrt previous version:\n * Use STRING_LIST_INIT_NODUP to avoid leaks in bisect_clean_state()\n * Use test_path_is_missing in the patch 2/6\n * drop file_size()\n * move is_empty_file() method from builtin/am.c to wrapper.c\n * use static for methods\n * remove the variable status in bisect_reset() altogether and put the whole\n   thing inside the if block.\n * one more method converted namely bisect_write().\n\nAn important thing to be discussed:\nIn shell script while reading/writing files, no error is reported but we can\nactually report it in C. In this series I have tried to output error wherever\npossible. What are your views?\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/296717\n\nPranit Bauva (6):\n  bisect--helper: `bisect_clean_state` shell function in C\n  t6030: explicitly test for bisection cleanup\n  wrapper: move is_empty_file() from builtin/am.c\n  bisect--helper: `bisect_reset` shell function in C\n  bisect--helper: `is_expected_rev` & `check_expected_revs` shell\n    function in C\n  bisect--helper: `bisect_write` shell function in C\n\n builtin/am.c                |  16 ----\n builtin/bisect--helper.c    | 194 +++++++++++++++++++++++++++++++++++++++++++-\n cache.h                     |   3 +\n git-bisect.sh               |  97 +++-------------------\n t/t6030-bisect-porcelain.sh |  17 ++++\n wrapper.c                   |  13 +++\n 6 files changed, 236 insertions(+), 104 deletions(-)\n\n-- \n2.9.0\n"},{"id":"289294","messageId":"20160615140026.10519-2-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:21Z","receivedAt":"2016-06-16T06:55:53Z","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 and will be called by\nbisect_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 builtin/bisect--helper.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 26 +++--------------------\n 2 files changed, 56 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 91027b0..3e4a458 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,12 +3,21 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_write_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_names, \"BISECT_NAMES\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -78,11 +87,48 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\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+static 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);\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tremove_path(git_path_bisect_expected_rev());\n+\tremove_path(git_path_bisect_ancestors_ok());\n+\tremove_path(git_path_bisect_log());\n+\tremove_path(git_path_bisect_names());\n+\tremove_path(git_path_bisect_run());\n+\tremove_path(git_path_bisect_write_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tremove_path(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+\tremove_path(git_path_bisect_start());\n+\n+\treturn result;\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\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -90,6 +136,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@@ -108,6 +156,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 cd39bd0..bbc57d2 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -187,7 +187,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@@ -196,7 +196,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-- \n2.9.0\n"},{"id":"289295","messageId":"20160615140026.10519-3-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 2/6] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:22Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"This is not an improvement in the test coverage but it helps in making\nit explicit as to what exactly would be the error as other tests are\nfocussed on testing other things.\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\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\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 e74662b..a17f7a6 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-- \n2.9.0\n"},{"id":"289296","messageId":"20160615140026.10519-4-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 3/6] wrapper: move is_empty_file() from builtin/am.c","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:23Z","receivedAt":"2016-06-16T06:55:53Z","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. Also it is quite\nhelpful while converting shell scripts which use `test -s`. Since\nis_empty_file() is now a \"library\" function, its inappropriate to die() so\ninstead error_errno() is used to convey the message to stderr while the\nappropriate boolean value is returned.\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 | 16 ----------------\n cache.h      |  3 +++\n wrapper.c    | 13 +++++++++++++\n 3 files changed, 16 insertions(+), 16 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 3dfe70b..84f21d0 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)\ndiff --git a/cache.h b/cache.h\nindex 6049f86..8eaad70 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1870,4 +1870,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_file(const char *filename);\n+\n #endif /* CACHE_H */\ndiff --git a/wrapper.c b/wrapper.c\nindex 5dc4e15..36a3eeb 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -696,3 +696,16 @@ void sleep_millisec(int millisec)\n {\n \tpoll(NULL, 0, millisec);\n }\n+\n+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\terror_errno(_(\"could not stat %s\"), filename);\n+\t}\n+\n+\treturn !st.st_size;\n+}\n-- \n2.9.0\n"},{"id":"289297","messageId":"20160615140026.10519-6-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:25Z","receivedAt":"2016-06-16T06:55:53Z","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 and will be\ncalled 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 | 37 ++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 20 ++------------------\n 2 files changed, 38 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 14043a8..f11c247 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -162,13 +162,44 @@ 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;\n+\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n+\t\tstrbuf_release(&actual_hex);\n+\t\treturn 0;\n+\t}\n+\n+\tstrbuf_trim(&actual_hex);\n+\tres = !strcmp(actual_hex.buf, expected_hex);\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\tremove_path(git_path_bisect_ancestors_ok());\n+\t\t\tremove_path(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@@ -180,6 +211,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@@ -206,6 +239,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 18580b7..4f6545e 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -238,22 +238,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 $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n"},{"id":"289298","messageId":"20160615140026.10519-5-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 4/6] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:24Z","receivedAt":"2016-06-16T06:55:53Z","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 and will be called by some\nother 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 3e4a458..14043a8 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,6 +4,8 @@\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_write_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -13,11 +15,13 @@ static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -123,12 +127,48 @@ static int bisect_clean_state(void)\n \treturn result;\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+\n+\t} else {\n+\t\tstruct object_id oid;\n+\t\tif (get_oid(commit, &oid))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addf(&branch, \"%s\", 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\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@@ -138,6 +178,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@@ -160,6 +202,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 bbc57d2..18580b7 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-- \n2.9.0\n"},{"id":"289299","messageId":"20160615140026.10519-7-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"[PATCH v2 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T14:00:26Z","receivedAt":"2016-06-16T06:55:53Z","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 and will be called by some\nother 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. After the whole conversion, we can remove the extra\narguments and make the method use the two variables from the global scope\nwithin the C code.\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 | 61 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 25 ++++----------------\n 2 files changed, 64 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex f11c247..eebfcf0 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -22,6 +22,7 @@ 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@@ -192,6 +193,55 @@ 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 char *term_good, const char *term_bad,\n+\t\t\tint nolog)\n+{\n+\tstruct strbuf tag = STRBUF_INIT;\n+\tstruct strbuf commit_name = STRBUF_INIT;\n+\tstruct object_id oid;\n+\tstruct commit *commit;\n+\tstruct pretty_print_context pp = {0};\n+\tFILE *fp;\n+\n+\tif (!strcmp(state, term_bad))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\telse if(one_of(state, term_good, \"skip\", NULL))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\telse\n+\t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn -1;\n+\t}\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\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+\tstrbuf_release(&commit_name);\n+\tstrbuf_release(&tag);\n+\tfclose(fp);\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -199,7 +249,8 @@ 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 \tstruct option options[] = {\n@@ -213,6 +264,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"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@@ -225,6 +278,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n \tswitch (cmdmode) {\n+\tint nolog;\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n@@ -241,6 +295,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\treturn bisect_reset(argc ? argv[0] : NULL);\n \tcase CHECK_EXPECTED_REVS:\n \t\treturn check_expected_revs(argv, argc);\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\treturn bisect_write(argv[0], argv[1], argv[2], argv[3], nolog);\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 4f6545e..b9896a4 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -145,7 +145,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@@ -221,23 +221,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 \t1,\"$TERM_BAD\"|1,\"$TERM_GOOD\"|1,skip)\n \t\trev=$(git rev-parse --verify $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n"},{"id":"289301","messageId":"CAPig+cTV8Mum1b7XxUit4Kn5WBX2kukWvvjkhOCqxnFtcjfp0w@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-1-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 0/6] convert various shell functions in git-bisect to C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T17:53:33Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Changes wrt previous version:\n>  * Use STRING_LIST_INIT_NODUP to avoid leaks in bisect_clean_state()\n>  * Use test_path_is_missing in the patch 2/6\n>  * drop file_size()\n>  * move is_empty_file() method from builtin/am.c to wrapper.c\n>  * use static for methods\n>  * remove the variable status in bisect_reset() altogether and put the whole\n>    thing inside the if block.\n>  * one more method converted namely bisect_write().\n\nAs an aid to reviewers, in the future, please also include in the\ncover letter an interdiff between the previous and current version of\nthe patch series. Thanks.\n"},{"id":"289303","messageId":"CAPig+cRfYS4FX+z4Yn-He_LctWdh7Ua56JU2HJs2C2+nTi5YyA@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-2-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T18:04:12Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `bisect_clean_state` shell function in C and add a\n> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh .\n> [...]\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> +static int mark_for_removal(const char *refname, const struct object_id *oid,\n> +                           int flag, void *cb_data)\n> +{\n> +       struct string_list *refs = cb_data;\n> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n> +       string_list_append(refs, ref);\n> +       return 0;\n> +}\n> +\n> +static 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);\n> +       string_list_clear(&refs_for_removal, 0);\n\nThis is leaking all the strings added to 'refs_for_removal', isn't it?\nEither you need to loop over the items and free the strings manually,\nor (if it's not too ugly), set 'strdup_strings' before invoking\nstring_list_clear().\n\n> +       remove_path(git_path_bisect_expected_rev());\n> +       remove_path(git_path_bisect_ancestors_ok());\n> +       remove_path(git_path_bisect_log());\n> +       remove_path(git_path_bisect_names());\n> +       remove_path(git_path_bisect_run());\n> +       remove_path(git_path_bisect_write_terms());\n> +       /* Cleanup head-name if it got left by an old version of git-bisect */\n> +       remove_path(git_path_head_name());\n> +       /*\n> +        * Cleanup BISECT_START last to support the --no-checkout option\n> +        * introduced in the commit 4796e823a.\n> +        */\n> +       remove_path(git_path_bisect_start());\n> +\n> +       return result;\n> +}\n"},{"id":"289304","messageId":"CAFZEwPO3z6FPwigM3GUecp95wBHaMetvHStj01oeOfSfgG84-A@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTV8Mum1b7XxUit4Kn5WBX2kukWvvjkhOCqxnFtcjfp0w@mail.gmail.com","subject":"Re: [PATCH v2 0/6] convert various shell functions in git-bisect to C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T18:09:06Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 15, 2016 at 11:23 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Changes wrt previous version:\n>>  * Use STRING_LIST_INIT_NODUP to avoid leaks in bisect_clean_state()\n>>  * Use test_path_is_missing in the patch 2/6\n>>  * drop file_size()\n>>  * move is_empty_file() method from builtin/am.c to wrapper.c\n>>  * use static for methods\n>>  * remove the variable status in bisect_reset() altogether and put the whole\n>>    thing inside the if block.\n>>  * one more method converted namely bisect_write().\n>\n> As an aid to reviewers, in the future, please also include in the\n> cover letter an interdiff between the previous and current version of\n> the patch series. Thanks.\n\nSure!\n\nRegards,\nPranit Bauva\n"},{"id":"289305","messageId":"xmqqh9cu724n.fsf@gitster.mtv.corp.google.com","threadId":"42559","inReplyTo":"20160615140026.10519-4-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 3/6] wrapper: move is_empty_file() from builtin/am.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-06-15T18:12:08Z","receivedAt":"2016-06-16T06:55:53Z","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> diff --git a/builtin/am.c b/builtin/am.c\n> index 3dfe70b..84f21d0 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\nThis is perfectly fine in the context of \"git am\", but as a public\nfunction that is called is_empty_file(), callers can come from two\ncamps.  One is like the caller of this function in \"am\" where an\nempty and a missing file are treated equivalently.  The other would\nwant to act differently.\n\nRenaming it \"is-empty-or-missing\" is necessary in order to make it\nclear that this helper function is not targetted for the latter\ncallers.\n"},{"id":"289306","messageId":"CAFZEwPOH_mkESin+Ykx4yXqS6oo2yAy0WzqvUgTh_eZ3HwXZXQ@mail.gmail.com","threadId":"42559","inReplyTo":"xmqqh9cu724n.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 3/6] wrapper: move is_empty_file() from builtin/am.c","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T18:15:06Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Junio,\n\nOn Wed, Jun 15, 2016 at 11:42 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Pranit Bauva <pranit.bauva@gmail.com> writes:\n>\n>> diff --git a/builtin/am.c b/builtin/am.c\n>> index 3dfe70b..84f21d0 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>> -     struct stat st;\n>> -\n>> -     if (stat(filename, &st) < 0) {\n>> -             if (errno == ENOENT)\n>> -                     return 1;\n>> -             die_errno(_(\"could not stat %s\"), filename);\n>> -     }\n>> -\n>> -     return !st.st_size;\n>> -}\n>> -\n>\n> This is perfectly fine in the context of \"git am\", but as a public\n> function that is called is_empty_file(), callers can come from two\n> camps.  One is like the caller of this function in \"am\" where an\n> empty and a missing file are treated equivalently.  The other would\n> want to act differently.\n>\n> Renaming it \"is-empty-or-missing\" is necessary in order to make it\n> clear that this helper function is not targetted for the latter\n> callers.\n\nYes, its better to rename the function as is_empty_or_missing() . Thanks!\n\nRegards,\nPranit Bauva\n"},{"id":"289307","messageId":"CAPig+cTu1msxkjBZgLfy9g3+_VF5OzKNDbR0E0zVvopTNe2Q=g@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-4-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 3/6] wrapper: move is_empty_file() from builtin/am.c","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T18:22:50Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> is_empty_file() can help to refactor a lot of code. Also it is quite\n> helpful while converting shell scripts which use `test -s`. Since\n\nAs justification, \"can help to refactor a lot of code\" is very\nnebulous. It would be better to give a concrete reason for moving the\nfunction, such as explaining that the functionality will be needed by\nthe \"git bisect\" port to C.\n\n> is_empty_file() is now a \"library\" function, its inappropriate to die() so\n> instead error_errno() is used to convey the message to stderr while the\n> appropriate boolean value is returned.\n>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/am.c b/builtin/am.c\n> @@ -30,22 +30,6 @@\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> -       struct stat st;\n> -\n> -       if (stat(filename, &st) < 0) {\n> -               if (errno == ENOENT)\n> -                       return 1;\n> -               die_errno(_(\"could not stat %s\"), filename);\n> -       }\n> -\n> -       return !st.st_size;\n> -}\n\nSo, the original function die()'d for unexpected errors, but the\nrewrite does not. This is a big behavior change. To account for such a\nchange in behavior I'd expect to see git-am updated to die() on its\nown for such failures, but no such changes are present in this patch.\nMore about this below...\n\n> diff --git a/wrapper.c b/wrapper.c\n> @@ -696,3 +696,16 @@ void sleep_millisec(int millisec)\n> +int is_empty_file(const char *filename)\n> +{\n> +       struct stat st;\n> +\n> +       if (stat(filename, &st) < 0) {\n> +               if (errno == ENOENT)\n> +                       return 1;\n> +               error_errno(_(\"could not stat %s\"), filename);\n\nMental note: There is no 'return' in front of error_errno(), so the\nfunction does not exit here...\n\n> +       }\n> +\n> +       return !st.st_size;\n> +}\n\nIf stat() returns some error other than ENOENT, then the value of 'st'\nwill be undefined, yet this return statement accesses its 'st_size'\nfield, which is clearly a bad thing to do.\n\nYou either need to return a designated value (such as -1) upon errors\nother than ENOENT (and update the documentation to mention -1) so that\nthe caller can decided what to do, or die() as the original did. While\nit's true that die()'ing is not necessarily friendly in library code,\nit may be acceptable until such time that you find a caller which\nneeds different behavior.\n"},{"id":"289310","messageId":"CAFZEwPOkojqvivXpP7vq6WuMWPAjE1uXruoxsxH76LGT+1Eu4A@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTu1msxkjBZgLfy9g3+_VF5OzKNDbR0E0zVvopTNe2Q=g@mail.gmail.com","subject":"Re: [PATCH v2 3/6] wrapper: move is_empty_file() from builtin/am.c","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T18:40:03Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 15, 2016 at 11:52 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> is_empty_file() can help to refactor a lot of code. Also it is quite\n>> helpful while converting shell scripts which use `test -s`. Since\n>\n> As justification, \"can help to refactor a lot of code\" is very\n> nebulous. It would be better to give a concrete reason for moving the\n> function, such as explaining that the functionality will be needed by\n> the \"git bisect\" port to C.\n\nSure I can include that.\n\n>> is_empty_file() is now a \"library\" function, its inappropriate to die() so\n>> instead error_errno() is used to convey the message to stderr while the\n>> appropriate boolean value is returned.\n>>\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/am.c b/builtin/am.c\n>> @@ -30,22 +30,6 @@\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>> -       struct stat st;\n>> -\n>> -       if (stat(filename, &st) < 0) {\n>> -               if (errno == ENOENT)\n>> -                       return 1;\n>> -               die_errno(_(\"could not stat %s\"), filename);\n>> -       }\n>> -\n>> -       return !st.st_size;\n>> -}\n>\n> So, the original function die()'d for unexpected errors, but the\n> rewrite does not. This is a big behavior change. To account for such a\n> change in behavior I'd expect to see git-am updated to die() on its\n> own for such failures, but no such changes are present in this patch.\n> More about this below...\n>\n>> diff --git a/wrapper.c b/wrapper.c\n>> @@ -696,3 +696,16 @@ void sleep_millisec(int millisec)\n>> +int is_empty_file(const char *filename)\n>> +{\n>> +       struct stat st;\n>> +\n>> +       if (stat(filename, &st) < 0) {\n>> +               if (errno == ENOENT)\n>> +                       return 1;\n>> +               error_errno(_(\"could not stat %s\"), filename);\n>\n> Mental note: There is no 'return' in front of error_errno(), so the\n> function does not exit here...\n\nThis is purposely as I want to keep this function to return only\nboolean values ( 0 or 1).\n\n>> +       }\n>> +\n>> +       return !st.st_size;\n>> +}\n>\n> If stat() returns some error other than ENOENT, then the value of 'st'\n> will be undefined, yet this return statement accesses its 'st_size'\n> field, which is clearly a bad thing to do.\n>\n> You either need to return a designated value (such as -1) upon errors\n> other than ENOENT (and update the documentation to mention -1) so that\n> the caller can decided what to do, or die() as the original did. While\n> it's true that die()'ing is not necessarily friendly in library code,\n> it may be acceptable until such time that you find a caller which\n> needs different behavior.\n\nI didn't realize the complexity the patch carried with itself before.\nI probably shouldn't fidget with am code right now, its a work better\nleft to who are converting the code to library code. I think its the\nbest fit for this situation to leave it as die()'ing.\n\nRegards,\nPranit Bauva\n"},{"id":"289312","messageId":"CAFZEwPNtWkG54dpcLz+E=QjED8ftJqemyNKFwFKdty6HiPtNDw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cRfYS4FX+z4Yn-He_LctWdh7Ua56JU2HJs2C2+nTi5YyA@mail.gmail.com","subject":"Re: [PATCH v2 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-15T18:47:29Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Wed, Jun 15, 2016 at 11:34 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `bisect_clean_state` shell function in C and add a\n>> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n>> git-bisect.sh .\n>> [...]\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> +static int mark_for_removal(const char *refname, const struct object_id *oid,\n>> +                           int flag, void *cb_data)\n>> +{\n>> +       struct string_list *refs = cb_data;\n>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>> +       string_list_append(refs, ref);\n>> +       return 0;\n>> +}\n>> +\n>> +static 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);\n>> +       string_list_clear(&refs_for_removal, 0);\n>\n> This is leaking all the strings added to 'refs_for_removal', isn't it?\n> Either you need to loop over the items and free the strings manually,\n> or (if it's not too ugly), set 'strdup_strings' before invoking\n> string_list_clear().\n\nI didn't carefully see that in the function string_list_clear() it\nonly free()'s the memory if strdup_strings is 1. I think changing\nstrdup_strings to 1 would be an easy way out but it would make the\ncode very ugly and non-trivial. On the other hand, I can initialize\nthe string as STRING_LIST_INIT_DUP which will automatically set\nstrdup_strings as 1 and then also free the memory of ref at that point\nafter the string ref was appended to the list. Personally, I will\nprefer the latter one.\n\nRegards,\nPranit Bauva\n"},{"id":"289319","messageId":"CAPig+cQavSpojzrbWbz-W6yRjdJX-kBfUa5XtMWCO2B2CZmryg@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPNtWkG54dpcLz+E=QjED8ftJqemyNKFwFKdty6HiPtNDw@mail.gmail.com","subject":"Re: [PATCH v2 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T20:22:44Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 2:47 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Wed, Jun 15, 2016 at 11:34 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> Reimplement `bisect_clean_state` shell function in C and add a\n>>> `bisect-clean-state` subcommand to `git bisect--helper` to call it from\n>>> git-bisect.sh .\n>>> [...]\n>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>> ---\n>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>> +static int mark_for_removal(const char *refname, const struct object_id *oid,\n>>> +                           int flag, void *cb_data)\n>>> +{\n>>> +       struct string_list *refs = cb_data;\n>>> +       char *ref = xstrfmt(\"refs/bisect/%s\", refname);\n>>> +       string_list_append(refs, ref);\n>>> +       return 0;\n>>> +}\n>>> +\n>>> +static 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);\n>>> +       string_list_clear(&refs_for_removal, 0);\n>>\n>> This is leaking all the strings added to 'refs_for_removal', isn't it?\n>> Either you need to loop over the items and free the strings manually,\n>> or (if it's not too ugly), set 'strdup_strings' before invoking\n>> string_list_clear().\n>\n> I didn't carefully see that in the function string_list_clear() it\n> only free()'s the memory if strdup_strings is 1. I think changing\n> strdup_strings to 1 would be an easy way out but it would make the\n> code very ugly and non-trivial.\n\nI disagree about it making the code \"*very* ugly and non-trivial\". It\nis quite trivial. What I meant by \"ugly\" was that it may be too\nintimate with the implementation of string_list. However, since the\nsolution is already used in the codebase, it may be acceptable. For\ninstance, in builtin/fetch.c:\n\n    /* All names were strdup()ed or strndup()ed */\n    list.strdup_strings = 1;\n    string_list_clear(&list, 0);\n\nwhich is exactly the approach I was suggesting. You'll find the same\npattern in builtin/shortlog.c.\n\n> On the other hand, I can initialize\n> the string as STRING_LIST_INIT_DUP which will automatically set\n> strdup_strings as 1 and then also free the memory of ref at that point\n> after the string ref was appended to the list. Personally, I will\n> prefer the latter one.\n\nMeh.\n"},{"id":"289322","messageId":"CAPig+cTf72M2iaZr3bZj+0V_0VHXJahpusY6zwT_B5uJx0BP1g@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-5-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 4/6] bisect--helper: `bisect_reset` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T21:05:11Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n> [...]\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> @@ -123,12 +127,48 @@ static int bisect_clean_state(void)\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> +                       return 0;\n> +               }\n> +               strbuf_rtrim(&branch);\n> +\n\nStyle: unnecessary blank line\n\n> +       } else {\n> +               struct object_id oid;\n> +               if (get_oid(commit, &oid))\n> +                       return error(_(\"'%s' is not a valid commit\"), commit);\n> +               strbuf_addf(&branch, \"%s\", commit);\n\nstrbuf_addstr(&branch, commit);\n\n> +       }\n> +\n> +       if (!file_exists(git_path_bisect_head())) {\n> +               struct argv_array argv = ARGV_ARRAY_INIT;\n> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n> +               if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n> +                       error(_(\"Could not check out original HEAD '%s'. Try\"\n> +                                       \"'git bisect reset <commit>'.\"), branch.buf);\n> +                       strbuf_release(&branch);\n> +                       argv_array_clear(&argv);\n> +                       return -1;\n> +               }\n> +               argv_array_clear(&argv);\n> +       }\n> +\n> +       strbuf_release(&branch);\n> +       return bisect_clean_state();\n> +}\n"},{"id":"289323","messageId":"CAPig+cRNcg496Ty2SJ1ojm1n3OpHzX0obMAD2bY3AzoyrKdA9w@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-6-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-15T21:14:48Z","receivedAt":"2016-06-16T06:55:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n> call it from git-bisect.sh .\n> [...]\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n> +static int is_expected_rev(const char *expected_hex)\n> +{\n> +       struct strbuf actual_hex = STRBUF_INIT;\n> +       int res;\n> +\n> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n> +               strbuf_release(&actual_hex);\n> +               return 0;\n> +       }\n> +\n> +       strbuf_trim(&actual_hex);\n> +       res = !strcmp(actual_hex.buf, expected_hex);\n> +       strbuf_release(&actual_hex);\n> +       return res;\n> +}\n\nNot worth a re-roll, but this could be re-structured to avoid having\nto remember to release the strbuf at all exits:\n\n    struct strbuf actual_hex = ...;\n    int res = 0;\n\n    if (strbuf_read_file(...) >= 0) {\n        strbuf_trim(...);\n        res = !strcmp(...);\n    }\n    strbuf_release(...);\n    return res;\n\nAlternately:\n\n    if (strbuf_read_file(...) < 0)\n        goto done;\n\n    strbuf_trim(...);\n    res = !strcmp(...);\n\ndone:\n    strbuf_release(...);\n    return res;\n\nwhich is a bit less compact.\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> +                       remove_path(git_path_bisect_ancestors_ok());\n> +                       remove_path(git_path_bisect_expected_rev());\n> +                       return 0;\n> +               }\n> +       }\n> +       return 0;\n> +}\n\nHmm, all execution paths return 0, so it feels a bit pointless to have\nthis function return a value at all.\n\nYou could also use a 'break' inside the loop rather than 'return'\nsince the return value is the same inside or outside the loop and\nnothing else happens after the loop.\n"},{"id":"289382","messageId":"CAPig+cQV3FTGJBvS0Kuc3CNPiwZMZtApT6r8+Ojhw3y7O2VTiw@mail.gmail.com","threadId":"42559","inReplyTo":"20160615140026.10519-7-pranit.bauva@gmail.com","subject":"Re: [PATCH v2 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-16T18:55:01Z","receivedAt":"2016-06-16T18:55:16Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Reimplement the `bisect_write` shell function in C and add a\n> `bisect-write` subcommand to `git bisect--helper` to call it from\n> git-bisect.sh\n>\n> Using `--bisect-write` subcommand is a temporary measure to port shell\n> function in C so as to use the existing test suite. As more functions\n> are ported, this subcommand will be retired and will be called by some\n> other methods.\n>\n> Note: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\n> from the global shell script thus we need to pass it to the subcommand\n> using the arguments. After the whole conversion, we can remove the extra\n> arguments and make the method use the two variables from the global scope\n> within the C code.\n\nYou could do this now rather than waiting for later. Instead of\npassing these arguments to bisect_write(), create global variables in\nthis patch and assign them in the BISECT_WRITE case of\ncmd_bisect__helper() before calling bisect_write().\n\nNot necessarily worth a re-roll, but would save you the effort of\nhaving to explain it here and then change it in some later patch.\n\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> @@ -192,6 +193,55 @@ static int check_expected_revs(const char **revs, int rev_nr)\n> +static int bisect_write(const char *state, const char *rev,\n> +                       const char *term_good, const char *term_bad,\n> +                       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;\n> +\n> +       if (!strcmp(state, term_bad))\n> +               strbuf_addf(&tag, \"refs/bisect/%s\", state);\n> +       else if(one_of(state, term_good, \"skip\", NULL))\n> +               strbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n> +       else\n> +               return error(_(\"Bad bisect_write argument: %s\"), state);\n> +\n> +       if (get_oid(rev, &oid)) {\n> +               strbuf_release(&tag);\n> +               return error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n> +       }\n\nMinor: If you move the get_oid() conditional before the one above it,\nthen you won't have to worry about releasing 'strbuf tag' at this\npoint.\n\n> +       if (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n> +                      UPDATE_REFS_MSG_ON_ERR)) {\n> +               strbuf_release(&tag);\n> +               return -1;\n> +       }\n\nIf you release 'strbuf tag' right here, after it's final use, then you\nwon't have to worry about releasing it anywhere below (particularly in\nthe error cases).\n\n> +       fp = fopen(git_path_bisect_log(), \"a\");\n> +       if (!fp) {\n> +               strbuf_release(&tag);\n> +               return error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n> +       }\n> +\n> +       commit = lookup_commit_reference(oid.hash);\n> +       format_commit_message(commit, \"%s\", &commit_name, &pp);\n> +       fprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n> +               commit_name.buf);\n> +\n> +       if (!nolog)\n> +               fprintf(fp, \"git bisect %s %s\\n\", state, rev);\n> +\n> +       strbuf_release(&commit_name);\n> +       strbuf_release(&tag);\n> +       fclose(fp);\n> +       return 0;\n> +}\n> @@ -241,6 +295,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n> +       case BISECT_WRITE:\n> +               if (argc != 4 && argc != 5)\n> +                       die(_(\"--bisect-write requires either 4 or 5 arguments\"));\n> +               nolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n\nThis is minor and won't matter in the long run when this code goes\naway later in the C conversion, but this differs from the shell code\nwhich only cared that a (non-empty) fifth argument was provided but\ndidn't care about the actual value, whereas this code expects the\nargument to be exactly \"nolog\".\n\n> +               return bisect_write(argv[0], argv[1], argv[2], argv[3], nolog);\n>         default:\n>                 die(\"BUG: unknown subcommand '%d'\", cmdmode);\n>         }\n"},{"id":"289384","messageId":"CAFZEwPNpeD3+6kzY7HDH_ZXcL-Nu0B7jGeM5GMjH7PT0eSTLBw@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cQV3FTGJBvS0Kuc3CNPiwZMZtApT6r8+Ojhw3y7O2VTiw@mail.gmail.com","subject":"Re: [PATCH v2 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-16T19:01:06Z","receivedAt":"2016-06-16T19:01:13Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Fri, Jun 17, 2016 at 12:25 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement the `bisect_write` shell function in C and add a\n>> `bisect-write` subcommand to `git bisect--helper` to call it from\n>> git-bisect.sh\n>>\n>> Using `--bisect-write` subcommand is a temporary measure to port shell\n>> function in C so as to use the existing test suite. As more functions\n>> are ported, this subcommand will be retired and will be called by some\n>> other methods.\n>>\n>> Note: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\n>> from the global shell script thus we need to pass it to the subcommand\n>> using the arguments. After the whole conversion, we can remove the extra\n>> arguments and make the method use the two variables from the global scope\n>> within the C code.\n>\n> You could do this now rather than waiting for later. Instead of\n> passing these arguments to bisect_write(), create global variables in\n> this patch and assign them in the BISECT_WRITE case of\n> cmd_bisect__helper() before calling bisect_write().\n>\n> Not necessarily worth a re-roll, but would save you the effort of\n> having to explain it here and then change it in some later patch.\n\nI have actually done it in my next conversion which is converting\ncheck_and_set_terms()[1] which also sets those variables to some value\nso its more appropriate there.\n\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -192,6 +193,55 @@ static int check_expected_revs(const char **revs, int rev_nr)\n>> +static int bisect_write(const char *state, const char *rev,\n>> +                       const char *term_good, const char *term_bad,\n>> +                       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;\n>> +\n>> +       if (!strcmp(state, term_bad))\n>> +               strbuf_addf(&tag, \"refs/bisect/%s\", state);\n>> +       else if(one_of(state, term_good, \"skip\", NULL))\n>> +               strbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n>> +       else\n>> +               return error(_(\"Bad bisect_write argument: %s\"), state);\n>> +\n>> +       if (get_oid(rev, &oid)) {\n>> +               strbuf_release(&tag);\n>> +               return error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n>> +       }\n>\n> Minor: If you move the get_oid() conditional before the one above it,\n> then you won't have to worry about releasing 'strbuf tag' at this\n> point.\n\nNice. I will do that. :)\n\n>> +       if (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n>> +                      UPDATE_REFS_MSG_ON_ERR)) {\n>> +               strbuf_release(&tag);\n>> +               return -1;\n>> +       }\n>\n> If you release 'strbuf tag' right here, after it's final use, then you\n> won't have to worry about releasing it anywhere below (particularly in\n> the error cases).\n\nTrue.\n\n>> +       fp = fopen(git_path_bisect_log(), \"a\");\n>> +       if (!fp) {\n>> +               strbuf_release(&tag);\n>> +               return error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n>> +       }\n>> +\n>> +       commit = lookup_commit_reference(oid.hash);\n>> +       format_commit_message(commit, \"%s\", &commit_name, &pp);\n>> +       fprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n>> +               commit_name.buf);\n>> +\n>> +       if (!nolog)\n>> +               fprintf(fp, \"git bisect %s %s\\n\", state, rev);\n>> +\n>> +       strbuf_release(&commit_name);\n>> +       strbuf_release(&tag);\n>> +       fclose(fp);\n>> +       return 0;\n>> +}\n>> @@ -241,6 +295,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n>> +       case BISECT_WRITE:\n>> +               if (argc != 4 && argc != 5)\n>> +                       die(_(\"--bisect-write requires either 4 or 5 arguments\"));\n>> +               nolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n>\n> This is minor and won't matter in the long run when this code goes\n> away later in the C conversion, but this differs from the shell code\n> which only cared that a (non-empty) fifth argument was provided but\n> didn't care about the actual value, whereas this code expects the\n> argument to be exactly \"nolog\".\n\nWe currently have tight control over the arguments we are passing as\nthey are only programmer defined.\n\n>> +               return bisect_write(argv[0], argv[1], argv[2], argv[3], nolog);\n>>         default:\n>>                 die(\"BUG: unknown subcommand '%d'\", cmdmode);\n>>         }\n\n[1]: https://github.com/pranitbauva1997/git/pull/16\n\nRegards,\nPranit Bauva\n"},{"id":"289385","messageId":"CAFZEwPP0-9rHOKFZBoE55pv4V-+okSLh4M5grNKWnq831Ug4+w@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cRNcg496Ty2SJ1ojm1n3OpHzX0obMAD2bY3AzoyrKdA9w@mail.gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-16T19:05:06Z","receivedAt":"2016-06-16T19:05:13Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Thu, Jun 16, 2016 at 2:44 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n>> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n>> call it from git-bisect.sh .\n>> [...]\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n>> +static int is_expected_rev(const char *expected_hex)\n>> +{\n>> +       struct strbuf actual_hex = STRBUF_INIT;\n>> +       int res;\n>> +\n>> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n>> +               strbuf_release(&actual_hex);\n>> +               return 0;\n>> +       }\n>> +\n>> +       strbuf_trim(&actual_hex);\n>> +       res = !strcmp(actual_hex.buf, expected_hex);\n>> +       strbuf_release(&actual_hex);\n>> +       return res;\n>> +}\n>\n> Not worth a re-roll, but this could be re-structured to avoid having\n> to remember to release the strbuf at all exits:\n>\n>     struct strbuf actual_hex = ...;\n>     int res = 0;\n>\n>     if (strbuf_read_file(...) >= 0) {\n>         strbuf_trim(...);\n>         res = !strcmp(...);\n>     }\n>     strbuf_release(...);\n>     return res;\n>\n> Alternately:\n>\n>     if (strbuf_read_file(...) < 0)\n>         goto done;\n>\n>     strbuf_trim(...);\n>     res = !strcmp(...);\n>\n> done:\n>     strbuf_release(...);\n>     return res;\n>\n> which is a bit less compact.\n\nI will avoid this for the reason that I will have to create a label\nfor a lot of functions. If I choose to do this for one function, I\nthink it would be more appropriate to do the same for other functions.\nThere would be a lot of functions in future which would be in the same\nscenario and creating a separate label for each of them would be quite\ntedious. What do you think?\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>> +                       remove_path(git_path_bisect_ancestors_ok());\n>> +                       remove_path(git_path_bisect_expected_rev());\n>> +                       return 0;\n>> +               }\n>> +       }\n>> +       return 0;\n>> +}\n>\n> Hmm, all execution paths return 0, so it feels a bit pointless to have\n> this function return a value at all.\n>\n> You could also use a 'break' inside the loop rather than 'return'\n> since the return value is the same inside or outside the loop and\n> nothing else happens after the loop.\n\nSure!\n"},{"id":"289386","messageId":"CAFZEwPPuoP6s2BZgKfvT5fZ_TGyqO16fCmJkGpbxDt8YR2gxVQ@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cTf72M2iaZr3bZj+0V_0VHXJahpusY6zwT_B5uJx0BP1g@mail.gmail.com","subject":"Re: [PATCH v2 4/6] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-16T19:06:01Z","receivedAt":"2016-06-16T19:06:09Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Thu, Jun 16, 2016 at 2:35 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Reimplement `bisect_reset` shell function in C and add a `--bisect-reset`\n>> subcommand to `git bisect--helper` to call it from git-bisect.sh .\n>> [...]\n>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>> ---\n>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>> @@ -123,12 +127,48 @@ static int bisect_clean_state(void)\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>> +                       return 0;\n>> +               }\n>> +               strbuf_rtrim(&branch);\n>> +\n>\n> Style: unnecessary blank line\n\nWill fix.\n\n>> +       } else {\n>> +               struct object_id oid;\n>> +               if (get_oid(commit, &oid))\n>> +                       return error(_(\"'%s' is not a valid commit\"), commit);\n>> +               strbuf_addf(&branch, \"%s\", commit);\n>\n> strbuf_addstr(&branch, commit);\n\nSeems better. :)\n\n>> +       }\n>> +\n>> +       if (!file_exists(git_path_bisect_head())) {\n>> +               struct argv_array argv = ARGV_ARRAY_INIT;\n>> +               argv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n>> +               if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n>> +                       error(_(\"Could not check out original HEAD '%s'. Try\"\n>> +                                       \"'git bisect reset <commit>'.\"), branch.buf);\n>> +                       strbuf_release(&branch);\n>> +                       argv_array_clear(&argv);\n>> +                       return -1;\n>> +               }\n>> +               argv_array_clear(&argv);\n>> +       }\n>> +\n>> +       strbuf_release(&branch);\n>> +       return bisect_clean_state();\n>> +}\n\nRegards,\nPranit Bauva\n"},{"id":"289387","messageId":"CAPig+cS1=bv588H6yrOy1oFvArjJNbetdTS7+ZhfGn-GtVp4qw@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPP0-9rHOKFZBoE55pv4V-+okSLh4M5grNKWnq831Ug4+w@mail.gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-06-16T19:16:20Z","receivedAt":"2016-06-16T19:16:26Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Jun 16, 2016 at 3:05 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> On Thu, Jun 16, 2016 at 2:44 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n>>> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n>>> call it from git-bisect.sh .\n>>> [...]\n>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>> ---\n>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n>>> +static int is_expected_rev(const char *expected_hex)\n>>> +{\n>>> +       struct strbuf actual_hex = STRBUF_INIT;\n>>> +       int res;\n>>> +\n>>> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n>>> +               strbuf_release(&actual_hex);\n>>> +               return 0;\n>>> +       }\n>>> +\n>>> +       strbuf_trim(&actual_hex);\n>>> +       res = !strcmp(actual_hex.buf, expected_hex);\n>>> +       strbuf_release(&actual_hex);\n>>> +       return res;\n>>> +}\n>>\n>> Not worth a re-roll, but this could be re-structured to avoid having\n>> to remember to release the strbuf at all exits:\n>>\n>>     struct strbuf actual_hex = ...;\n>>     int res = 0;\n>>\n>>     if (strbuf_read_file(...) >= 0) {\n>>         strbuf_trim(...);\n>>         res = !strcmp(...);\n>>     }\n>>     strbuf_release(...);\n>>     return res;\n>>\n>> Alternately:\n>>\n>>     if (strbuf_read_file(...) < 0)\n>>         goto done;\n>>\n>>     strbuf_trim(...);\n>>     res = !strcmp(...);\n>>\n>> done:\n>>     strbuf_release(...);\n>>     return res;\n>>\n>> which is a bit less compact.\n>\n> I will avoid this for the reason that I will have to create a label\n> for a lot of functions. If I choose to do this for one function, I\n> think it would be more appropriate to do the same for other functions.\n> There would be a lot of functions in future which would be in the same\n> scenario and creating a separate label for each of them would be quite\n> tedious. What do you think?\n\nNot sure what you're talking about. Label names are not shared across\nfunctions. Anyhow, the first suggestion I presented above is more\nconcise than the 'goto' version.\n"},{"id":"289388","messageId":"CAFZEwPPBTd6o7qg96cet8RAp5wY1shzQ=jU8dEK1irXSiMAxQg@mail.gmail.com","threadId":"42559","inReplyTo":"CAPig+cS1=bv588H6yrOy1oFvArjJNbetdTS7+ZhfGn-GtVp4qw@mail.gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-16T19:25:54Z","receivedAt":"2016-06-16T19:26:00Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Eric,\n\nOn Fri, Jun 17, 2016 at 12:46 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Thu, Jun 16, 2016 at 3:05 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> On Thu, Jun 16, 2016 at 2:44 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n>>>> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n>>>> call it from git-bisect.sh .\n>>>> [...]\n>>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>>> ---\n>>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>>> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n>>>> +static int is_expected_rev(const char *expected_hex)\n>>>> +{\n>>>> +       struct strbuf actual_hex = STRBUF_INIT;\n>>>> +       int res;\n>>>> +\n>>>> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n>>>> +               strbuf_release(&actual_hex);\n>>>> +               return 0;\n>>>> +       }\n>>>> +\n>>>> +       strbuf_trim(&actual_hex);\n>>>> +       res = !strcmp(actual_hex.buf, expected_hex);\n>>>> +       strbuf_release(&actual_hex);\n>>>> +       return res;\n>>>> +}\n>>>\n>>> Not worth a re-roll, but this could be re-structured to avoid having\n>>> to remember to release the strbuf at all exits:\n>>>\n>>>     struct strbuf actual_hex = ...;\n>>>     int res = 0;\n>>>\n>>>     if (strbuf_read_file(...) >= 0) {\n>>>         strbuf_trim(...);\n>>>         res = !strcmp(...);\n>>>     }\n>>>     strbuf_release(...);\n>>>     return res;\n>>>\n>>> Alternately:\n>>>\n>>>     if (strbuf_read_file(...) < 0)\n>>>         goto done;\n>>>\n>>>     strbuf_trim(...);\n>>>     res = !strcmp(...);\n>>>\n>>> done:\n>>>     strbuf_release(...);\n>>>     return res;\n>>>\n>>> which is a bit less compact.\n>>\n>> I will avoid this for the reason that I will have to create a label\n>> for a lot of functions. If I choose to do this for one function, I\n>> think it would be more appropriate to do the same for other functions.\n>> There would be a lot of functions in future which would be in the same\n>> scenario and creating a separate label for each of them would be quite\n>> tedious. What do you think?\n>\n> Not sure what you're talking about. Label names are not shared across\n> functions. Anyhow, the first suggestion I presented above is more\n> concise than the 'goto' version.\n\nYes I am aware of the fact that labels aren't shared across functions.\nWhat I meant by \"separate label\" was that I will have to make a label\n\"fail\" in each function. But I recently noticed that its used quite a\nlot so I think it would be okay to use it. Will re-roll with using\nlabels and goto.\n\nRegards,\nPranit Bauva\n"},{"id":"289403","messageId":"CAP8UFD1Fi53am5O+RBS4XfHOEF1rdYiNSbWBvhaAUv_9fgJ3Zg@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPNpeD3+6kzY7HDH_ZXcL-Nu0B7jGeM5GMjH7PT0eSTLBw@mail.gmail.com","subject":"Re: [PATCH v2 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-16T20:38:35Z","receivedAt":"2016-06-16T20:38:41Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Thu, Jun 16, 2016 at 9:01 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Hey Eric,\n>\n> On Fri, Jun 17, 2016 at 12:25 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>\n>>> Note: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\n>>> from the global shell script thus we need to pass it to the subcommand\n>>> using the arguments. After the whole conversion, we can remove the extra\n>>> arguments and make the method use the two variables from the global scope\n>>> within the C code.\n>>\n>> You could do this now rather than waiting for later. Instead of\n>> passing these arguments to bisect_write(), create global variables in\n>> this patch and assign them in the BISECT_WRITE case of\n>> cmd_bisect__helper() before calling bisect_write().\n>>\n>> Not necessarily worth a re-roll, but would save you the effort of\n>> having to explain it here and then change it in some later patch.\n>\n> I have actually done it in my next conversion which is converting\n> check_and_set_terms()[1] which also sets those variables to some value\n> so its more appropriate there.\n\nMy opinion about this is that using global variables would go against\na possible future libification of the bisect functionality and might\nbe less safe than just adding 2 parameters to a small number of\nfunctions.\n\nIf we think that 2 parameters are too much or that there could be more\nparameters to pass like this, we could just pass a pointer to a\n'struct bisect_state' or something like that ;-)\n"},{"id":"289404","messageId":"CAP8UFD0YNNzF4qqdvDbrONaMm8B8G_amePq2g58TYrjm+9W6Vw@mail.gmail.com","threadId":"42559","inReplyTo":"CAFZEwPPBTd6o7qg96cet8RAp5wY1shzQ=jU8dEK1irXSiMAxQg@mail.gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2016-06-16T20:47:45Z","receivedAt":"2016-06-16T20:48:33Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Thu, Jun 16, 2016 at 9:25 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n> Hey Eric,\n>\n> On Fri, Jun 17, 2016 at 12:46 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On Thu, Jun 16, 2016 at 3:05 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>> On Thu, Jun 16, 2016 at 2:44 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>>> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n>>>>> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n>>>>> call it from git-bisect.sh .\n>>>>> [...]\n>>>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>>>> ---\n>>>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>>>> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n>>>>> +static int is_expected_rev(const char *expected_hex)\n>>>>> +{\n>>>>> +       struct strbuf actual_hex = STRBUF_INIT;\n>>>>> +       int res;\n>>>>> +\n>>>>> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n>>>>> +               strbuf_release(&actual_hex);\n>>>>> +               return 0;\n>>>>> +       }\n>>>>> +\n>>>>> +       strbuf_trim(&actual_hex);\n>>>>> +       res = !strcmp(actual_hex.buf, expected_hex);\n>>>>> +       strbuf_release(&actual_hex);\n>>>>> +       return res;\n>>>>> +}\n>>>>\n>>>> Not worth a re-roll, but this could be re-structured to avoid having\n>>>> to remember to release the strbuf at all exits:\n>>>>\n>>>>     struct strbuf actual_hex = ...;\n>>>>     int res = 0;\n>>>>\n>>>>     if (strbuf_read_file(...) >= 0) {\n>>>>         strbuf_trim(...);\n>>>>         res = !strcmp(...);\n>>>>     }\n>>>>     strbuf_release(...);\n>>>>     return res;\n>>>>\n>>>> Alternately:\n>>>>\n>>>>     if (strbuf_read_file(...) < 0)\n>>>>         goto done;\n>>>>\n>>>>     strbuf_trim(...);\n>>>>     res = !strcmp(...);\n>>>>\n>>>> done:\n>>>>     strbuf_release(...);\n>>>>     return res;\n>>>>\n>>>> which is a bit less compact.\n>>>\n>>> I will avoid this for the reason that I will have to create a label\n>>> for a lot of functions. If I choose to do this for one function, I\n>>> think it would be more appropriate to do the same for other functions.\n>>> There would be a lot of functions in future which would be in the same\n>>> scenario and creating a separate label for each of them would be quite\n>>> tedious. What do you think?\n>>\n>> Not sure what you're talking about. Label names are not shared across\n>> functions. Anyhow, the first suggestion I presented above is more\n>> concise than the 'goto' version.\n>\n> Yes I am aware of the fact that labels aren't shared across functions.\n> What I meant by \"separate label\" was that I will have to make a label\n> \"fail\" in each function. But I recently noticed that its used quite a\n> lot so I think it would be okay to use it. Will re-roll with using\n> labels and goto.\n\nMy opinion is that if there is a more concise version without labels\nand gotos, it's better to use it, so I would suggest Eric's first\nsuggestion which is:\n\n>     struct strbuf actual_hex = ...;\n>     int res = 0;\n>\n>     if (strbuf_read_file(...) >= 0) {\n>         strbuf_trim(...);\n>         res = !strcmp(...);\n>     }\n>     strbuf_release(...);\n>     return res;\n\nThanks,\nChristian.\n"},{"id":"289438","messageId":"CAFZEwPPUX16omOgk4V87UYheJH_+kBueGd4OzAJsit=j2Q6mNg@mail.gmail.com","threadId":"42559","inReplyTo":"CAP8UFD0YNNzF4qqdvDbrONaMm8B8G_amePq2g58TYrjm+9W6Vw@mail.gmail.com","subject":"Re: [PATCH v2 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-17T12:49:39Z","receivedAt":"2016-06-17T12:49:44Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Christian,\n\nOn Fri, Jun 17, 2016 at 2:17 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Thu, Jun 16, 2016 at 9:25 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Hey Eric,\n>>\n>> On Fri, Jun 17, 2016 at 12:46 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Thu, Jun 16, 2016 at 3:05 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>> On Thu, Jun 16, 2016 at 2:44 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>>>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>>>> Reimplement `is_expected_rev` & `check_expected_revs` shell function in\n>>>>>> C and add a `--check-expected-revs` subcommand to `git bisect--helper` to\n>>>>>> call it from git-bisect.sh .\n>>>>>> [...]\n>>>>>> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>>>>>> ---\n>>>>>> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n>>>>>> @@ -162,13 +162,44 @@ static int bisect_reset(const char *commit)\n>>>>>> +static int is_expected_rev(const char *expected_hex)\n>>>>>> +{\n>>>>>> +       struct strbuf actual_hex = STRBUF_INIT;\n>>>>>> +       int res;\n>>>>>> +\n>>>>>> +       if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n>>>>>> +               strbuf_release(&actual_hex);\n>>>>>> +               return 0;\n>>>>>> +       }\n>>>>>> +\n>>>>>> +       strbuf_trim(&actual_hex);\n>>>>>> +       res = !strcmp(actual_hex.buf, expected_hex);\n>>>>>> +       strbuf_release(&actual_hex);\n>>>>>> +       return res;\n>>>>>> +}\n>>>>>\n>>>>> Not worth a re-roll, but this could be re-structured to avoid having\n>>>>> to remember to release the strbuf at all exits:\n>>>>>\n>>>>>     struct strbuf actual_hex = ...;\n>>>>>     int res = 0;\n>>>>>\n>>>>>     if (strbuf_read_file(...) >= 0) {\n>>>>>         strbuf_trim(...);\n>>>>>         res = !strcmp(...);\n>>>>>     }\n>>>>>     strbuf_release(...);\n>>>>>     return res;\n>>>>>\n>>>>> Alternately:\n>>>>>\n>>>>>     if (strbuf_read_file(...) < 0)\n>>>>>         goto done;\n>>>>>\n>>>>>     strbuf_trim(...);\n>>>>>     res = !strcmp(...);\n>>>>>\n>>>>> done:\n>>>>>     strbuf_release(...);\n>>>>>     return res;\n>>>>>\n>>>>> which is a bit less compact.\n>>>>\n>>>> I will avoid this for the reason that I will have to create a label\n>>>> for a lot of functions. If I choose to do this for one function, I\n>>>> think it would be more appropriate to do the same for other functions.\n>>>> There would be a lot of functions in future which would be in the same\n>>>> scenario and creating a separate label for each of them would be quite\n>>>> tedious. What do you think?\n>>>\n>>> Not sure what you're talking about. Label names are not shared across\n>>> functions. Anyhow, the first suggestion I presented above is more\n>>> concise than the 'goto' version.\n>>\n>> Yes I am aware of the fact that labels aren't shared across functions.\n>> What I meant by \"separate label\" was that I will have to make a label\n>> \"fail\" in each function. But I recently noticed that its used quite a\n>> lot so I think it would be okay to use it. Will re-roll with using\n>> labels and goto.\n>\n> My opinion is that if there is a more concise version without labels\n> and gotos, it's better to use it, so I would suggest Eric's first\n> suggestion which is:\n>\n>>     struct strbuf actual_hex = ...;\n>>     int res = 0;\n>>\n>>     if (strbuf_read_file(...) >= 0) {\n>>         strbuf_trim(...);\n>>         res = !strcmp(...);\n>>     }\n>>     strbuf_release(...);\n>>     return res;\n\nSure I could do that!\n\nRegards,\nPranit Bauva\n"},{"id":"289440","messageId":"CAFZEwPNnHC=ii=qkR1-i+FM5oPw9JRS5MYOfaEvpsKUO5vwyQw@mail.gmail.com","threadId":"42559","inReplyTo":"CAP8UFD1Fi53am5O+RBS4XfHOEF1rdYiNSbWBvhaAUv_9fgJ3Zg@mail.gmail.com","subject":"Re: [PATCH v2 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-17T13:10:54Z","receivedAt":"2016-06-17T13:11:00Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Hey Christian,\n\nOn Fri, Jun 17, 2016 at 2:08 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Thu, Jun 16, 2016 at 9:01 PM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>> Hey Eric,\n>>\n>> On Fri, Jun 17, 2016 at 12:25 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>>> On Wed, Jun 15, 2016 at 10:00 AM, Pranit Bauva <pranit.bauva@gmail.com> wrote:\n>>>>\n>>>> Note: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\n>>>> from the global shell script thus we need to pass it to the subcommand\n>>>> using the arguments. After the whole conversion, we can remove the extra\n>>>> arguments and make the method use the two variables from the global scope\n>>>> within the C code.\n>>>\n>>> You could do this now rather than waiting for later. Instead of\n>>> passing these arguments to bisect_write(), create global variables in\n>>> this patch and assign them in the BISECT_WRITE case of\n>>> cmd_bisect__helper() before calling bisect_write().\n>>>\n>>> Not necessarily worth a re-roll, but would save you the effort of\n>>> having to explain it here and then change it in some later patch.\n>>\n>> I have actually done it in my next conversion which is converting\n>> check_and_set_terms()[1] which also sets those variables to some value\n>> so its more appropriate there.\n>\n> My opinion about this is that using global variables would go against\n> a possible future libification of the bisect functionality and might\n> be less safe than just adding 2 parameters to a small number of\n> functions.\n>\n> If we think that 2 parameters are too much or that there could be more\n> parameters to pass like this, we could just pass a pointer to a\n> 'struct bisect_state' or something like that ;-)\n\nI had in mind something about 'struct bisect_state'.\n\nRegards,\nPranit Bauva\n"},{"id":"290187","messageId":"20160626122356.28999-1-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160607205454.22576-1-pranit.bauva@gmail.com","subject":"[PATCH v3 0/6] convert various shell functions in git-bisect to C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:50Z","receivedAt":"2016-06-26T12:25:12Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"The major change introduced in this version is that I have used `struct\nbisect_terms` to store term_good and term_bad and then I am passing around\nthe memory address of it to functions. Also I have made various changes\nin accordance with the previous review.\n\nHere is the link for v2.\nhttp://thread.gmane.org/gmane.comp.version-control.git/297372\n\nThanks for suggestions Eric Sunshine, Christian Couder and Junio C Hammano.\n\nHere's the interdiff:\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 84f21d0..6ee158f 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1307,7 +1307,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@@ -1895,7 +1895,7 @@ next:\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/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex eebfcf0..e946ba9 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -26,6 +26,25 @@ static const char * const git_bisect_helper_usage[] = {\n \tNULL\n };\n \n+struct bisect_terms {\n+\tstruct strbuf term_good;\n+\tstruct strbuf term_bad;\n+};\n+\n+static int bisect_terms_init(struct bisect_terms *term)\n+{\n+\tstrbuf_init(&term->term_good, 0);\n+\tstrbuf_init(&term->term_bad, 0);\n+\treturn 0;\n+}\n+\n+static int bisect_terms_release(struct bisect_terms *term)\n+{\n+\tstrbuf_release(&term->term_good);\n+\tstrbuf_release(&term->term_good);\n+\treturn 0;\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -110,6 +129,7 @@ static int bisect_clean_state(void)\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);\n+\trefs_for_removal.strdup_strings = 1;\n \tstring_list_clear(&refs_for_removal, 0);\n \tremove_path(git_path_bisect_expected_rev());\n \tremove_path(git_path_bisect_ancestors_ok());\n@@ -138,12 +158,11 @@ static int bisect_reset(const char *commit)\n \t\t\treturn 0;\n \t\t}\n \t\tstrbuf_rtrim(&branch);\n-\n \t} else {\n \t\tstruct object_id oid;\n \t\tif (get_oid(commit, &oid))\n \t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n-\t\tstrbuf_addf(&branch, \"%s\", commit);\n+\t\tstrbuf_addstr(&branch, commit);\n \t}\n \n \tif (!file_exists(git_path_bisect_head())) {\n@@ -151,7 +170,7 @@ static int bisect_reset(const char *commit)\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\t\"'git bisect reset <commit>'.\"), branch.buf);\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@@ -166,15 +185,11 @@ static int bisect_reset(const char *commit)\n static int is_expected_rev(const char *expected_hex)\n {\n \tstruct strbuf actual_hex = STRBUF_INIT;\n-\tint res;\n-\n-\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) < 0) {\n-\t\tstrbuf_release(&actual_hex);\n-\t\treturn 0;\n+\tint res = 0;\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 0) {\n+\t\tstrbuf_trim(&actual_hex);\n+\t\tres = !strcmp(actual_hex.buf, expected_hex);\n \t}\n-\n-\tstrbuf_trim(&actual_hex);\n-\tres = !strcmp(actual_hex.buf, expected_hex);\n \tstrbuf_release(&actual_hex);\n \treturn res;\n }\n@@ -194,8 +209,7 @@ static int check_expected_revs(const char **revs, int rev_nr)\n }\n \n static int bisect_write(const char *state, const char *rev,\n-\t\t\tconst char *term_good, const char *term_bad,\n-\t\t\tint nolog)\n+\t\t\tconst struct bisect_terms *term, int nolog)\n {\n \tstruct strbuf tag = STRBUF_INIT;\n \tstruct strbuf commit_name = STRBUF_INIT;\n@@ -204,9 +218,9 @@ static int bisect_write(const char *state, const char *rev,\n \tstruct pretty_print_context pp = {0};\n \tFILE *fp;\n \n-\tif (!strcmp(state, term_bad))\n+\tif (!strcmp(state, term->term_bad.buf))\n \t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n-\telse if(one_of(state, term_good, \"skip\", NULL))\n+\telse if(one_of(state, term->term_good.buf, \"skip\", NULL))\n \t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n \telse\n \t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n@@ -221,23 +235,21 @@ static int bisect_write(const char *state, const char *rev,\n \t\tstrbuf_release(&tag);\n \t\treturn -1;\n \t}\n+\tstrbuf_release(&tag);\n \n \tfp = fopen(git_path_bisect_log(), \"a\");\n-\tif (!fp) {\n-\t\tstrbuf_release(&tag);\n+\tif (!fp)\n \t\treturn error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\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+\tstrbuf_release(&commit_name);\n \n \tif (!nolog)\n \t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n \n-\tstrbuf_release(&commit_name);\n-\tstrbuf_release(&tag);\n \tfclose(fp);\n \treturn 0;\n }\n@@ -252,7 +264,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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@@ -270,6 +282,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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 state;\n+\tbisect_terms_init(&state);\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -284,24 +298,32 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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\treturn bisect_write(argv[0], argv[1], argv[2], argv[3], nolog);\n+\t\tstrbuf_addstr(&state.term_good, argv[2]);\n+\t\tstrbuf_addstr(&state.term_bad, argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &state, nolog);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tbisect_terms_release(&state);\n+\treturn res;\n }\ndiff --git a/cache.h b/cache.h\nindex 8eaad70..91e2f81 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1871,6 +1871,6 @@ void sleep_millisec(int millisec);\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_file(const char *filename);\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 36a3eeb..e70e4d1 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -697,14 +697,14 @@ void sleep_millisec(int millisec)\n \tpoll(NULL, 0, millisec);\n }\n \n-int is_empty_file(const char *filename)\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\terror_errno(_(\"could not stat %s\"), filename);\n+\t\tdie_errno(_(\"could not stat %s\"), filename);\n \t}\n \n \treturn !st.st_size;\n\n\n\nPranit Bauva (6):\n  bisect--helper: `bisect_clean_state` shell function in C\n  t6030: explicitly test for bisection cleanup\n  wrapper: move is_empty_file() and rename it as\n    is_empty_or_missing_file()\n  bisect--helper: `bisect_reset` shell function in C\n  bisect--helper: `is_expected_rev` & `check_expected_revs` shell\n    function in C\n  bisect--helper: `bisect_write` shell function in C\n\n builtin/am.c                |  20 +---\n builtin/bisect--helper.c    | 222 +++++++++++++++++++++++++++++++++++++++++++-\n cache.h                     |   3 +\n git-bisect.sh               |  97 ++-----------------\n t/t6030-bisect-porcelain.sh |  17 ++++\n wrapper.c                   |  13 +++\n 6 files changed, 263 insertions(+), 109 deletions(-)\n\n-- \n2.9.0\n\n"},{"id":"290188","messageId":"20160626122356.28999-2-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:51Z","receivedAt":"2016-06-26T12:25:22Z","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 and will be called by\nbisect_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 builtin/bisect--helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 26 +++--------------------\n 2 files changed, 57 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 91027b0..57fd4e9 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,12 +3,21 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_write_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_names, \"BISECT_NAMES\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -78,11 +87,49 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\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+static 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);\n+\trefs_for_removal.strdup_strings = 1;\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tremove_path(git_path_bisect_expected_rev());\n+\tremove_path(git_path_bisect_ancestors_ok());\n+\tremove_path(git_path_bisect_log());\n+\tremove_path(git_path_bisect_names());\n+\tremove_path(git_path_bisect_run());\n+\tremove_path(git_path_bisect_write_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tremove_path(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+\tremove_path(git_path_bisect_start());\n+\n+\treturn result;\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\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -90,6 +137,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@@ -108,6 +157,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 cd39bd0..bbc57d2 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -187,7 +187,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@@ -196,7 +196,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-- \n2.9.0\n\n"},{"id":"290189","messageId":"20160626122356.28999-3-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 2/6] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:52Z","receivedAt":"2016-06-26T12:25:27Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"This is not an improvement in the test coverage but it helps in making\nit explicit as to what exactly would be the error as other tests are\nfocussed on testing other things.\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\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\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 e74662b..a17f7a6 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-- \n2.9.0\n\n"},{"id":"290190","messageId":"20160626122356.28999-4-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 3/6] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:53Z","receivedAt":"2016-06-26T12:25:32Z","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 3dfe70b..6ee158f 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@@ -1323,7 +1307,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@@ -1911,7 +1895,7 @@ next:\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 6049f86..91e2f81 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1870,4 +1870,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 5dc4e15..e70e4d1 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -696,3 +696,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-- \n2.9.0\n\n"},{"id":"290191","messageId":"20160626122356.28999-5-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 4/6] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:54Z","receivedAt":"2016-06-26T12:25:35Z","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 and will be called by some\nother 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 | 47 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++--------------------------\n 2 files changed, 48 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 57fd4e9..96f6b65 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,6 +4,8 @@\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_write_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -13,11 +15,13 @@ static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -124,12 +128,47 @@ static int bisect_clean_state(void)\n \treturn result;\n }\n \n+static int bisect_reset(const char *commit)\n+{\n+\tstruct strbuf branch = STRBUF_INIT;\n+\n+\tif (!commit) {\n+\t\tif (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n+\t\t\tprintf(\"We are not bisecting.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tstruct object_id oid;\n+\t\tif (get_oid(commit, &oid))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addstr(&branch, commit);\n+\t}\n+\n+\tif (!file_exists(git_path_bisect_head())) {\n+\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\targv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n+\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\terror(_(\"Could not check out original HEAD '%s'. Try\"\n+\t\t\t\t\"'git bisect reset <commit>'.\"), branch.buf);\n+\t\t\tstrbuf_release(&branch);\n+\t\t\targv_array_clear(&argv);\n+\t\t\treturn -1;\n+\t\t}\n+\t\targv_array_clear(&argv);\n+\t}\n+\n+\tstrbuf_release(&branch);\n+\treturn bisect_clean_state();\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n-\t\tBISECT_CLEAN_STATE\n+\t\tBISECT_CLEAN_STATE,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -139,6 +178,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@@ -161,6 +202,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 bbc57d2..18580b7 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-- \n2.9.0\n\n"},{"id":"290192","messageId":"20160626122356.28999-6-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:55Z","receivedAt":"2016-06-26T12:25:39Z","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 and will be\ncalled 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 96f6b65..96de65a 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -162,13 +162,40 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static int is_expected_rev(const char *expected_hex)\n+{\n+\tstruct strbuf actual_hex = STRBUF_INIT;\n+\tint res = 0;\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 0) {\n+\t\tstrbuf_trim(&actual_hex);\n+\t\tres = !strcmp(actual_hex.buf, expected_hex);\n+\t}\n+\tstrbuf_release(&actual_hex);\n+\treturn res;\n+}\n+\n+static int check_expected_revs(const char **revs, int rev_nr)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < rev_nr; i++) {\n+\t\tif (!is_expected_rev(revs[i])) {\n+\t\t\tremove_path(git_path_bisect_ancestors_ok());\n+\t\t\tremove_path(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@@ -180,6 +207,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@@ -206,6 +235,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 18580b7..4f6545e 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -238,22 +238,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 $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n\n"},{"id":"290193","messageId":"20160626122356.28999-7-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v3 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-06-26T12:23:56Z","receivedAt":"2016-06-26T12:25:42Z","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 and will be called by some\nother 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_state and\npass the memory address around functions.\n\nThis patch also introduces new methods namely bisect_state_init() and\nbisect_state_release() for easy memory management for the struct\nbisect_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 | 99 ++++++++++++++++++++++++++++++++++++++++++++----\n git-bisect.sh            | 25 ++----------\n 2 files changed, 96 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 96de65a..e946ba9 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -22,9 +22,29 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n+\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tstruct strbuf term_good;\n+\tstruct strbuf term_bad;\n+};\n+\n+static int bisect_terms_init(struct bisect_terms *term)\n+{\n+\tstrbuf_init(&term->term_good, 0);\n+\tstrbuf_init(&term->term_bad, 0);\n+\treturn 0;\n+}\n+\n+static int bisect_terms_release(struct bisect_terms *term)\n+{\n+\tstrbuf_release(&term->term_good);\n+\tstrbuf_release(&term->term_good);\n+\treturn 0;\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -188,6 +208,52 @@ static int check_expected_revs(const char **revs, int rev_nr)\n \treturn 0;\n }\n \n+static int bisect_write(const char *state, const char *rev,\n+\t\t\tconst struct bisect_terms *term, int nolog)\n+{\n+\tstruct strbuf tag = STRBUF_INIT;\n+\tstruct strbuf commit_name = STRBUF_INIT;\n+\tstruct object_id oid;\n+\tstruct commit *commit;\n+\tstruct pretty_print_context pp = {0};\n+\tFILE *fp;\n+\n+\tif (!strcmp(state, term->term_bad.buf))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\telse if(one_of(state, term->term_good.buf, \"skip\", NULL))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\telse\n+\t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_release(&tag);\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp)\n+\t\treturn error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\n+\tcommit = lookup_commit_reference(oid.hash);\n+\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n+\t\tcommit_name.buf);\n+\tstrbuf_release(&commit_name);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+\tfclose(fp);\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -195,9 +261,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@@ -209,10 +276,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n+\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n+\t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n \t};\n+\tstruct bisect_terms state;\n+\tbisect_terms_init(&state);\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -221,24 +292,38 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n \tswitch (cmdmode) {\n+\tint nolog;\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n-\t\treturn write_terms(argv[0], argv[1]);\n+\t\tres = write_terms(argv[0], argv[1]);\n+\t\tbreak;\n \tcase BISECT_CLEAN_STATE:\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n-\t\treturn bisect_clean_state();\n+\t\tres = bisect_clean_state();\n+\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n-\t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\t\tres = bisect_reset(argc ? argv[0] : NULL);\n+\t\tbreak;\n \tcase CHECK_EXPECTED_REVS:\n-\t\treturn check_expected_revs(argv, argc);\n+\t\tres = check_expected_revs(argv, argc);\n+\t\tbreak;\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n+\t\tstrbuf_addstr(&state.term_good, argv[2]);\n+\t\tstrbuf_addstr(&state.term_bad, argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &state, nolog);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tbisect_terms_release(&state);\n+\treturn res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 4f6545e..b9896a4 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -145,7 +145,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@@ -221,23 +221,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 \t1,\"$TERM_BAD\"|1,\"$TERM_GOOD\"|1,skip)\n \t\trev=$(git rev-parse --verify $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n\n"},{"id":"290909","messageId":"20160706202523.9850-1-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160626122356.28999-1-pranit.bauva@gmail.com","subject":"[PATCH v4 0/6] convert various shell functions in git-bisect to C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:17Z","receivedAt":"2016-07-06T20:26:45Z","isPatch":true,"sender":{"key":"pranit.bauva@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2959938?v=4"},"body":"Some minor nits. Previous version can be found here[1].\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/298263\n\nThe inter-diff is :\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex e946ba9..c2f3cee 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -31,18 +31,16 @@ struct bisect_terms {\n \tstruct strbuf term_bad;\n };\n \n-static int bisect_terms_init(struct bisect_terms *term)\n+static void bisect_terms_init(struct bisect_terms *terms)\n {\n-\tstrbuf_init(&term->term_good, 0);\n-\tstrbuf_init(&term->term_bad, 0);\n-\treturn 0;\n+\tstrbuf_init(&terms->term_good, 0);\n+\tstrbuf_init(&terms->term_bad, 0);\n }\n \n-static int bisect_terms_release(struct bisect_terms *term)\n+static void bisect_terms_release(struct bisect_terms *terms)\n {\n-\tstrbuf_release(&term->term_good);\n-\tstrbuf_release(&term->term_good);\n-\treturn 0;\n+\tstrbuf_release(&terms->term_good);\n+\tstrbuf_release(&terms->term_bad);\n }\n \n /*\n@@ -209,7 +207,7 @@ static int check_expected_revs(const char **revs, int rev_nr)\n }\n \n static int bisect_write(const char *state, const char *rev,\n-\t\t\tconst struct bisect_terms *term, int nolog)\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@@ -218,9 +216,9 @@ static int bisect_write(const char *state, const char *rev,\n \tstruct pretty_print_context pp = {0};\n \tFILE *fp;\n \n-\tif (!strcmp(state, term->term_bad.buf))\n+\tif (!strcmp(state, terms->term_bad.buf))\n \t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n-\telse if(one_of(state, term->term_good.buf, \"skip\", NULL))\n+\telse if(one_of(state, terms->term_good.buf, \"skip\", NULL))\n \t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n \telse\n \t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n@@ -282,8 +280,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\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 state;\n-\tbisect_terms_init(&state);\n+\tstruct bisect_terms terms;\n+\tbisect_terms_init(&terms);\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -317,13 +315,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 4 && argc != 5)\n \t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n \t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n-\t\tstrbuf_addstr(&state.term_good, argv[2]);\n-\t\tstrbuf_addstr(&state.term_bad, argv[3]);\n-\t\tres = bisect_write(argv[0], argv[1], &state, nolog);\n+\t\tstrbuf_addstr(&terms.term_good, argv[2]);\n+\t\tstrbuf_addstr(&terms.term_bad, argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n \t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\tbisect_terms_release(&state);\n+\tbisect_terms_release(&terms);\n \treturn res;\n }\n\n\nPranit Bauva (6):\n  bisect--helper: `bisect_clean_state` shell function in C\n  t6030: explicitly test for bisection cleanup\n  wrapper: move is_empty_file() and rename it as\n    is_empty_or_missing_file()\n  bisect--helper: `bisect_reset` shell function in C\n  bisect--helper: `is_expected_rev` & `check_expected_revs` shell\n    function in C\n  bisect--helper: `bisect_write` shell function in C\n\n builtin/am.c                |  20 +---\n builtin/bisect--helper.c    | 220 +++++++++++++++++++++++++++++++++++++++++++-\n cache.h                     |   3 +\n git-bisect.sh               |  97 ++-----------------\n t/t6030-bisect-porcelain.sh |  17 ++++\n wrapper.c                   |  13 +++\n 6 files changed, 261 insertions(+), 109 deletions(-)\n\n-- \n2.9.0\n\n"},{"id":"290910","messageId":"20160706202523.9850-2-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 1/6] bisect--helper: `bisect_clean_state` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:18Z","receivedAt":"2016-07-06T20:26:49Z","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 and will be called by\nbisect_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 builtin/bisect--helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 26 +++--------------------\n 2 files changed, 57 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 91027b0..57fd4e9 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -3,12 +3,21 @@\n #include \"parse-options.h\"\n #include \"bisect.h\"\n #include \"refs.h\"\n+#include \"dir.h\"\n \n static GIT_PATH_FUNC(git_path_bisect_write_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_names, \"BISECT_NAMES\")\n+static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n+static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -78,11 +87,49 @@ static int write_terms(const char *bad, const char *good)\n \treturn (res < 0) ? -1 : 0;\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+static 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);\n+\trefs_for_removal.strdup_strings = 1;\n+\tstring_list_clear(&refs_for_removal, 0);\n+\tremove_path(git_path_bisect_expected_rev());\n+\tremove_path(git_path_bisect_ancestors_ok());\n+\tremove_path(git_path_bisect_log());\n+\tremove_path(git_path_bisect_names());\n+\tremove_path(git_path_bisect_run());\n+\tremove_path(git_path_bisect_write_terms());\n+\t/* Cleanup head-name if it got left by an old version of git-bisect */\n+\tremove_path(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+\tremove_path(git_path_bisect_start());\n+\n+\treturn result;\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\tWRITE_TERMS,\n+\t\tBISECT_CLEAN_STATE\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -90,6 +137,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@@ -108,6 +157,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 cd39bd0..bbc57d2 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -187,7 +187,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@@ -196,7 +196,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-- \n2.9.0\n\n"},{"id":"290911","messageId":"20160706202523.9850-3-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 2/6] t6030: explicitly test for bisection cleanup","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:19Z","receivedAt":"2016-07-06T20:26:53Z","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\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\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 e74662b..a17f7a6 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-- \n2.9.0\n\n"},{"id":"290912","messageId":"20160706202523.9850-4-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 3/6] wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:20Z","receivedAt":"2016-07-06T20:26:57Z","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 3dfe70b..6ee158f 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@@ -1323,7 +1307,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@@ -1911,7 +1895,7 @@ next:\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 6049f86..91e2f81 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1870,4 +1870,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 5dc4e15..e70e4d1 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -696,3 +696,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-- \n2.9.0\n\n"},{"id":"290913","messageId":"20160706202523.9850-5-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 4/6] bisect--helper: `bisect_reset` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:21Z","receivedAt":"2016-07-06T20:27:04Z","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 and will be called by some\nother 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 | 47 ++++++++++++++++++++++++++++++++++++++++++++++-\n git-bisect.sh            | 28 ++--------------------------\n 2 files changed, 48 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 57fd4e9..96f6b65 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -4,6 +4,8 @@\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_write_terms, \"BISECT_TERMS\")\n static GIT_PATH_FUNC(git_path_bisect_expected_rev, \"BISECT_EXPECTED_REV\")\n@@ -13,11 +15,13 @@ static GIT_PATH_FUNC(git_path_bisect_names, \"BISECT_NAMES\")\n static GIT_PATH_FUNC(git_path_bisect_run, \"BISECT_RUN\")\n static GIT_PATH_FUNC(git_path_head_name, \"head-name\")\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@@ -124,12 +128,47 @@ static int bisect_clean_state(void)\n \treturn result;\n }\n \n+static int bisect_reset(const char *commit)\n+{\n+\tstruct strbuf branch = STRBUF_INIT;\n+\n+\tif (!commit) {\n+\t\tif (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {\n+\t\t\tprintf(\"We are not bisecting.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\tstrbuf_rtrim(&branch);\n+\t} else {\n+\t\tstruct object_id oid;\n+\t\tif (get_oid(commit, &oid))\n+\t\t\treturn error(_(\"'%s' is not a valid commit\"), commit);\n+\t\tstrbuf_addstr(&branch, commit);\n+\t}\n+\n+\tif (!file_exists(git_path_bisect_head())) {\n+\t\tstruct argv_array argv = ARGV_ARRAY_INIT;\n+\t\targv_array_pushl(&argv, \"checkout\", branch.buf, \"--\", NULL);\n+\t\tif (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {\n+\t\t\terror(_(\"Could not check out original HEAD '%s'. Try\"\n+\t\t\t\t\"'git bisect reset <commit>'.\"), branch.buf);\n+\t\t\tstrbuf_release(&branch);\n+\t\t\targv_array_clear(&argv);\n+\t\t\treturn -1;\n+\t\t}\n+\t\targv_array_clear(&argv);\n+\t}\n+\n+\tstrbuf_release(&branch);\n+\treturn bisect_clean_state();\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n \t\tNEXT_ALL = 1,\n \t\tWRITE_TERMS,\n-\t\tBISECT_CLEAN_STATE\n+\t\tBISECT_CLEAN_STATE,\n+\t\tBISECT_RESET\n \t} cmdmode = 0;\n \tint no_checkout = 0;\n \tstruct option options[] = {\n@@ -139,6 +178,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@@ -161,6 +202,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 bbc57d2..18580b7 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-- \n2.9.0\n\n"},{"id":"290914","messageId":"20160706202523.9850-6-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 5/6] bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:22Z","receivedAt":"2016-07-06T20:27:07Z","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 and will be\ncalled 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 96f6b65..96de65a 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -162,13 +162,40 @@ static int bisect_reset(const char *commit)\n \treturn bisect_clean_state();\n }\n \n+static int is_expected_rev(const char *expected_hex)\n+{\n+\tstruct strbuf actual_hex = STRBUF_INIT;\n+\tint res = 0;\n+\tif (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 0) {\n+\t\tstrbuf_trim(&actual_hex);\n+\t\tres = !strcmp(actual_hex.buf, expected_hex);\n+\t}\n+\tstrbuf_release(&actual_hex);\n+\treturn res;\n+}\n+\n+static int check_expected_revs(const char **revs, int rev_nr)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < rev_nr; i++) {\n+\t\tif (!is_expected_rev(revs[i])) {\n+\t\t\tremove_path(git_path_bisect_ancestors_ok());\n+\t\t\tremove_path(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@@ -180,6 +207,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@@ -206,6 +235,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 18580b7..4f6545e 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -238,22 +238,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 $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n\n"},{"id":"290915","messageId":"20160706202523.9850-7-pranit.bauva@gmail.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"[PATCH v4 6/6] bisect--helper: `bisect_write` shell function in C","fromName":"Pranit Bauva","fromEmail":"pranit.bauva@gmail.com","sentAt":"2016-07-06T20:25:23Z","receivedAt":"2016-07-06T20:27:10Z","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 and will be called by some\nother methods.\n\nNote: bisect_write() uses two variables namely TERM_GOOD and TERM_BAD\nfrom the global shell script thus we need to pass it to the subcommand\nusing the arguments. We then store them in a struct bisect_terms and\npass the memory address around functions.\n\nThis patch also introduces new methods namely bisect_state_init() and\nbisect_terms_release() for easy memory management for the struct\nbisect_terms.\n\nMentored-by: Lars Schneider <larsxschneider@gmail.com>\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nSigned-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n---\n builtin/bisect--helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++----\n git-bisect.sh            | 25 ++-----------\n 2 files changed, 94 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\nindex 96de65a..c2f3cee 100644\n--- a/builtin/bisect--helper.c\n+++ b/builtin/bisect--helper.c\n@@ -22,9 +22,27 @@ static const char * const git_bisect_helper_usage[] = {\n \tN_(\"git bisect--helper --write-terms <bad_term> <good_term>\"),\n \tN_(\"git bisect--helper --bisect-clean-state\"),\n \tN_(\"git bisect--helper --bisect-reset [<commit>]\"),\n+\tN_(\"git bisect--helper --bisect-write <state> <revision> <TERM_GOOD> <TERM_BAD> [<nolog>]\"),\n \tNULL\n };\n \n+struct bisect_terms {\n+\tstruct strbuf term_good;\n+\tstruct strbuf term_bad;\n+};\n+\n+static void bisect_terms_init(struct bisect_terms *terms)\n+{\n+\tstrbuf_init(&terms->term_good, 0);\n+\tstrbuf_init(&terms->term_bad, 0);\n+}\n+\n+static void bisect_terms_release(struct bisect_terms *terms)\n+{\n+\tstrbuf_release(&terms->term_good);\n+\tstrbuf_release(&terms->term_bad);\n+}\n+\n /*\n  * Check whether the string `term` belongs to the set of strings\n  * included in the variable arguments.\n@@ -188,6 +206,52 @@ static int check_expected_revs(const char **revs, int rev_nr)\n \treturn 0;\n }\n \n+static int bisect_write(const char *state, const char *rev,\n+\t\t\tconst struct bisect_terms *terms, int nolog)\n+{\n+\tstruct strbuf tag = STRBUF_INIT;\n+\tstruct strbuf commit_name = STRBUF_INIT;\n+\tstruct object_id oid;\n+\tstruct commit *commit;\n+\tstruct pretty_print_context pp = {0};\n+\tFILE *fp;\n+\n+\tif (!strcmp(state, terms->term_bad.buf))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s\", state);\n+\telse if(one_of(state, terms->term_good.buf, \"skip\", NULL))\n+\t\tstrbuf_addf(&tag, \"refs/bisect/%s-%s\", state, rev);\n+\telse\n+\t\treturn error(_(\"Bad bisect_write argument: %s\"), state);\n+\n+\tif (get_oid(rev, &oid)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn error(_(\"couldn't get the oid of the rev '%s'\"), rev);\n+\t}\n+\n+\tif (update_ref(NULL, tag.buf, oid.hash, NULL, 0,\n+\t\t       UPDATE_REFS_MSG_ON_ERR)) {\n+\t\tstrbuf_release(&tag);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_release(&tag);\n+\n+\tfp = fopen(git_path_bisect_log(), \"a\");\n+\tif (!fp)\n+\t\treturn error_errno(_(\"couldn't open the file '%s'\"), git_path_bisect_log());\n+\n+\tcommit = lookup_commit_reference(oid.hash);\n+\tformat_commit_message(commit, \"%s\", &commit_name, &pp);\n+\tfprintf(fp, \"# %s: [%s] %s\\n\", state, sha1_to_hex(oid.hash),\n+\t\tcommit_name.buf);\n+\tstrbuf_release(&commit_name);\n+\n+\tif (!nolog)\n+\t\tfprintf(fp, \"git bisect %s %s\\n\", state, rev);\n+\n+\tfclose(fp);\n+\treturn 0;\n+}\n+\n int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n@@ -195,9 +259,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@@ -209,10 +274,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"reset the bisection state\"), BISECT_RESET),\n \t\tOPT_CMDMODE(0, \"check-expected-revs\", &cmdmode,\n \t\t\t N_(\"check for expected revs\"), CHECK_EXPECTED_REVS),\n+\t\tOPT_CMDMODE(0, \"bisect-write\", &cmdmode,\n+\t\t\t N_(\"write out the bisection state in BISECT_LOG\"), BISECT_WRITE),\n \t\tOPT_BOOL(0, \"no-checkout\", &no_checkout,\n \t\t\t N_(\"update BISECT_HEAD instead of checking out the current commit\")),\n \t\tOPT_END()\n \t};\n+\tstruct bisect_terms terms;\n+\tbisect_terms_init(&terms);\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_bisect_helper_usage, 0);\n@@ -221,24 +290,38 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_bisect_helper_usage, options);\n \n \tswitch (cmdmode) {\n+\tint nolog;\n \tcase NEXT_ALL:\n \t\treturn bisect_next_all(prefix, no_checkout);\n \tcase WRITE_TERMS:\n \t\tif (argc != 2)\n \t\t\tdie(_(\"--write-terms requires two arguments\"));\n-\t\treturn write_terms(argv[0], argv[1]);\n+\t\tres = write_terms(argv[0], argv[1]);\n+\t\tbreak;\n \tcase BISECT_CLEAN_STATE:\n \t\tif (argc != 0)\n \t\t\tdie(_(\"--bisect-clean-state requires no arguments\"));\n-\t\treturn bisect_clean_state();\n+\t\tres = bisect_clean_state();\n+\t\tbreak;\n \tcase BISECT_RESET:\n \t\tif (argc > 1)\n \t\t\tdie(_(\"--bisect-reset requires either zero or one arguments\"));\n-\t\treturn bisect_reset(argc ? argv[0] : NULL);\n+\t\tres = bisect_reset(argc ? argv[0] : NULL);\n+\t\tbreak;\n \tcase CHECK_EXPECTED_REVS:\n-\t\treturn check_expected_revs(argv, argc);\n+\t\tres = check_expected_revs(argv, argc);\n+\t\tbreak;\n+\tcase BISECT_WRITE:\n+\t\tif (argc != 4 && argc != 5)\n+\t\t\tdie(_(\"--bisect-write requires either 4 or 5 arguments\"));\n+\t\tnolog = (argc == 5) && !strcmp(argv[4], \"nolog\");\n+\t\tstrbuf_addstr(&terms.term_good, argv[2]);\n+\t\tstrbuf_addstr(&terms.term_bad, argv[3]);\n+\t\tres = bisect_write(argv[0], argv[1], &terms, nolog);\n+\t\tbreak;\n \tdefault:\n \t\tdie(\"BUG: unknown subcommand '%d'\", cmdmode);\n \t}\n-\treturn 0;\n+\tbisect_terms_release(&terms);\n+\treturn res;\n }\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 4f6545e..b9896a4 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -145,7 +145,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@@ -221,23 +221,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 \t1,\"$TERM_BAD\"|1,\"$TERM_GOOD\"|1,skip)\n \t\trev=$(git rev-parse --verify $(bisect_head)) ||\n \t\t\tdie \"$(gettext \"Bad rev input: $(bisect_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-- \n2.9.0\n\n"},{"id":"291195","messageId":"xmqq37ng9e9v.fsf@gitster.mtv.corp.google.com","threadId":"42559","inReplyTo":"20160706202523.9850-3-pranit.bauva@gmail.com","subject":"Re: [PATCH v4 2/6] t6030: explicitly test for bisection cleanup","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-11T19:16:12Z","receivedAt":"2016-07-11T19:16:21Z","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> Add test to explicitly check that 'git bisect reset' is working as\n> expected. This is already covered implicitly by the test suite.\n\nWithout fuzzy \"this is not an improvement but it helps\" that sounds\nlike making excuse, the above reads much better.\n\n\n> Mentored-by: Lars Schneider <larsxschneider@gmail.com>\n> Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n>\n> ---\n> I faced this problem while converting `bisect_clean_state` and the tests\n> where showing breakages but it wasn't clear as to where exactly are they\n> breaking. This will patch  will help in that. Also I tested the test\n> coverage of the test suite before this patch and it covers this (I did\n> this by purposely changing names of files in git-bisect.sh and running\n> the test suite).\n>\n> Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>\n> ---\n>  t/t6030-bisect-porcelain.sh | 17 +++++++++++++++++\n>  1 file changed, 17 insertions(+)\n>\n> diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\n> index e74662b..a17f7a6 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"},{"id":"291196","messageId":"xmqqy4587zjl.fsf@gitster.mtv.corp.google.com","threadId":"42559","inReplyTo":"20160706202523.9850-1-pranit.bauva@gmail.com","subject":"Re: [PATCH v4 0/6] convert various shell functions in git-bisect to C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-11T19:19:42Z","receivedAt":"2016-07-11T19:19:49Z","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> Some minor nits. Previous version can be found here[1].\n>\n> [1]: http://thread.gmane.org/gmane.comp.version-control.git/298263\n>\n> The inter-diff is :\n> ...\n> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c\n> ...\n> Pranit Bauva (6):\n>   bisect--helper: `bisect_clean_state` shell function in C\n>   t6030: explicitly test for bisection cleanup\n>   wrapper: move is_empty_file() and rename it as\n>     is_empty_or_missing_file()\n>   bisect--helper: `bisect_reset` shell function in C\n>   bisect--helper: `is_expected_rev` & `check_expected_revs` shell\n>     function in C\n>   bisect--helper: `bisect_write` shell function in C\n>\n>  builtin/am.c                |  20 +---\n>  builtin/bisect--helper.c    | 220 +++++++++++++++++++++++++++++++++++++++++++-\n>  cache.h                     |   3 +\n>  git-bisect.sh               |  97 ++-----------------\n>  t/t6030-bisect-porcelain.sh |  17 ++++\n>  wrapper.c                   |  13 +++\n>  6 files changed, 261 insertions(+), 109 deletions(-)\n\nWill replace.  Thanks.\n\n"}]}