Coverage Report

Created: 2026-03-31 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/tree-diff.c
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
}