@matheusbsbs / matheus-bagliano / commits / ec775c41dc
Fork 0

attr: Expand macros immediately when encountered.

When using macros it is otherwise hard to know whether an attribute set by the macro should override an already set attribute. Consider the following .gitattributes file: [attr]mybinary binary -ident * ident foo.bin mybinary bar.bin mybinary ident Without this patch both foo.bin and bar.bin will have the ident attribute set, which is probably not what the user expects. With this patch foo.bin will have an unset ident attribute, while bar.bin will have it set. Signed-off-by: Henrik Grubbström <grubba@grubba.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Henrik Grubbström committed Apr 6, 2010 at 14:46 UTC ec775c41dc4bb7382ebbbb61ede59e63846b3644
2 files changed +29 -12
attr.c
+20 -12
@@ -594,6 +594,8 @@ static int path_matches(const char *pathname, int pathlen,
594 return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
595 }
596
597 +static int macroexpand_one(int attr_nr, int rem);
598 +
599 static int fill_one(const char *what, struct match_attr *a, int rem)
600 {
601 struct git_attr_check *check = check_all_attr;
@@ -610,6 +612,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
612 attr, v);
613 *n = v;
614 rem--;
615 + rem = macroexpand_one(attr->attr_nr, rem);
616 }
617 }
618 return rem;
@@ -631,19 +634,27 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
634 return rem;
635 }
636
634 -static int macroexpand(struct attr_stack *stk, int rem)
637 +static int macroexpand_one(int attr_nr, int rem)
638 {
639 + struct attr_stack *stk;
640 + struct match_attr *a = NULL;
641 int i;
637 - struct git_attr_check *check = check_all_attr;
642
639 - for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
640 - struct match_attr *a = stk->attrs[i];
641 - if (!a->is_macro)
642 - continue;
643 - if (check[a->u.attr->attr_nr].value != ATTR__TRUE)
644 - continue;
643 + if (check_all_attr[attr_nr].value != ATTR__TRUE)
644 + return rem;
645 +
646 + for (stk = attr_stack; !a && stk; stk = stk->prev)
647 + for (i = stk->num_matches - 1; !a && 0 <= i; i--) {
648 + struct match_attr *ma = stk->attrs[i];
649 + if (!ma->is_macro)
650 + continue;
651 + if (ma->u.attr->attr_nr == attr_nr)
652 + a = ma;
653 + }
654 +
655 + if (a)
656 rem = fill_one("expand", a, rem);
646 - }
657 +
658 return rem;
659 }
660
@@ -668,9 +679,6 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
679 for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
680 rem = fill(path, pathlen, stk, rem);
681
671 - for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
672 - rem = macroexpand(stk, rem);
673 -
682 for (i = 0; i < num; i++) {
683 const char *value = check_all_attr[check[i].attr->attr_nr].value;
684 if (value == ATTR__UNKNOWN)
t/t0003-attributes.sh
+9
@@ -20,10 +20,12 @@ test_expect_success 'setup' '
20
21 mkdir -p a/b/d a/c &&
22 (
23 + echo "[attr]notest !test"
24 echo "f test=f"
25 echo "a/i test=a/i"
26 echo "onoff test -test"
27 echo "offon -test test"
28 + echo "no notest"
29 ) >.gitattributes &&
30 (
31 echo "g test=a/g" &&
@@ -32,6 +34,7 @@ test_expect_success 'setup' '
34 (
35 echo "h test=a/b/h" &&
36 echo "d/* test=a/b/d/*"
37 + echo "d/yes notest"
38 ) >a/b/.gitattributes
39
40 '
@@ -48,6 +51,9 @@ test_expect_success 'attribute test' '
51 attr_check a/b/d/g "a/b/d/*"
52 attr_check onoff unset
53 attr_check offon set
54 + attr_check no unspecified
55 + attr_check a/b/d/no "a/b/d/*"
56 + attr_check a/b/d/yes unspecified
57
58 '
59
@@ -64,6 +70,9 @@ a/b/h: test: a/b/h
70 a/b/d/g: test: a/b/d/*
71 onoff: test: unset
72 offon: test: set
73 +no: test: unspecified
74 +a/b/d/no: test: a/b/d/*
75 +a/b/d/yes: test: unspecified
76 EOF
77
78 sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&