{"thread":{"id":"8225","subject":"[PATCH] Tech 'git-apply' that spaces before a tab are candidate for stripping","startedAt":"2007-05-19T16:44:33Z","lastAt":"2007-05-20T07:53:11Z","messageCount":2,"participants":["Marco Costalba","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"42631","messageId":"e5bfff550705190944y44cb57baiccb139b1d649face@mail.gmail.com","threadId":"8225","inReplyTo":null,"subject":"[PATCH] Tech 'git-apply' that spaces before a tab are candidate for stripping","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2007-05-19T16:44:33Z","receivedAt":"2007-05-19T16:44:33Z","isPatch":true,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"Currently 'git-apply' identify as stealth space a line starting with\nspaces followed by a tab.\n\nThis patch updates the algorithm to find spaces + tab also in the\nmiddle of a line and not only at the beginning.\n\nAs example lines like\n\n\"#define MY_VALUE   \\t 1\"\n\nare now identified and cleaned up if option '--whitespace=strip' is\nused.\n\nSigned-off-by: Marco Costalba <mcostalba@gmail.com>\n---\n\nThere are a bunch of this type in current git tree.\n\n  builtin-apply.c |   72 ++++++++++++++++++++++++++++++------------------------\n 1 files changed, 40 insertions(+), 32 deletions(-)\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex f17f838..9e82757 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -1586,6 +1586,32 @@ static void remove_last_line(const char **rbuf,\nint *rsize)\n  \t*rsize = offset + 1;\n }\n\n+static int copy_line(char **output_ptr, const char *patch, int start, int len)\n+{\n+\tchar *output = *output_ptr;\n+\tint space_start = 0;\n+\tint i, end = start + len;\n+\n+\tfor (i = start; i < end; i++) {\n+\n+\t\tchar ch = patch[i];\n+\n+\t\tif (ch == ' ' && !space_start)\n+\t\t\tspace_start = i;\n+\n+\t\telse if (space_start && ch != ' ') {\n+\t\t\tif (ch == '\\t') {\n+\t\t\t\t*output_ptr = output - (i - space_start);\n+\t\t\t\treturn space_start;\n+\t\t\t}\n+\t\t\tspace_start = 0;\n+\t\t}\n+\t\t*output++ = ch;\n+\t}\n+\t*output_ptr = output;\n+\treturn 0;\n+}\n+\n struct buffer_desc {\n \tchar *buffer;\n \tunsigned long size;\n@@ -1602,17 +1628,14 @@ static int apply_line(char *output, const char\n*patch, int plen)\n \tint i;\n \tint add_nl_to_tail = 0;\n \tint fixed = 0;\n-\tint last_tab_in_indent = -1;\n-\tint last_space_in_indent = -1;\n-\tint need_fix_leading_space = 0;\n-\tchar *buf;\n+\tint space_start;\n+\tconst char *old = output;\n\n \tif ((new_whitespace != strip_whitespace) || !whitespace_error ||\n \t    *patch != '+') {\n \t\tmemcpy(output, patch + 1, plen);\n \t\treturn plen;\n \t}\n-\n \tif (1 < plen && isspace(patch[plen-1])) {\n \t\tif (patch[plen] == '\\n')\n \t\t\tadd_nl_to_tail = 1;\n@@ -1621,44 +1644,29 @@ static int apply_line(char *output, const char\n*patch, int plen)\n \t\t\tplen--;\n \t\tfixed = 1;\n \t}\n+\tspace_start = copy_line(&output, patch, 1, plen);\n+\twhile (space_start) {\n\n-\tfor (i = 1; i < plen; i++) {\n-\t\tchar ch = patch[i];\n-\t\tif (ch == '\\t') {\n-\t\t\tlast_tab_in_indent = i;\n-\t\t\tif (0 <= last_space_in_indent)\n-\t\t\t\tneed_fix_leading_space = 1;\n-\t\t}\n-\t\telse if (ch == ' ')\n-\t\t\tlast_space_in_indent = i;\n-\t\telse\n-\t\t\tbreak;\n-\t}\n-\n-\tbuf = output;\n-\tif (need_fix_leading_space) {\n-\t\t/* between patch[1..last_tab_in_indent] strip the\n-\t\t * funny spaces, updating them to tab as needed.\n+\t\t/* strip the funny spaces, updating them to tab as needed\n+\t\t * strip is done one space sequence at time, until line end\n \t\t */\n-\t\tfor (i = 1; i < last_tab_in_indent; i++, plen--) {\n+\t\tfixed = 1;\n+\t\tfor (i = space_start; i < plen + 1; i++) {\n+\n \t\t\tchar ch = patch[i];\n \t\t\tif (ch != ' ')\n-\t\t\t\t*output++ = ch;\n+\t\t\t\tbreak;\n \t\t\telse if ((i % 8) == 0)\n \t\t\t\t*output++ = '\\t';\n \t\t}\n-\t\tfixed = 1;\n-\t\ti = last_tab_in_indent;\n+\t\tspace_start = copy_line(&output, patch, i, plen + 1 - i);\n \t}\n-\telse\n-\t\ti = 1;\n-\n-\tmemcpy(output, patch + i, plen);\n \tif (add_nl_to_tail)\n-\t\toutput[plen++] = '\\n';\n+\t\t*output++ = '\\n';\n \tif (fixed)\n \t\tapplied_after_stripping++;\n-\treturn output + plen - buf;\n+\n+\treturn output - old;\n }\n\n static int apply_one_fragment(struct buffer_desc *desc, struct\nfragment *frag, int inaccurate_eof)\n-- \n1.5.2.rc3.88.g4c3ba-dirty\n"},{"id":"42671","messageId":"7v8xbkrkwo.fsf@assigned-by-dhcp.cox.net","threadId":"8225","inReplyTo":"e5bfff550705190944y44cb57baiccb139b1d649face@mail.gmail.com","subject":"Re: [PATCH] Tech 'git-apply' that spaces before a tab are candidate for stripping","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-20T07:53:11Z","receivedAt":"2007-05-20T07:53:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Marco Costalba\" <mcostalba@gmail.com> writes:\n\n> Currently 'git-apply' identify as stealth space a line starting with\n> spaces followed by a tab.\n>\n> This patch updates the algorithm to find spaces + tab also in the\n> middle of a line and not only at the beginning.\n>\n> As example lines like\n>\n> \"#define MY_VALUE   \\t 1\"\n>\n> are now identified and cleaned up if option '--whitespace=strip' is\n> used.\n\nI specifically did not want to do the above, as it would also\nmunge something like this:\n\n\tconst char string[] = \"abc <HT> de\";\n"}]}