{"thread":{"id":"56509","subject":"[PATCH 0/2] (experimental) diff --quote-path-with-sp","startedAt":"2021-09-15T22:33:20Z","lastAt":"2021-09-16T20:59:18Z","messageCount":7,"participants":["Junio C Hamano","Gwyneth Morgan","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"436054","messageId":"20210915223316.1653443-1-gitster@pobox.com","threadId":"56509","inReplyTo":null,"subject":"[PATCH 0/2] (experimental) diff --quote-path-with-sp","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-15T22:33:14Z","receivedAt":"2021-09-15T22:33:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Long time ago, we had a discussion with GNU patch/diff maintainer\nand agreed that pathnames with certain \"difficult\" bytes needs to be\nquoted to ensure the resulting patch is machine parseable in an\nunambiguous way [*1*].  Recently, we saw a report that found that\nGNU patch is unhappy with our diff output for a path with SP in it\n[*2*].\n\nWith this experimental option, the beginning part of the patch\noutput will have pathnames with SP in them enclosed inside a pair of\ndouble quotes, like so:\n\n\tdiff --git \"a/A Name\" \"b/A Name\"\n\t--- \"a/A Name\"\n\t+++ \"b/A Name\"\n\nWe have always done this enclosing inside dq when the pathname had\nan even more difficult byte (like LF, double quotes, and HT), so we\nknow Git tools can handle such a patch output just fine already.\n\n *1* https://lore.kernel.org/git/87ek6s0w34.fsf@penguin.cs.ucla.edu/\n *2* https://lore.kernel.org/git/YR9Iaj%2FFqAyCMade@tilde.club/\n\n\nJunio C Hamano (2):\n  diff: simplify quote_two()\n  diff: --quote-path-with-sp\n\n Documentation/diff-options.txt |  5 +++++\n diff.c                         | 26 ++++++++++----------------\n diff.h                         |  1 +\n quote.c                        | 23 ++++++++++++++++++-----\n quote.h                        |  3 ++-\n t/t3902-quoted.sh              | 24 +++++++++++++++++++++++-\n 6 files changed, 59 insertions(+), 23 deletions(-)\n\n-- \n2.33.0-649-gd4f4107c2b\n\n"},{"id":"436055","messageId":"20210915223316.1653443-3-gitster@pobox.com","threadId":"56509","inReplyTo":"20210915223316.1653443-1-gitster@pobox.com","subject":"[PATCH 2/2] diff: --quote-path-with-sp","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-15T22:33:16Z","receivedAt":"2021-09-15T22:33:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Long time ago, we had a discussion with GNU patch/diff maintainer\nand agreed that pathnames with certain \"difficult\" bytes needs to be\nquoted to ensure the resulting patch is machine parseable in an\nunambiguous way [*1*].  Recently, we saw a report that found that\nGNU patch is unhappy with our diff output for a path with SP in it\n[*2*].\n\nTeach \"git diff\" and friends the \"--quote-path-with-sp\" option, that\nencloses a pathname with SP in it inside a pair of double-quotes,\neven though there is otherwise no byte in the pathname that need to\nbe encoded in the octal.\n\nAs an earlier parts of t/t3902 (outside the patch context) shows,\noutput from \"ls-files\", \"ls-tree\", and \"diff --name-only\" all follow\nthe same rule to decide paths with what bytes in them need quoting\nand how they are quoted.\n\nThis experimental option deliberately refrains from touching these\noutput and affects ONLY the paths that appear in the patch header,\ni.e. \"diff --git\", \"--- a/path\" and \"+++ b/path\" lines, that GNU\npatch may care.  This is to minimize potential damage this change\nmay cause to tools and scripts the users have been relying on.\n\n *1* https://lore.kernel.org/git/87ek6s0w34.fsf@penguin.cs.ucla.edu/\n *2* https://lore.kernel.org/git/YR9Iaj%2FFqAyCMade@tilde.club/\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/diff-options.txt |  5 +++++\n diff.c                         | 16 ++++++++++------\n diff.h                         |  1 +\n quote.c                        | 23 ++++++++++++++++++-----\n quote.h                        |  3 ++-\n t/t3902-quoted.sh              | 24 +++++++++++++++++++++++-\n 6 files changed, 59 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex c89d530d3d..dd9b35c806 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -507,6 +507,11 @@ ifndef::git-format-patch[]\n \tImplies `--patch`.\n endif::git-format-patch[]\n \n+--quote-path-with-sp::\n+\t(experimental) Quote a pathname that has SP in it inside a\n+\tpair of double quotes.  Such a quoted pathname should be\n+\thandled correctly by both Git and \"GNU patch\".\n+\n --abbrev[=<n>]::\n \tInstead of showing the full 40-byte hexadecimal object\n \tname in diff-raw format output and diff-tree header\ndiff --git a/diff.c b/diff.c\nindex 8143b737b7..73e42a9e18 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -480,11 +480,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static char *quote_two(const char *one, const char *two)\n+static char *quote_two(const char *one, const char *two, const struct diff_options *o)\n {\n \tstruct strbuf res = STRBUF_INIT;\n+\tint flags = o->flags.quote_path_with_sp ? CQUOTE_QUOTE_SP : 0;\n \n-\tquote_two_c_style(&res, one, two, 0);\n+\tquote_two_c_style(&res, one, two, flags);\n \treturn strbuf_detach(&res, NULL);\n }\n \n@@ -1784,6 +1785,7 @@ static void emit_rewrite_diff(const char *name_a,\n \tsize_t size_one, size_two;\n \tstruct emit_callback ecbdata;\n \tstruct strbuf out = STRBUF_INIT;\n+\tint flags = o->flags.quote_path_with_sp ? CQUOTE_QUOTE_SP : 0;\n \n \tif (diff_mnemonic_prefix && o->flags.reverse_diff) {\n \t\ta_prefix = o->b_prefix;\n@@ -1798,8 +1800,8 @@ static void emit_rewrite_diff(const char *name_a,\n \n \tstrbuf_reset(&a_name);\n \tstrbuf_reset(&b_name);\n-\tquote_two_c_style(&a_name, a_prefix, name_a, 0);\n-\tquote_two_c_style(&b_name, b_prefix, name_b, 0);\n+\tquote_two_c_style(&a_name, a_prefix, name_a, flags);\n+\tquote_two_c_style(&b_name, b_prefix, name_b, flags);\n \n \tsize_one = fill_textconv(o->repo, textconv_one, one, &data_one);\n \tsize_two = fill_textconv(o->repo, textconv_two, two, &data_two);\n@@ -3449,8 +3451,8 @@ static void builtin_diff(const char *name_a,\n \tname_a = DIFF_FILE_VALID(one) ? name_a : name_b;\n \tname_b = DIFF_FILE_VALID(two) ? name_b : name_a;\n \n-\ta_one = quote_two(a_prefix, name_a + (*name_a == '/'));\n-\tb_two = quote_two(b_prefix, name_b + (*name_b == '/'));\n+\ta_one = quote_two(a_prefix, name_a + (*name_a == '/'), o);\n+\tb_two = quote_two(b_prefix, name_b + (*name_b == '/'), o);\n \tlbl[0] = DIFF_FILE_VALID(one) ? a_one : \"/dev/null\";\n \tlbl[1] = DIFF_FILE_VALID(two) ? b_two : \"/dev/null\";\n \tstrbuf_addf(&header, \"%s%sdiff --git %s %s%s\\n\", line_prefix, meta, a_one, b_two, reset);\n@@ -5445,6 +5447,8 @@ static void prep_parse_options(struct diff_options *options)\n \t\t\t       PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_binary),\n \t\tOPT_BOOL(0, \"full-index\", &options->flags.full_index,\n \t\t\t N_(\"show full pre- and post-image object names on the \\\"index\\\" lines\")),\n+\t\tOPT_BOOL(0, \"quote-path-with-sp\", &options->flags.quote_path_with_sp,\n+\t\t\t N_(\"quote path with SP in it\")),\n \t\tOPT_COLOR_FLAG(0, \"color\", &options->use_color,\n \t\t\t       N_(\"show colored diff\")),\n \t\tOPT_CALLBACK_F(0, \"ws-error-highlight\", options, N_(\"<kind>\"),\ndiff --git a/diff.h b/diff.h\nindex 8ba85c5e60..f90f07bb72 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -198,6 +198,7 @@ struct diff_flags {\n \tunsigned suppress_diff_headers;\n \tunsigned dual_color_diffed_diffs;\n \tunsigned suppress_hunk_header_line_count;\n+\tunsigned quote_path_with_sp;\n };\n \n static inline void diff_flags_or(struct diff_flags *a,\ndiff --git a/quote.c b/quote.c\nindex 8a3a5e39eb..292ad76de5 100644\n--- a/quote.c\n+++ b/quote.c\n@@ -233,9 +233,11 @@ static inline int cq_must_quote(char c)\n \treturn cq_lookup[(unsigned char)c] + quote_path_fully > 0;\n }\n \n-/* returns the longest prefix not needing a quote up to maxlen if positive.\n-   This stops at the first \\0 because it's marked as a character needing an\n-   escape */\n+/*\n+ * Return the longest prefix not needing a quote up to maxlen if positive.\n+ * This stops at the first \\0 because it's marked as a character needing an\n+ * escape.\n+ */\n static size_t next_quote_pos(const char *s, ssize_t maxlen)\n {\n \tsize_t len;\n@@ -320,11 +322,22 @@ size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, unsigned fla\n \treturn quote_c_style_counted(name, -1, sb, fp, flags);\n }\n \n+/*\n+ * Quote concatenation of prefix and path (nothing in between); when\n+ * even one of the two needs quoting, the whole thing needs to be\n+ * quoted.  This is done by concatenating the result of quoting prefix\n+ * and path without surrounding dq next to each other and then enclosing\n+ * the whole thing inside a dq pair if needed.\n+ */\n void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path,\n \t\t       unsigned flags)\n {\n-\tint nodq = !!(flags & CQUOTE_NODQ);\n-\tif (quote_c_style(prefix, NULL, NULL, 0) ||\n+\tint nodq = (flags & CQUOTE_NODQ);\n+\tint force_dq = ((flags & CQUOTE_QUOTE_SP) &&\n+\t\t\t(strchr(prefix, ' ') || strchr(path, ' ')));\n+\n+\tif (force_dq ||\n+\t    quote_c_style(prefix, NULL, NULL, 0) ||\n \t    quote_c_style(path, NULL, NULL, 0)) {\n \t\tif (!nodq)\n \t\t\tstrbuf_addch(sb, '\"');\ndiff --git a/quote.h b/quote.h\nindex 049d8dd0b3..3e027d28c2 100644\n--- a/quote.h\n+++ b/quote.h\n@@ -81,7 +81,8 @@ int sq_dequote_to_strvec(char *arg, struct strvec *);\n int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);\n \n /* Bits in the flags parameter to quote_c_style() */\n-#define CQUOTE_NODQ 01\n+#define CQUOTE_NODQ 01 /* do not enclose the result in dq pair */\n+#define CQUOTE_QUOTE_SP 02 /* string with SP needs quoting */\n size_t quote_c_style(const char *name, struct strbuf *, FILE *, unsigned);\n void quote_two_c_style(struct strbuf *, const char *, const char *, unsigned);\n \ndiff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh\nindex f528008c36..c76cde435c 100755\n--- a/t/t3902-quoted.sh\n+++ b/t/t3902-quoted.sh\n@@ -27,7 +27,7 @@ for_each_name () {\n \t    \"$FN$HT$GN\" \"$FN$LF$GN\" \"$FN $GN\" \"$FN$GN\" \"$FN$DQ$GN\" \\\n \t    \"With SP in it\" \"$FN/file\"\n \tdo\n-\t\teval \"$1\"\n+\t\teval \"$1\" || return 1\n \tdone\n }\n \n@@ -45,6 +45,14 @@ test_expect_success 'setup' '\n \n '\n \n+# With core.quotepath=true (default), bytes with hi-bit set, in addition to\n+# controls like \\n and \\t, are written in octal and the path is enclosed in\n+# a pair of double-quotes.\n+#\n+# With core.quotepath=false, the special case for bytes with hi-bit set is\n+# disabled.\n+#\n+# A SP is treated just like any other bytes, nothing special.\n test_expect_success 'setup expected files' '\n cat >expect.quoted <<\\EOF &&\n Name\n@@ -149,4 +157,18 @@ test_expect_success 'check fully quoted output from ls-tree' '\n \n '\n \n+test_expect_success 'diff --quote-path-with-sp' '\n+\tgit diff --quote-path-with-sp HEAD^ HEAD -- \"With*\" >actual &&\n+\tsed -e \"s/Z$//\" >expect <<-\\EOF &&\n+\tdiff --git \"a/With SP in it\" \"b/With SP in it\"\n+\tindex e79c5e8..e019be0 100644\n+\t--- \"a/With SP in it\"\tZ\n+\t+++ \"b/With SP in it\"\tZ\n+\t@@ -1 +1 @@\n+\t-initial\n+\t+second\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.33.0-649-gd4f4107c2b\n\n"},{"id":"436056","messageId":"20210915223316.1653443-2-gitster@pobox.com","threadId":"56509","inReplyTo":"20210915223316.1653443-1-gitster@pobox.com","subject":"[PATCH 1/2] diff: simplify quote_two()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-15T22:33:15Z","receivedAt":"2021-09-15T22:33:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Reimplement the function as a mere thin wrapper around\nquote_two_c_style().\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c | 12 +-----------\n 1 file changed, 1 insertion(+), 11 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex a8113f1707..8143b737b7 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -482,19 +482,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)\n \n static char *quote_two(const char *one, const char *two)\n {\n-\tint need_one = quote_c_style(one, NULL, NULL, CQUOTE_NODQ);\n-\tint need_two = quote_c_style(two, NULL, NULL, CQUOTE_NODQ);\n \tstruct strbuf res = STRBUF_INIT;\n \n-\tif (need_one + need_two) {\n-\t\tstrbuf_addch(&res, '\"');\n-\t\tquote_c_style(one, &res, NULL, CQUOTE_NODQ);\n-\t\tquote_c_style(two, &res, NULL, CQUOTE_NODQ);\n-\t\tstrbuf_addch(&res, '\"');\n-\t} else {\n-\t\tstrbuf_addstr(&res, one);\n-\t\tstrbuf_addstr(&res, two);\n-\t}\n+\tquote_two_c_style(&res, one, two, 0);\n \treturn strbuf_detach(&res, NULL);\n }\n \n-- \n2.33.0-649-gd4f4107c2b\n\n"},{"id":"436062","messageId":"YUK7Bl9uzNE1YErg@tilde.club","threadId":"56509","inReplyTo":"20210915223316.1653443-1-gitster@pobox.com","subject":"Re: [PATCH 0/2] (experimental) diff --quote-path-with-sp","fromName":"Gwyneth Morgan","fromEmail":"gwymor@tilde.club","sentAt":"2021-09-16T03:33:26Z","receivedAt":"2021-09-16T03:33:41Z","isPatch":true,"sender":{"key":"gwymor@tilde.club","avatar":"https://avatars.githubusercontent.com/u/87623694?v=4"},"body":"On 2021-09-15 15:33:14-0700, Junio C Hamano wrote:\n> Long time ago, we had a discussion with GNU patch/diff maintainer\n> and agreed that pathnames with certain \"difficult\" bytes needs to be\n> quoted to ensure the resulting patch is machine parseable in an\n> unambiguous way [*1*].  Recently, we saw a report that found that\n> GNU patch is unhappy with our diff output for a path with SP in it\n> [*2*].\n> \n> With this experimental option, the beginning part of the patch\n> output will have pathnames with SP in them enclosed inside a pair of\n> double quotes, like so:\n> \n> \tdiff --git \"a/A Name\" \"b/A Name\"\n> \t--- \"a/A Name\"\n> \t+++ \"b/A Name\"\n\nI believe GNU patch is fine with unquoted spaces in the \"--- a/path\"\nand \"+++ b/path\", and only has an issue with unquoted spaces in the\n\"diff --git\" line. busybox patch does seem to have an issue with quoted\nfilenames in the \"---\" and \"+++\" lines but is fine if those lines are\nunquoted. Maybe we could leave spaces unquoted in those lines, only\nquoted if there's some other character that needs it.\n"},{"id":"436076","messageId":"xmqqh7elulvc.fsf@gitster.g","threadId":"56509","inReplyTo":"YUK7Bl9uzNE1YErg@tilde.club","subject":"Re: [PATCH 0/2] (experimental) diff --quote-path-with-sp","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-16T05:31:51Z","receivedAt":"2021-09-16T05:31:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gwyneth Morgan <gwymor@tilde.club> writes:\n\n> On 2021-09-15 15:33:14-0700, Junio C Hamano wrote:\n>> Long time ago, we had a discussion with GNU patch/diff maintainer\n>> and agreed that pathnames with certain \"difficult\" bytes needs to be\n>> quoted to ensure the resulting patch is machine parseable in an\n>> unambiguous way [*1*].  Recently, we saw a report that found that\n>> GNU patch is unhappy with our diff output for a path with SP in it\n>> [*2*].\n>> \n>> With this experimental option, the beginning part of the patch\n>> output will have pathnames with SP in them enclosed inside a pair of\n>> double quotes, like so:\n>> \n>> \tdiff --git \"a/A Name\" \"b/A Name\"\n>> \t--- \"a/A Name\"\n>> \t+++ \"b/A Name\"\n>\n> I believe GNU patch is fine with unquoted spaces in the \"--- a/path\"\n> and \"+++ b/path\", and only has an issue with unquoted spaces in the\n> \"diff --git\" line. busybox patch does seem to have an issue with quoted\n> filenames in the \"---\" and \"+++\" lines but is fine if those lines are\n> unquoted. Maybe we could leave spaces unquoted in those lines, only\n> quoted if there's some other character that needs it.\n\nWell, if they are so inconsistent, perhaps we shouldn't bend over\nbackwards to cater to them, I would have to say.  I do not think we\nwant to break the convention that these a/ & b/ labeled paths are\nspelled exactly the same way, only to please external tools.\n\nThanks for a quick report.\n"},{"id":"436093","messageId":"87ee9ohnqd.fsf@evledraar.gmail.com","threadId":"56509","inReplyTo":"20210915223316.1653443-3-gitster@pobox.com","subject":"Re: [PATCH 2/2] diff: --quote-path-with-sp","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-09-16T09:06:42Z","receivedAt":"2021-09-16T09:30:07Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Sep 15 2021, Junio C Hamano wrote:\n\n[CC-ing Andreas Gruenbacher who's currently active in GNU patch\ndevelopment, and Paul Eggert at his current address, in case he's\ncurious about this blast from the past.\n\nBoth: The full context for this proposed change in Git is at\nhttps://lore.kernel.org/git/20210915223316.1653443-1-gitster@pobox.com/]\n\n> Long time ago, we had a discussion with GNU patch/diff maintainer\n> and agreed that pathnames with certain \"difficult\" bytes needs to be\n> quoted to ensure the resulting patch is machine parseable in an\n> unambiguous way [*1*].  Recently, we saw a report that found that\n> GNU patch is unhappy with our diff output for a path with SP in it\n> [*2*].\n\nIt would also be good to mention 4f6fbcdcf96 (Functions to quote and\nunquote pathnames in C-style., 2005-10-14) here, which is what came out\nof the [*1*] discussion you're citing, and that also link to the later:\n\n    https://lore.kernel.org/git/7vll0wvb2a.fsf@assigned-by-dhcp.cox.net/\n\nWhere you quote a message of Paul Eggert's that didn't make it into the\narchive, but which AFAICT accurately summarizes the behavior in\n4f6fbcdcf96.\n\nWhereas the [*1*] you linked to is still the early proposal of handling\nUTF-8 specially (not quoting it), which doesn't appear to be what either\nGNU patch or Git went for in the end (both fully quote some fairly\nvanilla (also in latin1) UTF-8 when I tested it).\n\nIt's still not clear to me if what was agreed upon was accurately\nimplemented by Git at the time, but that GNU patch had a bug vis-a-vis\nthe desired discussed behavior, if the bug is Git's, or both etc. Does a\nfix still need to be made in GNU patch?\n\nThere's also a mention of busybox's interaction with this behavior in\nhttps://lore.kernel.org/git/YUK7Bl9uzNE1YErg@tilde.club/; has anyone\n(you or Gwyneth) sent them an FYI about this in case they'd like to\nadjust the behavior of their patch tool?\n\n> Teach \"git diff\" and friends the \"--quote-path-with-sp\" option, that\n> encloses a pathname with SP in it inside a pair of double-quotes,\n> even though there is otherwise no byte in the pathname that need to\n> be encoded in the octal.\n>\n> As an earlier parts of t/t3902 (outside the patch context) shows,\n> output from \"ls-files\", \"ls-tree\", and \"diff --name-only\" all follow\n> the same rule to decide paths with what bytes in them need quoting\n> and how they are quoted.\n>\n> This experimental option deliberately refrains from touching these\n> output and affects ONLY the paths that appear in the patch header,\n> i.e. \"diff --git\", \"--- a/path\" and \"+++ b/path\" lines, that GNU\n> patch may care.  This is to minimize potential damage this change\n> may cause to tools and scripts the users have been relying on.\n>\n>  *1* https://lore.kernel.org/git/87ek6s0w34.fsf@penguin.cs.ucla.edu/\n>  *2* https://lore.kernel.org/git/YR9Iaj%2FFqAyCMade@tilde.club/\n> [...patch omitted...]\n"},{"id":"436162","messageId":"xmqq35q4texo.fsf@gitster.g","threadId":"56509","inReplyTo":"87ee9ohnqd.fsf@evledraar.gmail.com","subject":"Re: [PATCH 2/2] diff: --quote-path-with-sp","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-16T20:59:15Z","receivedAt":"2021-09-16T20:59:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> On Wed, Sep 15 2021, Junio C Hamano wrote:\n>\n> [CC-ing Andreas Gruenbacher who's currently active in GNU patch\n> development, and Paul Eggert at his current address, in case he's\n> curious about this blast from the past.\n>\n> Both: The full context for this proposed change in Git is at\n> https://lore.kernel.org/git/20210915223316.1653443-1-gitster@pobox.com/]\n>\n>> Long time ago, we had a discussion with GNU patch/diff maintainer\n>> and agreed that pathnames with certain \"difficult\" bytes needs to be\n>> quoted to ensure the resulting patch is machine parseable in an\n>> unambiguous way [*1*].  Recently, we saw a report that found that\n>> GNU patch is unhappy with our diff output for a path with SP in it\n>> [*2*].\n>\n> It would also be good to mention 4f6fbcdcf96 ...\n\nAh, I didn't mean \"this is the single message to understand the\nissue\".  The reference was meant as \"you need to read the discussion\nthat starts around here\", which you apparently did ;-)\n\nThere is another message that is much more relevant that does not\nappear in the thread (and I do not know its message ID), where Linus\ncame up with a way to parse the \"diff --git a/... b/...\" line, or\nthe first \"--- a/...\" and \"+++ b/...\" lines, and learn the pathnames\non the preimage side and on the postimage side unambiguously.  I think\nthat discovery led to the current implementation.\n\n"}]}