Skip to content

Commit 60a1272

Browse files
bmwillgitster
authored andcommitted
attr: remove maybe-real, maybe-macro from git_attr
Whether or not a git attribute is real or a macro isn't a property of the attribute but rather it depends on the attribute stack (which .gitattribute files were read). This patch removes the 'maybe_real' and 'maybe_macro' fields in a git_attr and instead adds the 'macro' field to a attr_check_item. The 'macro' indicates (if non-NULL) that a particular attribute is a macro for the given attribute stack. It's populated, through a quick scan of the attribute stack, with the match_attr that corresponds to the macro's definition. This way the attribute stack only needs to be scanned a single time prior to attribute collection instead of each time a macro needs to be expanded. Signed-off-by: Brandon Williams <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 685b292 commit 60a1272

File tree

1 file changed

+37
-38
lines changed

1 file changed

+37
-38
lines changed

attr.c

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,9 @@ static const char git_attr__unknown[] = "(builtin)unknown";
3030

3131
struct 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-
4736
const 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,
142131
struct 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,
904893
static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
905894

906895
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)
908897
{
909898
int i;
910899

@@ -945,24 +934,34 @@ static int fill(const char *path, int pathlen, int basename_offset,
945934

946935
static 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

Comments
 (0)