{"thread":{"id":"11543","subject":"[PATCH 2/2] core.whitespace cr-at-eol-is-ok","startedAt":"2008-01-08T23:51:00Z","lastAt":"2008-01-08T23:51:00Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"64797","messageId":"7v4pdnri57.fsf@gitster.siamese.dyndns.org","threadId":"11543","inReplyTo":null,"subject":"[PATCH 2/2] core.whitespace cr-at-eol-is-ok","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-08T23:51:00Z","receivedAt":"2008-01-08T23:51:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This allows a line to have a carriage return at the end when\nchecking and fixing trailing whitespaces.\n\nI think the previous one to fix the message from --check is a\n1.5.4 material, but this certainly is not.  The naming of the\nrule is iffy at best and the semantics when enabling all error\nchecks via attributes by setting whitespace attribute to true\nshould not include this option.\n\nI haven't tested this very seriously other than adding just a\nfew tests to an existing test script.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n builtin-apply.c         |   21 +++++++++++++++------\n cache.h                 |    1 +\n t/t4019-diff-wserror.sh |   40 ++++++++++++++++++++++++++++++++++++++++\n ws.c                    |   15 +++++++++++++--\n 4 files changed, 69 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex d57bb6e..dcd9f09 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -1549,6 +1549,7 @@ static int apply_line(char *output, const char *patch, int plen,\n \t */\n \tint i;\n \tint add_nl_to_tail = 0;\n+\tint add_cr_to_tail = 0;\n \tint fixed = 0;\n \tint last_tab_in_indent = 0;\n \tint last_space_in_indent = 0;\n@@ -1564,14 +1565,20 @@ static int apply_line(char *output, const char *patch, int plen,\n \t/*\n \t * Strip trailing whitespace\n \t */\n-\tif ((ws_rule & WS_TRAILING_SPACE) &&\n-\t    (1 < plen && isspace(patch[plen-1]))) {\n-\t\tif (patch[plen] == '\\n')\n+\tif ((ws_rule & WS_TRAILING_SPACE)) {\n+\t\tif (patch[plen] == '\\n') {\n \t\t\tadd_nl_to_tail = 1;\n-\t\tplen--;\n-\t\twhile (0 < plen && isspace(patch[plen]))\n \t\t\tplen--;\n-\t\tfixed = 1;\n+\t\t\tif (1 < plen && patch[plen - 1] == '\\r') {\n+\t\t\t\tadd_cr_to_tail = 1;\n+\t\t\t\tplen--;\n+\t\t\t}\n+\t\t}\n+\t\tif (isspace(patch[plen])) {\n+\t\t\twhile (0 < plen && isspace(patch[plen]))\n+\t\t\t\tplen--;\n+\t\t\tfixed = 1;\n+\t\t}\n \t}\n \n \t/*\n@@ -1633,6 +1640,8 @@ static int apply_line(char *output, const char *patch, int plen,\n \t\ti = 1;\n \n \tmemcpy(output, patch + i, plen);\n+\tif (add_cr_to_tail)\n+\t\toutput[plen++] = '\\r';\n \tif (add_nl_to_tail)\n \t\toutput[plen++] = '\\n';\n \tif (fixed)\ndiff --git a/cache.h b/cache.h\nindex 39331c2..3836176 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -651,6 +651,7 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i\n #define WS_TRAILING_SPACE\t01\n #define WS_SPACE_BEFORE_TAB\t02\n #define WS_INDENT_WITH_NON_TAB\t04\n+#define WS_CR_AT_EOL_IS_OK\t010\n #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)\n extern unsigned whitespace_rule_cfg;\n extern unsigned whitespace_rule(const char *);\ndiff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh\nindex 67e080b..429d870 100755\n--- a/t/t4019-diff-wserror.sh\n+++ b/t/t4019-diff-wserror.sh\n@@ -12,6 +12,7 @@ test_expect_success setup '\n \techo \"         Eight SP indent\" >>F &&\n \techo \" \tHT and SP indent\" >>F &&\n \techo \"With trailing SP \" >>F &&\n+\techo \"Carriage ReturnQ\" | tr Q \"\\015\" >>F &&\n \techo \"No problem\" >>F\n \n '\n@@ -27,6 +28,7 @@ test_expect_success default '\n \tgrep Eight normal >/dev/null &&\n \tgrep HT error >/dev/null &&\n \tgrep With error >/dev/null &&\n+\tgrep Return error >/dev/null &&\n \tgrep No normal >/dev/null\n \n '\n@@ -41,6 +43,7 @@ test_expect_success 'without -trail' '\n \tgrep Eight normal >/dev/null &&\n \tgrep HT error >/dev/null &&\n \tgrep With normal >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n \tgrep No normal >/dev/null\n \n '\n@@ -56,6 +59,7 @@ test_expect_success 'without -trail (attribute)' '\n \tgrep Eight normal >/dev/null &&\n \tgrep HT error >/dev/null &&\n \tgrep With normal >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n \tgrep No normal >/dev/null\n \n '\n@@ -70,6 +74,7 @@ test_expect_success 'without -space' '\n \n \tgrep Eight normal >/dev/null &&\n \tgrep HT normal >/dev/null &&\n+\tgrep Return error >/dev/null &&\n \tgrep With error >/dev/null &&\n \tgrep No normal >/dev/null\n \n@@ -85,6 +90,7 @@ test_expect_success 'without -space (attribute)' '\n \n \tgrep Eight normal >/dev/null &&\n \tgrep HT normal >/dev/null &&\n+\tgrep Return error >/dev/null &&\n \tgrep With error >/dev/null &&\n \tgrep No normal >/dev/null\n \n@@ -100,6 +106,7 @@ test_expect_success 'with indent-non-tab only' '\n \n \tgrep Eight error >/dev/null &&\n \tgrep HT normal >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n \tgrep With normal >/dev/null &&\n \tgrep No normal >/dev/null\n \n@@ -115,9 +122,42 @@ test_expect_success 'with indent-non-tab only (attribute)' '\n \n \tgrep Eight error >/dev/null &&\n \tgrep HT normal >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n \tgrep With normal >/dev/null &&\n \tgrep No normal >/dev/null\n \n '\n \n+test_expect_success 'with cr-at-eol-is-ok' '\n+\n+\trm -f .gitattributes\n+\tgit config core.whitespace cr-at-eol-is-ok\n+\tgit diff --color >output\n+\tgrep \"$blue_grep\" output >error\n+\tgrep -v \"$blue_grep\" output >normal\n+\n+\tgrep Eight normal >/dev/null &&\n+\tgrep HT error >/dev/null &&\n+\tgrep With error >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n+\tgrep No normal >/dev/null\n+\n+'\n+\n+test_expect_success 'with cr-at-eol-is-ok (attribute)' '\n+\n+\tgit config --unset core.whitespace\n+\techo \"F whitespace=trailing,cr-at-eol-is-ok\" >.gitattributes\n+\tgit diff --color >output\n+\tgrep \"$blue_grep\" output >error\n+\tgrep -v \"$blue_grep\" output >normal\n+\n+\tgrep Eight normal >/dev/null &&\n+\tgrep HT error >/dev/null &&\n+\tgrep With error >/dev/null &&\n+\tgrep Return normal >/dev/null &&\n+\tgrep No normal >/dev/null\n+\n+'\n+\n test_done\ndiff --git a/ws.c b/ws.c\nindex d09b9df..805be56 100644\n--- a/ws.c\n+++ b/ws.c\n@@ -14,6 +14,7 @@ static struct whitespace_rule {\n \t{ \"trailing-space\", WS_TRAILING_SPACE },\n \t{ \"space-before-tab\", WS_SPACE_BEFORE_TAB },\n \t{ \"indent-with-non-tab\", WS_INDENT_WITH_NON_TAB },\n+\t{ \"cr-at-eol-is-ok\", WS_CR_AT_EOL_IS_OK },\n };\n \n unsigned parse_whitespace_rule(const char *string)\n@@ -124,6 +125,7 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,\n \tint written = 0;\n \tint trailing_whitespace = -1;\n \tint trailing_newline = 0;\n+\tint trailing_carriage_return = 0;\n \tint i;\n \n \t/* Logic is simpler if we temporarily ignore the trailing newline. */\n@@ -131,6 +133,11 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,\n \t\ttrailing_newline = 1;\n \t\tlen--;\n \t}\n+\tif ((ws_rule & WS_CR_AT_EOL_IS_OK) &&\n+\t    len > 0 && line[len - 1] == '\\r') {\n+\t\ttrailing_carriage_return = 1;\n+\t\tlen--;\n+\t}\n \n \t/* Check for trailing whitespace. */\n \tif (ws_rule & WS_TRAILING_SPACE) {\n@@ -176,8 +183,10 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,\n \t}\n \n \tif (stream) {\n-\t\t/* Now the rest of the line starts at written.\n-\t\t * The non-highlighted part ends at trailing_whitespace. */\n+\t\t/*\n+\t\t * Now the rest of the line starts at \"written\".\n+\t\t * The non-highlighted part ends at \"trailing_whitespace\".\n+\t\t */\n \t\tif (trailing_whitespace == -1)\n \t\t\ttrailing_whitespace = len;\n \n@@ -196,6 +205,8 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,\n \t\t\t    len - trailing_whitespace, 1, stream);\n \t\t\tfputs(reset, stream);\n \t\t}\n+\t\tif (trailing_carriage_return)\n+\t\t\tfputc('\\r', stream);\n \t\tif (trailing_newline)\n \t\t\tfputc('\\n', stream);\n \t}\n"}]}