{"thread":{"id":"8708","subject":"[PATCH] Add core.quotepath configuration variable.","startedAt":"2007-06-25T00:11:05Z","lastAt":"2007-06-25T00:11:05Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"45723","messageId":"1182730265719-git-send-email-gitster@pobox.com","threadId":"8708","inReplyTo":null,"subject":"[PATCH] Add core.quotepath configuration variable.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-06-25T00:11:05Z","receivedAt":"2007-06-25T00:11:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"We always quote \"unusual\" byte values in a pathname using\nC-string style, to make it safer for parsing scripts that do not\nhandle NUL separated records well (or just too lazy to bother).\nThe absolute minimum bytes that need to be quoted for this\npurpose are TAB, LF (and other control characters), double quote\nand backslash.\n\nHowever, we have also always quoted the bytes in high 8-bit\nrange; this was partly because we were lazy and partly because\nwe were being cautious.\n\nThis introduces an internal \"quote_path_fully\" variable, and\ncore.quotepath configuration variable to control it.  When set\nto false, it does not quote bytes in high 8-bit range anymore\nbut passes them intact.\n\nThe variable defaults to \"true\" to retain the traditional\nbehaviour for now.  Maybe in later versions of git we might want\nto change the default to false, so people need to explicitly ask\nfor safer quoting.  But that would be for a separate patch in\ndifferent timeframe.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/config.txt |   12 ++++\n cache.h                  |    1 +\n config.c                 |    5 ++\n environment.c            |    1 +\n quote.c                  |    5 +-\n t/t3902-quoted.sh        |  126 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 148 insertions(+), 2 deletions(-)\n create mode 100755 t/t3902-quoted.sh\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex a2057d9..34b1c97 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -117,6 +117,18 @@ core.fileMode::\n \tthe working copy are ignored; useful on broken filesystems like FAT.\n \tSee gitlink:git-update-index[1]. True by default.\n \n+core.quotepath::\n+\tThe commands that output paths (e.g. `ls-files`,\n+\t`diff`), when not given the `-z` option, will quote\n+\t\"unusual\" characters in the pathname by enclosing the\n+\tpathname in a double-quote pair and with backslashes the\n+\tsame way strings in C source code are quoted.  If this\n+\tvariable is set to false, the bytes higher than 0x80 are\n+\tnot quoted but output as verbatim.  Note that double\n+\tquote, backslash and control characters are always\n+\tquoted without `-z` regardless of the setting of this\n+\tvariable.\n+\n core.autocrlf::\n \tIf true, makes git convert `CRLF` at the end of lines in text files to\n \t`LF` when reading from the filesystem, and convert in reverse when\ndiff --git a/cache.h b/cache.h\nindex ed83d92..6776357 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -292,6 +292,7 @@ extern int delete_ref(const char *, const unsigned char *sha1);\n \n /* Environment bits from configuration mechanism */\n extern int trust_executable_bit;\n+extern int quote_path_fully;\n extern int has_symlinks;\n extern int assume_unchanged;\n extern int prefer_symlink_refs;\ndiff --git a/config.c b/config.c\nindex e323153..4de8926 100644\n--- a/config.c\n+++ b/config.c\n@@ -271,6 +271,11 @@ int git_default_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.quotepath\")) {\n+\t\tquote_path_fully = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \tif (!strcmp(var, \"core.symlinks\")) {\n \t\thas_symlinks = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 8b9b89d..1c2773f 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -12,6 +12,7 @@\n char git_default_email[MAX_GITNAME];\n char git_default_name[MAX_GITNAME];\n int trust_executable_bit = 1;\n+int quote_path_fully = 1;\n int has_symlinks = 1;\n int assume_unchanged;\n int prefer_symlink_refs;\ndiff --git a/quote.c b/quote.c\nindex aa44009..d88bf75 100644\n--- a/quote.c\n+++ b/quote.c\n@@ -188,7 +188,8 @@ static int quote_c_style_counted(const char *name, int namelen,\n #define EMITQ() EMIT('\\\\')\n \n \tconst char *sp;\n-\tint ch, count = 0, needquote = 0;\n+\tunsigned char ch;\n+\tint count = 0, needquote = 0;\n \n \tif (!no_dq)\n \t\tEMIT('\"');\n@@ -197,7 +198,7 @@ static int quote_c_style_counted(const char *name, int namelen,\n \t\tif (!ch)\n \t\t\tbreak;\n \t\tif ((ch < ' ') || (ch == '\"') || (ch == '\\\\') ||\n-\t\t    (ch >= 0177)) {\n+\t\t    (quote_path_fully && (ch >= 0177))) {\n \t\t\tneedquote = 1;\n \t\t\tswitch (ch) {\n \t\t\tcase '\\a': EMITQ(); ch = 'a'; break;\ndiff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh\nnew file mode 100755\nindex 0000000..63f950b\n--- /dev/null\n+++ b/t/t3902-quoted.sh\n@@ -0,0 +1,126 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2006 Junio C Hamano\n+#\n+\n+test_description='quoted output'\n+\n+. ./test-lib.sh\n+\n+FN='濱野'\n+GN='純'\n+HT='\t'\n+LF='\n+'\n+DQ='\"'\n+\n+for_each_name () {\n+\tfor name in \\\n+\t    Name \"Name and a${LF}LF\" \"Name and an${HT}HT\" \"Name${DQ}\" \\\n+\t    \"$FN$HT$GN\" \"$FN$LF$GN\" \"$FN $GN\" \"$FN$GN\" \"$FN$DQ$GN\" \\\n+\t    \"With SP in it\"\n+\tdo\n+\t\teval \"$1\"\n+\tdone\n+}\n+\n+test_expect_success setup '\n+\n+\tfor_each_name \"echo initial >\\\"\\$name\\\"\"\n+\tgit add . &&\n+\tgit commit -q -m Initial &&\n+\n+\tfor_each_name \"echo second >\\\"\\$name\\\"\" &&\n+\tgit commit -a -m Second\n+\n+\tfor_each_name \"echo modified >\\\"\\$name\\\"\"\n+\n+'\n+\n+cat >expect.quoted <<\\EOF\n+Name\n+\"Name and a\\nLF\"\n+\"Name and an\\tHT\"\n+\"Name\\\"\"\n+With SP in it\n+\"\\346\\277\\261\\351\\207\\216\\t\\347\\264\\224\"\n+\"\\346\\277\\261\\351\\207\\216\\n\\347\\264\\224\"\n+\"\\346\\277\\261\\351\\207\\216 \\347\\264\\224\"\n+\"\\346\\277\\261\\351\\207\\216\\\"\\347\\264\\224\"\n+\"\\346\\277\\261\\351\\207\\216\\347\\264\\224\"\n+EOF\n+\n+cat >expect.raw <<\\EOF\n+Name\n+\"Name and a\\nLF\"\n+\"Name and an\\tHT\"\n+\"Name\\\"\"\n+With SP in it\n+\"濱野\\t純\"\n+\"濱野\\n純\"\n+濱野 純\n+\"濱野\\\"純\"\n+濱野純\n+EOF\n+\n+test_expect_success 'check fully quoted output from ls-files' '\n+\n+\tgit ls-files >current && diff -u expect.quoted current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-files' '\n+\n+\tgit diff --name-only >current &&\n+\tdiff -u expect.quoted current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-index' '\n+\n+\tgit diff --name-only HEAD >current &&\n+\tdiff -u expect.quoted current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-tree' '\n+\n+\tgit diff --name-only HEAD^ HEAD >current &&\n+\tdiff -u expect.quoted current\n+\n+'\n+\n+test_expect_success 'setting core.quotepath' '\n+\n+\tgit config --bool core.quotepath false\n+\n+'\n+\n+test_expect_success 'check fully quoted output from ls-files' '\n+\n+\tgit ls-files >current && diff -u expect.raw current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-files' '\n+\n+\tgit diff --name-only >current &&\n+\tdiff -u expect.raw current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-index' '\n+\n+\tgit diff --name-only HEAD >current &&\n+\tdiff -u expect.raw current\n+\n+'\n+\n+test_expect_success 'check fully quoted output from diff-tree' '\n+\n+\tgit diff --name-only HEAD^ HEAD >current &&\n+\tdiff -u expect.raw current\n+\n+'\n+\n+test_done\n-- \n1.5.2.2.1334.g1625\n"}]}