Code

Merge the attributes fix in from maint-1.6.6 branch
authorJunio C Hamano <gitster@pobox.com>
Tue, 10 Jan 2012 22:14:26 +0000 (14:14 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 10 Jan 2012 22:14:26 +0000 (14:14 -0800)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1  2 
Documentation/config.txt
attr.c
t/t0003-attributes.sh

Simple merge
diff --cc attr.c
index 76b079f0f530e1372b2866f40cce21ec5266394c,2ce73651381c8ebfa6dfed6c2013b72059861b2b..96eda0ef078f998c020666f89eea29ac4b1bfb53
--- 1/attr.c
--- 2/attr.c
+++ b/attr.c
@@@ -493,62 -478,68 +493,63 @@@ static int git_attr_system(void
        return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
  }
  
 -static int git_attr_config(const char *var, const char *value, void *dummy)
 -{
 -      if (!strcmp(var, "core.attributesfile"))
 -              return git_config_pathname(&attributes_file, var, value);
 -
 -      return 0;
 -}
 -
  static void bootstrap_attr_stack(void)
  {
-       if (!attr_stack) {
-               struct attr_stack *elem;
+       struct attr_stack *elem;
  
-               elem = read_attr_from_array(builtin_attr);
-               elem->origin = NULL;
-               elem->prev = attr_stack;
-               attr_stack = elem;
+       if (attr_stack)
+               return;
  
-               if (git_attr_system()) {
-                       elem = read_attr_from_file(git_etc_gitattributes(), 1);
-                       if (elem) {
-                               elem->origin = NULL;
-                               elem->prev = attr_stack;
-                               attr_stack = elem;
-                       }
-               }
+       elem = read_attr_from_array(builtin_attr);
+       elem->origin = NULL;
+       elem->prev = attr_stack;
+       attr_stack = elem;
  
-               if (git_attributes_file) {
-                       elem = read_attr_from_file(git_attributes_file, 1);
-                       if (elem) {
-                               elem->origin = NULL;
-                               elem->prev = attr_stack;
-                               attr_stack = elem;
-                       }
+       if (git_attr_system()) {
+               elem = read_attr_from_file(git_etc_gitattributes(), 1);
+               if (elem) {
+                       elem->origin = NULL;
+                       elem->prev = attr_stack;
+                       attr_stack = elem;
                }
+       }
  
-               if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
-                       elem = read_attr(GITATTRIBUTES_FILE, 1);
-                       elem->origin = xstrdup("");
 -      git_config(git_attr_config, NULL);
 -      if (attributes_file) {
 -              elem = read_attr_from_file(attributes_file, 1);
++      if (git_attributes_file) {
++              elem = read_attr_from_file(git_attributes_file, 1);
+               if (elem) {
+                       elem->origin = NULL;
                        elem->prev = attr_stack;
                        attr_stack = elem;
-                       debug_push(elem);
                }
+       }
  
-               elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
-               if (!elem)
-                       elem = xcalloc(1, sizeof(*elem));
-               elem->origin = NULL;
+       if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
+               elem = read_attr(GITATTRIBUTES_FILE, 1);
 -              elem->origin = strdup("");
++              elem->origin = xstrdup("");
                elem->prev = attr_stack;
                attr_stack = elem;
+               debug_push(elem);
        }
+       elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
+       if (!elem)
+               elem = xcalloc(1, sizeof(*elem));
+       elem->origin = NULL;
+       elem->prev = attr_stack;
+       attr_stack = elem;
  }
  
 -static void prepare_attr_stack(const char *path, int dirlen)
 +static void prepare_attr_stack(const char *path)
  {
        struct attr_stack *elem, *info;
 -      int len;
 -      struct strbuf pathbuf;
 +      int dirlen, len;
 +      const char *cp;
  
 -      strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
 +      cp = strrchr(path, '/');
 +      if (!cp)
 +              dirlen = 0;
 +      else
 +              dirlen = cp - path;
  
        /*
         * At the bottom of the attribute stack is the built-in
         * Read from parent directories and push them down
         */
        if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
+               /*
+                * bootstrap_attr_stack() should have added, and the
+                * above loop should have stopped before popping, the
+                * root element whose attr_stack->origin is set to an
+                * empty string.
+                */
 +              struct strbuf pathbuf = STRBUF_INIT;
 +
+               assert(attr_stack->origin);
                while (1) {
 -                      char *cp;
 -
                        len = strlen(attr_stack->origin);
                        if (dirlen <= len)
                                break;
index 6946c4b82f9291f6618d49de2e3892a2c203d337,61b5a2eba633d52ebf53efb3c0539f8abf4094ea..19265c77cf0b1df828eea188d5f880cbb7497c63
@@@ -94,84 -60,16 +94,94 @@@ test_expect_success 'attribute test' 
  
  '
  
 +test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '
 +
 +      test_must_fail attr_check F f "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/F f "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/c/F f "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/G a/g "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" &&
 +      test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" &&
 +      test_must_fail attr_check oFfOn set "-c core.ignorecase=0" &&
 +      attr_check NO unspecified "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
 +      attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&
 +      test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0"
 +
 +'
 +
 +test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '
 +
 +      attr_check F f "-c core.ignorecase=1" &&
 +      attr_check a/F f "-c core.ignorecase=1" &&
 +      attr_check a/c/F f "-c core.ignorecase=1" &&
 +      attr_check a/G a/g "-c core.ignorecase=1" &&
 +      attr_check a/B/g a/b/g "-c core.ignorecase=1" &&
 +      attr_check a/b/G a/b/g "-c core.ignorecase=1" &&
 +      attr_check a/b/H a/b/h "-c core.ignorecase=1" &&
 +      attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&
 +      attr_check oNoFf unset "-c core.ignorecase=1" &&
 +      attr_check oFfOn set "-c core.ignorecase=1" &&
 +      attr_check NO unspecified "-c core.ignorecase=1" &&
 +      attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&
 +      attr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&
 +      attr_check a/E/f "A/e/F" "-c core.ignorecase=1"
 +
 +'
 +
 +test_expect_success 'check whether FS is case-insensitive' '
 +      mkdir junk &&
 +      echo good >junk/CamelCase &&
 +      echo bad >junk/camelcase &&
 +      if test "$(cat junk/CamelCase)" != good
 +      then
 +              test_set_prereq CASE_INSENSITIVE_FS
 +      fi
 +'
 +
 +test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '
 +      test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" &&
 +      test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
 +      attr_check A/b/h a/b/h "-c core.ignorecase=1" &&
 +      attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&
 +      attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"
 +'
 +
 +test_expect_success 'unnormalized paths' '
 +
 +      attr_check ./f f &&
 +      attr_check ./a/g a/g &&
 +      attr_check a/./g a/g &&
 +      attr_check a/c/../b/g a/b/g
 +
 +'
 +
 +test_expect_success 'relative paths' '
 +
 +      (cd a && attr_check ../f f) &&
 +      (cd a && attr_check f f) &&
 +      (cd a && attr_check i a/i) &&
 +      (cd a && attr_check g a/g) &&
 +      (cd a && attr_check b/g a/b/g) &&
 +      (cd b && attr_check ../a/f f) &&
 +      (cd b && attr_check ../a/g a/g) &&
 +      (cd b && attr_check ../a/b/g a/b/g)
 +
 +'
 +
+ test_expect_success 'prefixes are not confused with leading directories' '
+       attr_check a_plus/g unspecified &&
+       cat >expect <<-\EOF &&
+       a/g: test: a/g
+       a_plus/g: test: unspecified
+       EOF
+       git check-attr test a/g a_plus/g >actual &&
+       test_cmp expect actual
+ '
  test_expect_success 'core.attributesfile' '
        attr_check global unspecified &&
        git config core.attributesfile "$HOME/global-gitattributes" &&