]>
Commit | Line | Data |
---|---|---|
73b51450 | 1 | #include "repository.h" |
ee1f0b1a RB |
2 | #include "fileops.h" |
3 | #include "config.h" | |
4 | #include <ctype.h> | |
5 | ||
c2b67043 | 6 | GIT__USE_STRMAP; |
01fed0a8 | 7 | |
ee1f0b1a | 8 | static int collect_attr_files( |
f917481e RB |
9 | git_repository *repo, |
10 | uint32_t flags, | |
11 | const char *path, | |
12 | git_vector *files); | |
ee1f0b1a RB |
13 | |
14 | ||
15 | int git_attr_get( | |
f917481e RB |
16 | git_repository *repo, |
17 | uint32_t flags, | |
18 | const char *pathname, | |
19 | const char *name, | |
20 | const char **value) | |
ee1f0b1a RB |
21 | { |
22 | int error; | |
23 | git_attr_path path; | |
24 | git_vector files = GIT_VECTOR_INIT; | |
25 | unsigned int i, j; | |
26 | git_attr_file *file; | |
27 | git_attr_name attr; | |
28 | git_attr_rule *rule; | |
29 | ||
30 | *value = NULL; | |
31 | ||
d58336dd RB |
32 | if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) |
33 | return -1; | |
34 | ||
f917481e | 35 | if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) |
d58336dd | 36 | goto cleanup; |
ee1f0b1a RB |
37 | |
38 | attr.name = name; | |
39 | attr.name_hash = git_attr_file__name_hash(name); | |
40 | ||
41 | git_vector_foreach(&files, i, file) { | |
42 | ||
43 | git_attr_file__foreach_matching_rule(file, &path, j, rule) { | |
44 | int pos = git_vector_bsearch(&rule->assigns, &attr); | |
ee1f0b1a RB |
45 | if (pos >= 0) { |
46 | *value = ((git_attr_assignment *)git_vector_get( | |
47 | &rule->assigns, pos))->value; | |
d58336dd | 48 | goto cleanup; |
ee1f0b1a RB |
49 | } |
50 | } | |
51 | } | |
52 | ||
d58336dd | 53 | cleanup: |
ee1f0b1a | 54 | git_vector_free(&files); |
d58336dd | 55 | git_attr_path__free(&path); |
ee1f0b1a RB |
56 | |
57 | return error; | |
58 | } | |
59 | ||
60 | ||
61 | typedef struct { | |
62 | git_attr_name name; | |
63 | git_attr_assignment *found; | |
64 | } attr_get_many_info; | |
65 | ||
66 | int git_attr_get_many( | |
f917481e RB |
67 | git_repository *repo, |
68 | uint32_t flags, | |
69 | const char *pathname, | |
70 | size_t num_attr, | |
71 | const char **names, | |
72 | const char **values) | |
ee1f0b1a RB |
73 | { |
74 | int error; | |
75 | git_attr_path path; | |
76 | git_vector files = GIT_VECTOR_INIT; | |
77 | unsigned int i, j, k; | |
78 | git_attr_file *file; | |
79 | git_attr_rule *rule; | |
80 | attr_get_many_info *info = NULL; | |
81 | size_t num_found = 0; | |
82 | ||
acb159e1 | 83 | memset((void *)values, 0, sizeof(const char *) * num_attr); |
ee1f0b1a | 84 | |
d58336dd RB |
85 | if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) |
86 | return -1; | |
87 | ||
f917481e | 88 | if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) |
d58336dd | 89 | goto cleanup; |
ee1f0b1a | 90 | |
0d0fa7c3 RB |
91 | info = git__calloc(num_attr, sizeof(attr_get_many_info)); |
92 | GITERR_CHECK_ALLOC(info); | |
ee1f0b1a RB |
93 | |
94 | git_vector_foreach(&files, i, file) { | |
95 | ||
96 | git_attr_file__foreach_matching_rule(file, &path, j, rule) { | |
97 | ||
98 | for (k = 0; k < num_attr; k++) { | |
99 | int pos; | |
100 | ||
101 | if (info[k].found != NULL) /* already found assignment */ | |
102 | continue; | |
103 | ||
104 | if (!info[k].name.name) { | |
105 | info[k].name.name = names[k]; | |
106 | info[k].name.name_hash = git_attr_file__name_hash(names[k]); | |
107 | } | |
108 | ||
109 | pos = git_vector_bsearch(&rule->assigns, &info[k].name); | |
ee1f0b1a RB |
110 | if (pos >= 0) { |
111 | info[k].found = (git_attr_assignment *) | |
112 | git_vector_get(&rule->assigns, pos); | |
113 | values[k] = info[k].found->value; | |
114 | ||
115 | if (++num_found == num_attr) | |
116 | goto cleanup; | |
117 | } | |
118 | } | |
119 | } | |
120 | } | |
121 | ||
122 | cleanup: | |
123 | git_vector_free(&files); | |
d58336dd | 124 | git_attr_path__free(&path); |
ee1f0b1a RB |
125 | git__free(info); |
126 | ||
127 | return error; | |
128 | } | |
129 | ||
130 | ||
131 | int git_attr_foreach( | |
f917481e RB |
132 | git_repository *repo, |
133 | uint32_t flags, | |
134 | const char *pathname, | |
ee1f0b1a RB |
135 | int (*callback)(const char *name, const char *value, void *payload), |
136 | void *payload) | |
137 | { | |
138 | int error; | |
139 | git_attr_path path; | |
140 | git_vector files = GIT_VECTOR_INIT; | |
141 | unsigned int i, j, k; | |
142 | git_attr_file *file; | |
143 | git_attr_rule *rule; | |
144 | git_attr_assignment *assign; | |
c2b67043 | 145 | git_strmap *seen = NULL; |
ee1f0b1a | 146 | |
d58336dd RB |
147 | if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) |
148 | return -1; | |
149 | ||
f917481e | 150 | if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) |
d58336dd | 151 | goto cleanup; |
ee1f0b1a | 152 | |
c2b67043 | 153 | seen = git_strmap_alloc(); |
0d0fa7c3 | 154 | GITERR_CHECK_ALLOC(seen); |
ee1f0b1a RB |
155 | |
156 | git_vector_foreach(&files, i, file) { | |
157 | ||
158 | git_attr_file__foreach_matching_rule(file, &path, j, rule) { | |
159 | ||
160 | git_vector_foreach(&rule->assigns, k, assign) { | |
161 | /* skip if higher priority assignment was already seen */ | |
c2b67043 | 162 | if (git_strmap_exists(seen, assign->name)) |
ee1f0b1a RB |
163 | continue; |
164 | ||
c2b67043 | 165 | git_strmap_insert(seen, assign->name, assign, error); |
01fed0a8 | 166 | if (error >= 0) |
0d0fa7c3 | 167 | error = callback(assign->name, assign->value, payload); |
ee1f0b1a | 168 | |
0d0fa7c3 | 169 | if (error != 0) |
ee1f0b1a RB |
170 | goto cleanup; |
171 | } | |
172 | } | |
173 | } | |
174 | ||
175 | cleanup: | |
c2b67043 | 176 | git_strmap_free(seen); |
ee1f0b1a | 177 | git_vector_free(&files); |
d58336dd | 178 | git_attr_path__free(&path); |
ee1f0b1a | 179 | |
ee1f0b1a RB |
180 | return error; |
181 | } | |
182 | ||
183 | ||
73b51450 RB |
184 | int git_attr_add_macro( |
185 | git_repository *repo, | |
186 | const char *name, | |
187 | const char *values) | |
188 | { | |
189 | int error; | |
190 | git_attr_rule *macro = NULL; | |
19fa2bc1 | 191 | git_pool *pool; |
73b51450 | 192 | |
0d0fa7c3 RB |
193 | if (git_attr_cache__init(repo) < 0) |
194 | return -1; | |
73b51450 RB |
195 | |
196 | macro = git__calloc(1, sizeof(git_attr_rule)); | |
0d0fa7c3 | 197 | GITERR_CHECK_ALLOC(macro); |
73b51450 | 198 | |
19fa2bc1 RB |
199 | pool = &git_repository_attr_cache(repo)->pool; |
200 | ||
201 | macro->match.pattern = git_pool_strdup(pool, name); | |
0d0fa7c3 | 202 | GITERR_CHECK_ALLOC(macro->match.pattern); |
73b51450 RB |
203 | |
204 | macro->match.length = strlen(macro->match.pattern); | |
205 | macro->match.flags = GIT_ATTR_FNMATCH_MACRO; | |
206 | ||
19fa2bc1 | 207 | error = git_attr_assignment__parse(repo, pool, ¯o->assigns, &values); |
73b51450 | 208 | |
0d0fa7c3 | 209 | if (!error) |
73b51450 RB |
210 | error = git_attr_cache__insert_macro(repo, macro); |
211 | ||
0d0fa7c3 | 212 | if (error < 0) |
73b51450 | 213 | git_attr_rule__free(macro); |
73b51450 RB |
214 | |
215 | return error; | |
216 | } | |
217 | ||
f917481e RB |
218 | bool git_attr_cache__is_cached( |
219 | git_repository *repo, git_attr_file_source source, const char *path) | |
e8c96ed2 | 220 | { |
f917481e | 221 | git_buf cache_key = GIT_BUF_INIT; |
c2b67043 | 222 | git_strmap *files = git_repository_attr_cache(repo)->files; |
f917481e RB |
223 | const char *workdir = git_repository_workdir(repo); |
224 | bool rval; | |
225 | ||
226 | if (workdir && git__prefixcmp(path, workdir) == 0) | |
227 | path += strlen(workdir); | |
228 | if (git_buf_printf(&cache_key, "%d#%s", (int)source, path) < 0) | |
229 | return false; | |
230 | ||
231 | rval = git_strmap_exists(files, git_buf_cstr(&cache_key)); | |
232 | ||
233 | git_buf_free(&cache_key); | |
234 | ||
235 | return rval; | |
236 | } | |
237 | ||
238 | static int load_attr_file(const char *filename, const char **data) | |
239 | { | |
240 | int error; | |
241 | git_buf content = GIT_BUF_INIT; | |
242 | ||
243 | error = git_futils_readbuffer(&content, filename); | |
244 | *data = error ? NULL : git_buf_detach(&content); | |
245 | ||
246 | return error; | |
247 | } | |
01fed0a8 | 248 | |
f917481e RB |
249 | static int load_attr_blob_from_index( |
250 | git_repository *repo, const char *filename, git_blob **blob) | |
251 | { | |
252 | int error; | |
253 | git_index *index; | |
254 | git_index_entry *entry; | |
255 | ||
256 | if ((error = git_repository_index__weakptr(&index, repo)) < 0 || | |
257 | (error = git_index_find(index, filename)) < 0) | |
258 | return error; | |
01fed0a8 | 259 | |
f917481e RB |
260 | entry = git_index_get(index, error); |
261 | ||
262 | return git_blob_lookup(blob, repo, &entry->oid); | |
e8c96ed2 | 263 | } |
73b51450 | 264 | |
f917481e | 265 | int git_attr_cache__internal_file( |
b6c93aef | 266 | git_repository *repo, |
b6c93aef | 267 | const char *filename, |
f917481e | 268 | git_attr_file **file) |
b6c93aef | 269 | { |
f917481e | 270 | int error = 0; |
95dfb031 | 271 | git_attr_cache *cache = git_repository_attr_cache(repo); |
f917481e | 272 | khiter_t cache_pos = git_strmap_lookup_index(cache->files, filename); |
b6c93aef | 273 | |
f917481e RB |
274 | if (git_strmap_valid_index(cache->files, cache_pos)) { |
275 | *file = git_strmap_value_at(cache->files, cache_pos); | |
0d0fa7c3 | 276 | return 0; |
b6c93aef RB |
277 | } |
278 | ||
f917481e | 279 | if (git_attr_file__new(file, 0, filename, &cache->pool) < 0) |
0d0fa7c3 | 280 | return -1; |
b6c93aef | 281 | |
f917481e RB |
282 | git_strmap_insert(cache->files, (*file)->key + 2, *file, error); |
283 | if (error > 0) | |
284 | error = 0; | |
b6c93aef | 285 | |
b6c93aef RB |
286 | return error; |
287 | } | |
288 | ||
df743c7d | 289 | int git_attr_cache__push_file( |
ee1f0b1a | 290 | git_repository *repo, |
f917481e RB |
291 | const char *base, |
292 | const char *filename, | |
293 | git_attr_file_source source, | |
294 | git_attr_file_parser parse, | |
295 | git_vector *stack) | |
ee1f0b1a | 296 | { |
f917481e | 297 | int error = 0; |
ee1f0b1a | 298 | git_buf path = GIT_BUF_INIT; |
f917481e RB |
299 | const char *workdir = git_repository_workdir(repo); |
300 | const char *relfile, *content = NULL; | |
301 | git_attr_cache *cache = git_repository_attr_cache(repo); | |
62a1f713 | 302 | git_attr_file *file = NULL; |
f917481e RB |
303 | git_blob *blob = NULL; |
304 | ||
305 | assert(filename && stack); | |
ee1f0b1a | 306 | |
f917481e RB |
307 | /* join base and path as needed */ |
308 | if (base != NULL && git_path_root(filename) < 0) { | |
0d0fa7c3 RB |
309 | if (git_buf_joinpath(&path, base, filename) < 0) |
310 | return -1; | |
1dbcc9fc RB |
311 | filename = path.ptr; |
312 | } | |
ee1f0b1a | 313 | |
f917481e RB |
314 | relfile = filename; |
315 | if (workdir && git__prefixcmp(relfile, workdir) == 0) | |
316 | relfile += strlen(workdir); | |
62a1f713 | 317 | |
f917481e RB |
318 | /* check cache */ |
319 | if (cache && cache->files) { | |
320 | git_buf cache_key = GIT_BUF_INIT; | |
321 | khiter_t cache_pos; | |
322 | ||
323 | if (git_buf_printf(&cache_key, "%d#%s", (int)source, relfile) < 0) | |
324 | return -1; | |
ee1f0b1a | 325 | |
f917481e RB |
326 | cache_pos = git_strmap_lookup_index(cache->files, cache_key.ptr); |
327 | ||
328 | git_buf_free(&cache_key); | |
329 | ||
330 | if (git_strmap_valid_index(cache->files, cache_pos)) { | |
331 | file = git_strmap_value_at(cache->files, cache_pos); | |
332 | goto finish; | |
333 | } | |
334 | } | |
335 | ||
336 | /* if not in cache, load data, parse, and cache */ | |
f917481e RB |
337 | |
338 | if (source == GIT_ATTR_FILE_FROM_FILE) | |
339 | error = load_attr_file(filename, &content); | |
340 | else | |
341 | error = load_attr_blob_from_index(repo, relfile, &blob); | |
342 | ||
343 | if (error) { | |
344 | /* not finding a file is not an error for this function */ | |
345 | if (error == GIT_ENOTFOUND) { | |
346 | giterr_clear(); | |
347 | error = 0; | |
348 | } | |
349 | goto finish; | |
350 | } | |
351 | ||
352 | if (blob) | |
353 | content = git_blob_rawcontent(blob); | |
354 | ||
b709e951 RB |
355 | if ((error = git_attr_file__new(&file, source, relfile, &cache->pool)) < 0) |
356 | goto finish; | |
357 | ||
f917481e RB |
358 | if (parse && (error = parse(repo, content, file)) < 0) |
359 | goto finish; | |
360 | ||
361 | git_strmap_insert(cache->files, file->key, file, error); | |
362 | if (error > 0) | |
363 | error = 0; | |
364 | ||
365 | finish: | |
366 | /* push file onto vector if we found one*/ | |
0d0fa7c3 | 367 | if (!error && file != NULL) |
df743c7d | 368 | error = git_vector_insert(stack, file); |
ee1f0b1a | 369 | |
f917481e RB |
370 | if (error != 0) |
371 | git_attr_file__free(file); | |
372 | ||
373 | if (blob) | |
374 | git_blob_free(blob); | |
375 | else | |
376 | git__free((void *)content); | |
377 | ||
ee1f0b1a | 378 | git_buf_free(&path); |
f917481e | 379 | |
ee1f0b1a RB |
380 | return error; |
381 | } | |
382 | ||
f917481e RB |
383 | #define push_attr_file(R,S,B,F) \ |
384 | git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,(S)) | |
ee1f0b1a | 385 | |
0cfcff5d RB |
386 | typedef struct { |
387 | git_repository *repo; | |
f917481e RB |
388 | uint32_t flags; |
389 | const char *workdir; | |
390 | git_index *index; | |
0cfcff5d RB |
391 | git_vector *files; |
392 | } attr_walk_up_info; | |
393 | ||
f917481e RB |
394 | int git_attr_cache__decide_sources( |
395 | uint32_t flags, bool has_wd, bool has_index, git_attr_file_source *srcs) | |
396 | { | |
397 | int count = 0; | |
398 | ||
399 | switch (flags & 0x03) { | |
400 | case GIT_ATTR_CHECK_FILE_THEN_INDEX: | |
401 | if (has_wd) | |
402 | srcs[count++] = GIT_ATTR_FILE_FROM_FILE; | |
403 | if (has_index) | |
404 | srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; | |
405 | break; | |
406 | case GIT_ATTR_CHECK_INDEX_THEN_FILE: | |
407 | if (has_index) | |
408 | srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; | |
409 | if (has_wd) | |
410 | srcs[count++] = GIT_ATTR_FILE_FROM_FILE; | |
411 | break; | |
412 | case GIT_ATTR_CHECK_INDEX_ONLY: | |
413 | if (has_index) | |
414 | srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; | |
415 | break; | |
416 | } | |
417 | ||
418 | return count; | |
419 | } | |
420 | ||
0cfcff5d RB |
421 | static int push_one_attr(void *ref, git_buf *path) |
422 | { | |
f917481e | 423 | int error = 0, n_src, i; |
0cfcff5d | 424 | attr_walk_up_info *info = (attr_walk_up_info *)ref; |
f917481e RB |
425 | git_attr_file_source src[2]; |
426 | ||
427 | n_src = git_attr_cache__decide_sources( | |
428 | info->flags, info->workdir != NULL, info->index != NULL, src); | |
429 | ||
430 | for (i = 0; !error && i < n_src; ++i) | |
431 | error = git_attr_cache__push_file( | |
432 | info->repo, path->ptr, GIT_ATTR_FILE, src[i], | |
433 | git_attr_file__parse_buffer, info->files); | |
434 | ||
435 | return error; | |
0cfcff5d RB |
436 | } |
437 | ||
ee1f0b1a | 438 | static int collect_attr_files( |
f917481e RB |
439 | git_repository *repo, |
440 | uint32_t flags, | |
441 | const char *path, | |
442 | git_vector *files) | |
ee1f0b1a | 443 | { |
0d0fa7c3 | 444 | int error; |
ee1f0b1a | 445 | git_buf dir = GIT_BUF_INIT; |
ee1f0b1a | 446 | const char *workdir = git_repository_workdir(repo); |
0cfcff5d | 447 | attr_walk_up_info info; |
ee1f0b1a | 448 | |
ab43ad2f RB |
449 | if (git_attr_cache__init(repo) < 0 || |
450 | git_vector_init(files, 4, NULL) < 0) | |
451 | return -1; | |
ee1f0b1a | 452 | |
f917481e RB |
453 | /* given a unrooted path in a non-bare repo, resolve it */ |
454 | if (workdir && git_path_root(path) < 0) | |
455 | error = git_path_find_dir(&dir, path, workdir); | |
456 | else | |
457 | error = git_buf_sets(&dir, path); | |
ab43ad2f | 458 | if (error < 0) |
ee1f0b1a RB |
459 | goto cleanup; |
460 | ||
ee1f0b1a RB |
461 | /* in precendence order highest to lowest: |
462 | * - $GIT_DIR/info/attributes | |
463 | * - path components with .gitattributes | |
464 | * - config core.attributesfile | |
465 | * - $GIT_PREFIX/etc/gitattributes | |
466 | */ | |
467 | ||
f917481e | 468 | error = push_attr_file( |
95dfb031 | 469 | repo, files, git_repository_path(repo), GIT_ATTR_FILE_INREPO); |
ab43ad2f | 470 | if (error < 0) |
ee1f0b1a RB |
471 | goto cleanup; |
472 | ||
f917481e RB |
473 | info.repo = repo; |
474 | info.flags = flags; | |
475 | info.workdir = workdir; | |
476 | if (git_repository_index__weakptr(&info.index, repo) < 0) | |
477 | giterr_clear(); /* no error even if there is no index */ | |
0cfcff5d | 478 | info.files = files; |
f917481e | 479 | |
0cfcff5d | 480 | error = git_path_walk_up(&dir, workdir, push_one_attr, &info); |
ab43ad2f | 481 | if (error < 0) |
ee1f0b1a RB |
482 | goto cleanup; |
483 | ||
95dfb031 | 484 | if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) { |
f917481e | 485 | error = push_attr_file( |
95dfb031 RB |
486 | repo, files, NULL, git_repository_attr_cache(repo)->cfg_attr_file); |
487 | if (error < 0) | |
488 | goto cleanup; | |
ee1f0b1a RB |
489 | } |
490 | ||
f917481e RB |
491 | if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) { |
492 | error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM); | |
493 | if (!error) | |
494 | error = push_attr_file(repo, files, NULL, dir.ptr); | |
495 | else if (error == GIT_ENOTFOUND) | |
496 | error = 0; | |
497 | } | |
ee1f0b1a RB |
498 | |
499 | cleanup: | |
ab43ad2f | 500 | if (error < 0) |
ee1f0b1a | 501 | git_vector_free(files); |
ee1f0b1a RB |
502 | git_buf_free(&dir); |
503 | ||
504 | return error; | |
505 | } | |
506 | ||
507 | ||
df743c7d | 508 | int git_attr_cache__init(git_repository *repo) |
ee1f0b1a | 509 | { |
7784bcbb | 510 | int ret; |
95dfb031 RB |
511 | git_attr_cache *cache = git_repository_attr_cache(repo); |
512 | git_config *cfg; | |
73b51450 RB |
513 | |
514 | if (cache->initialized) | |
ab43ad2f | 515 | return 0; |
73b51450 | 516 | |
95dfb031 | 517 | /* cache config settings for attributes and ignores */ |
7784bcbb | 518 | if (git_repository_config__weakptr(&cfg, repo) < 0) |
95dfb031 | 519 | return -1; |
7784bcbb RB |
520 | |
521 | ret = git_config_get_string(cfg, GIT_ATTR_CONFIG, &cache->cfg_attr_file); | |
522 | if (ret < 0 && ret != GIT_ENOTFOUND) | |
523 | return ret; | |
524 | ||
525 | ret = git_config_get_string(cfg, GIT_IGNORE_CONFIG, &cache->cfg_excl_file); | |
526 | if (ret < 0 && ret != GIT_ENOTFOUND) | |
527 | return ret; | |
528 | ||
529 | giterr_clear(); | |
95dfb031 RB |
530 | |
531 | /* allocate hashtable for attribute and ignore file contents */ | |
73b51450 | 532 | if (cache->files == NULL) { |
c2b67043 | 533 | cache->files = git_strmap_alloc(); |
01fed0a8 | 534 | GITERR_CHECK_ALLOC(cache->files); |
73b51450 RB |
535 | } |
536 | ||
95dfb031 | 537 | /* allocate hashtable for attribute macros */ |
73b51450 | 538 | if (cache->macros == NULL) { |
c2b67043 | 539 | cache->macros = git_strmap_alloc(); |
01fed0a8 | 540 | GITERR_CHECK_ALLOC(cache->macros); |
ee1f0b1a | 541 | } |
73b51450 | 542 | |
19fa2bc1 RB |
543 | /* allocate string pool */ |
544 | if (git_pool_init(&cache->pool, 1, 0) < 0) | |
545 | return -1; | |
546 | ||
73b51450 RB |
547 | cache->initialized = 1; |
548 | ||
549 | /* insert default macros */ | |
0d0fa7c3 | 550 | return git_attr_add_macro(repo, "binary", "-diff -crlf -text"); |
73b51450 RB |
551 | } |
552 | ||
73b51450 RB |
553 | void git_attr_cache_flush( |
554 | git_repository *repo) | |
555 | { | |
19fa2bc1 | 556 | git_attr_cache *cache; |
95dfb031 | 557 | |
73b51450 RB |
558 | if (!repo) |
559 | return; | |
560 | ||
19fa2bc1 | 561 | cache = git_repository_attr_cache(repo); |
73b51450 | 562 | |
19fa2bc1 RB |
563 | if (cache->files != NULL) { |
564 | git_attr_file *file; | |
01fed0a8 | 565 | |
c2b67043 | 566 | git_strmap_foreach_value(cache->files, file, { |
01fed0a8 RB |
567 | git_attr_file__free(file); |
568 | }); | |
569 | ||
c2b67043 | 570 | git_strmap_free(cache->files); |
73b51450 RB |
571 | } |
572 | ||
19fa2bc1 | 573 | if (cache->macros != NULL) { |
73b51450 RB |
574 | git_attr_rule *rule; |
575 | ||
c2b67043 | 576 | git_strmap_foreach_value(cache->macros, rule, { |
01fed0a8 RB |
577 | git_attr_rule__free(rule); |
578 | }); | |
579 | ||
c2b67043 | 580 | git_strmap_free(cache->macros); |
73b51450 RB |
581 | } |
582 | ||
19fa2bc1 RB |
583 | git_pool_clear(&cache->pool); |
584 | ||
585 | cache->initialized = 0; | |
ee1f0b1a | 586 | } |
df743c7d RB |
587 | |
588 | int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) | |
589 | { | |
c2b67043 | 590 | git_strmap *macros = git_repository_attr_cache(repo)->macros; |
01fed0a8 RB |
591 | int error; |
592 | ||
ab43ad2f | 593 | /* TODO: generate warning log if (macro->assigns.length == 0) */ |
df743c7d | 594 | if (macro->assigns.length == 0) |
ab43ad2f | 595 | return 0; |
df743c7d | 596 | |
c2b67043 | 597 | git_strmap_insert(macros, macro->match.pattern, macro, error); |
01fed0a8 | 598 | return (error < 0) ? -1 : 0; |
df743c7d | 599 | } |
01fed0a8 RB |
600 | |
601 | git_attr_rule *git_attr_cache__lookup_macro( | |
602 | git_repository *repo, const char *name) | |
603 | { | |
c2b67043 | 604 | git_strmap *macros = git_repository_attr_cache(repo)->macros; |
01fed0a8 RB |
605 | khiter_t pos; |
606 | ||
c2b67043 | 607 | pos = git_strmap_lookup_index(macros, name); |
01fed0a8 | 608 | |
c2b67043 | 609 | if (!git_strmap_valid_index(macros, pos)) |
01fed0a8 RB |
610 | return NULL; |
611 | ||
c2b67043 | 612 | return (git_attr_rule *)git_strmap_value_at(macros, pos); |
01fed0a8 RB |
613 | } |
614 |