Line | Count | Source |
1 | | /* |
2 | | * Helper functions for tree diff generation |
3 | | */ |
4 | | |
5 | | #define DISABLE_SIGN_COMPARE_WARNINGS |
6 | | |
7 | | #include "git-compat-util.h" |
8 | | #include "diff.h" |
9 | | #include "diffcore.h" |
10 | | #include "hash.h" |
11 | | #include "tree.h" |
12 | | #include "tree-walk.h" |
13 | | #include "repository.h" |
14 | | #include "dir.h" |
15 | | |
16 | | /* |
17 | | * Some mode bits are also used internally for computations. |
18 | | * |
19 | | * They *must* not overlap with any valid modes, and they *must* not be emitted |
20 | | * to outside world - i.e. appear on disk or network. In other words, it's just |
21 | | * temporary fields, which we internally use, but they have to stay in-house. |
22 | | * |
23 | | * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git |
24 | | * codebase mode is `unsigned int` which is assumed to be at least 32 bits ) |
25 | | */ |
26 | | |
27 | 0 | #define S_DIFFTREE_IFXMIN_NEQ 0x80000000 |
28 | | |
29 | | /* |
30 | | * internal mode marker, saying a tree entry != entry of tp[imin] |
31 | | * (see ll_diff_tree_paths for what it means there) |
32 | | * |
33 | | * we will update/use/emit entry for diff only with it unset. |
34 | | */ |
35 | 0 | #define S_IFXMIN_NEQ S_DIFFTREE_IFXMIN_NEQ |
36 | | |
37 | 0 | #define FAST_ARRAY_ALLOC(x, nr) do { \ |
38 | 0 | if ((nr) <= 2) \ |
39 | 0 | (x) = xalloca((nr) * sizeof(*(x))); \ |
40 | 0 | else \ |
41 | 0 | ALLOC_ARRAY((x), nr); \ |
42 | 0 | } while(0) |
43 | 0 | #define FAST_ARRAY_FREE(x, nr) do { \ |
44 | 0 | if ((nr) <= 2) \ |
45 | 0 | xalloca_free((x)); \ |
46 | 0 | else \ |
47 | 0 | free((x)); \ |
48 | 0 | } while(0) |
49 | | |
50 | | /* Returns true if and only if "dir" is a leading directory of "path" */ |
51 | | static int is_dir_prefix(const char *path, const char *dir, int dirlen) |
52 | 0 | { |
53 | 0 | return !strncmp(path, dir, dirlen) && |
54 | 0 | (!path[dirlen] || path[dirlen] == '/'); |
55 | 0 | } |
56 | | |
57 | | static int check_recursion_depth(const struct strbuf *name, |
58 | | const struct pathspec *ps, |
59 | | int max_depth) |
60 | 0 | { |
61 | 0 | int i; |
62 | |
|
63 | 0 | if (!ps->nr) |
64 | 0 | return within_depth(name->buf, name->len, 1, max_depth); |
65 | | |
66 | | /* |
67 | | * We look through the pathspecs in reverse-sorted order, because we |
68 | | * want to find the longest match first (e.g., "a/b" is better for |
69 | | * checking depth than "a/b/c"). |
70 | | */ |
71 | 0 | for (i = ps->nr - 1; i >= 0; i--) { |
72 | 0 | const struct pathspec_item *item = ps->items+i; |
73 | | |
74 | | /* |
75 | | * If the name to match is longer than the pathspec, then we |
76 | | * are only interested if the pathspec matches and we are |
77 | | * within the allowed depth. |
78 | | */ |
79 | 0 | if (name->len >= item->len) { |
80 | 0 | if (!is_dir_prefix(name->buf, item->match, item->len)) |
81 | 0 | continue; |
82 | 0 | return within_depth(name->buf + item->len, |
83 | 0 | name->len - item->len, |
84 | 0 | 1, max_depth); |
85 | 0 | } |
86 | | |
87 | | /* |
88 | | * Otherwise, our name is shorter than the pathspec. We need to |
89 | | * check if it is a prefix of the pathspec; if so, we must |
90 | | * always recurse in order to process further (the resulting |
91 | | * paths we find might or might not match our pathspec, but we |
92 | | * cannot know until we recurse). |
93 | | */ |
94 | 0 | if (is_dir_prefix(item->match, name->buf, name->len)) |
95 | 0 | return 1; |
96 | 0 | } |
97 | 0 | return 0; |
98 | 0 | } |
99 | | |
100 | | static int should_recurse(const struct strbuf *name, struct diff_options *opt) |
101 | 0 | { |
102 | 0 | if (!opt->flags.recursive) |
103 | 0 | return 0; |
104 | 0 | if (!opt->max_depth_valid) |
105 | 0 | return 1; |
106 | | |
107 | | /* |
108 | | * We catch this during diff_setup_done, but let's double-check |
109 | | * against any internal munging. |
110 | | */ |
111 | 0 | if (opt->pathspec.has_wildcard) |
112 | 0 | BUG("wildcard pathspecs are incompatible with max-depth"); |
113 | | |
114 | 0 | return check_recursion_depth(name, &opt->pathspec, opt->max_depth); |
115 | 0 | } |
116 | | |
117 | | static void ll_diff_tree_paths( |
118 | | struct combine_diff_path ***tail, const struct object_id *oid, |
119 | | const struct object_id **parents_oid, int nparent, |
120 | | struct strbuf *base, struct diff_options *opt, |
121 | | int depth); |
122 | | static void ll_diff_tree_oid(const struct object_id *old_oid, |
123 | | const struct object_id *new_oid, |
124 | | struct strbuf *base, struct diff_options *opt); |
125 | | |
126 | | /* |
127 | | * Compare two tree entries, taking into account only path/S_ISDIR(mode), |
128 | | * but not their sha1's. |
129 | | * |
130 | | * NOTE files and directories *always* compare differently, even when having |
131 | | * the same name - thanks to base_name_compare(). |
132 | | * |
133 | | * NOTE empty (=invalid) descriptor(s) take part in comparison as +infty, |
134 | | * so that they sort *after* valid tree entries. |
135 | | * |
136 | | * Due to this convention, if trees are scanned in sorted order, all |
137 | | * non-empty descriptors will be processed first. |
138 | | */ |
139 | | static int tree_entry_pathcmp(struct tree_desc *t1, struct tree_desc *t2) |
140 | 0 | { |
141 | 0 | struct name_entry *e1, *e2; |
142 | 0 | int cmp; |
143 | | |
144 | | /* empty descriptors sort after valid tree entries */ |
145 | 0 | if (!t1->size) |
146 | 0 | return t2->size ? 1 : 0; |
147 | 0 | else if (!t2->size) |
148 | 0 | return -1; |
149 | | |
150 | 0 | e1 = &t1->entry; |
151 | 0 | e2 = &t2->entry; |
152 | 0 | cmp = base_name_compare(e1->path, tree_entry_len(e1), e1->mode, |
153 | 0 | e2->path, tree_entry_len(e2), e2->mode); |
154 | 0 | return cmp; |
155 | 0 | } |
156 | | |
157 | | |
158 | | /* |
159 | | * convert path -> opt->diff_*() callbacks |
160 | | * |
161 | | * emits diff to first parent only, and tells diff tree-walker that we are done |
162 | | * with p and it can be freed. |
163 | | */ |
164 | | static int emit_diff_first_parent_only(struct diff_options *opt, struct combine_diff_path *p) |
165 | 0 | { |
166 | 0 | struct combine_diff_parent *p0 = &p->parent[0]; |
167 | 0 | if (p->mode && p0->mode) { |
168 | 0 | opt->change(opt, p0->mode, p->mode, &p0->oid, &p->oid, |
169 | 0 | 1, 1, p->path, 0, 0); |
170 | 0 | } |
171 | 0 | else { |
172 | 0 | const struct object_id *oid; |
173 | 0 | unsigned int mode; |
174 | 0 | int addremove; |
175 | |
|
176 | 0 | if (p->mode) { |
177 | 0 | addremove = '+'; |
178 | 0 | oid = &p->oid; |
179 | 0 | mode = p->mode; |
180 | 0 | } else { |
181 | 0 | addremove = '-'; |
182 | 0 | oid = &p0->oid; |
183 | 0 | mode = p0->mode; |
184 | 0 | } |
185 | |
|
186 | 0 | opt->add_remove(opt, addremove, mode, oid, 1, p->path, 0); |
187 | 0 | } |
188 | |
|
189 | 0 | return 0; /* we are done with p */ |
190 | 0 | } |
191 | | |
192 | | |
193 | | /* |
194 | | * new path should be added to combine diff |
195 | | * |
196 | | * 3 cases on how/when it should be called and behaves: |
197 | | * |
198 | | * t, !tp -> path added, all parents lack it |
199 | | * !t, tp -> path removed from all parents |
200 | | * t, tp -> path modified/added |
201 | | * (M for tp[i]=tp[imin], A otherwise) |
202 | | */ |
203 | | static void emit_path(struct combine_diff_path ***tail, |
204 | | struct strbuf *base, struct diff_options *opt, |
205 | | int nparent, struct tree_desc *t, struct tree_desc *tp, |
206 | | int imin, int depth) |
207 | 0 | { |
208 | 0 | unsigned short mode; |
209 | 0 | const char *path; |
210 | 0 | const struct object_id *oid; |
211 | 0 | int pathlen; |
212 | 0 | int old_baselen = base->len; |
213 | 0 | int i, isdir, recurse = 0, emitthis = 1; |
214 | | |
215 | | /* at least something has to be valid */ |
216 | 0 | assert(t || tp); |
217 | |
|
218 | 0 | if (t) { |
219 | | /* path present in resulting tree */ |
220 | 0 | oid = tree_entry_extract(t, &path, &mode); |
221 | 0 | pathlen = tree_entry_len(&t->entry); |
222 | 0 | isdir = S_ISDIR(mode); |
223 | 0 | } else { |
224 | | /* |
225 | | * a path was removed - take path from imin parent. Also take |
226 | | * mode from that parent, to decide on recursion(1). |
227 | | * |
228 | | * 1) all modes for tp[i]=tp[imin] should be the same wrt |
229 | | * S_ISDIR, thanks to base_name_compare(). |
230 | | */ |
231 | 0 | tree_entry_extract(&tp[imin], &path, &mode); |
232 | 0 | pathlen = tree_entry_len(&tp[imin].entry); |
233 | |
|
234 | 0 | isdir = S_ISDIR(mode); |
235 | 0 | oid = NULL; |
236 | 0 | mode = 0; |
237 | 0 | } |
238 | |
|
239 | 0 | if (isdir) { |
240 | 0 | strbuf_add(base, path, pathlen); |
241 | 0 | if (should_recurse(base, opt)) { |
242 | 0 | recurse = 1; |
243 | 0 | emitthis = opt->flags.tree_in_recursive; |
244 | 0 | } |
245 | 0 | strbuf_setlen(base, old_baselen); |
246 | 0 | } |
247 | |
|
248 | 0 | if (emitthis) { |
249 | 0 | int keep; |
250 | 0 | struct combine_diff_path *p; |
251 | |
|
252 | 0 | strbuf_add(base, path, pathlen); |
253 | 0 | p = combine_diff_path_new(base->buf, base->len, mode, |
254 | 0 | oid ? oid : null_oid(opt->repo->hash_algo), |
255 | 0 | nparent); |
256 | 0 | strbuf_setlen(base, old_baselen); |
257 | |
|
258 | 0 | for (i = 0; i < nparent; ++i) { |
259 | | /* |
260 | | * tp[i] is valid, if present and if tp[i]==tp[imin] - |
261 | | * otherwise, we should ignore it. |
262 | | */ |
263 | 0 | int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ); |
264 | |
|
265 | 0 | const struct object_id *oid_i; |
266 | 0 | unsigned mode_i; |
267 | |
|
268 | 0 | p->parent[i].status = |
269 | 0 | !t ? DIFF_STATUS_DELETED : |
270 | 0 | tpi_valid ? |
271 | 0 | DIFF_STATUS_MODIFIED : |
272 | 0 | DIFF_STATUS_ADDED; |
273 | |
|
274 | 0 | if (tpi_valid) { |
275 | 0 | oid_i = &tp[i].entry.oid; |
276 | 0 | mode_i = tp[i].entry.mode; |
277 | 0 | } |
278 | 0 | else { |
279 | 0 | oid_i = null_oid(opt->repo->hash_algo); |
280 | 0 | mode_i = 0; |
281 | 0 | } |
282 | |
|
283 | 0 | p->parent[i].mode = mode_i; |
284 | 0 | oidcpy(&p->parent[i].oid, oid_i); |
285 | 0 | } |
286 | |
|
287 | 0 | keep = 1; |
288 | 0 | if (opt->pathchange) |
289 | 0 | keep = opt->pathchange(opt, p); |
290 | |
|
291 | 0 | if (keep) { |
292 | 0 | **tail = p; |
293 | 0 | *tail = &p->next; |
294 | 0 | } else { |
295 | 0 | free(p); |
296 | 0 | } |
297 | 0 | } |
298 | |
|
299 | 0 | if (recurse) { |
300 | 0 | const struct object_id **parents_oid; |
301 | |
|
302 | 0 | FAST_ARRAY_ALLOC(parents_oid, nparent); |
303 | 0 | for (i = 0; i < nparent; ++i) { |
304 | | /* same rule as in emitthis */ |
305 | 0 | int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ); |
306 | |
|
307 | 0 | parents_oid[i] = tpi_valid ? &tp[i].entry.oid : NULL; |
308 | 0 | } |
309 | |
|
310 | 0 | strbuf_add(base, path, pathlen); |
311 | 0 | strbuf_addch(base, '/'); |
312 | 0 | ll_diff_tree_paths(tail, oid, parents_oid, nparent, base, opt, |
313 | 0 | depth + 1); |
314 | 0 | FAST_ARRAY_FREE(parents_oid, nparent); |
315 | 0 | } |
316 | |
|
317 | 0 | strbuf_setlen(base, old_baselen); |
318 | 0 | } |
319 | | |
320 | | static void skip_uninteresting(struct tree_desc *t, struct strbuf *base, |
321 | | struct diff_options *opt) |
322 | 0 | { |
323 | 0 | enum interesting match; |
324 | |
|
325 | 0 | while (t->size) { |
326 | 0 | match = tree_entry_interesting(opt->repo->index, &t->entry, |
327 | 0 | base, &opt->pathspec); |
328 | 0 | if (match) { |
329 | 0 | if (match == all_entries_not_interesting) |
330 | 0 | t->size = 0; |
331 | 0 | break; |
332 | 0 | } |
333 | 0 | update_tree_entry(t); |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | | |
338 | | /* |
339 | | * generate paths for combined diff D(sha1,parents_oid[]) |
340 | | * |
341 | | * Resulting paths are appended to combine_diff_path linked list, and also, are |
342 | | * emitted on the go via opt->pathchange() callback, so it is possible to |
343 | | * process the result as batch or incrementally. |
344 | | * |
345 | | * The paths are generated scanning new tree and all parents trees |
346 | | * simultaneously, similarly to what diff_tree() was doing for 2 trees. |
347 | | * The theory behind such scan is as follows: |
348 | | * |
349 | | * |
350 | | * D(T,P1...Pn) calculation scheme |
351 | | * ------------------------------- |
352 | | * |
353 | | * D(T,P1...Pn) = D(T,P1) ^ ... ^ D(T,Pn) (regarding resulting paths set) |
354 | | * |
355 | | * D(T,Pj) - diff between T..Pj |
356 | | * D(T,P1...Pn) - combined diff from T to parents P1,...,Pn |
357 | | * |
358 | | * |
359 | | * We start from all trees, which are sorted, and compare their entries in |
360 | | * lock-step: |
361 | | * |
362 | | * T P1 Pn |
363 | | * - - - |
364 | | * |t| |p1| |pn| |
365 | | * |-| |--| ... |--| imin = argmin(p1...pn) |
366 | | * | | | | | | |
367 | | * |-| |--| |--| |
368 | | * |.| |. | |. | |
369 | | * . . . |
370 | | * . . . |
371 | | * |
372 | | * at any time there could be 3 cases: |
373 | | * |
374 | | * 1) t < p[imin]; |
375 | | * 2) t > p[imin]; |
376 | | * 3) t = p[imin]. |
377 | | * |
378 | | * Schematic deduction of what every case means, and what to do, follows: |
379 | | * |
380 | | * 1) t < p[imin] -> ∀j t ∉ Pj -> "+t" ∈ D(T,Pj) -> D += "+t"; t↓ |
381 | | * |
382 | | * 2) t > p[imin] |
383 | | * |
384 | | * 2.1) ∃j: pj > p[imin] -> "-p[imin]" ∉ D(T,Pj) -> D += ø; ∀ pi=p[imin] pi↓ |
385 | | * 2.2) ∀i pi = p[imin] -> pi ∉ T -> "-pi" ∈ D(T,Pi) -> D += "-p[imin]"; ∀i pi↓ |
386 | | * |
387 | | * 3) t = p[imin] |
388 | | * |
389 | | * 3.1) ∃j: pj > p[imin] -> "+t" ∈ D(T,Pj) -> only pi=p[imin] remains to investigate |
390 | | * 3.2) pi = p[imin] -> investigate δ(t,pi) |
391 | | * | |
392 | | * | |
393 | | * v |
394 | | * |
395 | | * 3.1+3.2) looking at δ(t,pi) ∀i: pi=p[imin] - if all != ø -> |
396 | | * |
397 | | * ⎧δ(t,pi) - if pi=p[imin] |
398 | | * -> D += ⎨ |
399 | | * ⎩"+t" - if pi>p[imin] |
400 | | * |
401 | | * |
402 | | * in any case t↓ ∀ pi=p[imin] pi↓ |
403 | | * |
404 | | * |
405 | | * ~~~~~~~~ |
406 | | * |
407 | | * NOTE |
408 | | * |
409 | | * Usual diff D(A,B) is by definition the same as combined diff D(A,[B]), |
410 | | * so this diff paths generator can, and is used, for plain diffs |
411 | | * generation too. |
412 | | * |
413 | | * Please keep attention to the common D(A,[B]) case when working on the |
414 | | * code, in order not to slow it down. |
415 | | * |
416 | | * NOTE |
417 | | * nparent must be > 0. |
418 | | */ |
419 | | |
420 | | |
421 | | /* ∀ pi=p[imin] pi↓ */ |
422 | | static inline void update_tp_entries(struct tree_desc *tp, int nparent) |
423 | 0 | { |
424 | 0 | int i; |
425 | 0 | for (i = 0; i < nparent; ++i) |
426 | 0 | if (!(tp[i].entry.mode & S_IFXMIN_NEQ)) |
427 | 0 | update_tree_entry(&tp[i]); |
428 | 0 | } |
429 | | |
430 | | static void ll_diff_tree_paths( |
431 | | struct combine_diff_path ***tail, const struct object_id *oid, |
432 | | const struct object_id **parents_oid, int nparent, |
433 | | struct strbuf *base, struct diff_options *opt, |
434 | | int depth) |
435 | 0 | { |
436 | 0 | struct tree_desc t, *tp; |
437 | 0 | void *ttree, **tptree; |
438 | 0 | int i; |
439 | |
|
440 | 0 | if (depth > opt->repo->settings.max_allowed_tree_depth) |
441 | 0 | die("exceeded maximum allowed tree depth"); |
442 | | |
443 | 0 | FAST_ARRAY_ALLOC(tp, nparent); |
444 | 0 | FAST_ARRAY_ALLOC(tptree, nparent); |
445 | | |
446 | | /* |
447 | | * load parents first, as they are probably already cached. |
448 | | * |
449 | | * ( log_tree_diff() parses commit->parent before calling here via |
450 | | * diff_tree_oid(parent, commit) ) |
451 | | */ |
452 | 0 | for (i = 0; i < nparent; ++i) |
453 | 0 | tptree[i] = fill_tree_descriptor(opt->repo, &tp[i], parents_oid[i]); |
454 | 0 | ttree = fill_tree_descriptor(opt->repo, &t, oid); |
455 | | |
456 | | /* Enable recursion indefinitely */ |
457 | 0 | opt->pathspec.recursive = opt->flags.recursive; |
458 | |
|
459 | 0 | for (;;) { |
460 | 0 | int imin, cmp; |
461 | |
|
462 | 0 | if (diff_can_quit_early(opt)) |
463 | 0 | break; |
464 | | |
465 | 0 | if (opt->max_changes && diff_queued_diff.nr > opt->max_changes) |
466 | 0 | break; |
467 | | |
468 | 0 | if (opt->pathspec.nr) { |
469 | 0 | skip_uninteresting(&t, base, opt); |
470 | 0 | for (i = 0; i < nparent; i++) |
471 | 0 | skip_uninteresting(&tp[i], base, opt); |
472 | 0 | } |
473 | | |
474 | | /* comparing is finished when all trees are done */ |
475 | 0 | if (!t.size) { |
476 | 0 | int done = 1; |
477 | 0 | for (i = 0; i < nparent; ++i) |
478 | 0 | if (tp[i].size) { |
479 | 0 | done = 0; |
480 | 0 | break; |
481 | 0 | } |
482 | 0 | if (done) |
483 | 0 | break; |
484 | 0 | } |
485 | | |
486 | | /* |
487 | | * lookup imin = argmin(p1...pn), |
488 | | * mark entries whether they =p[imin] along the way |
489 | | */ |
490 | 0 | imin = 0; |
491 | 0 | tp[0].entry.mode &= ~S_IFXMIN_NEQ; |
492 | |
|
493 | 0 | for (i = 1; i < nparent; ++i) { |
494 | 0 | cmp = tree_entry_pathcmp(&tp[i], &tp[imin]); |
495 | 0 | if (cmp < 0) { |
496 | 0 | imin = i; |
497 | 0 | tp[i].entry.mode &= ~S_IFXMIN_NEQ; |
498 | 0 | } |
499 | 0 | else if (cmp == 0) { |
500 | 0 | tp[i].entry.mode &= ~S_IFXMIN_NEQ; |
501 | 0 | } |
502 | 0 | else { |
503 | 0 | tp[i].entry.mode |= S_IFXMIN_NEQ; |
504 | 0 | } |
505 | 0 | } |
506 | | |
507 | | /* fixup markings for entries before imin */ |
508 | 0 | for (i = 0; i < imin; ++i) |
509 | 0 | tp[i].entry.mode |= S_IFXMIN_NEQ; /* pi > p[imin] */ |
510 | | |
511 | | |
512 | | |
513 | | /* compare t vs p[imin] */ |
514 | 0 | cmp = tree_entry_pathcmp(&t, &tp[imin]); |
515 | | |
516 | | /* t = p[imin] */ |
517 | 0 | if (cmp == 0) { |
518 | | /* are either pi > p[imin] or diff(t,pi) != ø ? */ |
519 | 0 | if (!opt->flags.find_copies_harder) { |
520 | 0 | for (i = 0; i < nparent; ++i) { |
521 | | /* p[i] > p[imin] */ |
522 | 0 | if (tp[i].entry.mode & S_IFXMIN_NEQ) |
523 | 0 | continue; |
524 | | |
525 | | /* diff(t,pi) != ø */ |
526 | 0 | if (!oideq(&t.entry.oid, &tp[i].entry.oid) || |
527 | 0 | (t.entry.mode != tp[i].entry.mode)) |
528 | 0 | continue; |
529 | | |
530 | 0 | goto skip_emit_t_tp; |
531 | 0 | } |
532 | 0 | } |
533 | | |
534 | | /* D += {δ(t,pi) if pi=p[imin]; "+a" if pi > p[imin]} */ |
535 | 0 | emit_path(tail, base, opt, nparent, |
536 | 0 | &t, tp, imin, depth); |
537 | |
|
538 | 0 | skip_emit_t_tp: |
539 | | /* t↓, ∀ pi=p[imin] pi↓ */ |
540 | 0 | update_tree_entry(&t); |
541 | 0 | update_tp_entries(tp, nparent); |
542 | 0 | } |
543 | | |
544 | | /* t < p[imin] */ |
545 | 0 | else if (cmp < 0) { |
546 | | /* D += "+t" */ |
547 | 0 | emit_path(tail, base, opt, nparent, |
548 | 0 | &t, /*tp=*/NULL, -1, depth); |
549 | | |
550 | | /* t↓ */ |
551 | 0 | update_tree_entry(&t); |
552 | 0 | } |
553 | | |
554 | | /* t > p[imin] */ |
555 | 0 | else { |
556 | | /* ∀i pi=p[imin] -> D += "-p[imin]" */ |
557 | 0 | if (!opt->flags.find_copies_harder) { |
558 | 0 | for (i = 0; i < nparent; ++i) |
559 | 0 | if (tp[i].entry.mode & S_IFXMIN_NEQ) |
560 | 0 | goto skip_emit_tp; |
561 | 0 | } |
562 | | |
563 | 0 | emit_path(tail, base, opt, nparent, |
564 | 0 | /*t=*/NULL, tp, imin, depth); |
565 | |
|
566 | 0 | skip_emit_tp: |
567 | | /* ∀ pi=p[imin] pi↓ */ |
568 | 0 | update_tp_entries(tp, nparent); |
569 | 0 | } |
570 | 0 | } |
571 | | |
572 | 0 | free(ttree); |
573 | 0 | for (i = nparent-1; i >= 0; i--) |
574 | 0 | free(tptree[i]); |
575 | 0 | FAST_ARRAY_FREE(tptree, nparent); |
576 | 0 | FAST_ARRAY_FREE(tp, nparent); |
577 | 0 | } |
578 | | |
579 | | struct combine_diff_path *diff_tree_paths( |
580 | | const struct object_id *oid, |
581 | | const struct object_id **parents_oid, int nparent, |
582 | | struct strbuf *base, struct diff_options *opt) |
583 | 0 | { |
584 | 0 | struct combine_diff_path *head = NULL, **tail = &head; |
585 | 0 | ll_diff_tree_paths(&tail, oid, parents_oid, nparent, base, opt, 0); |
586 | 0 | return head; |
587 | 0 | } |
588 | | |
589 | | /* |
590 | | * Does it look like the resulting diff might be due to a rename? |
591 | | * - single entry |
592 | | * - not a valid previous file |
593 | | */ |
594 | | static inline int diff_might_be_rename(void) |
595 | 0 | { |
596 | 0 | return diff_queued_diff.nr == 1 && |
597 | 0 | !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one); |
598 | 0 | } |
599 | | |
600 | | static void try_to_follow_renames(const struct object_id *old_oid, |
601 | | const struct object_id *new_oid, |
602 | | struct strbuf *base, struct diff_options *opt) |
603 | 0 | { |
604 | 0 | struct diff_options diff_opts; |
605 | 0 | struct diff_queue_struct *q = &diff_queued_diff; |
606 | 0 | struct diff_filepair *choice; |
607 | 0 | int i; |
608 | | |
609 | | /* |
610 | | * follow-rename code is very specific, we need exactly one |
611 | | * path. Magic that matches more than one path is not |
612 | | * supported. |
613 | | */ |
614 | 0 | GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); |
615 | | #if 0 |
616 | | /* |
617 | | * We should reject wildcards as well. Unfortunately we |
618 | | * haven't got a reliable way to detect that 'foo\*bar' in |
619 | | * fact has no wildcards. nowildcard_len is merely a hint for |
620 | | * optimization. Let it slip for now until wildmatch is taught |
621 | | * about dry-run mode and returns wildcard info. |
622 | | */ |
623 | | if (opt->pathspec.has_wildcard) |
624 | | BUG("wildcards are not supported"); |
625 | | #endif |
626 | | |
627 | | /* Remove the file creation entry from the diff queue, and remember it */ |
628 | 0 | choice = q->queue[0]; |
629 | 0 | q->nr = 0; |
630 | |
|
631 | 0 | repo_diff_setup(opt->repo, &diff_opts); |
632 | 0 | diff_opts.flags.recursive = 1; |
633 | 0 | diff_opts.flags.find_copies_harder = 1; |
634 | 0 | diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; |
635 | 0 | diff_opts.single_follow = opt->pathspec.items[0].match; |
636 | 0 | diff_opts.break_opt = opt->break_opt; |
637 | 0 | diff_opts.rename_score = opt->rename_score; |
638 | 0 | diff_setup_done(&diff_opts); |
639 | 0 | ll_diff_tree_oid(old_oid, new_oid, base, &diff_opts); |
640 | 0 | diffcore_std(&diff_opts); |
641 | 0 | clear_pathspec(&diff_opts.pathspec); |
642 | | |
643 | | /* Go through the new set of filepairing, and see if we find a more interesting one */ |
644 | 0 | opt->found_follow = 0; |
645 | 0 | for (i = 0; i < q->nr; i++) { |
646 | 0 | struct diff_filepair *p = q->queue[i]; |
647 | | |
648 | | /* |
649 | | * Found a source? Not only do we use that for the new |
650 | | * diff_queued_diff, we will also use that as the path in |
651 | | * the future! |
652 | | */ |
653 | 0 | if ((p->status == 'R' || p->status == 'C') && |
654 | 0 | !strcmp(p->two->path, opt->pathspec.items[0].match)) { |
655 | 0 | const char *path[2]; |
656 | | |
657 | | /* Switch the file-pairs around */ |
658 | 0 | q->queue[i] = choice; |
659 | 0 | choice = p; |
660 | | |
661 | | /* Update the path we use from now on.. */ |
662 | 0 | path[0] = p->one->path; |
663 | 0 | path[1] = NULL; |
664 | 0 | clear_pathspec(&opt->pathspec); |
665 | 0 | parse_pathspec(&opt->pathspec, |
666 | 0 | PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL, |
667 | 0 | PATHSPEC_LITERAL_PATH, "", path); |
668 | | |
669 | | /* |
670 | | * The caller expects us to return a set of vanilla |
671 | | * filepairs to let a later call to diffcore_std() |
672 | | * it makes to sort the renames out (among other |
673 | | * things), but we already have found renames |
674 | | * ourselves; signal diffcore_std() not to muck with |
675 | | * rename information. |
676 | | */ |
677 | 0 | opt->found_follow = 1; |
678 | 0 | break; |
679 | 0 | } |
680 | 0 | } |
681 | | |
682 | | /* |
683 | | * Then, discard all the non-relevant file pairs... |
684 | | */ |
685 | 0 | for (i = 0; i < q->nr; i++) { |
686 | 0 | struct diff_filepair *p = q->queue[i]; |
687 | 0 | diff_free_filepair(p); |
688 | 0 | } |
689 | | |
690 | | /* |
691 | | * .. and re-instate the one we want (which might be either the |
692 | | * original one, or the rename/copy we found) |
693 | | */ |
694 | 0 | q->queue[0] = choice; |
695 | 0 | q->nr = 1; |
696 | 0 | } |
697 | | |
698 | | static void ll_diff_tree_oid(const struct object_id *old_oid, |
699 | | const struct object_id *new_oid, |
700 | | struct strbuf *base, struct diff_options *opt) |
701 | 0 | { |
702 | 0 | struct combine_diff_path *paths, *p; |
703 | 0 | pathchange_fn_t pathchange_old = opt->pathchange; |
704 | |
|
705 | 0 | opt->pathchange = emit_diff_first_parent_only; |
706 | 0 | paths = diff_tree_paths(new_oid, &old_oid, 1, base, opt); |
707 | |
|
708 | 0 | for (p = paths; p;) { |
709 | 0 | struct combine_diff_path *pprev = p; |
710 | 0 | p = p->next; |
711 | 0 | free(pprev); |
712 | 0 | } |
713 | |
|
714 | 0 | opt->pathchange = pathchange_old; |
715 | 0 | } |
716 | | |
717 | | void diff_tree_oid(const struct object_id *old_oid, |
718 | | const struct object_id *new_oid, |
719 | | const char *base_str, struct diff_options *opt) |
720 | 0 | { |
721 | 0 | struct strbuf base; |
722 | |
|
723 | 0 | strbuf_init(&base, PATH_MAX); |
724 | 0 | strbuf_addstr(&base, base_str); |
725 | |
|
726 | 0 | ll_diff_tree_oid(old_oid, new_oid, &base, opt); |
727 | 0 | if (!*base_str && opt->flags.follow_renames && diff_might_be_rename()) |
728 | 0 | try_to_follow_renames(old_oid, new_oid, &base, opt); |
729 | |
|
730 | 0 | strbuf_release(&base); |
731 | 0 | } |
732 | | |
733 | | void diff_root_tree_oid(const struct object_id *new_oid, |
734 | | const char *base, |
735 | | struct diff_options *opt) |
736 | 0 | { |
737 | | diff_tree_oid(NULL, new_oid, base, opt); |
738 | 0 | } |