{"thread":{"id":"28612","subject":"[PATCH v3 2/5] cleanup: use internal memory allocation wrapper functions everywhere","startedAt":"2011-10-06T18:22:21Z","lastAt":"2011-10-12T20:24:49Z","messageCount":13,"participants":["Brandon Casey","Michael Haggerty","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":5},"messages":[{"id":"177084","messageId":"U4wiHVyDLLG1PhI-8iY3YpRCHWWi1IE65h4oZsMtte9f21i1djIDHGQtHssxat_eXec7H3Qbo4MfDoWvguInipQUJgljvIPZw-HcavAqSnyX27VBdUvY8BvWiIBaYW193fZG_SNtSjg@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"VYN8m1JCy102-eaWWa-bsunEvt3zeXLJkVg7FZKZCtXT-Ww0vg7a8xA7NTvrZTiovKTnJ9Hlom0@cipher.nrlssc.navy.mil","subject":"[PATCH v3 1/5] attr.c: avoid inappropriate access to strbuf \"buf\" member","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-06T18:22:21Z","receivedAt":"2011-10-06T18:22:21Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Brandon Casey <drafnel@gmail.com>\n\nThis code sequence performs a strcpy into the buf member of a strbuf\nstruct.  The strcpy may move the position of the terminating nul of the\nstring and effectively change the length of string so that it does not\nmatch the len member of the strbuf struct.\n\nCurrently, this sequence works since the strbuf was given a hint when it\nwas initialized to allocate enough space to accomodate the string that will\nbe strcpy'ed, but this is an implementation detail of strbufs, not a\nguarantee.\n\nSo, lets rework this sequence so that the strbuf is only manipulated by\nstrbuf functions, and direct modification of its \"buf\" member is not\nnecessary.\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n attr.c |   24 +++++++++++-------------\n 1 files changed, 11 insertions(+), 13 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 33cb4e4..fe38fcc 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -552,7 +552,6 @@ static void prepare_attr_stack(const char *path)\n {\n \tstruct attr_stack *elem, *info;\n \tint dirlen, len;\n-\tstruct strbuf pathbuf;\n \tconst char *cp;\n \n \tcp = strrchr(path, '/');\n@@ -561,8 +560,6 @@ static void prepare_attr_stack(const char *path)\n \telse\n \t\tdirlen = cp - path;\n \n-\tstrbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));\n-\n \t/*\n \t * At the bottom of the attribute stack is the built-in\n \t * set of attribute definitions, followed by the contents\n@@ -607,27 +604,28 @@ static void prepare_attr_stack(const char *path)\n \t * Read from parent directories and push them down\n \t */\n \tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n-\t\twhile (1) {\n-\t\t\tchar *cp;\n+\t\tstruct strbuf pathbuf = STRBUF_INIT;\n \n+\t\twhile (1) {\n \t\t\tlen = strlen(attr_stack->origin);\n \t\t\tif (dirlen <= len)\n \t\t\t\tbreak;\n-\t\t\tstrbuf_reset(&pathbuf);\n-\t\t\tstrbuf_add(&pathbuf, path, dirlen);\n+\t\t\tcp = memchr(path + len + 1, '/', dirlen - len - 1);\n+\t\t\tif (!cp)\n+\t\t\t\tcp = path + dirlen;\n+\t\t\tstrbuf_add(&pathbuf, path, cp - path);\n \t\t\tstrbuf_addch(&pathbuf, '/');\n-\t\t\tcp = strchr(pathbuf.buf + len + 1, '/');\n-\t\t\tstrcpy(cp + 1, GITATTRIBUTES_FILE);\n+\t\t\tstrbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);\n \t\t\telem = read_attr(pathbuf.buf, 0);\n-\t\t\t*cp = '\\0';\n-\t\t\telem->origin = strdup(pathbuf.buf);\n+\t\t\tstrbuf_setlen(&pathbuf, cp - path);\n+\t\t\telem->origin = strbuf_detach(&pathbuf, NULL);\n \t\t\telem->prev = attr_stack;\n \t\t\tattr_stack = elem;\n \t\t\tdebug_push(elem);\n \t\t}\n-\t}\n \n-\tstrbuf_release(&pathbuf);\n+\t\tstrbuf_release(&pathbuf);\n+\t}\n \n \t/*\n \t * Finally push the \"info\" one at the top of the stack.\n-- \n1.7.7\n"},{"id":"177083","messageId":"U4wiHVyDLLG1PhI-8iY3YhQhUEJpupTAsAMAf7ha--5LJd-HaCPI_bAfH_gLpi4Z_VB9uFLivO__yWGFob6NjBHVz3Jg2A4WNU2nLePu9VdvuY0-bP95SnEKthVUIq_iVrm6ELT6mec@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"VYN8m1JCy102-eaWWa-bsunEvt3zeXLJkVg7FZKZCtXT-Ww0vg7a8xA7NTvrZTiovKTnJ9Hlom0@cipher.nrlssc.navy.mil","subject":"[PATCH v3 2/5] cleanup: use internal memory allocation wrapper functions everywhere","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-06T18:22:22Z","receivedAt":"2011-10-06T18:22:22Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Brandon Casey <drafnel@gmail.com>\n\nThe \"x\"-prefixed versions of strdup, malloc, etc. will check whether the\nallocation was successful and terminate the process otherwise.\n\nA few uses of malloc were left alone since they already implemented a\ngraceful path of failure or were in a quasi external library like xdiff.\n\nAdditionally, the call to malloc in compat/win32/syslog.c was not modified\nsince the syslog() implemented there is a die handler and a call to the\nx-wrappers within a die handler could result in recursion should memory\nallocation fail.  This will have to be addressed separately.\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n attr.c             |    2 +-\n builtin/mv.c       |    2 +-\n compat/mingw.c     |    2 +-\n compat/qsort.c     |    2 +-\n remote.c           |    2 +-\n show-index.c       |    2 +-\n transport-helper.c |    4 ++--\n 7 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex fe38fcc..0793859 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -533,7 +533,7 @@ static void bootstrap_attr_stack(void)\n \n \t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n-\t\t\telem->origin = strdup(\"\");\n+\t\t\telem->origin = xstrdup(\"\");\n \t\t\telem->prev = attr_stack;\n \t\t\tattr_stack = elem;\n \t\t\tdebug_push(elem);\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 40f33ca..e9d191f 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -29,7 +29,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,\n \t\t\tto_copy--;\n \t\tif (to_copy != length || base_name) {\n \t\t\tchar *it = xmemdupz(result[i], to_copy);\n-\t\t\tresult[i] = base_name ? strdup(basename(it)) : it;\n+\t\t\tresult[i] = base_name ? xstrdup(basename(it)) : it;\n \t\t}\n \t}\n \treturn get_pathspec(prefix, result);\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6ef0cc4..8947418 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1183,7 +1183,7 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n \t}\n \tai->ai_addrlen = sizeof(struct sockaddr_in);\n \tif (hints && (hints->ai_flags & AI_CANONNAME))\n-\t\tai->ai_canonname = h ? strdup(h->h_name) : NULL;\n+\t\tai->ai_canonname = h ? xstrdup(h->h_name) : NULL;\n \telse\n \t\tai->ai_canonname = NULL;\n \ndiff --git a/compat/qsort.c b/compat/qsort.c\nindex d93dce2..9574d53 100644\n--- a/compat/qsort.c\n+++ b/compat/qsort.c\n@@ -55,7 +55,7 @@ void git_qsort(void *b, size_t n, size_t s,\n \t\tmsort_with_tmp(b, n, s, cmp, buf);\n \t} else {\n \t\t/* It's somewhat large, so malloc it.  */\n-\t\tchar *tmp = malloc(size);\n+\t\tchar *tmp = xmalloc(size);\n \t\tmsort_with_tmp(b, n, s, cmp, tmp);\n \t\tfree(tmp);\n \t}\ndiff --git a/remote.c b/remote.c\nindex b8ecfa5..7840d2f 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -840,7 +840,7 @@ char *apply_refspecs(struct refspec *refspecs, int nr_refspec,\n \t\t\t\t\t\t    refspec->dst, &ret))\n \t\t\t\treturn ret;\n \t\t} else if (!strcmp(refspec->src, name))\n-\t\t\treturn strdup(refspec->dst);\n+\t\t\treturn xstrdup(refspec->dst);\n \t}\n \treturn NULL;\n }\ndiff --git a/show-index.c b/show-index.c\nindex 4c0ac13..63f9da5 100644\n--- a/show-index.c\n+++ b/show-index.c\n@@ -48,7 +48,7 @@ int main(int argc, char **argv)\n \t\t\tunsigned char sha1[20];\n \t\t\tuint32_t crc;\n \t\t\tuint32_t off;\n-\t\t} *entries = malloc(nr * sizeof(entries[0]));\n+\t\t} *entries = xmalloc(nr * sizeof(entries[0]));\n \t\tfor (i = 0; i < nr; i++)\n \t\t\tif (fread(entries[i].sha1, 20, 1, stdin) != 1)\n \t\t\t\tdie(\"unable to read sha1 %u/%u\", i, nr);\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 4eab844..0713126 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -183,7 +183,7 @@ static struct child_process *get_helper(struct transport *transport)\n \t\t\tALLOC_GROW(refspecs,\n \t\t\t\t   refspec_nr + 1,\n \t\t\t\t   refspec_alloc);\n-\t\t\trefspecs[refspec_nr++] = strdup(capname + strlen(\"refspec \"));\n+\t\t\trefspecs[refspec_nr++] = xstrdup(capname + strlen(\"refspec \"));\n \t\t} else if (!strcmp(capname, \"connect\")) {\n \t\t\tdata->connect = 1;\n \t\t} else if (!prefixcmp(capname, \"export-marks \")) {\n@@ -445,7 +445,7 @@ static int fetch_with_import(struct transport *transport,\n \t\tif (data->refspecs)\n \t\t\tprivate = apply_refspecs(data->refspecs, data->refspec_nr, posn->name);\n \t\telse\n-\t\t\tprivate = strdup(posn->name);\n+\t\t\tprivate = xstrdup(posn->name);\n \t\tread_ref(private, posn->old_sha1);\n \t\tfree(private);\n \t}\n-- \n1.7.7\n"},{"id":"177085","messageId":"U4wiHVyDLLG1PhI-8iY3YqpVXvr151LbD3OSy1NeXQm5ByYpuasT4PQ2mikx8l9NCM-x0SQVCoNYKu2B_37OiPIe7xhKUs0BWoBswpMpuwrxmIZKhEHGr_44lDLJGr3mebaKn5BoGro@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"VYN8m1JCy102-eaWWa-bsunEvt3zeXLJkVg7FZKZCtXT-Ww0vg7a8xA7NTvrZTiovKTnJ9Hlom0@cipher.nrlssc.navy.mil","subject":"[PATCH v3 3/5] builtin/mv.c: plug miniscule memory leak","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-06T18:22:23Z","receivedAt":"2011-10-06T18:22:23Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Brandon Casey <drafnel@gmail.com>\n\nThe \"it\" string would not be free'ed if base_name was non-NULL.\nLet's free it.\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n builtin/mv.c |    6 +++++-\n 1 files changed, 5 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex e9d191f..5efe6c5 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -29,7 +29,11 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,\n \t\t\tto_copy--;\n \t\tif (to_copy != length || base_name) {\n \t\t\tchar *it = xmemdupz(result[i], to_copy);\n-\t\t\tresult[i] = base_name ? xstrdup(basename(it)) : it;\n+\t\t\tif (base_name) {\n+\t\t\t\tresult[i] = xstrdup(basename(it));\n+\t\t\t\tfree(it);\n+\t\t\t} else\n+\t\t\t\tresult[i] = it;\n \t\t}\n \t}\n \treturn get_pathspec(prefix, result);\n-- \n1.7.7\n"},{"id":"177086","messageId":"U4wiHVyDLLG1PhI-8iY3YljG5XnXCSQW-EJ7qKWa1bE0OZIDnUlSVkFyweS7FdaYLHyDajBWhaSSiQNIf4HLi7sINgYDYgNVVZFZ6Sg5YaJNBhMXLQ1f9nSs13sKBYh_-kN6HUeDiTQ@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"VYN8m1JCy102-eaWWa-bsunEvt3zeXLJkVg7FZKZCtXT-Ww0vg7a8xA7NTvrZTiovKTnJ9Hlom0@cipher.nrlssc.navy.mil","subject":"[PATCH v3 4/5] attr: read core.attributesfile from git_default_core_config","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-06T18:22:24Z","receivedAt":"2011-10-06T18:22:24Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nThis code calls git_config from a helper function to parse the config entry\nit is interested in.  Calling git_config in this way may cause a problem if\nthe helper function can be called after a previous call to git_config by\nanother function since the second call to git_config may reset some\nvariable to the value in the config file which was previously overridden.\n\nThe above is not a problem in this case since the function passed to\ngit_config only parses one config entry and the variable it sets is not\nassigned outside of the parsing function.  But a programmer who desires\nall of the standard config options to be parsed may be tempted to modify\ngit_attr_config() so that it falls back to git_default_config() and then it\n_would_ be vulnerable to the above described behavior.\n\nSo, move the call to git_config up into the top-level cmd_* function and\nmove the responsibility for parsing core.attributesfile into the main\nconfig file parser.\n\nWhich is only the logical thing to do ;-)\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n attr.c               |   15 ++-------------\n builtin/check-attr.c |    2 ++\n cache.h              |    1 +\n config.c             |    3 +++\n environment.c        |    1 +\n 5 files changed, 9 insertions(+), 13 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 0793859..124337d 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -20,8 +20,6 @@ static const char git_attr__unknown[] = \"(builtin)unknown\";\n #define ATTR__UNSET NULL\n #define ATTR__UNKNOWN git_attr__unknown\n \n-static const char *attributes_file;\n-\n /* This is a randomly chosen prime. */\n #define HASHSIZE 257\n \n@@ -494,14 +492,6 @@ static int git_attr_system(void)\n \treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n }\n \n-static int git_attr_config(const char *var, const char *value, void *dummy)\n-{\n-\tif (!strcmp(var, \"core.attributesfile\"))\n-\t\treturn git_config_pathname(&attributes_file, var, value);\n-\n-\treturn 0;\n-}\n-\n static void bootstrap_attr_stack(void)\n {\n \tif (!attr_stack) {\n@@ -521,9 +511,8 @@ static void bootstrap_attr_stack(void)\n \t\t\t}\n \t\t}\n \n-\t\tgit_config(git_attr_config, NULL);\n-\t\tif (attributes_file) {\n-\t\t\telem = read_attr_from_file(attributes_file, 1);\n+\t\tif (git_attributes_file) {\n+\t\t\telem = read_attr_from_file(git_attributes_file, 1);\n \t\t\tif (elem) {\n \t\t\t\telem->origin = NULL;\n \t\t\t\telem->prev = attr_stack;\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 708988a..abb1165 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -92,6 +92,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \tstruct git_attr_check *check;\n \tint cnt, i, doubledash, filei;\n \n+\tgit_config(git_default_config, NULL);\n+\n \targc = parse_options(argc, argv, prefix, check_attr_options,\n \t\t\t     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);\n \ndiff --git a/cache.h b/cache.h\nindex 607c2ea..8d95fb2 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -589,6 +589,7 @@ extern int warn_ambiguous_refs;\n extern int shared_repository;\n extern const char *apply_default_whitespace;\n extern const char *apply_default_ignorewhitespace;\n+extern const char *git_attributes_file;\n extern int zlib_compression_level;\n extern int core_compression_level;\n extern int core_compression_seen;\ndiff --git a/config.c b/config.c\nindex 4183f80..d3bcaa0 100644\n--- a/config.c\n+++ b/config.c\n@@ -491,6 +491,9 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.attributesfile\"))\n+\t\treturn git_config_pathname(&git_attributes_file, var, value);\n+\n \tif (!strcmp(var, \"core.bare\")) {\n \t\tis_bare_repository_cfg = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex e96edcf..d60b73f 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -29,6 +29,7 @@ const char *git_log_output_encoding;\n int shared_repository = PERM_UMASK;\n const char *apply_default_whitespace;\n const char *apply_default_ignorewhitespace;\n+const char *git_attributes_file;\n int zlib_compression_level = Z_BEST_SPEED;\n int core_compression_level;\n int core_compression_seen;\n-- \n1.7.7\n"},{"id":"177087","messageId":"U4wiHVyDLLG1PhI-8iY3YhHT7CEcTMEfg9MCDSaeuwAkg0N1a5wRE5NXaKAVQx8kpEYt75REVpRavoc-HiKe6rLk2AUepzHWptkevo08MRbGyWxqBHT_rySLemcbi66NKLRXwFGtaRQ@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"VYN8m1JCy102-eaWWa-bsunEvt3zeXLJkVg7FZKZCtXT-Ww0vg7a8xA7NTvrZTiovKTnJ9Hlom0@cipher.nrlssc.navy.mil","subject":"[PATCH v3 5/5] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-06T18:22:25Z","receivedAt":"2011-10-06T18:22:25Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Brandon Casey <drafnel@gmail.com>\n\nWhen core.ignorecase is true, the file globs configured in the\n.gitattributes file should be matched case-insensitively against the paths\nin the working directory.  Let's do so.\n\nPlus, add some tests.\n\nThe last set of tests is performed only on a case-insensitive filesystem.\nThose tests make sure that git handles the case where the .gitignore file\nresides in a subdirectory and the user supplies a path that does not match\nthe case in the filesystem.  In that case^H^H^H^Hsituation, part of the\npath supplied by the user is effectively interpreted case-insensitively,\nand part of it is dependent on the setting of core.ignorecase.  git should\nonly match the portion of the path below the directory holding the\n.gitignore file according to the setting of core.ignorecase.\n\nThis is also partly future-proofing.  Currently, git builds the attr stack\nbased on the path supplied by the user, so we don't have to do anything\nspecial (like use strcmp_icase) to handle the parts of that path that don't\nmatch the filesystem with respect to case.  If git instead built the attr\nstack by scanning the repository, then the paths in the origin field would\nnot necessarily match the paths supplied by the user.  If someone makes a\nchange like that in the future, these tests will notice.\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n attr.c                |    5 ++-\n t/t0003-attributes.sh |   60 ++++++++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 62 insertions(+), 3 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 124337d..76b079f 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -11,6 +11,7 @@\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n #include \"attr.h\"\n+#include \"dir.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n const char git_attr__false[] = \"\\0(builtin)false\";\n@@ -631,7 +632,7 @@ static int path_matches(const char *pathname, int pathlen,\n \t\t/* match basename */\n \t\tconst char *basename = strrchr(pathname, '/');\n \t\tbasename = basename ? basename + 1 : pathname;\n-\t\treturn (fnmatch(pattern, basename, 0) == 0);\n+\t\treturn (fnmatch_icase(pattern, basename, 0) == 0);\n \t}\n \t/*\n \t * match with FNM_PATHNAME; the pattern has base implicitly\n@@ -645,7 +646,7 @@ static int path_matches(const char *pathname, int pathlen,\n \t\treturn 0;\n \tif (baselen != 0)\n \t\tbaselen++;\n-\treturn fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n+\treturn fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n }\n \n static int macroexpand_one(int attr_nr, int rem);\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex ae2f1da..47a70c4 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -9,7 +9,7 @@ attr_check () {\n \tpath=\"$1\"\n \texpect=\"$2\"\n \n-\tgit check-attr test -- \"$path\" >actual 2>err &&\n+\tgit $3 check-attr test -- \"$path\" >actual 2>err &&\n \techo \"$path: test: $2\" >expect &&\n \ttest_cmp expect actual &&\n \ttest_line_count = 0 err\n@@ -27,6 +27,7 @@ test_expect_success 'setup' '\n \t\techo \"onoff test -test\"\n \t\techo \"offon -test test\"\n \t\techo \"no notest\"\n+\t\techo \"A/e/F test=A/e/F\"\n \t) >.gitattributes &&\n \t(\n \t\techo \"g test=a/g\" &&\n@@ -93,6 +94,63 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '\n+\n+\ttest_must_fail attr_check F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/c/F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/G a/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/B/g a/b/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/G a/b/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/H a/b/h \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check oNoFf unset \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check oFfOn set \"-c core.ignorecase=0\" &&\n+\tattr_check NO unspecified \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\tattr_check a/b/d/YES a/b/d/* \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/E/f \"A/e/F\" \"-c core.ignorecase=0\"\n+\n+'\n+\n+test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '\n+\n+\tattr_check F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/c/F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/G a/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/B/g a/b/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/G a/b/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/H a/b/h \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check oNoFf unset \"-c core.ignorecase=1\" &&\n+\tattr_check oFfOn set \"-c core.ignorecase=1\" &&\n+\tattr_check NO unspecified \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/d/YES unspecified \"-c core.ignorecase=1\" &&\n+\tattr_check a/E/f \"A/e/F\" \"-c core.ignorecase=1\"\n+\n+'\n+\n+test_expect_success 'check whether FS is case-insensitive' '\n+\tmkdir junk &&\n+\techo good >junk/CamelCase &&\n+\techo bad >junk/camelcase &&\n+\tif test \"$(cat junk/CamelCase)\" != good\n+\tthen\n+\t\ttest_set_prereq CASE_INSENSITIVE_FS\n+\tfi\n+'\n+\n+test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '\n+\ttest_must_fail attr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\tattr_check A/b/h a/b/h \"-c core.ignorecase=0\" &&\n+\tattr_check A/b/h a/b/h \"-c core.ignorecase=1\" &&\n+\tattr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\"\n+'\n+\n test_expect_success 'unnormalized paths' '\n \n \tattr_check ./f f &&\n-- \n1.7.7\n"},{"id":"177275","messageId":"4E91BAC8.9060606@alum.mit.edu","threadId":"28612","inReplyTo":"U4wiHVyDLLG1PhI-8iY3YhHT7CEcTMEfg9MCDSaeuwAkg0N1a5wRE5NXaKAVQx8kpEYt75REVpRavoc-HiKe6rLk2AUepzHWptkevo08MRbGyWxqBHT_rySLemcbi66NKLRXwFGtaRQ@cipher.nrlssc.navy.mil","subject":"Re: [PATCH v3 5/5] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-09T15:16:24Z","receivedAt":"2011-10-09T15:16:24Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/06/2011 08:22 PM, Brandon Casey wrote:\n> The last set of tests is performed only on a case-insensitive filesystem.\n> Those tests make sure that git handles the case where the .gitignore file\n> resides in a subdirectory and the user supplies a path that does not match\n> the case in the filesystem.  In that case^H^H^H^Hsituation, part of the\n> path supplied by the user is effectively interpreted case-insensitively,\n> and part of it is dependent on the setting of core.ignorecase.  git should\n> only match the portion of the path below the directory holding the\n> .gitignore file according to the setting of core.ignorecase.\n\nIsn't this a rather perverse scenario?  It is hard to imagine that\nanybody *wants* part of a single filename to be matched\ncase-insensitively and another part to be matched case-sensitively.\nISTM that a person who is using a case-insensitive filesystem and has\ncore-ignorecase=false is (1) a glutton for punishment and (2) probably\nvery careful to make sure that the case of all pathnames is correct.  So\nsuch a person is not likely to benefit from this schizophrenic behavior.\n\n> [...]  If git instead built the attr\n> stack by scanning the repository, then the paths in the origin field would\n> not necessarily match the paths supplied by the user.  If someone makes a\n> change like that in the future, these tests will notice.\n\nYour decision to treat path names as partly case-insensitive will make\nthis kind of improvement considerably more complicated.\n\nTherefore, weighing the negligible benefit of declaring this\nschizophrenic behavior against the potential big pain of remaining\nbackwards-compatible with this behavior, I suggest that we either (1)\ndeclare that when core.ignorecase=false then the *whole* filenames\n(including the path leading up to the .gitignore file) must match\ncase-sensitively, or (2) declare the behavior in this situation to be\nundefined so that nobody thinks they should depend on it.\n\nBut given that I'm a potential implementer but not a potential Windows\nuser, perhaps my judgment is biased...\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"177322","messageId":"CA+sFfMd9exQcGfTGLJFPXG3-bq-ukn7K4m1R=LvLKqc1-jDVQw@mail.gmail.com","threadId":"28612","inReplyTo":"4E91BAC8.9060606@alum.mit.edu","subject":"Re: [PATCH v3 5/5] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Brandon Casey","fromEmail":"drafnel@gmail.com","sentAt":"2011-10-10T18:01:03Z","receivedAt":"2011-10-10T18:01:03Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"On Sun, Oct 9, 2011 at 10:16 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> On 10/06/2011 08:22 PM, Brandon Casey wrote:\n>> The last set of tests is performed only on a case-insensitive filesystem.\n>> Those tests make sure that git handles the case where the .gitignore file\n>> resides in a subdirectory and the user supplies a path that does not match\n>> the case in the filesystem.  In that case^H^H^H^Hsituation, part of the\n>> path supplied by the user is effectively interpreted case-insensitively,\n>> and part of it is dependent on the setting of core.ignorecase.  git should\n>> only match the portion of the path below the directory holding the\n>> .gitignore file according to the setting of core.ignorecase.\n>\n> Isn't this a rather perverse scenario?\n\nNo argument here. :)\n\n> It is hard to imagine that\n> anybody *wants* part of a single filename to be matched\n> case-insensitively and another part to be matched case-sensitively.\n> ISTM that a person who is using a case-insensitive filesystem and has\n> core-ignorecase=false is (1) a glutton for punishment and (2) probably\n> very careful to make sure that the case of all pathnames is correct.  So\n> such a person is not likely to benefit from this schizophrenic behavior.\n>\n>> [...]  If git instead built the attr\n>> stack by scanning the repository, then the paths in the origin field would\n>> not necessarily match the paths supplied by the user.  If someone makes a\n>> change like that in the future, these tests will notice.\n>\n> Your decision to treat path names as partly case-insensitive...\n\nYou are giving more credit to this patch than it deserves.  It really\ndoesn't do much.  It's not a design decision that I made to treat path\nnames as case-insensitive.  That is a consequence of using a\ncase-insensitive file system.  When you give git the path A/b/c and\nthere exists a/.gitattributes, then on a case insensitive file system\ngit will try to read A/.gitattributes and the filesystem will return a\nhandle for a/.gitattributes and git won't be able to tell the\ndifference.  git will then apply the rules in the file to the paths\nbelow a/ even when the path is supplied like A/.  So, at the moment,\nregardless of the setting of core.ignorecase, the path above a\n.gitignore file is treated as case-insensitive on a case-insensitive\nfilesystem.\n\nThe purpose of the tests are primarily to ensure that nothing special\nneeds to be done concerning paths leading up to a directory containing\na .gitignore file in the core.ignorecase=1 case.  For example, it is\n_not_ necessary to use strncmp_icase instead of strncmp on the leading\nportion of the path.\n\nWhat I meant when I said \"If someone makes a change like that in the\nfuture, these tests will notice\", is that they will notice that they\nmust now use strncmp_icase when comparing the portion of the path\nabove the .gitattributes file.\n\n> will make\n> this kind of improvement considerably more complicated.\n> Therefore, weighing the negligible benefit of declaring this\n> schizophrenic behavior against the potential big pain of remaining\n> backwards-compatible with this behavior, I suggest that we either (1)\n> declare that when core.ignorecase=false then the *whole* filenames\n> (including the path leading up to the .gitignore file) must match\n> case-sensitively, or (2) declare the behavior in this situation to be\n> undefined so that nobody thinks they should depend on it.\n\nI do not plan to make git treat leading paths case-sensitively on a\ncase-insensitive file system when core.ignorecase=0 any more than I\nplan to make git treat leading paths case-insensitively on a\ncase-sensitive file system when core.ignorecase=1.  For justification,\nI refer back to your original comment about perversion. :)\n\nSo, #2 gets my vote.\n\n\nMaybe my commit message is not clear that it is describing the current\nbehavior and not defining it.  Instead of\n\n   git should only match the portion of the path below the directory\n   holding the .gitignore file according to the setting of\n   core.ignorecase.\n\nmaybe I should say\n\n    git will currently only match the portion of the path...\n\nI could also remove the following test from the CASE_INSENSITIVE_FS\ntests since it is really a dontcare:\n\n   attr_check A/b/h a/b/h \"-c core.ignorecase=0\"\n\nWe don't care what happens when the user supplies A/b/h and a/b/h\nexists on disk when core.ignorecase=0, we only care that A/b/h is\ninterpreted correctly when core.ignorecase=1.\n\n-Brandon\n"},{"id":"177345","messageId":"7vmxd8ieid.fsf@alter.siamese.dyndns.org","threadId":"28612","inReplyTo":"4E91BAC8.9060606@alum.mit.edu","subject":"Re: [PATCH v3 5/5] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-11T00:00:10Z","receivedAt":"2011-10-11T00:00:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael Haggerty <mhagger@alum.mit.edu> writes:\n\n> On 10/06/2011 08:22 PM, Brandon Casey wrote:\n>> The last set of tests is performed only on a case-insensitive filesystem.\n>> Those tests make sure that git handles the case where the .gitignore file\n>> resides in a subdirectory and the user supplies a path that does not match\n>> the case in the filesystem.  In that case^H^H^H^Hsituation, part of the\n>> path supplied by the user is effectively interpreted case-insensitively,\n>> and part of it is dependent on the setting of core.ignorecase.  git should\n>> only match the portion of the path below the directory holding the\n>> .gitignore file according to the setting of core.ignorecase.\n>\n> ... It is hard to imagine that\n> anybody *wants* part of a single filename to be matched\n> case-insensitively and another part to be matched case-sensitively.\n\nThat is not necessarily coming from the user's wish. When a command that\ntakes a pathspec from the user is run from a subdirectory, almost always\nthe output from $(git rev-parse --show-prefix) is prefixed to them. This\nvalue is read from the filesystem, and unless on a system whose readdir()\nmay lie to us, we do not _have_ to ignore the case of this part of the\nsubstring of a resulting pathspec element to get a successful match, even\nthough we _do_ want to match the user-supplied part case insensitively\nif/when the user says he wants us to with core.ignorecase.\n\nHaving said that, it may not hurt in practice if we matched the prefix\npart case insensitvely, because prefix=foobar/ obtained on a filesystem\nwhere core.ignorecase is true would mean there won't be FooBar/ and other\ncase-permuted names on the filesystem at the same time.\n\nBut of course I may be missing something...\n"},{"id":"177353","messageId":"4E93BBA8.6080403@alum.mit.edu","threadId":"28612","inReplyTo":"CA+sFfMd9exQcGfTGLJFPXG3-bq-ukn7K4m1R=LvLKqc1-jDVQw@mail.gmail.com","subject":"Re: [PATCH v3 5/5] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-11T03:44:40Z","receivedAt":"2011-10-11T03:44:40Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/10/2011 08:01 PM, Brandon Casey wrote:\n> On Sun, Oct 9, 2011 at 10:16 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> Maybe my commit message is not clear that it is describing the current\n> behavior and not defining it.  Instead of\n> \n>    git should only match the portion of the path below the directory\n>    holding the .gitignore file according to the setting of\n>    core.ignorecase.\n> \n> maybe I should say\n> \n>     git will currently only match the portion of the path...\n> \n> I could also remove the following test from the CASE_INSENSITIVE_FS\n> tests since it is really a dontcare:\n> \n>    attr_check A/b/h a/b/h \"-c core.ignorecase=0\"\n> \n> We don't care what happens when the user supplies A/b/h and a/b/h\n> exists on disk when core.ignorecase=0, we only care that A/b/h is\n> interpreted correctly when core.ignorecase=1.\n\nSounds good to me.\n\nThanks,\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"177373","messageId":"HBn1XX5GLcGG9WPqS0RC9Uscll_6Kbd741mHOR7uc_IFxdOpGSDGF7qEBPF66SbtO3keG4GcnkbtEvKDQ5D3bCDNiV9EPgEh-CMLKgbfFJcpVD5Gcb69-QoqTpHG_J9pDQG844LtNZU@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"4E93BBA8.6080403@alum.mit.edu","subject":"[PATCH v4] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-11T15:53:31Z","receivedAt":"2011-10-11T15:53:31Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"From: Brandon Casey <drafnel@gmail.com>\n\nWhen core.ignorecase is true, the file globs configured in the\n.gitattributes file should be matched case-insensitively against the paths\nin the working directory.  Let's do so.\n\nPlus, add some tests.\n\nThe last set of tests is performed only on a case-insensitive filesystem.\nThose tests make sure that git handles the case where the .gitignore file\nresides in a subdirectory and the user supplies a path that does not match\nthe case in the filesystem.  In that case^H^H^H^Hsituation, part of the\npath supplied by the user is effectively interpreted case-insensitively,\nand part of it is dependent on the setting of core.ignorecase.  git will\ncurrently only match the portion of the path below the directory holding\nthe .gitignore file according to the setting of core.ignorecase.\n\nThis is also partly future-proofing.  Currently, git builds the attr stack\nbased on the path supplied by the user, so we don't have to do anything\nspecial (like use strcmp_icase) to handle the parts of that path that don't\nmatch the filesystem with respect to case.  If git instead built the attr\nstack by scanning the repository, then the paths in the origin field would\nnot necessarily match the paths supplied by the user.  If someone makes a\nchange like that in the future, these tests will notice.\n\nSigned-off-by: Brandon Casey <drafnel@gmail.com>\n---\n\n\nOn Mon, Oct 10, 2011 at 10:44 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> On 10/10/2011 08:01 PM, Brandon Casey wrote:\n>> On Sun, Oct 9, 2011 at 10:16 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n>> Maybe my commit message is not clear that it is describing the current\n>> behavior and not defining it.  Instead of\n>>\n>>    git should only match the portion of the path below the directory\n>>    holding the .gitignore file according to the setting of\n>>    core.ignorecase.\n>>\n>> maybe I should say\n>>\n>>     git will currently only match the portion of the path...\n>>\n>> I could also remove the following test from the CASE_INSENSITIVE_FS\n>> tests since it is really a dontcare:\n>>\n>>    attr_check A/b/h a/b/h \"-c core.ignorecase=0\"\n>>\n>> We don't care what happens when the user supplies A/b/h and a/b/h\n>> exists on disk when core.ignorecase=0, we only care that A/b/h is\n>> interpreted correctly when core.ignorecase=1.\n>\n> Sounds good to me.\n\nOk, here it is.\n\nMinor tweak which, hopefully, adds clarity to the commit message and\nremoves an unnecessary test.\n\nOn top of bc/attr-ignore-case^ 64589a03a8ffb3eb4fb2ff8f416ff638a9aaa439.\n\n-Brandon\n\n\n attr.c                |    5 ++-\n t/t0003-attributes.sh |   59 ++++++++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 61 insertions(+), 3 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 124337d..76b079f 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -11,6 +11,7 @@\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n #include \"attr.h\"\n+#include \"dir.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n const char git_attr__false[] = \"\\0(builtin)false\";\n@@ -631,7 +632,7 @@ static int path_matches(const char *pathname, int pathlen,\n \t\t/* match basename */\n \t\tconst char *basename = strrchr(pathname, '/');\n \t\tbasename = basename ? basename + 1 : pathname;\n-\t\treturn (fnmatch(pattern, basename, 0) == 0);\n+\t\treturn (fnmatch_icase(pattern, basename, 0) == 0);\n \t}\n \t/*\n \t * match with FNM_PATHNAME; the pattern has base implicitly\n@@ -645,7 +646,7 @@ static int path_matches(const char *pathname, int pathlen,\n \t\treturn 0;\n \tif (baselen != 0)\n \t\tbaselen++;\n-\treturn fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n+\treturn fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n }\n \n static int macroexpand_one(int attr_nr, int rem);\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex ae2f1da..6946c4b 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -9,7 +9,7 @@ attr_check () {\n \tpath=\"$1\"\n \texpect=\"$2\"\n \n-\tgit check-attr test -- \"$path\" >actual 2>err &&\n+\tgit $3 check-attr test -- \"$path\" >actual 2>err &&\n \techo \"$path: test: $2\" >expect &&\n \ttest_cmp expect actual &&\n \ttest_line_count = 0 err\n@@ -27,6 +27,7 @@ test_expect_success 'setup' '\n \t\techo \"onoff test -test\"\n \t\techo \"offon -test test\"\n \t\techo \"no notest\"\n+\t\techo \"A/e/F test=A/e/F\"\n \t) >.gitattributes &&\n \t(\n \t\techo \"g test=a/g\" &&\n@@ -93,6 +94,62 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '\n+\n+\ttest_must_fail attr_check F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/c/F f \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/G a/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/B/g a/b/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/G a/b/g \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/H a/b/h \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check oNoFf unset \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check oFfOn set \"-c core.ignorecase=0\" &&\n+\tattr_check NO unspecified \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\tattr_check a/b/d/YES a/b/d/* \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check a/E/f \"A/e/F\" \"-c core.ignorecase=0\"\n+\n+'\n+\n+test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '\n+\n+\tattr_check F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/c/F f \"-c core.ignorecase=1\" &&\n+\tattr_check a/G a/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/B/g a/b/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/G a/b/g \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/H a/b/h \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check oNoFf unset \"-c core.ignorecase=1\" &&\n+\tattr_check oFfOn set \"-c core.ignorecase=1\" &&\n+\tattr_check NO unspecified \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check a/b/d/YES unspecified \"-c core.ignorecase=1\" &&\n+\tattr_check a/E/f \"A/e/F\" \"-c core.ignorecase=1\"\n+\n+'\n+\n+test_expect_success 'check whether FS is case-insensitive' '\n+\tmkdir junk &&\n+\techo good >junk/CamelCase &&\n+\techo bad >junk/camelcase &&\n+\tif test \"$(cat junk/CamelCase)\" != good\n+\tthen\n+\t\ttest_set_prereq CASE_INSENSITIVE_FS\n+\tfi\n+'\n+\n+test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '\n+\ttest_must_fail attr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\ttest_must_fail attr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n+\tattr_check A/b/h a/b/h \"-c core.ignorecase=1\" &&\n+\tattr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n+\tattr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\"\n+'\n+\n test_expect_success 'unnormalized paths' '\n \n \tattr_check ./f f &&\n-- \n1.7.7.138.g7f41b6\n"},{"id":"177377","messageId":"7v8vorh3kg.fsf@alter.siamese.dyndns.org","threadId":"28612","inReplyTo":"HBn1XX5GLcGG9WPqS0RC9Uscll_6Kbd741mHOR7uc_IFxdOpGSDGF7qEBPF66SbtO3keG4GcnkbtEvKDQ5D3bCDNiV9EPgEh-CMLKgbfFJcpVD5Gcb69-QoqTpHG_J9pDQG844LtNZU@cipher.nrlssc.navy.mil","subject":"Re: [PATCH v4] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-11T16:54:07Z","receivedAt":"2011-10-11T16:54:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Casey <casey@nrlssc.navy.mil> writes:\n\n> ...  Currently, git builds the attr stack\n> based on the path supplied by the user, so we don't have to do anything\n> special (like use strcmp_icase) to handle the parts of that path that don't\n> match the filesystem with respect to case.  If git instead built the attr\n> stack by scanning the repository, then the paths in the origin field would\n> not necessarily match the paths supplied by the user.\n\nI find this description somewhat misleading. \"check-attr\" at the plumbing\nlevel does take full path from the end user, but a common thing Git does\nis to ask the system to learn the prefix to the current directory with\ngetcwd(3) append what fill_directory() enumerates as matching a pathspec\ngiven by the user with readdir(3) to the prefix to form the full path, and\nthen feed that full path to git_check_attr().\n\nWithout anybody changing anything, we already do build the attr stack by\n\"scanning the repository\" in that case, no?\n"},{"id":"177482","messageId":"y0zSE7mQNTqQ3B_hRG_UvK2pQCTYIP8jr_bGkjb8qdCqyfJ544ZQhQCmwkL-_MxlparVZWmDgqL7VO68y3trgjciKw2QRAK_j7KNVcXXJW0@cipher.nrlssc.navy.mil","threadId":"28612","inReplyTo":"7v8vorh3kg.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2011-10-12T20:18:34Z","receivedAt":"2011-10-12T20:18:34Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"On 10/11/2011 11:54 AM, Junio C Hamano wrote:\n> Brandon Casey <casey@nrlssc.navy.mil> writes:\n> \n>> ...  Currently, git builds the attr stack\n>> based on the path supplied by the user, so we don't have to do anything\n>> special (like use strcmp_icase) to handle the parts of that path that don't\n>> match the filesystem with respect to case.  If git instead built the attr\n>> stack by scanning the repository, then the paths in the origin field would\n>> not necessarily match the paths supplied by the user.\n> \n> I find this description somewhat misleading. \"check-attr\" at the plumbing\n> level does take full path from the end user, but a common thing Git does\n> is to ask the system to learn the prefix to the current directory with\n> getcwd(3) append what fill_directory() enumerates as matching a pathspec\n> given by the user with readdir(3) to the prefix to form the full path, and\n> then feed that full path to git_check_attr().\n> \n> Without anybody changing anything, we already do build the attr stack by\n> \"scanning the repository\" in that case, no?\n\nWell, kind of.  What I meant by \"scanning the repository\", was having\ntwo separate mechanisms: one to build the attr stack, and one to scan it\nto get the attributes.  Right now, the two operations are tied together\nand the stack is built as needed, and it is built using the same path\nstring that the scan operation will use for checking for attributes.\nSo, the leading paths will match.\n\nWhen I wrote that commit message, I really was only thinking about a\nuser-supplied path, but the focus should be on prepare_attr_stack().\nThe reason the leading paths to a .gitattributes file will necessarily\nmatch is because the attr stack is built using the path supplied to\nprepare_attr_stack(), and the same path string is used when scanning\nthe stack to check for attributes.  So each path that is supplied,\nregardless of whether its case matches the case in the file system or\nin the repository, will have an entry in the attr stack.\n\nMaybe that last paragraph in the commit message should just be dropped.\nI think the preceding paragraph explains the purpose of the tests, and\nthis last one doesn't really add any value.\n\nDo you want me to resubmit or can you fix it up?  I ask not because I\nam too lazy to do 'commit --amend' myself, but because you may prefer\nto receive one less patch in your inbox if you can easily apply the\nchange yourself.\n\n-Brandon\n"},{"id":"177483","messageId":"7vaa967yb2.fsf@alter.siamese.dyndns.org","threadId":"28612","inReplyTo":"y0zSE7mQNTqQ3B_hRG_UvK2pQCTYIP8jr_bGkjb8qdCqyfJ544ZQhQCmwkL-_MxlparVZWmDgqL7VO68y3trgjciKw2QRAK_j7KNVcXXJW0@cipher.nrlssc.navy.mil","subject":"Re: [PATCH v4] attr.c: respect core.ignorecase when matching attribute patterns","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-12T20:24:49Z","receivedAt":"2011-10-12T20:24:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Casey <casey@nrlssc.navy.mil> writes:\n\n> On 10/11/2011 11:54 AM, Junio C Hamano wrote:\n> ...\n> Maybe that last paragraph in the commit message should just be dropped.\n> I think the preceding paragraph explains the purpose of the tests, and\n> this last one doesn't really add any value.\n\nI wasn't saying the description was wrong per-se. It only makes difference\nfor \"git check-attr\" users, but it still _does_ make difference for them,\nI think. So I kept the paragraph in the end.\n\n> Do you want me to resubmit or can you fix it up?  I ask not because I\n> am too lazy to do 'commit --amend' myself, but because you may prefer\n> to receive one less patch in your inbox if you can easily apply the\n> change yourself.\n\nIt doesn't make much difference to me, as long as I don't forget a simple\nand no-brainer amend I am supposed to do myself ;-).\n\nThanks.\n"}]}