{"thread":{"id":"11192","subject":"[PATCH 0/3] builtin-commit fixes","startedAt":"2007-12-08T11:38:06Z","lastAt":"2007-12-09T12:22:32Z","messageCount":8,"participants":["Wincent Colaiuta","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"62403","messageId":"1197113889-16243-1-git-send-email-win@wincent.com","threadId":"11192","inReplyTo":null,"subject":"[PATCH 0/3] builtin-commit fixes","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T11:38:06Z","receivedAt":"2007-12-08T11:38:06Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"A little series to bring built-in commit back in line with the\nbehaviour as implemented by git-commit.sh and described in the\ndocumentation.\n\n1/3 Allow --no-verify to bypass commit-msg hook\n\n- git-commit.sh used to do this, but builtin-commit wasn't.\n\n2/3 Documentation: fix --no-verify documentation for \"git commit\"\n\n- The \"git commit\" man page should mention the commit-msg hook to\nbring it in line with what's in the hook notes and in\nDocumentation/hooks.txt.\n\n3/3 Fix commit-msg hook to allow editing\n\n- Again, git-commit.sh allowed this, but builtin-commit wasn't\ndoing so.\n\nI have manually tested these changes and they seem to work, but\nthe fact that the test suite didn't break when the behaviour of\n\"git commit\" changed is indicative of a hole in the suite. I am\nnot very familiar yet with the test machinery, but I am going\nto see if I can whip something up.\n\nCheers,\nWincent\n"},{"id":"62404","messageId":"1197113889-16243-2-git-send-email-win@wincent.com","threadId":"11192","inReplyTo":"1197113889-16243-1-git-send-email-win@wincent.com","subject":"[PATCH 1/3] Allow --no-verify to bypass commit-msg hook","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T11:38:07Z","receivedAt":"2007-12-08T11:38:07Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"At the moment the --no-verify switch to \"git commit\" instructs it to\nskip over the pre-commit hook. Here we teach \"git commit --no-verify\"\nto skip over the commit-msg hook as well. This brings the behaviour\nof builtin-commit back in line with git-commit.sh.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n builtin-commit.c |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 2ec8223..df9377e 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -791,7 +791,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\trollback_index_files();\n \t\tdie(\"could not read commit message\");\n \t}\n-\tif (run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n+\tif (!no_verify &&\n+\t    run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n \t\trollback_index_files();\n \t\texit(1);\n \t}\n-- \n1.5.3.7.1115.gaa595\n"},{"id":"62405","messageId":"1197113889-16243-3-git-send-email-win@wincent.com","threadId":"11192","inReplyTo":"1197113889-16243-2-git-send-email-win@wincent.com","subject":"[PATCH 2/3] Documentation: fix --no-verify documentation for \"git commit\"","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T11:38:08Z","receivedAt":"2007-12-08T11:38:08Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The documentation for the --no-verify switch should mention the\ncommit-msg hook, not just the pre-commit hook.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n Documentation/git-commit.txt |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 4bb2791..4261384 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -86,7 +86,7 @@ OPTIONS\n \tAdd Signed-off-by line at the end of the commit message.\n \n --no-verify::\n-\tThis option bypasses the pre-commit hook.\n+\tThis option bypasses the pre-commit and commit-msg hooks.\n \tSee also link:hooks.html[hooks].\n \n --allow-empty::\n-- \n1.5.3.7.1115.gaa595\n"},{"id":"62406","messageId":"1197113889-16243-4-git-send-email-win@wincent.com","threadId":"11192","inReplyTo":"1197113889-16243-3-git-send-email-win@wincent.com","subject":"[PATCH 3/3] Fix commit-msg hook to allow editing","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T11:38:09Z","receivedAt":"2007-12-08T11:38:09Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The old git-commit.sh script allowed the commit-msg hook to not only\nprevent a commit from proceding, but also to edit the commit message\non the fly and allow it to proceed. So here we teach builtin-commit\nto do the same.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n builtin-commit.c |   16 ++++++++++------\n 1 files changed, 10 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex df9377e..a6223d2 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -787,14 +787,18 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tconst char *env[2] = { index, NULL };\n \t\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n \t\tlaunch_editor(git_path(commit_editmsg), &sb, env);\n-\t} else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n-\t\trollback_index_files();\n-\t\tdie(\"could not read commit message\");\n \t}\n-\tif (!no_verify &&\n-\t    run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n+\tif (!no_verify) {\n+\t\tif (run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n+\t\t\trollback_index_files();\n+\t\t\texit(1);\n+\t\t}\n+\t\tstrbuf_setlen(&sb, header_len);\n+\t}\n+\tif ((no_edit || !no_verify) &&\n+\t    strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n \t\trollback_index_files();\n-\t\texit(1);\n+\t\tdie(\"could not read commit message\");\n \t}\n \n \t/* Truncate the message just before the diff, if any. */\n-- \n1.5.3.7.1115.gaa595\n"},{"id":"62412","messageId":"1197116987-21802-1-git-send-email-win@wincent.com","threadId":"11192","inReplyTo":"1197113889-16243-1-git-send-email-win@wincent.com","subject":"[PATCH 4/4] Add tests for pre-commit and commit-msg hooks","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T12:29:47Z","receivedAt":"2007-12-08T12:29:47Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"As desired, these pass for git-commit.sh, fail for builtin-commit (prior\nto the fixes), and succeeded for builtin-commit (after the fixes).\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n t/t7501-commit.sh          |    2 +-\n t/t7503-pre-commit-hook.sh |   64 ++++++++++++++++++++++++++++++++\n t/t7504-commit-msg-hook.sh |   88 ++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 153 insertions(+), 1 deletions(-)\n create mode 100755 t/t7503-pre-commit-hook.sh\n create mode 100755 t/t7504-commit-msg-hook.sh\n\ndiff --git a/t/t7501-commit.sh b/t/t7501-commit.sh\nindex 19c4b2c..05aa97d 100755\n--- a/t/t7501-commit.sh\n+++ b/t/t7501-commit.sh\n@@ -4,7 +4,7 @@\n #\n \n # FIXME: Test the various index usages, -i and -o, test reflog,\n-# signoff, hooks\n+# signoff\n \n test_description='git-commit'\n . ./test-lib.sh\ndiff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh\nnew file mode 100755\nindex 0000000..c8097a7\n--- /dev/null\n+++ b/t/t7503-pre-commit-hook.sh\n@@ -0,0 +1,64 @@\n+#!/bin/sh\n+\n+test_description='pre-commit hook'\n+\n+. ./test-lib.sh\n+\n+test_expect_success \"with no hook\" \\\n+\t\"echo 'foo' > file &&\n+\t git add file &&\n+\t git commit -m 'first'\"\n+\n+test_expect_success \"--no-verify with no hook\" \\\n+\t\"echo 'bar' > file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'bar'\"\n+\n+# now install hook that always succeeds\n+HOOKDIR=\"$(git rev-parse --git-dir)/hooks\"\n+HOOK=\"$HOOKDIR/pre-commit\"\n+mkdir -p \"$HOOKDIR\"\n+cat > \"$HOOK\" <<EOF\n+#!/bin/sh\n+exit 0\n+EOF\n+chmod +x \"$HOOK\"\n+\n+test_expect_success \"with succeeding hook\" \\\n+\t\"echo 'more' >> file &&\n+\t git add file &&\n+\t git commit -m 'more'\"\n+\n+test_expect_success \"--no-verify with succeeding hook\" \\\n+\t\"echo 'even more' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'even more'\"\n+\n+# now a hook that fails\n+cat > \"$HOOK\" <<EOF\n+#!/bin/sh\n+exit 1\n+EOF\n+\n+test_expect_failure \"with failing hook\" \\\n+\t\"echo 'another' >> file &&\n+\t git add file &&\n+\t git commit -m 'another'\"\n+\n+test_expect_success \"--no-verify with failing hook\" \\\n+\t\"echo 'stuff' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'stuff'\"\n+\n+chmod -x \"$HOOK\"\n+test_expect_success \"with non-executable hook\" \\\n+\t\"echo 'content' >> file &&\n+\t git add file &&\n+\t git commit -m 'content'\"\n+\n+test_expect_success \"--no-verify with non-executable hook\" \\\n+\t\"echo 'more content' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'more content'\"\n+\n+test_done\ndiff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh\nnew file mode 100755\nindex 0000000..17aad7c\n--- /dev/null\n+++ b/t/t7504-commit-msg-hook.sh\n@@ -0,0 +1,88 @@\n+#!/bin/sh\n+\n+test_description='commit-msg hook'\n+\n+. ./test-lib.sh\n+\n+test_expect_success \"with no hook\" \\\n+\t\"echo 'foo' > file &&\n+\t git add file &&\n+\t git commit -m 'first'\"\n+\n+test_expect_success \"--no-verify with no hook\" \\\n+\t\"echo 'bar' > file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'bar'\"\n+\n+# now install hook that always succeeds\n+HOOKDIR=\"$(git rev-parse --git-dir)/hooks\"\n+HOOK=\"$HOOKDIR/commit-msg\"\n+mkdir -p \"$HOOKDIR\"\n+cat > \"$HOOK\" <<EOF\n+#!/bin/sh\n+exit 0\n+EOF\n+chmod +x \"$HOOK\"\n+\n+test_expect_success \"with succeeding hook\" \\\n+\t\"echo 'more' >> file &&\n+\t git add file &&\n+\t git commit -m 'more'\"\n+\n+test_expect_success \"--no-verify with succeeding hook\" \\\n+\t\"echo 'even more' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'even more'\"\n+\n+# now a hook that fails\n+cat > \"$HOOK\" <<EOF\n+#!/bin/sh\n+exit 1\n+EOF\n+\n+test_expect_failure \"with failing hook\" \\\n+\t\"echo 'another' >> file &&\n+\t git add file &&\n+\t git commit -m 'another'\"\n+\n+test_expect_success \"--no-verify with failing hook\" \\\n+\t\"echo 'stuff' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'stuff'\"\n+\n+chmod -x \"$HOOK\"\n+test_expect_success \"with non-executable hook\" \\\n+\t\"echo 'content' >> file &&\n+\t git add file &&\n+\t git commit -m 'content'\"\n+\n+test_expect_success \"--no-verify with non-executable hook\" \\\n+\t\"echo 'more content' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'more content'\"\n+\n+# now a hook that edits the commit message\n+cat > \"$HOOK\" <<'EOF'\n+#!/bin/sh\n+echo \"new message\" > \"$1\"\n+exit 0\n+EOF\n+chmod +x \"$HOOK\"\n+\n+commit_msg_is () {\n+\ttest \"`git log --pretty=format:%s%b -1`\" = \"$1\"\n+}\n+\n+test_expect_success \"hook edits commit message\" \\\n+\t\"echo 'additional' >> file &&\n+\t git add file &&\n+\t git commit -m 'additional' &&\n+\t commit_msg_is 'new message'\"\n+\n+test_expect_success \"hook doesn't edit commit message\" \\\n+\t\"echo 'plus' >> file &&\n+\t git add file &&\n+\t git commit --no-verify -m 'plus' &&\n+\t commit_msg_is 'plus'\"\n+\n+test_done\n-- \n1.5.3.7.1115.g3d1c\n"},{"id":"62414","messageId":"6C67E7B0-EE28-450C-A33F-35D3F742F495@wincent.com","threadId":"11192","inReplyTo":"1197116987-21802-1-git-send-email-win@wincent.com","subject":"Re: [PATCH 4/4] Add tests for pre-commit and commit-msg hooks","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-08T12:51:43Z","receivedAt":"2007-12-08T12:51:43Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 8/12/2007, a las 13:29, Wincent Colaiuta escribió:\n\n> As desired, these pass for git-commit.sh, fail for builtin-commit  \n> (prior\n> to the fixes), and succeeded for builtin-commit (after the fixes).\n\nActually, that's a slight lie.\n\nThe commit-msg tests 9 and 10 (editing the commit message from the  \nhook) fail for git-commit.sh (tested 1.5.3.4 and 1.5.3.7).\n\nBy the looks of it, this discrepancy isn't actually a bug in git- \ncommit.sh, but is because of stuff that was in commit.c back in  \n1.5.3.7 and prior which causes a commit message like \"foo\" to yield  \n\"foo<unknown>\" when you do a \"git log --pretty=format:%s%b -1\"; post  \n1.5.3.7 (on master) it instead yields \"foo\", which is what I was  \ntesting for.\n\nCheers,\nWincent\n"},{"id":"62460","messageId":"7vtzmss58h.fsf@gitster.siamese.dyndns.org","threadId":"11192","inReplyTo":"1197113889-16243-4-git-send-email-win@wincent.com","subject":"Re: [PATCH 3/3] Fix commit-msg hook to allow editing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-09T07:21:34Z","receivedAt":"2007-12-09T07:21:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Wincent Colaiuta <win@wincent.com> writes:\n\n> The old git-commit.sh script allowed the commit-msg hook to not only\n> prevent a commit from proceding, but also to edit the commit message\n> on the fly and allow it to proceed. So here we teach builtin-commit\n> to do the same.\n\nThis is a bit unfortunate.\n\n> @@ -787,14 +787,18 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n>  \t\tconst char *env[2] = { index, NULL };\n>  \t\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n>  \t\tlaunch_editor(git_path(commit_editmsg), &sb, env);\n\nHere, launch-editor lets the user edit an external file, and reads it\nback into &sb, but ...\n\n>  \t}\n> +\tif (!no_verify) {\n> +\t\tif (run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n> +\t\t\trollback_index_files();\n> +\t\t\texit(1);\n> +\t\t}\n> +\t\tstrbuf_setlen(&sb, header_len);\n> +\t}\n\nwe need to discard it (I would prefer setlen to be done before running\nthe hook, just to make the logic flow more natural), because we need to\nread it back again anyway.  On the other hand, if we do not start the\neditor, we used to read the contents before running the hook, which was\nwrong, and the call to read the file is moved after, like this:\n\n> +\tif ((no_edit || !no_verify) &&\n> +\t    strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n>  \t\trollback_index_files();\n> +\t\tdie(\"could not read commit message\");\n>  \t}\n\nwhich makes the logic to decide if we read the file back again\nunnecessarily convoluted.  The reason why (no_edit || !no_verify) is\nthere is very closely tied to the fact that you happened to have already\nread in the launch_editor() codepath but not yet in no_edit codepath.\nThis feels very error prone.\n\n\tSide note. an unrelated reason where this convolution comes from\n\tis the unfortunate naming of many options and double-negations\n\tthey bring in.  A normal human being needs to read expressions\n\tlike \"if (!no_foo || no_foo)\" three times before understanding\n\twhat is being checked.\n\nI would suggest doing the above differently.\n\n * Allow launch_editor() not to read back the edited result into strbuf\n   at all (perhaps pass NULL to signal that), and make \"if (!no_edit)\"\n   codepath use it;\n\n * The codeflow would become:\n\n\tif (!no_edit) {\n\t\tlaunch editor, in \"no readback\" mode;\n\t}\n\tif (!no_verify) {\n        \trun hook, let it interfere;\n\t}\n\tread the file to &sb, no matter what no_edit/no_verify says.\n\nIOW, how about something like this?\n\n---\n\n builtin-commit.c |    9 +++++----\n builtin-tag.c    |    2 ++\n 2 files changed, 7 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 2032ca3..30a9deb 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -787,16 +787,17 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tchar index[PATH_MAX];\n \t\tconst char *env[2] = { index, NULL };\n \t\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n-\t\tlaunch_editor(git_path(commit_editmsg), &sb, env);\n-\t} else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n-\t\trollback_index_files();\n-\t\tdie(\"could not read commit message\");\n+\t\tlaunch_editor(git_path(commit_editmsg), NULL, env);\n \t}\n \tif (!no_verify &&\n \t    run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n \t\trollback_index_files();\n \t\texit(1);\n \t}\n+\tif (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n+\t\trollback_index_files();\n+\t\tdie(\"could not read commit message\");\n+\t}\n \n \t/* Truncate the message just before the diff, if any. */\n \tp = strstr(sb.buf, \"\\ndiff --git a/\");\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex 729389b..9f966fc 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -53,6 +53,8 @@ void launch_editor(const char *path, struct strbuf *buffer, const char *const *e\n \t\t\tdie(\"There was a problem with the editor %s.\", editor);\n \t}\n \n+\tif (!buffer)\n+\t\treturn;\n \tif (strbuf_read_file(buffer, path, 0) < 0)\n \t\tdie(\"could not read message file '%s': %s\",\n \t\t    path, strerror(errno));\n\n\n                \n"},{"id":"62481","messageId":"5B3413C6-48E3-44CD-9577-622C9A93230A@wincent.com","threadId":"11192","inReplyTo":"7vtzmss58h.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 3/3] Fix commit-msg hook to allow editing","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-09T12:22:32Z","receivedAt":"2007-12-09T12:22:32Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 9/12/2007, a las 8:21, Junio C Hamano escribió:\n\n> IOW, how about something like this?\n>\n> ---\n>\n> builtin-commit.c |    9 +++++----\n> builtin-tag.c    |    2 ++\n> 2 files changed, 7 insertions(+), 4 deletions(-)\n>\n> diff --git a/builtin-commit.c b/builtin-commit.c\n> index 2032ca3..30a9deb 100644\n> --- a/builtin-commit.c\n> +++ b/builtin-commit.c\n> @@ -787,16 +787,17 @@ int cmd_commit(int argc, const char **argv,  \n> const char *prefix)\n> \t\tchar index[PATH_MAX];\n> \t\tconst char *env[2] = { index, NULL };\n> \t\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n> -\t\tlaunch_editor(git_path(commit_editmsg), &sb, env);\n> -\t} else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n> -\t\trollback_index_files();\n> -\t\tdie(\"could not read commit message\");\n> +\t\tlaunch_editor(git_path(commit_editmsg), NULL, env);\n> \t}\n> \tif (!no_verify &&\n> \t    run_hook(index_file, \"commit-msg\", git_path(commit_editmsg))) {\n> \t\trollback_index_files();\n> \t\texit(1);\n> \t}\n> +\tif (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {\n> +\t\trollback_index_files();\n> +\t\tdie(\"could not read commit message\");\n> +\t}\n>\n> \t/* Truncate the message just before the diff, if any. */\n> \tp = strstr(sb.buf, \"\\ndiff --git a/\");\n> diff --git a/builtin-tag.c b/builtin-tag.c\n> index 729389b..9f966fc 100644\n> --- a/builtin-tag.c\n> +++ b/builtin-tag.c\n> @@ -53,6 +53,8 @@ void launch_editor(const char *path, struct strbuf  \n> *buffer, const char *const *e\n> \t\t\tdie(\"There was a problem with the editor %s.\", editor);\n> \t}\n>\n> +\tif (!buffer)\n> +\t\treturn;\n> \tif (strbuf_read_file(buffer, path, 0) < 0)\n> \t\tdie(\"could not read message file '%s': %s\",\n> \t\t    path, strerror(errno));\n\nExcellent. Reads much better. I hadn't considered changing the strbuf  \nAPI, but looking at the callers of launch_editor this is a safe  \nchange. Ack.\n\nCheers,\nWincent\n"}]}