@@ -30,20 +30,9 @@ static const char git_attr__unknown[] = "(builtin)unknown";
30
30
31
31
struct git_attr {
32
32
int attr_nr ; /* unique attribute number */
33
- int maybe_macro ;
34
- int maybe_real ;
35
33
char name [FLEX_ARRAY ]; /* attribute name */
36
34
};
37
35
38
- /*
39
- * NEEDSWORK: maybe-real, maybe-macro are not property of
40
- * an attribute, as it depends on what .gitattributes are
41
- * read. Once we introduce per git_attr_check attr_stack
42
- * and check_all_attr, the optimization based on them will
43
- * become unnecessary and can go away. So is this variable.
44
- */
45
- static int cannot_trust_maybe_real ;
46
-
47
36
const char * git_attr_name (const struct git_attr * attr )
48
37
{
49
38
return attr -> name ;
@@ -142,6 +131,12 @@ static void attr_hashmap_add(struct attr_hashmap *map,
142
131
struct all_attrs_item {
143
132
const struct git_attr * attr ;
144
133
const char * value ;
134
+ /*
135
+ * If 'macro' is non-NULL, indicates that 'attr' is a macro based on
136
+ * the current attribute stack and contains a pointer to the match_attr
137
+ * definition of the macro
138
+ */
139
+ const struct match_attr * macro ;
145
140
};
146
141
147
142
/*
@@ -187,6 +182,7 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
187
182
*/
188
183
for (i = 0 ; i < check -> all_attrs_nr ; i ++ ) {
189
184
check -> all_attrs [i ].value = ATTR__UNKNOWN ;
185
+ check -> all_attrs [i ].macro = NULL ;
190
186
}
191
187
}
192
188
@@ -238,8 +234,6 @@ static struct git_attr *git_attr_internal(const char *name, int namelen)
238
234
if (!a ) {
239
235
FLEX_ALLOC_MEM (a , name , name , namelen );
240
236
a -> attr_nr = g_attr_hashmap .map .size ;
241
- a -> maybe_real = 0 ;
242
- a -> maybe_macro = 0 ;
243
237
244
238
attr_hashmap_add (& g_attr_hashmap , a -> name , namelen , a );
245
239
assert (a -> attr_nr == (g_attr_hashmap .map .size - 1 ));
@@ -402,7 +396,6 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
402
396
(is_macro ? 0 : namelen + 1 ));
403
397
if (is_macro ) {
404
398
res -> u .attr = git_attr_internal (name , namelen );
405
- res -> u .attr -> maybe_macro = 1 ;
406
399
} else {
407
400
char * p = (char * )& (res -> state [num_attr ]);
408
401
memcpy (p , name , namelen );
@@ -423,10 +416,6 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
423
416
/* Second pass to fill the attr_states */
424
417
for (cp = states , i = 0 ; * cp ; i ++ ) {
425
418
cp = parse_attr (src , lineno , cp , & (res -> state [i ]));
426
- if (!is_macro )
427
- res -> state [i ].attr -> maybe_real = 1 ;
428
- if (res -> state [i ].attr -> maybe_macro )
429
- cannot_trust_maybe_real = 1 ;
430
419
}
431
420
432
421
strbuf_release (& pattern );
@@ -904,7 +893,7 @@ static int path_matches(const char *pathname, int pathlen,
904
893
static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem );
905
894
906
895
static int fill_one (const char * what , struct all_attrs_item * all_attrs ,
907
- struct match_attr * a , int rem )
896
+ const struct match_attr * a , int rem )
908
897
{
909
898
int i ;
910
899
@@ -945,24 +934,34 @@ static int fill(const char *path, int pathlen, int basename_offset,
945
934
946
935
static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem )
947
936
{
948
- struct attr_stack * stk ;
949
- int i ;
937
+ const struct all_attrs_item * item = & all_attrs [nr ];
950
938
951
- if (all_attrs [nr ].value != ATTR__TRUE ||
952
- !all_attrs [nr ].attr -> maybe_macro )
939
+ if (item -> macro && item -> value == ATTR__TRUE )
940
+ return fill_one ("expand" , all_attrs , item -> macro , rem );
941
+ else
953
942
return rem ;
943
+ }
954
944
955
- for (stk = attr_stack ; stk ; stk = stk -> prev ) {
956
- for (i = stk -> num_matches - 1 ; 0 <= i ; i -- ) {
957
- struct match_attr * ma = stk -> attrs [i ];
958
- if (!ma -> is_macro )
959
- continue ;
960
- if (ma -> u .attr -> attr_nr == nr )
961
- return fill_one ("expand" , all_attrs , ma , rem );
945
+ /*
946
+ * Marks the attributes which are macros based on the attribute stack.
947
+ * This prevents having to search through the attribute stack each time
948
+ * a macro needs to be expanded during the fill stage.
949
+ */
950
+ static void determine_macros (struct all_attrs_item * all_attrs ,
951
+ const struct attr_stack * stack )
952
+ {
953
+ for (; stack ; stack = stack -> prev ) {
954
+ int i ;
955
+ for (i = stack -> num_matches - 1 ; i >= 0 ; i -- ) {
956
+ const struct match_attr * ma = stack -> attrs [i ];
957
+ if (ma -> is_macro ) {
958
+ int n = ma -> u .attr -> attr_nr ;
959
+ if (!all_attrs [n ].macro ) {
960
+ all_attrs [n ].macro = ma ;
961
+ }
962
+ }
962
963
}
963
964
}
964
-
965
- return rem ;
966
965
}
967
966
968
967
/*
@@ -992,15 +991,15 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
992
991
993
992
prepare_attr_stack (path , dirlen );
994
993
all_attrs_init (& g_attr_hashmap , check );
994
+ determine_macros (check -> all_attrs , attr_stack );
995
995
996
- if (check -> nr && ! cannot_trust_maybe_real ) {
996
+ if (check -> nr ) {
997
997
rem = 0 ;
998
998
for (i = 0 ; i < check -> nr ; i ++ ) {
999
- const struct git_attr * a = check -> items [i ].attr ;
1000
- if (!a -> maybe_real ) {
1001
- struct all_attrs_item * c ;
1002
- c = check -> all_attrs + a -> attr_nr ;
1003
- c -> value = ATTR__UNSET ;
999
+ int n = check -> items [i ].attr -> attr_nr ;
1000
+ struct all_attrs_item * item = & check -> all_attrs [n ];
1001
+ if (item -> macro ) {
1002
+ item -> value = ATTR__UNSET ;
1004
1003
rem ++ ;
1005
1004
}
1006
1005
}
0 commit comments