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