]> git.ipfire.org Git - thirdparty/git.git/blame - attr.c
attr: read core.attributesfile from git_default_core_config
[thirdparty/git.git] / attr.c
CommitLineData
86ab7f0c
MH
1/*
2 * Handle git attributes. See gitattributes(5) for a description of
3 * the file syntax, and Documentation/technical/api-gitattributes.txt
4 * for a description of the API.
5 *
6 * One basic design decision here is that we are not going to support
7 * an insanely large number of attributes.
8 */
9
06f33c17 10#define NO_THE_INDEX_COMPATIBILITY_MACROS
d0bfd026 11#include "cache.h"
6df42ab9 12#include "exec_cmd.h"
d0bfd026
JH
13#include "attr.h"
14
a5e92abd
JH
15const char git_attr__true[] = "(builtin)true";
16const char git_attr__false[] = "\0(builtin)false";
17static const char git_attr__unknown[] = "(builtin)unknown";
18#define ATTR__TRUE git_attr__true
19#define ATTR__FALSE git_attr__false
20#define ATTR__UNSET NULL
21#define ATTR__UNKNOWN git_attr__unknown
515106fa 22
86ab7f0c 23/* This is a randomly chosen prime. */
d0bfd026
JH
24#define HASHSIZE 257
25
26#ifndef DEBUG_ATTR
27#define DEBUG_ATTR 0
28#endif
29
30struct git_attr {
31 struct git_attr *next;
32 unsigned h;
f48fd688 33 int attr_nr;
d0bfd026
JH
34 char name[FLEX_ARRAY];
35};
f48fd688 36static int attr_nr;
d0bfd026 37
f48fd688 38static struct git_attr_check *check_all_attr;
d0bfd026
JH
39static struct git_attr *(git_attr_hash[HASHSIZE]);
40
352404ac
MH
41char *git_attr_name(struct git_attr *attr)
42{
43 return attr->name;
44}
45
d0bfd026
JH
46static unsigned hash_name(const char *name, int namelen)
47{
48fb7deb 48 unsigned val = 0, c;
d0bfd026
JH
49
50 while (namelen--) {
51 c = *name++;
52 val = ((val << 7) | (val >> 22)) ^ c;
53 }
54 return val;
55}
56
e4aee10a
JH
57static int invalid_attr_name(const char *name, int namelen)
58{
59 /*
d42453ab
MH
60 * Attribute name cannot begin with '-' and must consist of
61 * characters from [-A-Za-z0-9_.].
e4aee10a 62 */
c0b13b21 63 if (namelen <= 0 || *name == '-')
e4aee10a
JH
64 return -1;
65 while (namelen--) {
66 char ch = *name++;
67 if (! (ch == '-' || ch == '.' || ch == '_' ||
68 ('0' <= ch && ch <= '9') ||
69 ('a' <= ch && ch <= 'z') ||
70 ('A' <= ch && ch <= 'Z')) )
71 return -1;
72 }
73 return 0;
74}
75
7fb0eaa2 76static struct git_attr *git_attr_internal(const char *name, int len)
d0bfd026
JH
77{
78 unsigned hval = hash_name(name, len);
79 unsigned pos = hval % HASHSIZE;
80 struct git_attr *a;
81
82 for (a = git_attr_hash[pos]; a; a = a->next) {
83 if (a->h == hval &&
84 !memcmp(a->name, name, len) && !a->name[len])
85 return a;
86 }
87
e4aee10a
JH
88 if (invalid_attr_name(name, len))
89 return NULL;
90
d0bfd026
JH
91 a = xmalloc(sizeof(*a) + len + 1);
92 memcpy(a->name, name, len);
93 a->name[len] = 0;
94 a->h = hval;
95 a->next = git_attr_hash[pos];
f48fd688 96 a->attr_nr = attr_nr++;
d0bfd026 97 git_attr_hash[pos] = a;
f48fd688
JH
98
99 check_all_attr = xrealloc(check_all_attr,
100 sizeof(*check_all_attr) * attr_nr);
101 check_all_attr[a->attr_nr].attr = a;
515106fa 102 check_all_attr[a->attr_nr].value = ATTR__UNKNOWN;
d0bfd026
JH
103 return a;
104}
105
7fb0eaa2
JH
106struct git_attr *git_attr(const char *name)
107{
108 return git_attr_internal(name, strlen(name));
109}
110
515106fa 111/* What does a matched pattern decide? */
d0bfd026 112struct attr_state {
d0bfd026 113 struct git_attr *attr;
a5e92abd 114 const char *setto;
d0bfd026
JH
115};
116
ba845b75
MH
117/*
118 * One rule, as from a .gitattributes file.
119 *
120 * If is_macro is true, then u.attr is a pointer to the git_attr being
121 * defined.
122 *
123 * If is_macro is false, then u.pattern points at the filename pattern
124 * to which the rule applies. (The memory pointed to is part of the
125 * memory block allocated for the match_attr instance.)
126 *
127 * In either case, num_attr is the number of attributes affected by
128 * this rule, and state is an array listing them. The attributes are
129 * listed as they appear in the file (macros unexpanded).
130 */
d0bfd026 131struct match_attr {
f48fd688
JH
132 union {
133 char *pattern;
134 struct git_attr *attr;
135 } u;
136 char is_macro;
d0bfd026
JH
137 unsigned num_attr;
138 struct attr_state state[FLEX_ARRAY];
139};
140
141static const char blank[] = " \t\r\n";
142
d1751298
MH
143/*
144 * Parse a whitespace-delimited attribute state (i.e., "attr",
145 * "-attr", "!attr", or "attr=value") from the string starting at src.
146 * If e is not NULL, write the results to *e. Return a pointer to the
147 * remainder of the string (with leading whitespace removed), or NULL
148 * if there was an error.
149 */
515106fa 150static const char *parse_attr(const char *src, int lineno, const char *cp,
d1751298 151 struct attr_state *e)
515106fa
JH
152{
153 const char *ep, *equals;
154 int len;
155
156 ep = cp + strcspn(cp, blank);
157 equals = strchr(cp, '=');
158 if (equals && ep < equals)
159 equals = NULL;
160 if (equals)
161 len = equals - cp;
162 else
163 len = ep - cp;
d1751298 164 if (!e) {
515106fa
JH
165 if (*cp == '-' || *cp == '!') {
166 cp++;
167 len--;
168 }
169 if (invalid_attr_name(cp, len)) {
170 fprintf(stderr,
171 "%.*s is not a valid attribute name: %s:%d\n",
172 len, cp, src, lineno);
173 return NULL;
174 }
175 } else {
515106fa
JH
176 if (*cp == '-' || *cp == '!') {
177 e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET;
178 cp++;
179 len--;
180 }
181 else if (!equals)
182 e->setto = ATTR__TRUE;
183 else {
182af834 184 e->setto = xmemdupz(equals + 1, ep - equals - 1);
515106fa 185 }
7fb0eaa2 186 e->attr = git_attr_internal(cp, len);
515106fa 187 }
515106fa
JH
188 return ep + strspn(ep, blank);
189}
190
f48fd688
JH
191static struct match_attr *parse_attr_line(const char *line, const char *src,
192 int lineno, int macro_ok)
d0bfd026
JH
193{
194 int namelen;
d68e1c18 195 int num_attr, i;
85c4a0d0 196 const char *cp, *name, *states;
515106fa 197 struct match_attr *res = NULL;
f48fd688 198 int is_macro;
d0bfd026
JH
199
200 cp = line + strspn(line, blank);
201 if (!*cp || *cp == '#')
202 return NULL;
203 name = cp;
204 namelen = strcspn(name, blank);
f48fd688
JH
205 if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
206 !prefixcmp(name, ATTRIBUTE_MACRO_PREFIX)) {
207 if (!macro_ok) {
208 fprintf(stderr, "%s not allowed: %s:%d\n",
209 name, src, lineno);
210 return NULL;
211 }
212 is_macro = 1;
213 name += strlen(ATTRIBUTE_MACRO_PREFIX);
214 name += strspn(name, blank);
215 namelen = strcspn(name, blank);
e4aee10a
JH
216 if (invalid_attr_name(name, namelen)) {
217 fprintf(stderr,
218 "%.*s is not a valid attribute name: %s:%d\n",
219 namelen, name, src, lineno);
220 return NULL;
221 }
f48fd688
JH
222 }
223 else
224 is_macro = 0;
d0bfd026 225
85c4a0d0
MH
226 states = name + namelen;
227 states += strspn(states, blank);
228
d68e1c18
MH
229 /* First pass to count the attr_states */
230 for (cp = states, num_attr = 0; *cp; num_attr++) {
231 cp = parse_attr(src, lineno, cp, NULL);
232 if (!cp)
233 return NULL;
d0bfd026 234 }
d68e1c18
MH
235
236 res = xcalloc(1,
237 sizeof(*res) +
238 sizeof(struct attr_state) * num_attr +
239 (is_macro ? 0 : namelen + 1));
240 if (is_macro)
241 res->u.attr = git_attr_internal(name, namelen);
242 else {
243 res->u.pattern = (char *)&(res->state[num_attr]);
244 memcpy(res->u.pattern, name, namelen);
245 res->u.pattern[namelen] = 0;
d0bfd026 246 }
d68e1c18
MH
247 res->is_macro = is_macro;
248 res->num_attr = num_attr;
249
250 /* Second pass to fill the attr_states */
251 for (cp = states, i = 0; *cp; i++) {
252 cp = parse_attr(src, lineno, cp, &(res->state[i]));
253 }
254
d0bfd026
JH
255 return res;
256}
257
258/*
259 * Like info/exclude and .gitignore, the attribute information can
260 * come from many places.
261 *
262 * (1) .gitattribute file of the same directory;
515106fa
JH
263 * (2) .gitattribute file of the parent directory if (1) does not have
264 * any match; this goes recursively upwards, just like .gitignore.
265 * (3) $GIT_DIR/info/attributes, which overrides both of the above.
d0bfd026
JH
266 *
267 * In the same file, later entries override the earlier match, so in the
268 * global list, we would have entries from info/attributes the earliest
269 * (reading the file from top to bottom), .gitattribute of the root
270 * directory (again, reading the file from top to bottom) down to the
271 * current directory, and then scan the list backwards to find the first match.
272 * This is exactly the same as what excluded() does in dir.c to deal with
273 * .gitignore
274 */
275
276static struct attr_stack {
277 struct attr_stack *prev;
278 char *origin;
279 unsigned num_matches;
a4413118 280 unsigned alloc;
d0bfd026
JH
281 struct match_attr **attrs;
282} *attr_stack;
283
284static void free_attr_elem(struct attr_stack *e)
285{
286 int i;
287 free(e->origin);
515106fa
JH
288 for (i = 0; i < e->num_matches; i++) {
289 struct match_attr *a = e->attrs[i];
290 int j;
291 for (j = 0; j < a->num_attr; j++) {
a5e92abd 292 const char *setto = a->state[j].setto;
515106fa
JH
293 if (setto == ATTR__TRUE ||
294 setto == ATTR__FALSE ||
295 setto == ATTR__UNSET ||
296 setto == ATTR__UNKNOWN)
297 ;
298 else
4b25d091 299 free((char *) setto);
515106fa
JH
300 }
301 free(a);
302 }
d0bfd026
JH
303 free(e);
304}
305
306static const char *builtin_attr[] = {
5ec3e670 307 "[attr]binary -diff -text",
d0bfd026
JH
308 NULL,
309};
310
a4413118
JH
311static void handle_attr_line(struct attr_stack *res,
312 const char *line,
313 const char *src,
314 int lineno,
315 int macro_ok)
316{
317 struct match_attr *a;
318
319 a = parse_attr_line(line, src, lineno, macro_ok);
320 if (!a)
321 return;
322 if (res->alloc <= res->num_matches) {
323 res->alloc = alloc_nr(res->num_matches);
324 res->attrs = xrealloc(res->attrs,
325 sizeof(struct match_attr *) *
326 res->alloc);
327 }
328 res->attrs[res->num_matches++] = a;
329}
330
d0bfd026
JH
331static struct attr_stack *read_attr_from_array(const char **list)
332{
333 struct attr_stack *res;
334 const char *line;
f48fd688 335 int lineno = 0;
d0bfd026
JH
336
337 res = xcalloc(1, sizeof(*res));
a4413118
JH
338 while ((line = *(list++)) != NULL)
339 handle_attr_line(res, line, "[builtin]", ++lineno, 1);
d0bfd026
JH
340 return res;
341}
342
06f33c17
JH
343static enum git_attr_direction direction;
344static struct index_state *use_index;
345
f48fd688 346static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
d0bfd026 347{
a4413118 348 FILE *fp = fopen(path, "r");
d0bfd026
JH
349 struct attr_stack *res;
350 char buf[2048];
f48fd688 351 int lineno = 0;
d0bfd026 352
d0bfd026 353 if (!fp)
a4413118
JH
354 return NULL;
355 res = xcalloc(1, sizeof(*res));
356 while (fgets(buf, sizeof(buf), fp))
357 handle_attr_line(res, buf, path, ++lineno, macro_ok);
358 fclose(fp);
359 return res;
360}
d0bfd026 361
1a9d7e9b
JH
362static void *read_index_data(const char *path)
363{
364 int pos, len;
365 unsigned long sz;
366 enum object_type type;
367 void *data;
06f33c17 368 struct index_state *istate = use_index ? use_index : &the_index;
1a9d7e9b
JH
369
370 len = strlen(path);
06f33c17 371 pos = index_name_pos(istate, path, len);
1a9d7e9b
JH
372 if (pos < 0) {
373 /*
374 * We might be in the middle of a merge, in which
375 * case we would read stage #2 (ours).
376 */
377 int i;
378 for (i = -pos - 1;
06f33c17
JH
379 (pos < 0 && i < istate->cache_nr &&
380 !strcmp(istate->cache[i]->name, path));
1a9d7e9b 381 i++)
06f33c17 382 if (ce_stage(istate->cache[i]) == 2)
1a9d7e9b
JH
383 pos = i;
384 }
385 if (pos < 0)
386 return NULL;
06f33c17 387 data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
1a9d7e9b
JH
388 if (!data || type != OBJ_BLOB) {
389 free(data);
390 return NULL;
391 }
392 return data;
393}
394
06f33c17 395static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
a4413118
JH
396{
397 struct attr_stack *res;
1a9d7e9b
JH
398 char *buf, *sp;
399 int lineno = 0;
f48fd688 400
1a9d7e9b
JH
401 buf = read_index_data(path);
402 if (!buf)
06f33c17 403 return NULL;
1a9d7e9b 404
06f33c17 405 res = xcalloc(1, sizeof(*res));
1a9d7e9b
JH
406 for (sp = buf; *sp; ) {
407 char *ep;
408 int more;
409 for (ep = sp; *ep && *ep != '\n'; ep++)
410 ;
411 more = (*ep == '\n');
412 *ep = '\0';
413 handle_attr_line(res, sp, path, ++lineno, macro_ok);
414 sp = ep + more;
415 }
416 free(buf);
d0bfd026
JH
417 return res;
418}
419
06f33c17
JH
420static struct attr_stack *read_attr(const char *path, int macro_ok)
421{
422 struct attr_stack *res;
423
424 if (direction == GIT_ATTR_CHECKOUT) {
425 res = read_attr_from_index(path, macro_ok);
426 if (!res)
427 res = read_attr_from_file(path, macro_ok);
428 }
4191e80a 429 else if (direction == GIT_ATTR_CHECKIN) {
06f33c17
JH
430 res = read_attr_from_file(path, macro_ok);
431 if (!res)
432 /*
433 * There is no checked out .gitattributes file there, but
434 * we might have it in the index. We allow operation in a
435 * sparsely checked out work tree, so read from it.
436 */
437 res = read_attr_from_index(path, macro_ok);
438 }
4191e80a
NTND
439 else
440 res = read_attr_from_index(path, macro_ok);
06f33c17
JH
441 if (!res)
442 res = xcalloc(1, sizeof(*res));
443 return res;
444}
445
d0bfd026
JH
446#if DEBUG_ATTR
447static void debug_info(const char *what, struct attr_stack *elem)
448{
449 fprintf(stderr, "%s: %s\n", what, elem->origin ? elem->origin : "()");
450}
cf94ccda 451static void debug_set(const char *what, const char *match, struct git_attr *attr, const void *v)
f48fd688 452{
515106fa
JH
453 const char *value = v;
454
455 if (ATTR_TRUE(value))
456 value = "set";
457 else if (ATTR_FALSE(value))
458 value = "unset";
459 else if (ATTR_UNSET(value))
460 value = "unspecified";
461
462 fprintf(stderr, "%s: %s => %s (%s)\n",
463 what, attr->name, (char *) value, match);
f48fd688 464}
d0bfd026
JH
465#define debug_push(a) debug_info("push", (a))
466#define debug_pop(a) debug_info("pop", (a))
467#else
468#define debug_push(a) do { ; } while (0)
469#define debug_pop(a) do { ; } while (0)
f48fd688 470#define debug_set(a,b,c,d) do { ; } while (0)
d0bfd026
JH
471#endif
472
06f33c17
JH
473static void drop_attr_stack(void)
474{
475 while (attr_stack) {
476 struct attr_stack *elem = attr_stack;
477 attr_stack = elem->prev;
478 free_attr_elem(elem);
479 }
480}
481
c5147722 482static const char *git_etc_gitattributes(void)
6df42ab9
PO
483{
484 static const char *system_wide;
485 if (!system_wide)
486 system_wide = system_path(ETC_GITATTRIBUTES);
487 return system_wide;
488}
489
c5147722 490static int git_attr_system(void)
6df42ab9
PO
491{
492 return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
493}
494
f48fd688
JH
495static void bootstrap_attr_stack(void)
496{
497 if (!attr_stack) {
498 struct attr_stack *elem;
499
500 elem = read_attr_from_array(builtin_attr);
501 elem->origin = NULL;
502 elem->prev = attr_stack;
503 attr_stack = elem;
504
6df42ab9
PO
505 if (git_attr_system()) {
506 elem = read_attr_from_file(git_etc_gitattributes(), 1);
507 if (elem) {
508 elem->origin = NULL;
509 elem->prev = attr_stack;
510 attr_stack = elem;
511 }
512 }
513
64589a03
JH
514 if (git_attributes_file) {
515 elem = read_attr_from_file(git_attributes_file, 1);
6df42ab9
PO
516 if (elem) {
517 elem->origin = NULL;
518 elem->prev = attr_stack;
519 attr_stack = elem;
520 }
521 }
522
4191e80a 523 if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
2d35d556 524 elem = read_attr(GITATTRIBUTES_FILE, 1);
040a6551 525 elem->origin = xstrdup("");
2d35d556
RS
526 elem->prev = attr_stack;
527 attr_stack = elem;
528 debug_push(elem);
529 }
f48fd688
JH
530
531 elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
a4413118
JH
532 if (!elem)
533 elem = xcalloc(1, sizeof(*elem));
f48fd688
JH
534 elem->origin = NULL;
535 elem->prev = attr_stack;
536 attr_stack = elem;
537 }
538}
539
a8727017 540static void prepare_attr_stack(const char *path)
d0bfd026
JH
541{
542 struct attr_stack *elem, *info;
a8727017 543 int dirlen, len;
a8727017
MH
544 const char *cp;
545
546 cp = strrchr(path, '/');
547 if (!cp)
548 dirlen = 0;
549 else
550 dirlen = cp - path;
f66cf96d 551
d0bfd026
JH
552 /*
553 * At the bottom of the attribute stack is the built-in
6df42ab9
PO
554 * set of attribute definitions, followed by the contents
555 * of $(prefix)/etc/gitattributes and a file specified by
556 * core.attributesfile. Then, contents from
d0bfd026
JH
557 * .gitattribute files from directories closer to the
558 * root to the ones in deeper directories are pushed
559 * to the stack. Finally, at the very top of the stack
560 * we always keep the contents of $GIT_DIR/info/attributes.
561 *
562 * When checking, we use entries from near the top of the
563 * stack, preferring $GIT_DIR/info/attributes, then
564 * .gitattributes in deeper directories to shallower ones,
565 * and finally use the built-in set as the default.
566 */
7373eab4 567 bootstrap_attr_stack();
d0bfd026
JH
568
569 /*
570 * Pop the "info" one that is always at the top of the stack.
571 */
572 info = attr_stack;
573 attr_stack = info->prev;
574
575 /*
576 * Pop the ones from directories that are not the prefix of
577 * the path we are checking.
578 */
579 while (attr_stack && attr_stack->origin) {
580 int namelen = strlen(attr_stack->origin);
581
582 elem = attr_stack;
583 if (namelen <= dirlen &&
584 !strncmp(elem->origin, path, namelen))
585 break;
586
587 debug_pop(elem);
588 attr_stack = elem->prev;
589 free_attr_elem(elem);
590 }
591
592 /*
593 * Read from parent directories and push them down
594 */
4191e80a 595 if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
97410b27 596 struct strbuf pathbuf = STRBUF_INIT;
2d35d556 597
97410b27 598 while (1) {
2d35d556
RS
599 len = strlen(attr_stack->origin);
600 if (dirlen <= len)
601 break;
97410b27
BC
602 cp = memchr(path + len + 1, '/', dirlen - len - 1);
603 if (!cp)
604 cp = path + dirlen;
605 strbuf_add(&pathbuf, path, cp - path);
f66cf96d 606 strbuf_addch(&pathbuf, '/');
97410b27 607 strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);
f66cf96d 608 elem = read_attr(pathbuf.buf, 0);
97410b27
BC
609 strbuf_setlen(&pathbuf, cp - path);
610 elem->origin = strbuf_detach(&pathbuf, NULL);
2d35d556
RS
611 elem->prev = attr_stack;
612 attr_stack = elem;
613 debug_push(elem);
614 }
d0bfd026 615
97410b27
BC
616 strbuf_release(&pathbuf);
617 }
d4c98565 618
d0bfd026
JH
619 /*
620 * Finally push the "info" one at the top of the stack.
621 */
622 info->prev = attr_stack;
623 attr_stack = info;
624}
625
626static int path_matches(const char *pathname, int pathlen,
627 const char *pattern,
628 const char *base, int baselen)
629{
630 if (!strchr(pattern, '/')) {
631 /* match basename */
632 const char *basename = strrchr(pathname, '/');
633 basename = basename ? basename + 1 : pathname;
634 return (fnmatch(pattern, basename, 0) == 0);
635 }
636 /*
637 * match with FNM_PATHNAME; the pattern has base implicitly
638 * in front of it.
639 */
640 if (*pattern == '/')
641 pattern++;
642 if (pathlen < baselen ||
cf94ccda 643 (baselen && pathname[baselen] != '/') ||
d0bfd026
JH
644 strncmp(pathname, base, baselen))
645 return 0;
82881b38
MO
646 if (baselen != 0)
647 baselen++;
648 return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
d0bfd026
JH
649}
650
ec775c41
HG
651static int macroexpand_one(int attr_nr, int rem);
652
515106fa
JH
653static int fill_one(const char *what, struct match_attr *a, int rem)
654{
655 struct git_attr_check *check = check_all_attr;
656 int i;
657
969f9d73 658 for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {
515106fa 659 struct git_attr *attr = a->state[i].attr;
a5e92abd
JH
660 const char **n = &(check[attr->attr_nr].value);
661 const char *v = a->state[i].setto;
515106fa
JH
662
663 if (*n == ATTR__UNKNOWN) {
426c27b7
HG
664 debug_set(what,
665 a->is_macro ? a->u.attr->name : a->u.pattern,
666 attr, v);
515106fa
JH
667 *n = v;
668 rem--;
ec775c41 669 rem = macroexpand_one(attr->attr_nr, rem);
515106fa
JH
670 }
671 }
672 return rem;
673}
674
f48fd688 675static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
d0bfd026 676{
515106fa 677 int i;
d0bfd026
JH
678 const char *base = stk->origin ? stk->origin : "";
679
680 for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
681 struct match_attr *a = stk->attrs[i];
f48fd688
JH
682 if (a->is_macro)
683 continue;
d0bfd026 684 if (path_matches(path, pathlen,
515106fa
JH
685 a->u.pattern, base, strlen(base)))
686 rem = fill_one("fill", a, rem);
d0bfd026
JH
687 }
688 return rem;
689}
690
ec775c41 691static int macroexpand_one(int attr_nr, int rem)
f48fd688 692{
ec775c41
HG
693 struct attr_stack *stk;
694 struct match_attr *a = NULL;
515106fa 695 int i;
f48fd688 696
ec775c41
HG
697 if (check_all_attr[attr_nr].value != ATTR__TRUE)
698 return rem;
699
700 for (stk = attr_stack; !a && stk; stk = stk->prev)
701 for (i = stk->num_matches - 1; !a && 0 <= i; i--) {
702 struct match_attr *ma = stk->attrs[i];
703 if (!ma->is_macro)
704 continue;
705 if (ma->u.attr->attr_nr == attr_nr)
706 a = ma;
707 }
708
709 if (a)
515106fa 710 rem = fill_one("expand", a, rem);
ec775c41 711
f48fd688
JH
712 return rem;
713}
714
2d721744
MH
715/*
716 * Collect all attributes for path into the array pointed to by
717 * check_all_attr.
718 */
719static void collect_all_attrs(const char *path)
d0bfd026
JH
720{
721 struct attr_stack *stk;
2d721744 722 int i, pathlen, rem;
d0bfd026 723
2d721744 724 prepare_attr_stack(path);
f48fd688 725 for (i = 0; i < attr_nr; i++)
515106fa 726 check_all_attr[i].value = ATTR__UNKNOWN;
d0bfd026
JH
727
728 pathlen = strlen(path);
f48fd688
JH
729 rem = attr_nr;
730 for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
731 rem = fill(path, pathlen, stk, rem);
2d721744
MH
732}
733
d932f4eb 734int git_check_attr(const char *path, int num, struct git_attr_check *check)
2d721744
MH
735{
736 int i;
737
738 collect_all_attrs(path);
f48fd688 739
515106fa 740 for (i = 0; i < num; i++) {
a5e92abd 741 const char *value = check_all_attr[check[i].attr->attr_nr].value;
515106fa
JH
742 if (value == ATTR__UNKNOWN)
743 value = ATTR__UNSET;
744 check[i].value = value;
745 }
f48fd688 746
d0bfd026
JH
747 return 0;
748}
06f33c17 749
ee548df3
MH
750int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
751{
752 int i, count, j;
753
754 collect_all_attrs(path);
755
756 /* Count the number of attributes that are set. */
757 count = 0;
758 for (i = 0; i < attr_nr; i++) {
759 const char *value = check_all_attr[i].value;
760 if (value != ATTR__UNSET && value != ATTR__UNKNOWN)
761 ++count;
762 }
763 *num = count;
764 *check = xmalloc(sizeof(**check) * count);
765 j = 0;
766 for (i = 0; i < attr_nr; i++) {
767 const char *value = check_all_attr[i].value;
768 if (value != ATTR__UNSET && value != ATTR__UNKNOWN) {
769 (*check)[j].attr = check_all_attr[i].attr;
770 (*check)[j].value = value;
771 ++j;
772 }
773 }
774
775 return 0;
776}
777
06f33c17
JH
778void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
779{
780 enum git_attr_direction old = direction;
4191e80a
NTND
781
782 if (is_bare_repository() && new != GIT_ATTR_INDEX)
783 die("BUG: non-INDEX attr direction in a bare repo");
784
06f33c17
JH
785 direction = new;
786 if (new != old)
787 drop_attr_stack();
788 use_index = istate;
789}