30
31
struct git_attr {
32
int attr_nr; /* unique attribute number */
33
- int maybe_macro;
34
- int maybe_real;
33
char name[FLEX_ARRAY]; /* attribute name */
34
};
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
-
36
const char *git_attr_name(const struct git_attr *attr)
37
{
38
return attr->name;
131
struct all_attrs_item {
132
const struct git_attr *attr;
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;
140
};
141
142
/*
182
*/
183
for (i = 0; i < check->all_attrs_nr; i++) {
184
check->all_attrs[i].value = ATTR__UNKNOWN;
185
+ check->all_attrs[i].macro = NULL;
186
}
187
}
188
234
if (!a) {
235
FLEX_ALLOC_MEM(a, name, name, namelen);
236
a->attr_nr = g_attr_hashmap.map.size;
241
- a->maybe_real = 0;
242
- a->maybe_macro = 0;
237
238
attr_hashmap_add(&g_attr_hashmap, a->name, namelen, a);
239
assert(a->attr_nr == (g_attr_hashmap.map.size - 1));
396
(is_macro ? 0 : namelen + 1));
397
if (is_macro) {
398
res->u.attr = git_attr_internal(name, namelen);
405
- res->u.attr->maybe_macro = 1;
399
} else {
400
char *p = (char *)&(res->state[num_attr]);
401
memcpy(p, name, namelen);
416
/* Second pass to fill the attr_states */
417
for (cp = states, i = 0; *cp; i++) {
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;
419
}
420
421
strbuf_release(&pattern);
893
static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
894
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)
897
{
898
int i;
899
934
935
static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem)
936
{
948
- struct attr_stack *stk;
949
- int i;
937
+ const struct all_attrs_item *item = &all_attrs[nr];
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
942
return rem;
943
+}
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
+ }
963
}
964
}
964
-
965
- return rem;
965
}
966
967
/*
991
992
prepare_attr_stack(path, dirlen);
993
all_attrs_init(&g_attr_hashmap, check);
994
+ determine_macros(check->all_attrs, attr_stack);
995
996
- if (check->nr && !cannot_trust_maybe_real) {
996
+ if (check->nr) {
997
rem = 0;
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;
1003
rem++;
1004
}
1005
}