1298
return 0;
1299
}
1300
1301
-static void init_commit_graph_chain(struct write_commit_graph_context *ctx)
1302
-{
1303
- struct commit_graph *g = ctx->r->objects->commit_graph;
1304
- uint32_t i;
1305
-
1306
- ctx->new_base_graph = g;
1307
- ctx->base_graph_name = xstrdup(g->filename);
1308
- ctx->new_num_commits_in_base = g->num_commits + g->num_commits_in_base;
1309
-
1310
- ctx->num_commit_graphs_after = ctx->num_commit_graphs_before + 1;
1311
-
1312
- ALLOC_ARRAY(ctx->commit_graph_filenames_after, ctx->num_commit_graphs_after);
1313
- ALLOC_ARRAY(ctx->commit_graph_hash_after, ctx->num_commit_graphs_after);
1314
-
1315
- for (i = 0; i < ctx->num_commit_graphs_before - 1; i++)
1316
- ctx->commit_graph_filenames_after[i] = xstrdup(ctx->commit_graph_filenames_before[i]);
1317
-
1318
- if (ctx->num_commit_graphs_before)
1319
- ctx->commit_graph_filenames_after[ctx->num_commit_graphs_before - 1] =
1320
- get_split_graph_filename(ctx->obj_dir, oid_to_hex(&g->oid));
1321
-
1322
- i = ctx->num_commit_graphs_before - 1;
1323
-
1324
- while (g) {
1325
- ctx->commit_graph_hash_after[i] = xstrdup(oid_to_hex(&g->oid));
1326
- i--;
1327
- g = g->base_graph;
1328
- }
1329
-}
1330
-
1301
static int write_commit_graph_file(struct write_commit_graph_context *ctx)
1302
{
1303
uint32_t i;
1479
return 0;
1480
}
1481
1482
+static int split_strategy_max_commits = 64000;
1483
+static float split_strategy_size_mult = 2.0f;
1484
+
1485
+static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
1486
+{
1487
+ struct commit_graph *g = ctx->r->objects->commit_graph;
1488
+ uint32_t num_commits = ctx->commits.nr;
1489
+ uint32_t i;
1490
+
1491
+ g = ctx->r->objects->commit_graph;
1492
+ ctx->num_commit_graphs_after = ctx->num_commit_graphs_before + 1;
1493
+
1494
+ while (g && (g->num_commits <= split_strategy_size_mult * num_commits ||
1495
+ num_commits > split_strategy_max_commits)) {
1496
+ num_commits += g->num_commits;
1497
+ g = g->base_graph;
1498
+
1499
+ ctx->num_commit_graphs_after--;
1500
+ }
1501
+
1502
+ ctx->new_base_graph = g;
1503
+
1504
+ ALLOC_ARRAY(ctx->commit_graph_filenames_after, ctx->num_commit_graphs_after);
1505
+ ALLOC_ARRAY(ctx->commit_graph_hash_after, ctx->num_commit_graphs_after);
1506
+
1507
+ for (i = 0; i < ctx->num_commit_graphs_after &&
1508
+ i < ctx->num_commit_graphs_before; i++)
1509
+ ctx->commit_graph_filenames_after[i] = xstrdup(ctx->commit_graph_filenames_before[i]);
1510
+
1511
+ i = ctx->num_commit_graphs_before - 1;
1512
+ g = ctx->r->objects->commit_graph;
1513
+
1514
+ while (g) {
1515
+ if (i < ctx->num_commit_graphs_after)
1516
+ ctx->commit_graph_hash_after[i] = xstrdup(oid_to_hex(&g->oid));
1517
+
1518
+ i--;
1519
+ g = g->base_graph;
1520
+ }
1521
+}
1522
+
1523
+static void merge_commit_graph(struct write_commit_graph_context *ctx,
1524
+ struct commit_graph *g)
1525
+{
1526
+ uint32_t i;
1527
+ uint32_t offset = g->num_commits_in_base;
1528
+
1529
+ ALLOC_GROW(ctx->commits.list, ctx->commits.nr + g->num_commits, ctx->commits.alloc);
1530
+
1531
+ for (i = 0; i < g->num_commits; i++) {
1532
+ struct object_id oid;
1533
+ struct commit *result;
1534
+
1535
+ display_progress(ctx->progress, i + 1);
1536
+
1537
+ load_oid_from_graph(g, i + offset, &oid);
1538
+
1539
+ /* only add commits if they still exist in the repo */
1540
+ result = lookup_commit_reference_gently(ctx->r, &oid, 1);
1541
+
1542
+ if (result) {
1543
+ ctx->commits.list[ctx->commits.nr] = result;
1544
+ ctx->commits.nr++;
1545
+ }
1546
+ }
1547
+}
1548
+
1549
+static int commit_compare(const void *_a, const void *_b)
1550
+{
1551
+ const struct commit *a = *(const struct commit **)_a;
1552
+ const struct commit *b = *(const struct commit **)_b;
1553
+ return oidcmp(&a->object.oid, &b->object.oid);
1554
+}
1555
+
1556
+static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
1557
+{
1558
+ uint32_t i, num_parents;
1559
+ struct commit_list *parent;
1560
+
1561
+ if (ctx->report_progress)
1562
+ ctx->progress = start_delayed_progress(
1563
+ _("Scanning merged commits"),
1564
+ ctx->commits.nr);
1565
+
1566
+ QSORT(ctx->commits.list, ctx->commits.nr, commit_compare);
1567
+
1568
+ ctx->num_extra_edges = 0;
1569
+ for (i = 0; i < ctx->commits.nr; i++) {
1570
+ display_progress(ctx->progress, i);
1571
+
1572
+ if (i && oideq(&ctx->commits.list[i - 1]->object.oid,
1573
+ &ctx->commits.list[i]->object.oid)) {
1574
+ die(_("unexpected duplicate commit id %s"),
1575
+ oid_to_hex(&ctx->commits.list[i]->object.oid));
1576
+ } else {
1577
+ num_parents = 0;
1578
+ for (parent = ctx->commits.list[i]->parents; parent; parent = parent->next)
1579
+ num_parents++;
1580
+
1581
+ if (num_parents > 2)
1582
+ ctx->num_extra_edges += num_parents - 2;
1583
+ }
1584
+ }
1585
+
1586
+ stop_progress(&ctx->progress);
1587
+}
1588
+
1589
+static void merge_commit_graphs(struct write_commit_graph_context *ctx)
1590
+{
1591
+ struct commit_graph *g = ctx->r->objects->commit_graph;
1592
+ uint32_t current_graph_number = ctx->num_commit_graphs_before;
1593
+ struct strbuf progress_title = STRBUF_INIT;
1594
+
1595
+ while (g && current_graph_number >= ctx->num_commit_graphs_after) {
1596
+ current_graph_number--;
1597
+
1598
+ if (ctx->report_progress) {
1599
+ strbuf_addstr(&progress_title, _("Merging commit-graph"));
1600
+ ctx->progress = start_delayed_progress(progress_title.buf, 0);
1601
+ }
1602
+
1603
+ merge_commit_graph(ctx, g);
1604
+ stop_progress(&ctx->progress);
1605
+ strbuf_release(&progress_title);
1606
+
1607
+ g = g->base_graph;
1608
+ }
1609
+
1610
+ if (g) {
1611
+ ctx->new_base_graph = g;
1612
+ ctx->new_num_commits_in_base = g->num_commits + g->num_commits_in_base;
1613
+ }
1614
+
1615
+ if (ctx->new_base_graph)
1616
+ ctx->base_graph_name = xstrdup(ctx->new_base_graph->filename);
1617
+
1618
+ sort_and_scan_merged_commits(ctx);
1619
+}
1620
+
1621
int write_commit_graph(const char *obj_dir,
1622
struct string_list *pack_indexes,
1623
struct string_list *commit_hex,
1663
ctx->approx_nr_objects = approximate_object_count();
1664
ctx->oids.alloc = ctx->approx_nr_objects / 32;
1665
1666
+ if (ctx->split && ctx->oids.alloc > split_strategy_max_commits)
1667
+ ctx->oids.alloc = split_strategy_max_commits;
1668
+
1669
if (ctx->append) {
1670
prepare_commit_graph_one(ctx->r, ctx->obj_dir);
1671
if (ctx->r->objects->commit_graph)
1719
if (!ctx->commits.nr)
1720
goto cleanup;
1721
1610
- if (ctx->split)
1611
- init_commit_graph_chain(ctx);
1612
- else
1722
+ if (ctx->split) {
1723
+ split_graph_merge_strategy(ctx);
1724
+
1725
+ merge_commit_graphs(ctx);
1726
+ } else
1727
ctx->num_commit_graphs_after = 1;
1728
1729
compute_generation_numbers(ctx);