attr: change validity check for attribute names to use positive logic
[git/git.git] / attr.c
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
10 #define NO_THE_INDEX_COMPATIBILITY_MACROS
11 #include "cache.h"
12 #include "exec_cmd.h"
13 #include "attr.h"
14 #include "dir.h"
15 #include "utf8.h"
16 #include "quote.h"
17
18 const char git_attr__true[] = "(builtin)true";
19 const char git_attr__false[] = "\0(builtin)false";
20 static const char git_attr__unknown[] = "(builtin)unknown";
21 #define ATTR__TRUE git_attr__true
22 #define ATTR__FALSE git_attr__false
23 #define ATTR__UNSET NULL
24 #define ATTR__UNKNOWN git_attr__unknown
25
26 /* This is a randomly chosen prime. */
27 #define HASHSIZE 257
28
29 #ifndef DEBUG_ATTR
30 #define DEBUG_ATTR 0
31 #endif
32
33 /*
34 * NEEDSWORK: the global dictionary of the interned attributes
35 * must stay a singleton even after we become thread-ready.
36 * Access to these must be surrounded with mutex when it happens.
37 */
38 struct git_attr {
39 struct git_attr *next;
40 unsigned h;
41 int attr_nr;
42 int maybe_macro;
43 int maybe_real;
44 char name[FLEX_ARRAY];
45 };
46 static int attr_nr;
47 static struct git_attr *(git_attr_hash[HASHSIZE]);
48
49 /*
50 * NEEDSWORK: maybe-real, maybe-macro are not property of
51 * an attribute, as it depends on what .gitattributes are
52 * read. Once we introduce per git_attr_check attr_stack
53 * and check_all_attr, the optimization based on them will
54 * become unnecessary and can go away. So is this variable.
55 */
56 static int cannot_trust_maybe_real;
57
58 /* NEEDSWORK: This will become per git_attr_check */
59 static struct attr_check_item *check_all_attr;
60
61 const char *git_attr_name(const struct git_attr *attr)
62 {
63 return attr->name;
64 }
65
66 static unsigned hash_name(const char *name, int namelen)
67 {
68 unsigned val = 0, c;
69
70 while (namelen--) {
71 c = *name++;
72 val = ((val << 7) | (val >> 22)) ^ c;
73 }
74 return val;
75 }
76
77 static int attr_name_valid(const char *name, size_t namelen)
78 {
79 /*
80 * Attribute name cannot begin with '-' and must consist of
81 * characters from [-A-Za-z0-9_.].
82 */
83 if (namelen <= 0 || *name == '-')
84 return 0;
85 while (namelen--) {
86 char ch = *name++;
87 if (! (ch == '-' || ch == '.' || ch == '_' ||
88 ('0' <= ch && ch <= '9') ||
89 ('a' <= ch && ch <= 'z') ||
90 ('A' <= ch && ch <= 'Z')) )
91 return 0;
92 }
93 return 1;
94 }
95
96 static void report_invalid_attr(const char *name, size_t len,
97 const char *src, int lineno)
98 {
99 struct strbuf err = STRBUF_INIT;
100 strbuf_addf(&err, _("%.*s is not a valid attribute name"),
101 (int) len, name);
102 fprintf(stderr, "%s: %s:%d\n", err.buf, src, lineno);
103 strbuf_release(&err);
104 }
105
106 static struct git_attr *git_attr_internal(const char *name, int len)
107 {
108 unsigned hval = hash_name(name, len);
109 unsigned pos = hval % HASHSIZE;
110 struct git_attr *a;
111
112 for (a = git_attr_hash[pos]; a; a = a->next) {
113 if (a->h == hval &&
114 !memcmp(a->name, name, len) && !a->name[len])
115 return a;
116 }
117
118 if (!attr_name_valid(name, len))
119 return NULL;
120
121 FLEX_ALLOC_MEM(a, name, name, len);
122 a->h = hval;
123 a->next = git_attr_hash[pos];
124 a->attr_nr = attr_nr++;
125 a->maybe_macro = 0;
126 a->maybe_real = 0;
127 git_attr_hash[pos] = a;
128
129 /*
130 * NEEDSWORK: per git_attr_check check_all_attr
131 * will be initialized a lot more lazily, not
132 * like this, and not here.
133 */
134 REALLOC_ARRAY(check_all_attr, attr_nr);
135 check_all_attr[a->attr_nr].attr = a;
136 check_all_attr[a->attr_nr].value = ATTR__UNKNOWN;
137 return a;
138 }
139
140 struct git_attr *git_attr(const char *name)
141 {
142 return git_attr_internal(name, strlen(name));
143 }
144
145 /* What does a matched pattern decide? */
146 struct attr_state {
147 struct git_attr *attr;
148 const char *setto;
149 };
150
151 struct pattern {
152 const char *pattern;
153 int patternlen;
154 int nowildcardlen;
155 unsigned flags; /* EXC_FLAG_* */
156 };
157
158 /*
159 * One rule, as from a .gitattributes file.
160 *
161 * If is_macro is true, then u.attr is a pointer to the git_attr being
162 * defined.
163 *
164 * If is_macro is false, then u.pat is the filename pattern to which the
165 * rule applies.
166 *
167 * In either case, num_attr is the number of attributes affected by
168 * this rule, and state is an array listing them. The attributes are
169 * listed as they appear in the file (macros unexpanded).
170 */
171 struct match_attr {
172 union {
173 struct pattern pat;
174 struct git_attr *attr;
175 } u;
176 char is_macro;
177 unsigned num_attr;
178 struct attr_state state[FLEX_ARRAY];
179 };
180
181 static const char blank[] = " \t\r\n";
182
183 /*
184 * Parse a whitespace-delimited attribute state (i.e., "attr",
185 * "-attr", "!attr", or "attr=value") from the string starting at src.
186 * If e is not NULL, write the results to *e. Return a pointer to the
187 * remainder of the string (with leading whitespace removed), or NULL
188 * if there was an error.
189 */
190 static const char *parse_attr(const char *src, int lineno, const char *cp,
191 struct attr_state *e)
192 {
193 const char *ep, *equals;
194 int len;
195
196 ep = cp + strcspn(cp, blank);
197 equals = strchr(cp, '=');
198 if (equals && ep < equals)
199 equals = NULL;
200 if (equals)
201 len = equals - cp;
202 else
203 len = ep - cp;
204 if (!e) {
205 if (*cp == '-' || *cp == '!') {
206 cp++;
207 len--;
208 }
209 if (!attr_name_valid(cp, len)) {
210 report_invalid_attr(cp, len, src, lineno);
211 return NULL;
212 }
213 } else {
214 /*
215 * As this function is always called twice, once with
216 * e == NULL in the first pass and then e != NULL in
217 * the second pass, no need for attr_name_valid()
218 * check here.
219 */
220 if (*cp == '-' || *cp == '!') {
221 e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET;
222 cp++;
223 len--;
224 }
225 else if (!equals)
226 e->setto = ATTR__TRUE;
227 else {
228 e->setto = xmemdupz(equals + 1, ep - equals - 1);
229 }
230 e->attr = git_attr_internal(cp, len);
231 }
232 return ep + strspn(ep, blank);
233 }
234
235 static struct match_attr *parse_attr_line(const char *line, const char *src,
236 int lineno, int macro_ok)
237 {
238 int namelen;
239 int num_attr, i;
240 const char *cp, *name, *states;
241 struct match_attr *res = NULL;
242 int is_macro;
243 struct strbuf pattern = STRBUF_INIT;
244
245 cp = line + strspn(line, blank);
246 if (!*cp || *cp == '#')
247 return NULL;
248 name = cp;
249
250 if (*cp == '"' && !unquote_c_style(&pattern, name, &states)) {
251 name = pattern.buf;
252 namelen = pattern.len;
253 } else {
254 namelen = strcspn(name, blank);
255 states = name + namelen;
256 }
257
258 if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
259 starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {
260 if (!macro_ok) {
261 fprintf(stderr, "%s not allowed: %s:%d\n",
262 name, src, lineno);
263 goto fail_return;
264 }
265 is_macro = 1;
266 name += strlen(ATTRIBUTE_MACRO_PREFIX);
267 name += strspn(name, blank);
268 namelen = strcspn(name, blank);
269 if (!attr_name_valid(name, namelen)) {
270 report_invalid_attr(name, namelen, src, lineno);
271 goto fail_return;
272 }
273 }
274 else
275 is_macro = 0;
276
277 states += strspn(states, blank);
278
279 /* First pass to count the attr_states */
280 for (cp = states, num_attr = 0; *cp; num_attr++) {
281 cp = parse_attr(src, lineno, cp, NULL);
282 if (!cp)
283 goto fail_return;
284 }
285
286 res = xcalloc(1,
287 sizeof(*res) +
288 sizeof(struct attr_state) * num_attr +
289 (is_macro ? 0 : namelen + 1));
290 if (is_macro) {
291 res->u.attr = git_attr_internal(name, namelen);
292 res->u.attr->maybe_macro = 1;
293 } else {
294 char *p = (char *)&(res->state[num_attr]);
295 memcpy(p, name, namelen);
296 res->u.pat.pattern = p;
297 parse_exclude_pattern(&res->u.pat.pattern,
298 &res->u.pat.patternlen,
299 &res->u.pat.flags,
300 &res->u.pat.nowildcardlen);
301 if (res->u.pat.flags & EXC_FLAG_NEGATIVE) {
302 warning(_("Negative patterns are ignored in git attributes\n"
303 "Use '\\!' for literal leading exclamation."));
304 goto fail_return;
305 }
306 }
307 res->is_macro = is_macro;
308 res->num_attr = num_attr;
309
310 /* Second pass to fill the attr_states */
311 for (cp = states, i = 0; *cp; i++) {
312 cp = parse_attr(src, lineno, cp, &(res->state[i]));
313 if (!is_macro)
314 res->state[i].attr->maybe_real = 1;
315 if (res->state[i].attr->maybe_macro)
316 cannot_trust_maybe_real = 1;
317 }
318
319 strbuf_release(&pattern);
320 return res;
321
322 fail_return:
323 strbuf_release(&pattern);
324 free(res);
325 return NULL;
326 }
327
328 /*
329 * Like info/exclude and .gitignore, the attribute information can
330 * come from many places.
331 *
332 * (1) .gitattribute file of the same directory;
333 * (2) .gitattribute file of the parent directory if (1) does not have
334 * any match; this goes recursively upwards, just like .gitignore.
335 * (3) $GIT_DIR/info/attributes, which overrides both of the above.
336 *
337 * In the same file, later entries override the earlier match, so in the
338 * global list, we would have entries from info/attributes the earliest
339 * (reading the file from top to bottom), .gitattribute of the root
340 * directory (again, reading the file from top to bottom) down to the
341 * current directory, and then scan the list backwards to find the first match.
342 * This is exactly the same as what is_excluded() does in dir.c to deal with
343 * .gitignore file and info/excludes file as a fallback.
344 */
345
346 /* NEEDSWORK: This will become per git_attr_check */
347 static struct attr_stack {
348 struct attr_stack *prev;
349 char *origin;
350 size_t originlen;
351 unsigned num_matches;
352 unsigned alloc;
353 struct match_attr **attrs;
354 } *attr_stack;
355
356 static void free_attr_elem(struct attr_stack *e)
357 {
358 int i;
359 free(e->origin);
360 for (i = 0; i < e->num_matches; i++) {
361 struct match_attr *a = e->attrs[i];
362 int j;
363 for (j = 0; j < a->num_attr; j++) {
364 const char *setto = a->state[j].setto;
365 if (setto == ATTR__TRUE ||
366 setto == ATTR__FALSE ||
367 setto == ATTR__UNSET ||
368 setto == ATTR__UNKNOWN)
369 ;
370 else
371 free((char *) setto);
372 }
373 free(a);
374 }
375 free(e->attrs);
376 free(e);
377 }
378
379 struct attr_check *attr_check_alloc(void)
380 {
381 return xcalloc(1, sizeof(struct attr_check));
382 }
383
384 struct attr_check *attr_check_initl(const char *one, ...)
385 {
386 struct attr_check *check;
387 int cnt;
388 va_list params;
389 const char *param;
390
391 va_start(params, one);
392 for (cnt = 1; (param = va_arg(params, const char *)) != NULL; cnt++)
393 ;
394 va_end(params);
395
396 check = attr_check_alloc();
397 check->nr = cnt;
398 check->alloc = cnt;
399 check->items = xcalloc(cnt, sizeof(struct attr_check_item));
400
401 check->items[0].attr = git_attr(one);
402 va_start(params, one);
403 for (cnt = 1; cnt < check->nr; cnt++) {
404 const struct git_attr *attr;
405 param = va_arg(params, const char *);
406 if (!param)
407 die("BUG: counted %d != ended at %d",
408 check->nr, cnt);
409 attr = git_attr(param);
410 if (!attr)
411 die("BUG: %s: not a valid attribute name", param);
412 check->items[cnt].attr = attr;
413 }
414 va_end(params);
415 return check;
416 }
417
418 struct attr_check_item *attr_check_append(struct attr_check *check,
419 const struct git_attr *attr)
420 {
421 struct attr_check_item *item;
422
423 ALLOC_GROW(check->items, check->nr + 1, check->alloc);
424 item = &check->items[check->nr++];
425 item->attr = attr;
426 return item;
427 }
428
429 void attr_check_reset(struct attr_check *check)
430 {
431 check->nr = 0;
432 }
433
434 void attr_check_clear(struct attr_check *check)
435 {
436 free(check->items);
437 check->items = NULL;
438 check->alloc = 0;
439 check->nr = 0;
440 }
441
442 void attr_check_free(struct attr_check *check)
443 {
444 attr_check_clear(check);
445 free(check);
446 }
447
448 static const char *builtin_attr[] = {
449 "[attr]binary -diff -merge -text",
450 NULL,
451 };
452
453 static void handle_attr_line(struct attr_stack *res,
454 const char *line,
455 const char *src,
456 int lineno,
457 int macro_ok)
458 {
459 struct match_attr *a;
460
461 a = parse_attr_line(line, src, lineno, macro_ok);
462 if (!a)
463 return;
464 ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc);
465 res->attrs[res->num_matches++] = a;
466 }
467
468 static struct attr_stack *read_attr_from_array(const char **list)
469 {
470 struct attr_stack *res;
471 const char *line;
472 int lineno = 0;
473
474 res = xcalloc(1, sizeof(*res));
475 while ((line = *(list++)) != NULL)
476 handle_attr_line(res, line, "[builtin]", ++lineno, 1);
477 return res;
478 }
479
480 /*
481 * NEEDSWORK: these two are tricky. The callers assume there is a
482 * single, system-wide global state "where we read attributes from?"
483 * and when the state is flipped by calling git_attr_set_direction(),
484 * attr_stack is discarded so that subsequent attr_check will lazily
485 * read from the right place. And they do not know or care who called
486 * by them uses the attribute subsystem, hence have no knowledge of
487 * existing git_attr_check instances or future ones that will be
488 * created).
489 *
490 * Probably we need a thread_local that holds these two variables,
491 * and a list of git_attr_check instances (which need to be maintained
492 * by hooking into git_attr_check_alloc(), git_attr_check_initl(), and
493 * git_attr_check_clear(). Then git_attr_set_direction() updates the
494 * fields in that thread_local for these two variables, iterate over
495 * all the active git_attr_check instances and discard the attr_stack
496 * they hold. Yuck, but it sounds doable.
497 */
498 static enum git_attr_direction direction;
499 static struct index_state *use_index;
500
501 static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
502 {
503 FILE *fp = fopen(path, "r");
504 struct attr_stack *res;
505 char buf[2048];
506 int lineno = 0;
507
508 if (!fp) {
509 if (errno != ENOENT && errno != ENOTDIR)
510 warn_on_inaccessible(path);
511 return NULL;
512 }
513 res = xcalloc(1, sizeof(*res));
514 while (fgets(buf, sizeof(buf), fp)) {
515 char *bufp = buf;
516 if (!lineno)
517 skip_utf8_bom(&bufp, strlen(bufp));
518 handle_attr_line(res, bufp, path, ++lineno, macro_ok);
519 }
520 fclose(fp);
521 return res;
522 }
523
524 static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
525 {
526 struct attr_stack *res;
527 char *buf, *sp;
528 int lineno = 0;
529
530 buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL);
531 if (!buf)
532 return NULL;
533
534 res = xcalloc(1, sizeof(*res));
535 for (sp = buf; *sp; ) {
536 char *ep;
537 int more;
538
539 ep = strchrnul(sp, '\n');
540 more = (*ep == '\n');
541 *ep = '\0';
542 handle_attr_line(res, sp, path, ++lineno, macro_ok);
543 sp = ep + more;
544 }
545 free(buf);
546 return res;
547 }
548
549 static struct attr_stack *read_attr(const char *path, int macro_ok)
550 {
551 struct attr_stack *res;
552
553 if (direction == GIT_ATTR_CHECKOUT) {
554 res = read_attr_from_index(path, macro_ok);
555 if (!res)
556 res = read_attr_from_file(path, macro_ok);
557 }
558 else if (direction == GIT_ATTR_CHECKIN) {
559 res = read_attr_from_file(path, macro_ok);
560 if (!res)
561 /*
562 * There is no checked out .gitattributes file there, but
563 * we might have it in the index. We allow operation in a
564 * sparsely checked out work tree, so read from it.
565 */
566 res = read_attr_from_index(path, macro_ok);
567 }
568 else
569 res = read_attr_from_index(path, macro_ok);
570 if (!res)
571 res = xcalloc(1, sizeof(*res));
572 return res;
573 }
574
575 #if DEBUG_ATTR
576 static void debug_info(const char *what, struct attr_stack *elem)
577 {
578 fprintf(stderr, "%s: %s\n", what, elem->origin ? elem->origin : "()");
579 }
580 static void debug_set(const char *what, const char *match, struct git_attr *attr, const void *v)
581 {
582 const char *value = v;
583
584 if (ATTR_TRUE(value))
585 value = "set";
586 else if (ATTR_FALSE(value))
587 value = "unset";
588 else if (ATTR_UNSET(value))
589 value = "unspecified";
590
591 fprintf(stderr, "%s: %s => %s (%s)\n",
592 what, attr->name, (char *) value, match);
593 }
594 #define debug_push(a) debug_info("push", (a))
595 #define debug_pop(a) debug_info("pop", (a))
596 #else
597 #define debug_push(a) do { ; } while (0)
598 #define debug_pop(a) do { ; } while (0)
599 #define debug_set(a,b,c,d) do { ; } while (0)
600 #endif /* DEBUG_ATTR */
601
602 static void drop_attr_stack(void)
603 {
604 while (attr_stack) {
605 struct attr_stack *elem = attr_stack;
606 attr_stack = elem->prev;
607 free_attr_elem(elem);
608 }
609 }
610
611 static const char *git_etc_gitattributes(void)
612 {
613 static const char *system_wide;
614 if (!system_wide)
615 system_wide = system_path(ETC_GITATTRIBUTES);
616 return system_wide;
617 }
618
619 static int git_attr_system(void)
620 {
621 return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
622 }
623
624 static GIT_PATH_FUNC(git_path_info_attributes, INFOATTRIBUTES_FILE)
625
626 static void push_stack(struct attr_stack **attr_stack_p,
627 struct attr_stack *elem, char *origin, size_t originlen)
628 {
629 if (elem) {
630 elem->origin = origin;
631 if (origin)
632 elem->originlen = originlen;
633 elem->prev = *attr_stack_p;
634 *attr_stack_p = elem;
635 }
636 }
637
638 static void bootstrap_attr_stack(void)
639 {
640 struct attr_stack *elem;
641
642 if (attr_stack)
643 return;
644
645 push_stack(&attr_stack, read_attr_from_array(builtin_attr), NULL, 0);
646
647 if (git_attr_system())
648 push_stack(&attr_stack,
649 read_attr_from_file(git_etc_gitattributes(), 1),
650 NULL, 0);
651
652 if (!git_attributes_file)
653 git_attributes_file = xdg_config_home("attributes");
654 if (git_attributes_file)
655 push_stack(&attr_stack,
656 read_attr_from_file(git_attributes_file, 1),
657 NULL, 0);
658
659 if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
660 elem = read_attr(GITATTRIBUTES_FILE, 1);
661 push_stack(&attr_stack, elem, xstrdup(""), 0);
662 debug_push(elem);
663 }
664
665 if (startup_info->have_repository)
666 elem = read_attr_from_file(git_path_info_attributes(), 1);
667 else
668 elem = NULL;
669
670 if (!elem)
671 elem = xcalloc(1, sizeof(*elem));
672 push_stack(&attr_stack, elem, NULL, 0);
673 }
674
675 static void prepare_attr_stack(const char *path, int dirlen)
676 {
677 struct attr_stack *elem, *info;
678 const char *cp;
679
680 /*
681 * At the bottom of the attribute stack is the built-in
682 * set of attribute definitions, followed by the contents
683 * of $(prefix)/etc/gitattributes and a file specified by
684 * core.attributesfile. Then, contents from
685 * .gitattribute files from directories closer to the
686 * root to the ones in deeper directories are pushed
687 * to the stack. Finally, at the very top of the stack
688 * we always keep the contents of $GIT_DIR/info/attributes.
689 *
690 * When checking, we use entries from near the top of the
691 * stack, preferring $GIT_DIR/info/attributes, then
692 * .gitattributes in deeper directories to shallower ones,
693 * and finally use the built-in set as the default.
694 */
695 bootstrap_attr_stack();
696
697 /*
698 * Pop the "info" one that is always at the top of the stack.
699 */
700 info = attr_stack;
701 attr_stack = info->prev;
702
703 /*
704 * Pop the ones from directories that are not the prefix of
705 * the path we are checking. Break out of the loop when we see
706 * the root one (whose origin is an empty string "") or the builtin
707 * one (whose origin is NULL) without popping it.
708 */
709 while (attr_stack->origin) {
710 int namelen = strlen(attr_stack->origin);
711
712 elem = attr_stack;
713 if (namelen <= dirlen &&
714 !strncmp(elem->origin, path, namelen) &&
715 (!namelen || path[namelen] == '/'))
716 break;
717
718 debug_pop(elem);
719 attr_stack = elem->prev;
720 free_attr_elem(elem);
721 }
722
723 /*
724 * Read from parent directories and push them down
725 */
726 if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
727 /*
728 * bootstrap_attr_stack() should have added, and the
729 * above loop should have stopped before popping, the
730 * root element whose attr_stack->origin is set to an
731 * empty string.
732 */
733 struct strbuf pathbuf = STRBUF_INIT;
734
735 assert(attr_stack->origin);
736 while (1) {
737 size_t len = strlen(attr_stack->origin);
738 char *origin;
739
740 if (dirlen <= len)
741 break;
742 cp = memchr(path + len + 1, '/', dirlen - len - 1);
743 if (!cp)
744 cp = path + dirlen;
745 strbuf_addf(&pathbuf,
746 "%.*s/%s", (int)(cp - path), path,
747 GITATTRIBUTES_FILE);
748 elem = read_attr(pathbuf.buf, 0);
749 strbuf_setlen(&pathbuf, cp - path);
750 origin = strbuf_detach(&pathbuf, &len);
751 push_stack(&attr_stack, elem, origin, len);
752 debug_push(elem);
753 }
754
755 strbuf_release(&pathbuf);
756 }
757
758 /*
759 * Finally push the "info" one at the top of the stack.
760 */
761 push_stack(&attr_stack, info, NULL, 0);
762 }
763
764 static int path_matches(const char *pathname, int pathlen,
765 int basename_offset,
766 const struct pattern *pat,
767 const char *base, int baselen)
768 {
769 const char *pattern = pat->pattern;
770 int prefix = pat->nowildcardlen;
771 int isdir = (pathlen && pathname[pathlen - 1] == '/');
772
773 if ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir)
774 return 0;
775
776 if (pat->flags & EXC_FLAG_NODIR) {
777 return match_basename(pathname + basename_offset,
778 pathlen - basename_offset - isdir,
779 pattern, prefix,
780 pat->patternlen, pat->flags);
781 }
782 return match_pathname(pathname, pathlen - isdir,
783 base, baselen,
784 pattern, prefix, pat->patternlen, pat->flags);
785 }
786
787 static int macroexpand_one(int attr_nr, int rem);
788
789 static int fill_one(const char *what, struct match_attr *a, int rem)
790 {
791 struct attr_check_item *check = check_all_attr;
792 int i;
793
794 for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {
795 struct git_attr *attr = a->state[i].attr;
796 const char **n = &(check[attr->attr_nr].value);
797 const char *v = a->state[i].setto;
798
799 if (*n == ATTR__UNKNOWN) {
800 debug_set(what,
801 a->is_macro ? a->u.attr->name : a->u.pat.pattern,
802 attr, v);
803 *n = v;
804 rem--;
805 rem = macroexpand_one(attr->attr_nr, rem);
806 }
807 }
808 return rem;
809 }
810
811 static int fill(const char *path, int pathlen, int basename_offset,
812 struct attr_stack *stk, int rem)
813 {
814 int i;
815 const char *base = stk->origin ? stk->origin : "";
816
817 for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
818 struct match_attr *a = stk->attrs[i];
819 if (a->is_macro)
820 continue;
821 if (path_matches(path, pathlen, basename_offset,
822 &a->u.pat, base, stk->originlen))
823 rem = fill_one("fill", a, rem);
824 }
825 return rem;
826 }
827
828 static int macroexpand_one(int nr, int rem)
829 {
830 struct attr_stack *stk;
831 int i;
832
833 if (check_all_attr[nr].value != ATTR__TRUE ||
834 !check_all_attr[nr].attr->maybe_macro)
835 return rem;
836
837 for (stk = attr_stack; stk; stk = stk->prev) {
838 for (i = stk->num_matches - 1; 0 <= i; i--) {
839 struct match_attr *ma = stk->attrs[i];
840 if (!ma->is_macro)
841 continue;
842 if (ma->u.attr->attr_nr == nr)
843 return fill_one("expand", ma, rem);
844 }
845 }
846
847 return rem;
848 }
849
850 /*
851 * Collect attributes for path into the array pointed to by
852 * check_all_attr. If num is non-zero, only attributes in check[] are
853 * collected. Otherwise all attributes are collected.
854 */
855 static void collect_some_attrs(const char *path, struct attr_check *check)
856 {
857 struct attr_stack *stk;
858 int i, pathlen, rem, dirlen;
859 const char *cp, *last_slash = NULL;
860 int basename_offset;
861
862 for (cp = path; *cp; cp++) {
863 if (*cp == '/' && cp[1])
864 last_slash = cp;
865 }
866 pathlen = cp - path;
867 if (last_slash) {
868 basename_offset = last_slash + 1 - path;
869 dirlen = last_slash - path;
870 } else {
871 basename_offset = 0;
872 dirlen = 0;
873 }
874
875 prepare_attr_stack(path, dirlen);
876 for (i = 0; i < attr_nr; i++)
877 check_all_attr[i].value = ATTR__UNKNOWN;
878 if (check->nr && !cannot_trust_maybe_real) {
879 rem = 0;
880 for (i = 0; i < check->nr; i++) {
881 const struct git_attr *a = check->items[i].attr;
882 if (!a->maybe_real) {
883 struct attr_check_item *c;
884 c = check_all_attr + a->attr_nr;
885 c->value = ATTR__UNSET;
886 rem++;
887 }
888 }
889 if (rem == check->nr)
890 return;
891 }
892
893 rem = attr_nr;
894 for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
895 rem = fill(path, pathlen, basename_offset, stk, rem);
896 }
897
898 int git_check_attr(const char *path, struct attr_check *check)
899 {
900 int i;
901
902 collect_some_attrs(path, check);
903
904 for (i = 0; i < check->nr; i++) {
905 const char *value = check_all_attr[check->items[i].attr->attr_nr].value;
906 if (value == ATTR__UNKNOWN)
907 value = ATTR__UNSET;
908 check->items[i].value = value;
909 }
910
911 return 0;
912 }
913
914 void git_all_attrs(const char *path, struct attr_check *check)
915 {
916 int i;
917
918 attr_check_reset(check);
919 collect_some_attrs(path, check);
920
921 for (i = 0; i < attr_nr; i++) {
922 const char *name = check_all_attr[i].attr->name;
923 const char *value = check_all_attr[i].value;
924 struct attr_check_item *item;
925 if (value == ATTR__UNSET || value == ATTR__UNKNOWN)
926 continue;
927 item = attr_check_append(check, git_attr(name));
928 item->value = value;
929 }
930 }
931
932 void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
933 {
934 enum git_attr_direction old = direction;
935
936 if (is_bare_repository() && new != GIT_ATTR_INDEX)
937 die("BUG: non-INDEX attr direction in a bare repo");
938
939 direction = new;
940 if (new != old)
941 drop_attr_stack();
942 use_index = istate;
943 }