{"thread":{"id":"5655","subject":"[RFC/PATCH] git-diff/git-apply: make diff output a bit friendlier to GNU patch","startedAt":"2006-09-23T00:44:32Z","lastAt":"2006-09-23T00:44:32Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"27433","messageId":"7vu02zxvgv.fsf@assigned-by-dhcp.cox.net","threadId":"5655","inReplyTo":null,"subject":"[RFC/PATCH] git-diff/git-apply: make diff output a bit friendlier to GNU patch","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-09-23T00:44:32Z","receivedAt":"2006-09-23T00:44:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Somebody was wondering on #git channel why a git generated diff\ndoes not apply with GNU patch when the filename contains a SP.\nIt is because GNU patch expects to find TAB (and trailing timestamp)\non ---/+++ (old_name and new_name) lines after the filenames.\n\nThe \"diff --git\" output format was carefully designed to be\ncompatible with GNU patch where it can, but whitespace\ncharacters were always a pain.\n\nThis adds an extra TAB (but not trailing timestamp) to old_name\nand new_name lines of git-diff output when the filename has a SP\nin it.  When a filename contains a real tab, \"diff --git\" format\nalways c-quotes it as discussed on the list with GNU patch\nmaintainer previously:\n\n\thttp://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2\n\nso there is no real room for confusion.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * This patch, if people like its general direction, should be\n   split into two parts, one to update \"git-apply\" so that it\n   understands that old/new name lines may contain the extra TAB\n   at the end, and another to update \"git-diff\" to actually\n   generate such a patch.  We apply the former immediately to\n   get people prepared, and when everybody's git-apply is ready\n   then we can apply the latter to actually produce the new\n   format.\n\n builtin-apply.c |    4 ++--\n diff.c          |   20 +++++++++++++++++---\n 2 files changed, 19 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 25e90d8..84dbbc3 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -360,7 +360,7 @@ static int gitdiff_hdrend(const char *li\n static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)\n {\n \tif (!orig_name && !isnull)\n-\t\treturn find_name(line, NULL, 1, 0);\n+\t\treturn find_name(line, NULL, 1, TERM_TAB);\n \n \tif (orig_name) {\n \t\tint len;\n@@ -370,7 +370,7 @@ static char *gitdiff_verify_name(const c\n \t\tlen = strlen(name);\n \t\tif (isnull)\n \t\t\tdie(\"git-apply: bad git-diff - expected /dev/null, got %s on line %d\", name, linenr);\n-\t\tanother = find_name(line, NULL, 1, 0);\n+\t\tanother = find_name(line, NULL, 1, TERM_TAB);\n \t\tif (!another || memcmp(another, name, len))\n \t\t\tdie(\"git-apply: bad git-diff - inconsistent %s filename on line %d\", oldnew, linenr);\n \t\tfree(another);\ndiff --git a/diff.c b/diff.c\nindex 443e248..37a4ce1 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -201,11 +201,18 @@ static void emit_rewrite_diff(const char\n \t\t\t      struct diff_filespec *two)\n {\n \tint lc_a, lc_b;\n+\tconst char *name_a_tab, *name_b_tab;\n+\n+\tname_a_tab = strchr(name_a, ' ') ? \"\\t\" : \"\";\n+\tname_b_tab = strchr(name_b, ' ') ? \"\\t\" : \"\";\n+\n \tdiff_populate_filespec(one, 0);\n \tdiff_populate_filespec(two, 0);\n \tlc_a = count_lines(one->data, one->size);\n \tlc_b = count_lines(two->data, two->size);\n-\tprintf(\"--- %s\\n+++ %s\\n@@ -\", name_a, name_b);\n+\tprintf(\"--- %s%s\\n+++ %s%s\\n@@ -\",\n+\t       name_a, name_a_tab,\n+\t       name_b, name_b_tab);\n \tprint_line_count(lc_a);\n \tprintf(\" +\");\n \tprint_line_count(lc_b);\n@@ -391,8 +398,15 @@ static void fn_out_consume(void *priv, c\n \tconst char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);\n \n \tif (ecbdata->label_path[0]) {\n-\t\tprintf(\"%s--- %s%s\\n\", set, ecbdata->label_path[0], reset);\n-\t\tprintf(\"%s+++ %s%s\\n\", set, ecbdata->label_path[1], reset);\n+\t\tconst char *name_a_tab, *name_b_tab;\n+\n+\t\tname_a_tab = strchr(ecbdata->label_path[0], ' ') ? \"\\t\" : \"\";\n+\t\tname_b_tab = strchr(ecbdata->label_path[1], ' ') ? \"\\t\" : \"\";\n+\n+\t\tprintf(\"%s--- %s%s%s\\n\",\n+\t\t       set, ecbdata->label_path[0], reset, name_a_tab);\n+\t\tprintf(\"%s+++ %s%s%s\\n\",\n+\t\t       set, ecbdata->label_path[1], reset, name_b_tab);\n \t\tecbdata->label_path[0] = ecbdata->label_path[1] = NULL;\n \t}\n \n-- \n1.4.2.1.gb6052\n"}]}