@@ -1298,36 +1298,6 @@ static int write_graph_chunk_base(struct hashfile *f,
1298
1298
return 0 ;
1299
1299
}
1300
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
-
1331
1301
static int write_commit_graph_file (struct write_commit_graph_context * ctx )
1332
1302
{
1333
1303
uint32_t i ;
@@ -1509,6 +1479,145 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
1509
1479
return 0 ;
1510
1480
}
1511
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
+
1512
1621
int write_commit_graph (const char * obj_dir ,
1513
1622
struct string_list * pack_indexes ,
1514
1623
struct string_list * commit_hex ,
@@ -1554,6 +1663,9 @@ int write_commit_graph(const char *obj_dir,
1554
1663
ctx -> approx_nr_objects = approximate_object_count ();
1555
1664
ctx -> oids .alloc = ctx -> approx_nr_objects / 32 ;
1556
1665
1666
+ if (ctx -> split && ctx -> oids .alloc > split_strategy_max_commits )
1667
+ ctx -> oids .alloc = split_strategy_max_commits ;
1668
+
1557
1669
if (ctx -> append ) {
1558
1670
prepare_commit_graph_one (ctx -> r , ctx -> obj_dir );
1559
1671
if (ctx -> r -> objects -> commit_graph )
@@ -1607,9 +1719,11 @@ int write_commit_graph(const char *obj_dir,
1607
1719
if (!ctx -> commits .nr )
1608
1720
goto cleanup ;
1609
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
1613
1727
ctx -> num_commit_graphs_after = 1 ;
1614
1728
1615
1729
compute_generation_numbers (ctx );
0 commit comments