Skip to content

Commit ec775c4

Browse files
grubbagitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 969f9d7 commit ec775c4

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

attr.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,8 @@ static int path_matches(const char *pathname, int pathlen,
594594
return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
595595
}
596596

597+
static int macroexpand_one(int attr_nr, int rem);
598+
597599
static int fill_one(const char *what, struct match_attr *a, int rem)
598600
{
599601
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)
610612
attr, v);
611613
*n = v;
612614
rem--;
615+
rem = macroexpand_one(attr->attr_nr, rem);
613616
}
614617
}
615618
return rem;
@@ -631,19 +634,27 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
631634
return rem;
632635
}
633636

634-
static int macroexpand(struct attr_stack *stk, int rem)
637+
static int macroexpand_one(int attr_nr, int rem)
635638
{
639+
struct attr_stack *stk;
640+
struct match_attr *a = NULL;
636641
int i;
637-
struct git_attr_check *check = check_all_attr;
638642

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)
645656
rem = fill_one("expand", a, rem);
646-
}
657+
647658
return rem;
648659
}
649660

@@ -668,9 +679,6 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
668679
for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
669680
rem = fill(path, pathlen, stk, rem);
670681

671-
for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
672-
rem = macroexpand(stk, rem);
673-
674682
for (i = 0; i < num; i++) {
675683
const char *value = check_all_attr[check[i].attr->attr_nr].value;
676684
if (value == ATTR__UNKNOWN)

t/t0003-attributes.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ test_expect_success 'setup' '
2020
2121
mkdir -p a/b/d a/c &&
2222
(
23+
echo "[attr]notest !test"
2324
echo "f test=f"
2425
echo "a/i test=a/i"
2526
echo "onoff test -test"
2627
echo "offon -test test"
28+
echo "no notest"
2729
) >.gitattributes &&
2830
(
2931
echo "g test=a/g" &&
@@ -32,6 +34,7 @@ test_expect_success 'setup' '
3234
(
3335
echo "h test=a/b/h" &&
3436
echo "d/* test=a/b/d/*"
37+
echo "d/yes notest"
3538
) >a/b/.gitattributes
3639
3740
'
@@ -48,6 +51,9 @@ test_expect_success 'attribute test' '
4851
attr_check a/b/d/g "a/b/d/*"
4952
attr_check onoff unset
5053
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
5157
5258
'
5359

@@ -64,6 +70,9 @@ a/b/h: test: a/b/h
6470
a/b/d/g: test: a/b/d/*
6571
onoff: test: unset
6672
offon: test: set
73+
no: test: unspecified
74+
a/b/d/no: test: a/b/d/*
75+
a/b/d/yes: test: unspecified
6776
EOF
6877
6978
sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&

0 commit comments

Comments
 (0)