1303
1304
1305
/* find set of paths that every parent touches */
1306
-static struct combine_diff_path *find_paths(const unsigned char *sha1,
1306
+static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
1307
const struct sha1_array *parents, struct diff_options *opt)
1308
{
1309
struct combine_diff_path *paths = NULL;
1316
/* tell diff_tree to emit paths in sorted (=tree) order */
1317
opt->orderfile = NULL;
1318
1319
+ /* D(A,P1...Pn) = D(A,P1) ^ ... ^ D(A,Pn) (wrt paths) */
1320
for (i = 0; i < num_parent; i++) {
1321
/*
1322
* show stat against the first parent even when doing
1347
}
1348
1349
1350
+/*
1351
+ * find set of paths that everybody touches, assuming diff is run without
1352
+ * rename/copy detection, etc, comparing all trees simultaneously (= faster).
1353
+ */
1354
+static struct combine_diff_path *find_paths_multitree(
1355
+ const unsigned char *sha1, const struct sha1_array *parents,
1356
+ struct diff_options *opt)
1357
+{
1358
+ int i, nparent = parents->nr;
1359
+ const unsigned char **parents_sha1;
1360
+ struct combine_diff_path paths_head;
1361
+ struct strbuf base;
1362
+
1363
+ parents_sha1 = xmalloc(nparent * sizeof(parents_sha1[0]));
1364
+ for (i = 0; i < nparent; i++)
1365
+ parents_sha1[i] = parents->sha1[i];
1366
+
1367
+ /* fake list head, so worker can assume it is non-NULL */
1368
+ paths_head.next = NULL;
1369
+
1370
+ strbuf_init(&base, PATH_MAX);
1371
+ diff_tree_paths(&paths_head, sha1, parents_sha1, nparent, &base, opt);
1372
+
1373
+ strbuf_release(&base);
1374
+ free(parents_sha1);
1375
+ return paths_head.next;
1376
+}
1377
+
1378
+
1379
void diff_tree_combined(const unsigned char *sha1,
1380
const struct sha1_array *parents,
1381
int dense,
1385
struct diff_options diffopts;
1386
struct combine_diff_path *p, *paths;
1387
int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
1388
+ int need_generic_pathscan;
1389
1390
/* nothing to do, if no parents */
1391
if (!num_parent)
1408
1409
/* find set of paths that everybody touches
1410
*
1380
- * NOTE find_paths() also handles --stat, as it computes
1381
- * diff(sha1,parent_i) for all i to do the job, specifically
1382
- * for parent0.
1411
+ * NOTE
1412
+ *
1413
+ * Diffcore transformations are bound to diff_filespec and logic
1414
+ * comparing two entries - i.e. they do not apply directly to combine
1415
+ * diff.
1416
+ *
1417
+ * If some of such transformations is requested - we launch generic
1418
+ * path scanning, which works significantly slower compared to
1419
+ * simultaneous all-trees-in-one-go scan in find_paths_multitree().
1420
+ *
1421
+ * TODO some of the filters could be ported to work on
1422
+ * combine_diff_paths - i.e. all functionality that skips paths, so in
1423
+ * theory, we could end up having only multitree path scanning.
1424
+ *
1425
+ * NOTE please keep this semantically in sync with diffcore_std()
1426
*/
1384
- paths = find_paths(sha1, parents, &diffopts);
1427
+ need_generic_pathscan = opt->skip_stat_unmatch ||
1428
+ DIFF_OPT_TST(opt, FOLLOW_RENAMES) ||
1429
+ opt->break_opt != -1 ||
1430
+ opt->detect_rename ||
1431
+ opt->pickaxe ||
1432
+ opt->filter;
1433
+
1434
+
1435
+ if (need_generic_pathscan) {
1436
+ /*
1437
+ * NOTE generic case also handles --stat, as it computes
1438
+ * diff(sha1,parent_i) for all i to do the job, specifically
1439
+ * for parent0.
1440
+ */
1441
+ paths = find_paths_generic(sha1, parents, &diffopts);
1442
+ }
1443
+ else {
1444
+ int stat_opt;
1445
+ paths = find_paths_multitree(sha1, parents, &diffopts);
1446
+
1447
+ /*
1448
+ * show stat against the first parent even
1449
+ * when doing combined diff.
1450
+ */
1451
+ stat_opt = (opt->output_format &
1452
+ (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
1453
+ if (stat_opt) {
1454
+ diffopts.output_format = stat_opt;
1455
+
1456
+ diff_tree_sha1(parents->sha1[0], sha1, "", &diffopts);
1457
+ diffcore_std(&diffopts);
1458
+ if (opt->orderfile)
1459
+ diffcore_order(opt->orderfile);
1460
+ diff_flush(&diffopts);
1461
+ }
1462
+ }
1463
1464
/* find out number of surviving paths */
1465
for (num_paths = 0, p = paths; p; p = p->next)