Line | Count | Source (jump to first uncovered line) |
1 | | #define USE_THE_REPOSITORY_VARIABLE |
2 | | |
3 | | #include "git-compat-util.h" |
4 | | #include "tree-walk.h" |
5 | | #include "dir.h" |
6 | | #include "gettext.h" |
7 | | #include "hex.h" |
8 | | #include "object-file.h" |
9 | | #include "object-store-ll.h" |
10 | | #include "trace2.h" |
11 | | #include "tree.h" |
12 | | #include "pathspec.h" |
13 | | #include "json-writer.h" |
14 | | #include "environment.h" |
15 | | |
16 | | static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err) |
17 | 0 | { |
18 | 0 | const char *path; |
19 | 0 | unsigned int len; |
20 | 0 | uint16_t mode; |
21 | 0 | const unsigned hashsz = desc->algo->rawsz; |
22 | |
|
23 | 0 | if (size < hashsz + 3 || buf[size - (hashsz + 1)]) { |
24 | 0 | strbuf_addstr(err, _("too-short tree object")); |
25 | 0 | return -1; |
26 | 0 | } |
27 | | |
28 | 0 | path = parse_mode(buf, &mode); |
29 | 0 | if (!path) { |
30 | 0 | strbuf_addstr(err, _("malformed mode in tree entry")); |
31 | 0 | return -1; |
32 | 0 | } |
33 | 0 | if (!*path) { |
34 | 0 | strbuf_addstr(err, _("empty filename in tree entry")); |
35 | 0 | return -1; |
36 | 0 | } |
37 | 0 | len = strlen(path) + 1; |
38 | | |
39 | | /* Initialize the descriptor entry */ |
40 | 0 | desc->entry.path = path; |
41 | 0 | desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode); |
42 | 0 | desc->entry.pathlen = len - 1; |
43 | 0 | oidread(&desc->entry.oid, (const unsigned char *)path + len, |
44 | 0 | desc->algo); |
45 | |
|
46 | 0 | return 0; |
47 | 0 | } |
48 | | |
49 | | static int init_tree_desc_internal(struct tree_desc *desc, |
50 | | const struct object_id *oid, |
51 | | const void *buffer, unsigned long size, |
52 | | struct strbuf *err, |
53 | | enum tree_desc_flags flags) |
54 | 0 | { |
55 | 0 | desc->algo = (oid && oid->algo) ? &hash_algos[oid->algo] : the_hash_algo; |
56 | 0 | desc->buffer = buffer; |
57 | 0 | desc->size = size; |
58 | 0 | desc->flags = flags; |
59 | 0 | if (size) |
60 | 0 | return decode_tree_entry(desc, buffer, size, err); |
61 | 0 | return 0; |
62 | 0 | } |
63 | | |
64 | | void init_tree_desc(struct tree_desc *desc, const struct object_id *tree_oid, |
65 | | const void *buffer, unsigned long size) |
66 | 0 | { |
67 | 0 | struct strbuf err = STRBUF_INIT; |
68 | 0 | if (init_tree_desc_internal(desc, tree_oid, buffer, size, &err, 0)) |
69 | 0 | die("%s", err.buf); |
70 | 0 | strbuf_release(&err); |
71 | 0 | } |
72 | | |
73 | | int init_tree_desc_gently(struct tree_desc *desc, const struct object_id *oid, |
74 | | const void *buffer, unsigned long size, |
75 | | enum tree_desc_flags flags) |
76 | 0 | { |
77 | 0 | struct strbuf err = STRBUF_INIT; |
78 | 0 | int result = init_tree_desc_internal(desc, oid, buffer, size, &err, flags); |
79 | 0 | if (result) |
80 | 0 | error("%s", err.buf); |
81 | 0 | strbuf_release(&err); |
82 | 0 | return result; |
83 | 0 | } |
84 | | |
85 | | void *fill_tree_descriptor(struct repository *r, |
86 | | struct tree_desc *desc, |
87 | | const struct object_id *oid) |
88 | 0 | { |
89 | 0 | unsigned long size = 0; |
90 | 0 | void *buf = NULL; |
91 | |
|
92 | 0 | if (oid) { |
93 | 0 | buf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL); |
94 | 0 | if (!buf) |
95 | 0 | die(_("unable to read tree (%s)"), oid_to_hex(oid)); |
96 | 0 | } |
97 | 0 | init_tree_desc(desc, oid, buf, size); |
98 | 0 | return buf; |
99 | 0 | } |
100 | | |
101 | | static void entry_clear(struct name_entry *a) |
102 | 0 | { |
103 | 0 | memset(a, 0, sizeof(*a)); |
104 | 0 | } |
105 | | |
106 | | static void entry_extract(struct tree_desc *t, struct name_entry *a) |
107 | 0 | { |
108 | 0 | *a = t->entry; |
109 | 0 | } |
110 | | |
111 | | static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err) |
112 | 0 | { |
113 | 0 | const void *buf = desc->buffer; |
114 | 0 | const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + desc->algo->rawsz; |
115 | 0 | unsigned long size = desc->size; |
116 | 0 | unsigned long len = end - (const unsigned char *)buf; |
117 | |
|
118 | 0 | if (size < len) |
119 | 0 | die(_("too-short tree file")); |
120 | 0 | buf = end; |
121 | 0 | size -= len; |
122 | 0 | desc->buffer = buf; |
123 | 0 | desc->size = size; |
124 | 0 | if (size) |
125 | 0 | return decode_tree_entry(desc, buf, size, err); |
126 | 0 | return 0; |
127 | 0 | } |
128 | | |
129 | | void update_tree_entry(struct tree_desc *desc) |
130 | 0 | { |
131 | 0 | struct strbuf err = STRBUF_INIT; |
132 | 0 | if (update_tree_entry_internal(desc, &err)) |
133 | 0 | die("%s", err.buf); |
134 | 0 | strbuf_release(&err); |
135 | 0 | } |
136 | | |
137 | | int update_tree_entry_gently(struct tree_desc *desc) |
138 | 0 | { |
139 | 0 | struct strbuf err = STRBUF_INIT; |
140 | 0 | if (update_tree_entry_internal(desc, &err)) { |
141 | 0 | error("%s", err.buf); |
142 | 0 | strbuf_release(&err); |
143 | | /* Stop processing this tree after error */ |
144 | 0 | desc->size = 0; |
145 | 0 | return -1; |
146 | 0 | } |
147 | 0 | strbuf_release(&err); |
148 | 0 | return 0; |
149 | 0 | } |
150 | | |
151 | | int tree_entry(struct tree_desc *desc, struct name_entry *entry) |
152 | 0 | { |
153 | 0 | if (!desc->size) |
154 | 0 | return 0; |
155 | | |
156 | 0 | *entry = desc->entry; |
157 | 0 | update_tree_entry(desc); |
158 | 0 | return 1; |
159 | 0 | } |
160 | | |
161 | | int tree_entry_gently(struct tree_desc *desc, struct name_entry *entry) |
162 | 0 | { |
163 | 0 | if (!desc->size) |
164 | 0 | return 0; |
165 | | |
166 | 0 | *entry = desc->entry; |
167 | 0 | if (update_tree_entry_gently(desc)) |
168 | 0 | return 0; |
169 | 0 | return 1; |
170 | 0 | } |
171 | | |
172 | | static int traverse_trees_atexit_registered; |
173 | | static int traverse_trees_count; |
174 | | static int traverse_trees_cur_depth; |
175 | | static int traverse_trees_max_depth; |
176 | | |
177 | | static void trace2_traverse_trees_statistics_atexit(void) |
178 | 0 | { |
179 | 0 | struct json_writer jw = JSON_WRITER_INIT; |
180 | |
|
181 | 0 | jw_object_begin(&jw, 0); |
182 | 0 | jw_object_intmax(&jw, "traverse_trees_count", traverse_trees_count); |
183 | 0 | jw_object_intmax(&jw, "traverse_trees_max_depth", traverse_trees_max_depth); |
184 | 0 | jw_end(&jw); |
185 | |
|
186 | 0 | trace2_data_json("traverse_trees", the_repository, "statistics", &jw); |
187 | |
|
188 | 0 | jw_release(&jw); |
189 | 0 | } |
190 | | |
191 | | void setup_traverse_info(struct traverse_info *info, const char *base) |
192 | 0 | { |
193 | 0 | size_t pathlen = strlen(base); |
194 | 0 | static struct traverse_info dummy; |
195 | |
|
196 | 0 | memset(info, 0, sizeof(*info)); |
197 | 0 | if (pathlen && base[pathlen-1] == '/') |
198 | 0 | pathlen--; |
199 | 0 | info->pathlen = pathlen ? pathlen + 1 : 0; |
200 | 0 | info->name = base; |
201 | 0 | info->namelen = pathlen; |
202 | 0 | if (pathlen) |
203 | 0 | info->prev = &dummy; |
204 | |
|
205 | 0 | if (trace2_is_enabled() && !traverse_trees_atexit_registered) { |
206 | 0 | atexit(trace2_traverse_trees_statistics_atexit); |
207 | 0 | traverse_trees_atexit_registered = 1; |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | char *make_traverse_path(char *path, size_t pathlen, |
212 | | const struct traverse_info *info, |
213 | | const char *name, size_t namelen) |
214 | 0 | { |
215 | | /* Always points to the end of the name we're about to add */ |
216 | 0 | size_t pos = st_add(info->pathlen, namelen); |
217 | |
|
218 | 0 | if (pos >= pathlen) |
219 | 0 | BUG("too small buffer passed to make_traverse_path"); |
220 | | |
221 | 0 | path[pos] = 0; |
222 | 0 | for (;;) { |
223 | 0 | if (pos < namelen) |
224 | 0 | BUG("traverse_info pathlen does not match strings"); |
225 | 0 | pos -= namelen; |
226 | 0 | memcpy(path + pos, name, namelen); |
227 | |
|
228 | 0 | if (!pos) |
229 | 0 | break; |
230 | 0 | path[--pos] = '/'; |
231 | |
|
232 | 0 | if (!info) |
233 | 0 | BUG("traverse_info ran out of list items"); |
234 | 0 | name = info->name; |
235 | 0 | namelen = info->namelen; |
236 | 0 | info = info->prev; |
237 | 0 | } |
238 | 0 | return path; |
239 | 0 | } |
240 | | |
241 | | void strbuf_make_traverse_path(struct strbuf *out, |
242 | | const struct traverse_info *info, |
243 | | const char *name, size_t namelen) |
244 | 0 | { |
245 | 0 | size_t len = traverse_path_len(info, namelen); |
246 | |
|
247 | 0 | strbuf_grow(out, len); |
248 | 0 | make_traverse_path(out->buf + out->len, out->alloc - out->len, |
249 | 0 | info, name, namelen); |
250 | 0 | strbuf_setlen(out, out->len + len); |
251 | 0 | } |
252 | | |
253 | | struct tree_desc_skip { |
254 | | struct tree_desc_skip *prev; |
255 | | const void *ptr; |
256 | | }; |
257 | | |
258 | | struct tree_desc_x { |
259 | | struct tree_desc d; |
260 | | struct tree_desc_skip *skip; |
261 | | }; |
262 | | |
263 | | static int check_entry_match(const char *a, int a_len, const char *b, int b_len) |
264 | 0 | { |
265 | | /* |
266 | | * The caller wants to pick *a* from a tree or nothing. |
267 | | * We are looking at *b* in a tree. |
268 | | * |
269 | | * (0) If a and b are the same name, we are trivially happy. |
270 | | * |
271 | | * There are three possibilities where *a* could be hiding |
272 | | * behind *b*. |
273 | | * |
274 | | * (1) *a* == "t", *b* == "ab" i.e. *b* sorts earlier than *a* no |
275 | | * matter what. |
276 | | * (2) *a* == "t", *b* == "t-2" and "t" is a subtree in the tree; |
277 | | * (3) *a* == "t-2", *b* == "t" and "t-2" is a blob in the tree. |
278 | | * |
279 | | * Otherwise we know *a* won't appear in the tree without |
280 | | * scanning further. |
281 | | */ |
282 | |
|
283 | 0 | int cmp = name_compare(a, a_len, b, b_len); |
284 | | |
285 | | /* Most common case first -- reading sync'd trees */ |
286 | 0 | if (!cmp) |
287 | 0 | return cmp; |
288 | | |
289 | 0 | if (0 < cmp) { |
290 | | /* a comes after b; it does not matter if it is case (3) |
291 | | if (b_len < a_len && !memcmp(a, b, b_len) && a[b_len] < '/') |
292 | | return 1; |
293 | | */ |
294 | 0 | return 1; /* keep looking */ |
295 | 0 | } |
296 | | |
297 | | /* b comes after a; are we looking at case (2)? */ |
298 | 0 | if (a_len < b_len && !memcmp(a, b, a_len) && b[a_len] < '/') |
299 | 0 | return 1; /* keep looking */ |
300 | | |
301 | 0 | return -1; /* a cannot appear in the tree */ |
302 | 0 | } |
303 | | |
304 | | /* |
305 | | * From the extended tree_desc, extract the first name entry, while |
306 | | * paying attention to the candidate "first" name. Most importantly, |
307 | | * when looking for an entry, if there are entries that sorts earlier |
308 | | * in the tree object representation than that name, skip them and |
309 | | * process the named entry first. We will remember that we haven't |
310 | | * processed the first entry yet, and in the later call skip the |
311 | | * entry we processed early when update_extended_entry() is called. |
312 | | * |
313 | | * E.g. if the underlying tree object has these entries: |
314 | | * |
315 | | * blob "t-1" |
316 | | * blob "t-2" |
317 | | * tree "t" |
318 | | * blob "t=1" |
319 | | * |
320 | | * and the "first" asks for "t", remember that we still need to |
321 | | * process "t-1" and "t-2" but extract "t". After processing the |
322 | | * entry "t" from this call, the caller will let us know by calling |
323 | | * update_extended_entry() that we can remember "t" has been processed |
324 | | * already. |
325 | | */ |
326 | | |
327 | | static void extended_entry_extract(struct tree_desc_x *t, |
328 | | struct name_entry *a, |
329 | | const char *first, |
330 | | int first_len) |
331 | 0 | { |
332 | 0 | const char *path; |
333 | 0 | int len; |
334 | 0 | struct tree_desc probe; |
335 | 0 | struct tree_desc_skip *skip; |
336 | | |
337 | | /* |
338 | | * Extract the first entry from the tree_desc, but skip the |
339 | | * ones that we already returned in earlier rounds. |
340 | | */ |
341 | 0 | while (1) { |
342 | 0 | if (!t->d.size) { |
343 | 0 | entry_clear(a); |
344 | 0 | break; /* not found */ |
345 | 0 | } |
346 | 0 | entry_extract(&t->d, a); |
347 | 0 | for (skip = t->skip; skip; skip = skip->prev) |
348 | 0 | if (a->path == skip->ptr) |
349 | 0 | break; /* found */ |
350 | 0 | if (!skip) |
351 | 0 | break; |
352 | | /* We have processed this entry already. */ |
353 | 0 | update_tree_entry(&t->d); |
354 | 0 | } |
355 | |
|
356 | 0 | if (!first || !a->path) |
357 | 0 | return; |
358 | | |
359 | | /* |
360 | | * The caller wants "first" from this tree, or nothing. |
361 | | */ |
362 | 0 | path = a->path; |
363 | 0 | len = tree_entry_len(a); |
364 | 0 | switch (check_entry_match(first, first_len, path, len)) { |
365 | 0 | case -1: |
366 | 0 | entry_clear(a); |
367 | 0 | case 0: |
368 | 0 | return; |
369 | 0 | default: |
370 | 0 | break; |
371 | 0 | } |
372 | | |
373 | | /* |
374 | | * We need to look-ahead -- we suspect that a subtree whose |
375 | | * name is "first" may be hiding behind the current entry "path". |
376 | | */ |
377 | 0 | probe = t->d; |
378 | 0 | while (probe.size) { |
379 | 0 | entry_extract(&probe, a); |
380 | 0 | path = a->path; |
381 | 0 | len = tree_entry_len(a); |
382 | 0 | switch (check_entry_match(first, first_len, path, len)) { |
383 | 0 | case -1: |
384 | 0 | entry_clear(a); |
385 | 0 | case 0: |
386 | 0 | return; |
387 | 0 | default: |
388 | 0 | update_tree_entry(&probe); |
389 | 0 | break; |
390 | 0 | } |
391 | | /* keep looking */ |
392 | 0 | } |
393 | 0 | entry_clear(a); |
394 | 0 | } |
395 | | |
396 | | static void update_extended_entry(struct tree_desc_x *t, struct name_entry *a) |
397 | 0 | { |
398 | 0 | if (t->d.entry.path == a->path) { |
399 | 0 | update_tree_entry(&t->d); |
400 | 0 | } else { |
401 | | /* we have returned this entry early */ |
402 | 0 | struct tree_desc_skip *skip = xmalloc(sizeof(*skip)); |
403 | 0 | skip->ptr = a->path; |
404 | 0 | skip->prev = t->skip; |
405 | 0 | t->skip = skip; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | | static void free_extended_entry(struct tree_desc_x *t) |
410 | 0 | { |
411 | 0 | struct tree_desc_skip *p, *s; |
412 | |
|
413 | 0 | for (s = t->skip; s; s = p) { |
414 | 0 | p = s->prev; |
415 | 0 | free(s); |
416 | 0 | } |
417 | 0 | } |
418 | | |
419 | | static inline int prune_traversal(struct index_state *istate, |
420 | | struct name_entry *e, |
421 | | struct traverse_info *info, |
422 | | struct strbuf *base, |
423 | | int still_interesting) |
424 | 0 | { |
425 | 0 | if (!info->pathspec || still_interesting == 2) |
426 | 0 | return 2; |
427 | 0 | if (still_interesting < 0) |
428 | 0 | return still_interesting; |
429 | 0 | return tree_entry_interesting(istate, e, base, |
430 | 0 | info->pathspec); |
431 | 0 | } |
432 | | |
433 | | int traverse_trees(struct index_state *istate, |
434 | | int n, struct tree_desc *t, |
435 | | struct traverse_info *info) |
436 | 0 | { |
437 | 0 | int ret = 0; |
438 | 0 | struct name_entry *entry; |
439 | 0 | int i; |
440 | 0 | struct tree_desc_x *tx; |
441 | 0 | struct strbuf base = STRBUF_INIT; |
442 | 0 | int interesting = 1; |
443 | 0 | char *traverse_path; |
444 | |
|
445 | 0 | if (traverse_trees_cur_depth > max_allowed_tree_depth) |
446 | 0 | return error("exceeded maximum allowed tree depth"); |
447 | | |
448 | 0 | traverse_trees_count++; |
449 | 0 | traverse_trees_cur_depth++; |
450 | |
|
451 | 0 | if (traverse_trees_cur_depth > traverse_trees_max_depth) |
452 | 0 | traverse_trees_max_depth = traverse_trees_cur_depth; |
453 | |
|
454 | 0 | ALLOC_ARRAY(entry, n); |
455 | 0 | ALLOC_ARRAY(tx, n); |
456 | |
|
457 | 0 | for (i = 0; i < n; i++) { |
458 | 0 | tx[i].d = t[i]; |
459 | 0 | tx[i].skip = NULL; |
460 | 0 | } |
461 | |
|
462 | 0 | if (info->prev) { |
463 | 0 | strbuf_make_traverse_path(&base, info->prev, |
464 | 0 | info->name, info->namelen); |
465 | 0 | strbuf_addch(&base, '/'); |
466 | 0 | traverse_path = xstrndup(base.buf, base.len); |
467 | 0 | } else { |
468 | 0 | traverse_path = xstrndup(info->name, info->pathlen); |
469 | 0 | } |
470 | 0 | info->traverse_path = traverse_path; |
471 | 0 | for (;;) { |
472 | 0 | int trees_used; |
473 | 0 | unsigned long mask, dirmask; |
474 | 0 | const char *first = NULL; |
475 | 0 | int first_len = 0; |
476 | 0 | struct name_entry *e = NULL; |
477 | 0 | int len; |
478 | |
|
479 | 0 | for (i = 0; i < n; i++) { |
480 | 0 | e = entry + i; |
481 | 0 | extended_entry_extract(tx + i, e, NULL, 0); |
482 | 0 | } |
483 | | |
484 | | /* |
485 | | * A tree may have "t-2" at the current location even |
486 | | * though it may have "t" that is a subtree behind it, |
487 | | * and another tree may return "t". We want to grab |
488 | | * all "t" from all trees to match in such a case. |
489 | | */ |
490 | 0 | for (i = 0; i < n; i++) { |
491 | 0 | e = entry + i; |
492 | 0 | if (!e->path) |
493 | 0 | continue; |
494 | 0 | len = tree_entry_len(e); |
495 | 0 | if (!first) { |
496 | 0 | first = e->path; |
497 | 0 | first_len = len; |
498 | 0 | continue; |
499 | 0 | } |
500 | 0 | if (name_compare(e->path, len, first, first_len) < 0) { |
501 | 0 | first = e->path; |
502 | 0 | first_len = len; |
503 | 0 | } |
504 | 0 | } |
505 | |
|
506 | 0 | if (first) { |
507 | 0 | for (i = 0; i < n; i++) { |
508 | 0 | e = entry + i; |
509 | 0 | extended_entry_extract(tx + i, e, first, first_len); |
510 | | /* Cull the ones that are not the earliest */ |
511 | 0 | if (!e->path) |
512 | 0 | continue; |
513 | 0 | len = tree_entry_len(e); |
514 | 0 | if (name_compare(e->path, len, first, first_len)) |
515 | 0 | entry_clear(e); |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | | /* Now we have in entry[i] the earliest name from the trees */ |
520 | 0 | mask = 0; |
521 | 0 | dirmask = 0; |
522 | 0 | for (i = 0; i < n; i++) { |
523 | 0 | if (!entry[i].path) |
524 | 0 | continue; |
525 | 0 | mask |= 1ul << i; |
526 | 0 | if (S_ISDIR(entry[i].mode)) |
527 | 0 | dirmask |= 1ul << i; |
528 | 0 | e = &entry[i]; |
529 | 0 | } |
530 | 0 | if (!mask) |
531 | 0 | break; |
532 | 0 | interesting = prune_traversal(istate, e, info, &base, interesting); |
533 | 0 | if (interesting < 0) |
534 | 0 | break; |
535 | 0 | if (interesting) { |
536 | 0 | trees_used = info->fn(n, mask, dirmask, entry, info); |
537 | 0 | if (trees_used < 0) { |
538 | 0 | ret = trees_used; |
539 | 0 | if (!info->show_all_errors) |
540 | 0 | break; |
541 | 0 | } |
542 | 0 | mask &= trees_used; |
543 | 0 | } |
544 | 0 | for (i = 0; i < n; i++) |
545 | 0 | if (mask & (1ul << i)) |
546 | 0 | update_extended_entry(tx + i, entry + i); |
547 | 0 | } |
548 | 0 | for (i = 0; i < n; i++) |
549 | 0 | free_extended_entry(tx + i); |
550 | 0 | free(tx); |
551 | 0 | free(entry); |
552 | 0 | free(traverse_path); |
553 | 0 | info->traverse_path = NULL; |
554 | 0 | strbuf_release(&base); |
555 | |
|
556 | 0 | traverse_trees_cur_depth--; |
557 | 0 | return ret; |
558 | 0 | } |
559 | | |
560 | | struct dir_state { |
561 | | void *tree; |
562 | | unsigned long size; |
563 | | struct object_id oid; |
564 | | }; |
565 | | |
566 | | static int find_tree_entry(struct repository *r, struct tree_desc *t, |
567 | | const char *name, struct object_id *result, |
568 | | unsigned short *mode) |
569 | 0 | { |
570 | 0 | int namelen = strlen(name); |
571 | 0 | while (t->size) { |
572 | 0 | const char *entry; |
573 | 0 | struct object_id oid; |
574 | 0 | int entrylen, cmp; |
575 | |
|
576 | 0 | oidcpy(&oid, tree_entry_extract(t, &entry, mode)); |
577 | 0 | entrylen = tree_entry_len(&t->entry); |
578 | 0 | update_tree_entry(t); |
579 | 0 | if (entrylen > namelen) |
580 | 0 | continue; |
581 | 0 | cmp = memcmp(name, entry, entrylen); |
582 | 0 | if (cmp > 0) |
583 | 0 | continue; |
584 | 0 | if (cmp < 0) |
585 | 0 | break; |
586 | 0 | if (entrylen == namelen) { |
587 | 0 | oidcpy(result, &oid); |
588 | 0 | return 0; |
589 | 0 | } |
590 | 0 | if (name[entrylen] != '/') |
591 | 0 | continue; |
592 | 0 | if (!S_ISDIR(*mode)) |
593 | 0 | break; |
594 | 0 | if (++entrylen == namelen) { |
595 | 0 | oidcpy(result, &oid); |
596 | 0 | return 0; |
597 | 0 | } |
598 | 0 | return get_tree_entry(r, &oid, name + entrylen, result, mode); |
599 | 0 | } |
600 | 0 | return -1; |
601 | 0 | } |
602 | | |
603 | | int get_tree_entry(struct repository *r, |
604 | | const struct object_id *tree_oid, |
605 | | const char *name, |
606 | | struct object_id *oid, |
607 | | unsigned short *mode) |
608 | 0 | { |
609 | 0 | int retval; |
610 | 0 | void *tree; |
611 | 0 | unsigned long size; |
612 | 0 | struct object_id root; |
613 | |
|
614 | 0 | tree = read_object_with_reference(r, tree_oid, OBJ_TREE, &size, &root); |
615 | 0 | if (!tree) |
616 | 0 | return -1; |
617 | | |
618 | 0 | if (name[0] == '\0') { |
619 | 0 | oidcpy(oid, &root); |
620 | 0 | free(tree); |
621 | 0 | return 0; |
622 | 0 | } |
623 | | |
624 | 0 | if (!size) { |
625 | 0 | retval = -1; |
626 | 0 | } else { |
627 | 0 | struct tree_desc t; |
628 | 0 | init_tree_desc(&t, tree_oid, tree, size); |
629 | 0 | retval = find_tree_entry(r, &t, name, oid, mode); |
630 | 0 | } |
631 | 0 | free(tree); |
632 | 0 | return retval; |
633 | 0 | } |
634 | | |
635 | | /* |
636 | | * This is Linux's built-in max for the number of symlinks to follow. |
637 | | * That limit, of course, does not affect git, but it's a reasonable |
638 | | * choice. |
639 | | */ |
640 | 0 | #define GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS 40 |
641 | | |
642 | | /** |
643 | | * Find a tree entry by following symlinks in tree_sha (which is |
644 | | * assumed to be the root of the repository). In the event that a |
645 | | * symlink points outside the repository (e.g. a link to /foo or a |
646 | | * root-level link to ../foo), the portion of the link which is |
647 | | * outside the repository will be returned in result_path, and *mode |
648 | | * will be set to 0. It is assumed that result_path is uninitialized. |
649 | | * If there are no symlinks, or the end result of the symlink chain |
650 | | * points to an object inside the repository, result will be filled in |
651 | | * with the sha1 of the found object, and *mode will hold the mode of |
652 | | * the object. |
653 | | * |
654 | | * See the code for enum get_oid_result for a description of |
655 | | * the return values. |
656 | | */ |
657 | | enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, |
658 | | struct object_id *tree_oid, const char *name, |
659 | | struct object_id *result, struct strbuf *result_path, |
660 | | unsigned short *mode) |
661 | 0 | { |
662 | 0 | int retval = MISSING_OBJECT; |
663 | 0 | struct dir_state *parents = NULL; |
664 | 0 | size_t parents_alloc = 0; |
665 | 0 | size_t i, parents_nr = 0; |
666 | 0 | struct object_id current_tree_oid; |
667 | 0 | struct strbuf namebuf = STRBUF_INIT; |
668 | 0 | struct tree_desc t; |
669 | 0 | int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS; |
670 | |
|
671 | 0 | init_tree_desc(&t, NULL, NULL, 0UL); |
672 | 0 | strbuf_addstr(&namebuf, name); |
673 | 0 | oidcpy(¤t_tree_oid, tree_oid); |
674 | |
|
675 | 0 | while (1) { |
676 | 0 | int find_result; |
677 | 0 | char *first_slash; |
678 | 0 | char *remainder = NULL; |
679 | |
|
680 | 0 | if (!t.buffer) { |
681 | 0 | void *tree; |
682 | 0 | struct object_id root; |
683 | 0 | unsigned long size; |
684 | 0 | tree = read_object_with_reference(r, |
685 | 0 | ¤t_tree_oid, |
686 | 0 | OBJ_TREE, &size, |
687 | 0 | &root); |
688 | 0 | if (!tree) |
689 | 0 | goto done; |
690 | | |
691 | 0 | ALLOC_GROW(parents, parents_nr + 1, parents_alloc); |
692 | 0 | parents[parents_nr].tree = tree; |
693 | 0 | parents[parents_nr].size = size; |
694 | 0 | oidcpy(&parents[parents_nr].oid, &root); |
695 | 0 | parents_nr++; |
696 | |
|
697 | 0 | if (namebuf.buf[0] == '\0') { |
698 | 0 | oidcpy(result, &root); |
699 | 0 | retval = FOUND; |
700 | 0 | goto done; |
701 | 0 | } |
702 | | |
703 | 0 | if (!size) |
704 | 0 | goto done; |
705 | | |
706 | | /* descend */ |
707 | 0 | init_tree_desc(&t, ¤t_tree_oid, tree, size); |
708 | 0 | } |
709 | | |
710 | | /* Handle symlinks to e.g. a//b by removing leading slashes */ |
711 | 0 | while (namebuf.buf[0] == '/') { |
712 | 0 | strbuf_remove(&namebuf, 0, 1); |
713 | 0 | } |
714 | | |
715 | | /* Split namebuf into a first component and a remainder */ |
716 | 0 | if ((first_slash = strchr(namebuf.buf, '/'))) { |
717 | 0 | *first_slash = 0; |
718 | 0 | remainder = first_slash + 1; |
719 | 0 | } |
720 | |
|
721 | 0 | if (!strcmp(namebuf.buf, "..")) { |
722 | 0 | struct dir_state *parent; |
723 | | /* |
724 | | * We could end up with .. in the namebuf if it |
725 | | * appears in a symlink. |
726 | | */ |
727 | |
|
728 | 0 | if (parents_nr == 1) { |
729 | 0 | if (remainder) |
730 | 0 | *first_slash = '/'; |
731 | 0 | strbuf_add(result_path, namebuf.buf, |
732 | 0 | namebuf.len); |
733 | 0 | *mode = 0; |
734 | 0 | retval = FOUND; |
735 | 0 | goto done; |
736 | 0 | } |
737 | 0 | parent = &parents[parents_nr - 1]; |
738 | 0 | free(parent->tree); |
739 | 0 | parents_nr--; |
740 | 0 | parent = &parents[parents_nr - 1]; |
741 | 0 | init_tree_desc(&t, &parent->oid, parent->tree, parent->size); |
742 | 0 | strbuf_remove(&namebuf, 0, remainder ? 3 : 2); |
743 | 0 | continue; |
744 | 0 | } |
745 | | |
746 | | /* We could end up here via a symlink to dir/.. */ |
747 | 0 | if (namebuf.buf[0] == '\0') { |
748 | 0 | oidcpy(result, &parents[parents_nr - 1].oid); |
749 | 0 | retval = FOUND; |
750 | 0 | goto done; |
751 | 0 | } |
752 | | |
753 | | /* Look up the first (or only) path component in the tree. */ |
754 | 0 | find_result = find_tree_entry(r, &t, namebuf.buf, |
755 | 0 | ¤t_tree_oid, mode); |
756 | 0 | if (find_result) { |
757 | 0 | goto done; |
758 | 0 | } |
759 | | |
760 | 0 | if (S_ISDIR(*mode)) { |
761 | 0 | if (!remainder) { |
762 | 0 | oidcpy(result, ¤t_tree_oid); |
763 | 0 | retval = FOUND; |
764 | 0 | goto done; |
765 | 0 | } |
766 | | /* Descend the tree */ |
767 | 0 | t.buffer = NULL; |
768 | 0 | strbuf_remove(&namebuf, 0, |
769 | 0 | 1 + first_slash - namebuf.buf); |
770 | 0 | } else if (S_ISREG(*mode)) { |
771 | 0 | if (!remainder) { |
772 | 0 | oidcpy(result, ¤t_tree_oid); |
773 | 0 | retval = FOUND; |
774 | 0 | } else { |
775 | 0 | retval = NOT_DIR; |
776 | 0 | } |
777 | 0 | goto done; |
778 | 0 | } else if (S_ISLNK(*mode)) { |
779 | | /* Follow a symlink */ |
780 | 0 | unsigned long link_len; |
781 | 0 | size_t len; |
782 | 0 | char *contents, *contents_start; |
783 | 0 | struct dir_state *parent; |
784 | 0 | enum object_type type; |
785 | |
|
786 | 0 | if (follows_remaining-- == 0) { |
787 | | /* Too many symlinks followed */ |
788 | 0 | retval = SYMLINK_LOOP; |
789 | 0 | goto done; |
790 | 0 | } |
791 | | |
792 | | /* |
793 | | * At this point, we have followed at a least |
794 | | * one symlink, so on error we need to report this. |
795 | | */ |
796 | 0 | retval = DANGLING_SYMLINK; |
797 | |
|
798 | 0 | contents = repo_read_object_file(r, |
799 | 0 | ¤t_tree_oid, &type, |
800 | 0 | &link_len); |
801 | |
|
802 | 0 | if (!contents) |
803 | 0 | goto done; |
804 | | |
805 | 0 | if (contents[0] == '/') { |
806 | 0 | strbuf_addstr(result_path, contents); |
807 | 0 | free(contents); |
808 | 0 | *mode = 0; |
809 | 0 | retval = FOUND; |
810 | 0 | goto done; |
811 | 0 | } |
812 | | |
813 | 0 | if (remainder) |
814 | 0 | len = first_slash - namebuf.buf; |
815 | 0 | else |
816 | 0 | len = namebuf.len; |
817 | |
|
818 | 0 | contents_start = contents; |
819 | |
|
820 | 0 | parent = &parents[parents_nr - 1]; |
821 | 0 | init_tree_desc(&t, &parent->oid, parent->tree, parent->size); |
822 | 0 | strbuf_splice(&namebuf, 0, len, |
823 | 0 | contents_start, link_len); |
824 | 0 | if (remainder) |
825 | 0 | namebuf.buf[link_len] = '/'; |
826 | 0 | free(contents); |
827 | 0 | } |
828 | 0 | } |
829 | 0 | done: |
830 | 0 | for (i = 0; i < parents_nr; i++) |
831 | 0 | free(parents[i].tree); |
832 | 0 | free(parents); |
833 | |
|
834 | 0 | strbuf_release(&namebuf); |
835 | 0 | return retval; |
836 | 0 | } |
837 | | |
838 | | static int match_entry(const struct pathspec_item *item, |
839 | | const struct name_entry *entry, int pathlen, |
840 | | const char *match, int matchlen, |
841 | | enum interesting *never_interesting) |
842 | 0 | { |
843 | 0 | int m = -1; /* signals that we haven't called strncmp() */ |
844 | |
|
845 | 0 | if (item->magic & PATHSPEC_ICASE) |
846 | | /* |
847 | | * "Never interesting" trick requires exact |
848 | | * matching. We could do something clever with inexact |
849 | | * matching, but it's trickier (and not to forget that |
850 | | * strcasecmp is locale-dependent, at least in |
851 | | * glibc). Just disable it for now. It can't be worse |
852 | | * than the wildcard's codepath of '[Tt][Hi][Is][Ss]' |
853 | | * pattern. |
854 | | */ |
855 | 0 | *never_interesting = entry_not_interesting; |
856 | 0 | else if (*never_interesting != entry_not_interesting) { |
857 | | /* |
858 | | * We have not seen any match that sorts later |
859 | | * than the current path. |
860 | | */ |
861 | | |
862 | | /* |
863 | | * Does match sort strictly earlier than path |
864 | | * with their common parts? |
865 | | */ |
866 | 0 | m = strncmp(match, entry->path, |
867 | 0 | (matchlen < pathlen) ? matchlen : pathlen); |
868 | 0 | if (m < 0) |
869 | 0 | return 0; |
870 | | |
871 | | /* |
872 | | * If we come here even once, that means there is at |
873 | | * least one pathspec that would sort equal to or |
874 | | * later than the path we are currently looking at. |
875 | | * In other words, if we have never reached this point |
876 | | * after iterating all pathspecs, it means all |
877 | | * pathspecs are either outside of base, or inside the |
878 | | * base but sorts strictly earlier than the current |
879 | | * one. In either case, they will never match the |
880 | | * subsequent entries. In such a case, we initialized |
881 | | * the variable to -1 and that is what will be |
882 | | * returned, allowing the caller to terminate early. |
883 | | */ |
884 | 0 | *never_interesting = entry_not_interesting; |
885 | 0 | } |
886 | | |
887 | 0 | if (pathlen > matchlen) |
888 | 0 | return 0; |
889 | | |
890 | 0 | if (matchlen > pathlen) { |
891 | 0 | if (match[pathlen] != '/') |
892 | 0 | return 0; |
893 | | /* |
894 | | * Reject non-directories as partial pathnames, except |
895 | | * when match is a submodule with a trailing slash and |
896 | | * nothing else (to handle 'submod/' and 'submod' |
897 | | * uniformly). |
898 | | */ |
899 | 0 | if (!S_ISDIR(entry->mode) && |
900 | 0 | (!S_ISGITLINK(entry->mode) || matchlen > pathlen + 1)) |
901 | 0 | return 0; |
902 | 0 | } |
903 | | |
904 | 0 | if (m == -1) |
905 | | /* |
906 | | * we cheated and did not do strncmp(), so we do |
907 | | * that here. |
908 | | */ |
909 | 0 | m = ps_strncmp(item, match, entry->path, pathlen); |
910 | | |
911 | | /* |
912 | | * If common part matched earlier then it is a hit, |
913 | | * because we rejected the case where path is not a |
914 | | * leading directory and is shorter than match. |
915 | | */ |
916 | 0 | if (!m) |
917 | | /* |
918 | | * match_entry does not check if the prefix part is |
919 | | * matched case-sensitively. If the entry is a |
920 | | * directory and part of prefix, it'll be rematched |
921 | | * eventually by basecmp with special treatment for |
922 | | * the prefix. |
923 | | */ |
924 | 0 | return 1; |
925 | | |
926 | 0 | return 0; |
927 | 0 | } |
928 | | |
929 | | /* :(icase)-aware string compare */ |
930 | | static int basecmp(const struct pathspec_item *item, |
931 | | const char *base, const char *match, int len) |
932 | 0 | { |
933 | 0 | if (item->magic & PATHSPEC_ICASE) { |
934 | 0 | int ret, n = len > item->prefix ? item->prefix : len; |
935 | 0 | ret = strncmp(base, match, n); |
936 | 0 | if (ret) |
937 | 0 | return ret; |
938 | 0 | base += n; |
939 | 0 | match += n; |
940 | 0 | len -= n; |
941 | 0 | } |
942 | 0 | return ps_strncmp(item, base, match, len); |
943 | 0 | } |
944 | | |
945 | | static int match_dir_prefix(const struct pathspec_item *item, |
946 | | const char *base, |
947 | | const char *match, int matchlen) |
948 | 0 | { |
949 | 0 | if (basecmp(item, base, match, matchlen)) |
950 | 0 | return 0; |
951 | | |
952 | | /* |
953 | | * If the base is a subdirectory of a path which |
954 | | * was specified, all of them are interesting. |
955 | | */ |
956 | 0 | if (!matchlen || |
957 | 0 | base[matchlen] == '/' || |
958 | 0 | match[matchlen - 1] == '/') |
959 | 0 | return 1; |
960 | | |
961 | | /* Just a random prefix match */ |
962 | 0 | return 0; |
963 | 0 | } |
964 | | |
965 | | /* |
966 | | * Perform matching on the leading non-wildcard part of |
967 | | * pathspec. item->nowildcard_len must be greater than zero. Return |
968 | | * non-zero if base is matched. |
969 | | */ |
970 | | static int match_wildcard_base(const struct pathspec_item *item, |
971 | | const char *base, int baselen, |
972 | | int *matched) |
973 | 0 | { |
974 | 0 | const char *match = item->match; |
975 | | /* the wildcard part is not considered in this function */ |
976 | 0 | int matchlen = item->nowildcard_len; |
977 | |
|
978 | 0 | if (baselen) { |
979 | 0 | int dirlen; |
980 | | /* |
981 | | * Return early if base is longer than the |
982 | | * non-wildcard part but it does not match. |
983 | | */ |
984 | 0 | if (baselen >= matchlen) { |
985 | 0 | *matched = matchlen; |
986 | 0 | return !basecmp(item, base, match, matchlen); |
987 | 0 | } |
988 | | |
989 | 0 | dirlen = matchlen; |
990 | 0 | while (dirlen && match[dirlen - 1] != '/') |
991 | 0 | dirlen--; |
992 | | |
993 | | /* |
994 | | * Return early if base is shorter than the |
995 | | * non-wildcard part but it does not match. Note that |
996 | | * base ends with '/' so we are sure it really matches |
997 | | * directory |
998 | | */ |
999 | 0 | if (basecmp(item, base, match, baselen)) |
1000 | 0 | return 0; |
1001 | 0 | *matched = baselen; |
1002 | 0 | } else |
1003 | 0 | *matched = 0; |
1004 | | /* |
1005 | | * we could have checked entry against the non-wildcard part |
1006 | | * that is not in base and does similar never_interesting |
1007 | | * optimization as in match_entry. For now just be happy with |
1008 | | * base comparison. |
1009 | | */ |
1010 | 0 | return entry_interesting; |
1011 | 0 | } |
1012 | | |
1013 | | /* |
1014 | | * Is a tree entry interesting given the pathspec we have? |
1015 | | * |
1016 | | * Pre-condition: either baselen == 0 (i.e. empty path) |
1017 | | * or base[baselen-1] == '/' (i.e. with trailing slash). |
1018 | | */ |
1019 | | static enum interesting do_match(struct index_state *istate, |
1020 | | const struct name_entry *entry, |
1021 | | struct strbuf *base, |
1022 | | const struct pathspec *ps, |
1023 | | int exclude) |
1024 | 0 | { |
1025 | 0 | int i; |
1026 | 0 | int pathlen, baselen = base->len; |
1027 | 0 | enum interesting never_interesting = ps->has_wildcard ? |
1028 | 0 | entry_not_interesting : all_entries_not_interesting; |
1029 | |
|
1030 | 0 | GUARD_PATHSPEC(ps, |
1031 | 0 | PATHSPEC_FROMTOP | |
1032 | 0 | PATHSPEC_MAXDEPTH | |
1033 | 0 | PATHSPEC_LITERAL | |
1034 | 0 | PATHSPEC_GLOB | |
1035 | 0 | PATHSPEC_ICASE | |
1036 | 0 | PATHSPEC_EXCLUDE | |
1037 | 0 | PATHSPEC_ATTR); |
1038 | | |
1039 | 0 | if (!ps->nr) { |
1040 | 0 | if (!ps->recursive || |
1041 | 0 | !(ps->magic & PATHSPEC_MAXDEPTH) || |
1042 | 0 | ps->max_depth == -1) |
1043 | 0 | return all_entries_interesting; |
1044 | 0 | return within_depth(base->buf, baselen, |
1045 | 0 | !!S_ISDIR(entry->mode), |
1046 | 0 | ps->max_depth) ? |
1047 | 0 | entry_interesting : entry_not_interesting; |
1048 | 0 | } |
1049 | | |
1050 | 0 | pathlen = tree_entry_len(entry); |
1051 | |
|
1052 | 0 | for (i = ps->nr - 1; i >= 0; i--) { |
1053 | 0 | const struct pathspec_item *item = ps->items+i; |
1054 | 0 | const char *match = item->match; |
1055 | 0 | const char *base_str = base->buf; |
1056 | 0 | int matchlen = item->len, matched = 0; |
1057 | |
|
1058 | 0 | if ((!exclude && item->magic & PATHSPEC_EXCLUDE) || |
1059 | 0 | ( exclude && !(item->magic & PATHSPEC_EXCLUDE))) |
1060 | 0 | continue; |
1061 | | |
1062 | 0 | if (baselen >= matchlen) { |
1063 | | /* If it doesn't match, move along... */ |
1064 | 0 | if (!match_dir_prefix(item, base_str, match, matchlen)) |
1065 | 0 | goto match_wildcards; |
1066 | | |
1067 | 0 | if (!ps->recursive || |
1068 | 0 | !(ps->magic & PATHSPEC_MAXDEPTH) || |
1069 | 0 | ps->max_depth == -1) { |
1070 | 0 | if (!item->attr_match_nr) |
1071 | 0 | return all_entries_interesting; |
1072 | 0 | else |
1073 | 0 | goto interesting; |
1074 | 0 | } |
1075 | | |
1076 | 0 | if (within_depth(base_str + matchlen + 1, |
1077 | 0 | baselen - matchlen - 1, |
1078 | 0 | !!S_ISDIR(entry->mode), |
1079 | 0 | ps->max_depth)) |
1080 | 0 | goto interesting; |
1081 | 0 | else |
1082 | 0 | return entry_not_interesting; |
1083 | 0 | } |
1084 | | |
1085 | | /* Either there must be no base, or the base must match. */ |
1086 | 0 | if (baselen == 0 || !basecmp(item, base_str, match, baselen)) { |
1087 | 0 | if (match_entry(item, entry, pathlen, |
1088 | 0 | match + baselen, matchlen - baselen, |
1089 | 0 | &never_interesting)) |
1090 | 0 | goto interesting; |
1091 | | |
1092 | 0 | if (item->nowildcard_len < item->len) { |
1093 | 0 | if (!git_fnmatch(item, match + baselen, entry->path, |
1094 | 0 | item->nowildcard_len - baselen)) |
1095 | 0 | goto interesting; |
1096 | | |
1097 | | /* |
1098 | | * Match all directories. We'll try to |
1099 | | * match files later on. |
1100 | | */ |
1101 | 0 | if (ps->recursive && S_ISDIR(entry->mode)) |
1102 | 0 | return entry_interesting; |
1103 | | |
1104 | | /* |
1105 | | * When matching against submodules with |
1106 | | * wildcard characters, ensure that the entry |
1107 | | * at least matches up to the first wild |
1108 | | * character. More accurate matching can then |
1109 | | * be performed in the submodule itself. |
1110 | | */ |
1111 | 0 | if (ps->recurse_submodules && |
1112 | 0 | S_ISGITLINK(entry->mode) && |
1113 | 0 | !ps_strncmp(item, match + baselen, |
1114 | 0 | entry->path, |
1115 | 0 | item->nowildcard_len - baselen)) |
1116 | 0 | goto interesting; |
1117 | 0 | } |
1118 | | |
1119 | 0 | continue; |
1120 | 0 | } |
1121 | | |
1122 | 0 | match_wildcards: |
1123 | 0 | if (item->nowildcard_len == item->len) |
1124 | 0 | continue; |
1125 | | |
1126 | 0 | if (item->nowildcard_len && |
1127 | 0 | !match_wildcard_base(item, base_str, baselen, &matched)) |
1128 | 0 | continue; |
1129 | | |
1130 | | /* |
1131 | | * Concatenate base and entry->path into one and do |
1132 | | * fnmatch() on it. |
1133 | | * |
1134 | | * While we could avoid concatenation in certain cases |
1135 | | * [1], which saves a memcpy and potentially a |
1136 | | * realloc, it turns out not worth it. Measurement on |
1137 | | * linux-2.6 does not show any clear improvements, |
1138 | | * partly because of the nowildcard_len optimization |
1139 | | * in git_fnmatch(). Avoid micro-optimizations here. |
1140 | | * |
1141 | | * [1] if match_wildcard_base() says the base |
1142 | | * directory is already matched, we only need to match |
1143 | | * the rest, which is shorter so _in theory_ faster. |
1144 | | */ |
1145 | | |
1146 | 0 | strbuf_add(base, entry->path, pathlen); |
1147 | |
|
1148 | 0 | if (!git_fnmatch(item, match, base->buf, |
1149 | 0 | item->nowildcard_len)) { |
1150 | 0 | strbuf_setlen(base, baselen); |
1151 | 0 | goto interesting; |
1152 | 0 | } |
1153 | | |
1154 | | /* |
1155 | | * When matching against submodules with |
1156 | | * wildcard characters, ensure that the entry |
1157 | | * at least matches up to the first wild |
1158 | | * character. More accurate matching can then |
1159 | | * be performed in the submodule itself. |
1160 | | */ |
1161 | 0 | if (ps->recurse_submodules && S_ISGITLINK(entry->mode) && |
1162 | 0 | !ps_strncmp(item, match, base->buf, |
1163 | 0 | item->nowildcard_len)) { |
1164 | 0 | strbuf_setlen(base, baselen); |
1165 | 0 | goto interesting; |
1166 | 0 | } |
1167 | | |
1168 | 0 | strbuf_setlen(base, baselen); |
1169 | | |
1170 | | /* |
1171 | | * Match all directories. We'll try to match files |
1172 | | * later on. |
1173 | | * max_depth is ignored but we may consider support it |
1174 | | * in future, see |
1175 | | * https://lore.kernel.org/git/7vmxo5l2g4.fsf@alter.siamese.dyndns.org/ |
1176 | | */ |
1177 | 0 | if (ps->recursive && S_ISDIR(entry->mode)) |
1178 | 0 | return entry_interesting; |
1179 | 0 | continue; |
1180 | 0 | interesting: |
1181 | 0 | if (item->attr_match_nr) { |
1182 | 0 | int ret; |
1183 | | |
1184 | | /* |
1185 | | * Must not return all_entries_not_interesting |
1186 | | * prematurely. We do not know if all entries do not |
1187 | | * match some attributes with current attr API. |
1188 | | */ |
1189 | 0 | never_interesting = entry_not_interesting; |
1190 | | |
1191 | | /* |
1192 | | * Consider all directories interesting (because some |
1193 | | * of those files inside may match some attributes |
1194 | | * even though the parent dir does not) |
1195 | | * |
1196 | | * FIXME: attributes _can_ match directories and we |
1197 | | * can probably return all_entries_interesting or |
1198 | | * all_entries_not_interesting here if matched. |
1199 | | */ |
1200 | 0 | if (S_ISDIR(entry->mode)) |
1201 | 0 | return entry_interesting; |
1202 | | |
1203 | 0 | strbuf_add(base, entry->path, pathlen); |
1204 | 0 | ret = match_pathspec_attrs(istate, base->buf, |
1205 | 0 | base->len, item); |
1206 | 0 | strbuf_setlen(base, baselen); |
1207 | 0 | if (!ret) |
1208 | 0 | continue; |
1209 | 0 | } |
1210 | 0 | return entry_interesting; |
1211 | 0 | } |
1212 | 0 | return never_interesting; /* No matches */ |
1213 | 0 | } |
1214 | | |
1215 | | /* |
1216 | | * Is a tree entry interesting given the pathspec we have? |
1217 | | * |
1218 | | * Pre-condition: either baselen == 0 (i.e. empty path) |
1219 | | * or base[baselen-1] == '/' (i.e. with trailing slash). |
1220 | | */ |
1221 | | enum interesting tree_entry_interesting(struct index_state *istate, |
1222 | | const struct name_entry *entry, |
1223 | | struct strbuf *base, |
1224 | | const struct pathspec *ps) |
1225 | 0 | { |
1226 | 0 | enum interesting positive, negative; |
1227 | 0 | positive = do_match(istate, entry, base, ps, 0); |
1228 | | |
1229 | | /* |
1230 | | * case | entry | positive | negative | result |
1231 | | * -----+-------+----------+----------+------- |
1232 | | * 1 | file | -1 | -1..2 | -1 |
1233 | | * 2 | file | 0 | -1..2 | 0 |
1234 | | * 3 | file | 1 | -1 | 1 |
1235 | | * 4 | file | 1 | 0 | 1 |
1236 | | * 5 | file | 1 | 1 | 0 |
1237 | | * 6 | file | 1 | 2 | 0 |
1238 | | * 7 | file | 2 | -1 | 2 |
1239 | | * 8 | file | 2 | 0 | 1 |
1240 | | * 9 | file | 2 | 1 | 0 |
1241 | | * 10 | file | 2 | 2 | -1 |
1242 | | * -----+-------+----------+----------+------- |
1243 | | * 11 | dir | -1 | -1..2 | -1 |
1244 | | * 12 | dir | 0 | -1..2 | 0 |
1245 | | * 13 | dir | 1 | -1 | 1 |
1246 | | * 14 | dir | 1 | 0 | 1 |
1247 | | * 15 | dir | 1 | 1 | 1 (*) |
1248 | | * 16 | dir | 1 | 2 | 0 |
1249 | | * 17 | dir | 2 | -1 | 2 |
1250 | | * 18 | dir | 2 | 0 | 1 |
1251 | | * 19 | dir | 2 | 1 | 1 (*) |
1252 | | * 20 | dir | 2 | 2 | -1 |
1253 | | * |
1254 | | * (*) An exclude pattern interested in a directory does not |
1255 | | * necessarily mean it will exclude all of the directory. In |
1256 | | * wildcard case, it can't decide until looking at individual |
1257 | | * files inside. So don't write such directories off yet. |
1258 | | */ |
1259 | |
|
1260 | 0 | if (!(ps->magic & PATHSPEC_EXCLUDE) || |
1261 | 0 | positive <= entry_not_interesting) /* #1, #2, #11, #12 */ |
1262 | 0 | return positive; |
1263 | | |
1264 | 0 | negative = do_match(istate, entry, base, ps, 1); |
1265 | | |
1266 | | /* #8, #18 */ |
1267 | 0 | if (positive == all_entries_interesting && |
1268 | 0 | negative == entry_not_interesting) |
1269 | 0 | return entry_interesting; |
1270 | | |
1271 | | /* #3, #4, #7, #13, #14, #17 */ |
1272 | 0 | if (negative <= entry_not_interesting) |
1273 | 0 | return positive; |
1274 | | |
1275 | | /* #15, #19 */ |
1276 | 0 | if (S_ISDIR(entry->mode) && |
1277 | 0 | positive >= entry_interesting && |
1278 | 0 | negative == entry_interesting) |
1279 | 0 | return entry_interesting; |
1280 | | |
1281 | 0 | if ((positive == entry_interesting && |
1282 | 0 | negative >= entry_interesting) || /* #5, #6, #16 */ |
1283 | 0 | (positive == all_entries_interesting && |
1284 | 0 | negative == entry_interesting)) /* #9 */ |
1285 | 0 | return entry_not_interesting; |
1286 | | |
1287 | 0 | return all_entries_not_interesting; /* #10, #20 */ |
1288 | 0 | } |