@@ -30,20 +30,9 @@ static const char git_attr__unknown[] = "(builtin)unknown";
3030
3131struct git_attr {
3232 int attr_nr ; /* unique attribute number */
33- int maybe_macro ;
34- int maybe_real ;
3533 char name [FLEX_ARRAY ]; /* attribute name */
3634};
3735
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-
4736const char * git_attr_name (const struct git_attr * attr )
4837{
4938 return attr -> name ;
@@ -142,6 +131,12 @@ static void attr_hashmap_add(struct attr_hashmap *map,
142131struct all_attrs_item {
143132 const struct git_attr * attr ;
144133 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 ;
145140};
146141
147142/*
@@ -187,6 +182,7 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
187182 */
188183 for (i = 0 ; i < check -> all_attrs_nr ; i ++ ) {
189184 check -> all_attrs [i ].value = ATTR__UNKNOWN ;
185+ check -> all_attrs [i ].macro = NULL ;
190186 }
191187}
192188
@@ -238,8 +234,6 @@ static struct git_attr *git_attr_internal(const char *name, int namelen)
238234 if (!a ) {
239235 FLEX_ALLOC_MEM (a , name , name , namelen );
240236 a -> attr_nr = g_attr_hashmap .map .size ;
241- a -> maybe_real = 0 ;
242- a -> maybe_macro = 0 ;
243237
244238 attr_hashmap_add (& g_attr_hashmap , a -> name , namelen , a );
245239 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,
402396 (is_macro ? 0 : namelen + 1 ));
403397 if (is_macro ) {
404398 res -> u .attr = git_attr_internal (name , namelen );
405- res -> u .attr -> maybe_macro = 1 ;
406399 } else {
407400 char * p = (char * )& (res -> state [num_attr ]);
408401 memcpy (p , name , namelen );
@@ -423,10 +416,6 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
423416 /* Second pass to fill the attr_states */
424417 for (cp = states , i = 0 ; * cp ; i ++ ) {
425418 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 ;
430419 }
431420
432421 strbuf_release (& pattern );
@@ -904,7 +893,7 @@ static int path_matches(const char *pathname, int pathlen,
904893static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem );
905894
906895static 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 )
908897{
909898 int i ;
910899
@@ -945,24 +934,34 @@ static int fill(const char *path, int pathlen, int basename_offset,
945934
946935static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem )
947936{
948- struct attr_stack * stk ;
949- int i ;
937+ const struct all_attrs_item * item = & all_attrs [nr ];
950938
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
953942 return rem ;
943+ }
954944
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+ }
962963 }
963964 }
964-
965- return rem ;
966965}
967966
968967/*
@@ -992,15 +991,15 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
992991
993992 prepare_attr_stack (path , dirlen );
994993 all_attrs_init (& g_attr_hashmap , check );
994+ determine_macros (check -> all_attrs , attr_stack );
995995
996- if (check -> nr && ! cannot_trust_maybe_real ) {
996+ if (check -> nr ) {
997997 rem = 0 ;
998998 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 ;
10041003 rem ++ ;
10051004 }
10061005 }
0 commit comments