@@ -32,9 +32,12 @@ struct git_attr {
32
32
struct git_attr * next ;
33
33
unsigned h ;
34
34
int attr_nr ;
35
+ int maybe_macro ;
36
+ int maybe_real ;
35
37
char name [FLEX_ARRAY ];
36
38
};
37
39
static int attr_nr ;
40
+ static int cannot_trust_maybe_real ;
38
41
39
42
static struct git_attr_check * check_all_attr ;
40
43
static struct git_attr * (git_attr_hash [HASHSIZE ]);
@@ -95,6 +98,8 @@ static struct git_attr *git_attr_internal(const char *name, int len)
95
98
a -> h = hval ;
96
99
a -> next = git_attr_hash [pos ];
97
100
a -> attr_nr = attr_nr ++ ;
101
+ a -> maybe_macro = 0 ;
102
+ a -> maybe_real = 0 ;
98
103
git_attr_hash [pos ] = a ;
99
104
100
105
REALLOC_ARRAY (check_all_attr , attr_nr );
@@ -244,9 +249,10 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
244
249
sizeof (* res ) +
245
250
sizeof (struct attr_state ) * num_attr +
246
251
(is_macro ? 0 : namelen + 1 ));
247
- if (is_macro )
252
+ if (is_macro ) {
248
253
res -> u .attr = git_attr_internal (name , namelen );
249
- else {
254
+ res -> u .attr -> maybe_macro = 1 ;
255
+ } else {
250
256
char * p = (char * )& (res -> state [num_attr ]);
251
257
memcpy (p , name , namelen );
252
258
res -> u .pat .pattern = p ;
@@ -266,6 +272,10 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
266
272
/* Second pass to fill the attr_states */
267
273
for (cp = states , i = 0 ; * cp ; i ++ ) {
268
274
cp = parse_attr (src , lineno , cp , & (res -> state [i ]));
275
+ if (!is_macro )
276
+ res -> state [i ].attr -> maybe_real = 1 ;
277
+ if (res -> state [i ].attr -> maybe_macro )
278
+ cannot_trust_maybe_real = 1 ;
269
279
}
270
280
271
281
return res ;
@@ -681,21 +691,22 @@ static int fill(const char *path, int pathlen, int basename_offset,
681
691
return rem ;
682
692
}
683
693
684
- static int macroexpand_one (int attr_nr , int rem )
694
+ static int macroexpand_one (int nr , int rem )
685
695
{
686
696
struct attr_stack * stk ;
687
697
struct match_attr * a = NULL ;
688
698
int i ;
689
699
690
- if (check_all_attr [attr_nr ].value != ATTR__TRUE )
700
+ if (check_all_attr [nr ].value != ATTR__TRUE ||
701
+ !check_all_attr [nr ].attr -> maybe_macro )
691
702
return rem ;
692
703
693
704
for (stk = attr_stack ; !a && stk ; stk = stk -> prev )
694
705
for (i = stk -> num_matches - 1 ; !a && 0 <= i ; i -- ) {
695
706
struct match_attr * ma = stk -> attrs [i ];
696
707
if (!ma -> is_macro )
697
708
continue ;
698
- if (ma -> u .attr -> attr_nr == attr_nr )
709
+ if (ma -> u .attr -> attr_nr == nr )
699
710
a = ma ;
700
711
}
701
712
@@ -706,10 +717,13 @@ static int macroexpand_one(int attr_nr, int rem)
706
717
}
707
718
708
719
/*
709
- * Collect all attributes for path into the array pointed to by
710
- * check_all_attr.
720
+ * Collect attributes for path into the array pointed to by
721
+ * check_all_attr. If num is non-zero, only attributes in check[] are
722
+ * collected. Otherwise all attributes are collected.
711
723
*/
712
- static void collect_all_attrs (const char * path )
724
+ static void collect_some_attrs (const char * path , int num ,
725
+ struct git_attr_check * check )
726
+
713
727
{
714
728
struct attr_stack * stk ;
715
729
int i , pathlen , rem , dirlen ;
@@ -732,6 +746,19 @@ static void collect_all_attrs(const char *path)
732
746
prepare_attr_stack (path , dirlen );
733
747
for (i = 0 ; i < attr_nr ; i ++ )
734
748
check_all_attr [i ].value = ATTR__UNKNOWN ;
749
+ if (num && !cannot_trust_maybe_real ) {
750
+ rem = 0 ;
751
+ for (i = 0 ; i < num ; i ++ ) {
752
+ if (!check [i ].attr -> maybe_real ) {
753
+ struct git_attr_check * c ;
754
+ c = check_all_attr + check [i ].attr -> attr_nr ;
755
+ c -> value = ATTR__UNSET ;
756
+ rem ++ ;
757
+ }
758
+ }
759
+ if (rem == num )
760
+ return ;
761
+ }
735
762
736
763
rem = attr_nr ;
737
764
for (stk = attr_stack ; 0 < rem && stk ; stk = stk -> prev )
@@ -742,7 +769,7 @@ int git_check_attr(const char *path, int num, struct git_attr_check *check)
742
769
{
743
770
int i ;
744
771
745
- collect_all_attrs (path );
772
+ collect_some_attrs (path , num , check );
746
773
747
774
for (i = 0 ; i < num ; i ++ ) {
748
775
const char * value = check_all_attr [check [i ].attr -> attr_nr ].value ;
@@ -758,7 +785,7 @@ int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
758
785
{
759
786
int i , count , j ;
760
787
761
- collect_all_attrs (path );
788
+ collect_some_attrs (path , 0 , NULL );
762
789
763
790
/* Count the number of attributes that are set. */
764
791
count = 0 ;
0 commit comments