@@ -1277,36 +1277,6 @@ static int write_graph_chunk_base(struct hashfile *f,
1277
1277
return 0 ;
1278
1278
}
1279
1279
1280
- static void init_commit_graph_chain (struct write_commit_graph_context * ctx )
1281
- {
1282
- struct commit_graph * g = ctx -> r -> objects -> commit_graph ;
1283
- uint32_t i ;
1284
-
1285
- ctx -> new_base_graph = g ;
1286
- ctx -> base_graph_name = xstrdup (g -> filename );
1287
- ctx -> new_num_commits_in_base = g -> num_commits + g -> num_commits_in_base ;
1288
-
1289
- ctx -> num_commit_graphs_after = ctx -> num_commit_graphs_before + 1 ;
1290
-
1291
- ALLOC_ARRAY (ctx -> commit_graph_filenames_after , ctx -> num_commit_graphs_after );
1292
- ALLOC_ARRAY (ctx -> commit_graph_hash_after , ctx -> num_commit_graphs_after );
1293
-
1294
- for (i = 0 ; i < ctx -> num_commit_graphs_before - 1 ; i ++ )
1295
- ctx -> commit_graph_filenames_after [i ] = xstrdup (ctx -> commit_graph_filenames_before [i ]);
1296
-
1297
- if (ctx -> num_commit_graphs_before )
1298
- ctx -> commit_graph_filenames_after [ctx -> num_commit_graphs_before - 1 ] =
1299
- get_split_graph_filename (ctx -> obj_dir , oid_to_hex (& g -> oid ));
1300
-
1301
- i = ctx -> num_commit_graphs_before - 1 ;
1302
-
1303
- while (g ) {
1304
- ctx -> commit_graph_hash_after [i ] = xstrdup (oid_to_hex (& g -> oid ));
1305
- i -- ;
1306
- g = g -> base_graph ;
1307
- }
1308
- }
1309
-
1310
1280
static int write_commit_graph_file (struct write_commit_graph_context * ctx )
1311
1281
{
1312
1282
uint32_t i ;
@@ -1484,6 +1454,155 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
1484
1454
return 0 ;
1485
1455
}
1486
1456
1457
+ static int split_strategy_max_commits = 64000 ;
1458
+ static float split_strategy_size_mult = 2.0f ;
1459
+
1460
+ static void split_graph_merge_strategy (struct write_commit_graph_context * ctx )
1461
+ {
1462
+ struct commit_graph * g = ctx -> r -> objects -> commit_graph ;
1463
+ uint32_t num_commits = ctx -> commits .nr ;
1464
+ uint32_t i ;
1465
+
1466
+ g = ctx -> r -> objects -> commit_graph ;
1467
+ ctx -> num_commit_graphs_after = ctx -> num_commit_graphs_before + 1 ;
1468
+
1469
+ while (g && (g -> num_commits <= split_strategy_size_mult * num_commits ||
1470
+ num_commits > split_strategy_max_commits )) {
1471
+ num_commits += g -> num_commits ;
1472
+ g = g -> base_graph ;
1473
+
1474
+ ctx -> num_commit_graphs_after -- ;
1475
+ }
1476
+
1477
+ ctx -> new_base_graph = g ;
1478
+
1479
+ ALLOC_ARRAY (ctx -> commit_graph_filenames_after , ctx -> num_commit_graphs_after );
1480
+ ALLOC_ARRAY (ctx -> commit_graph_hash_after , ctx -> num_commit_graphs_after );
1481
+
1482
+ for (i = 0 ; i < ctx -> num_commit_graphs_after &&
1483
+ i < ctx -> num_commit_graphs_before ; i ++ )
1484
+ ctx -> commit_graph_filenames_after [i ] = xstrdup (ctx -> commit_graph_filenames_before [i ]);
1485
+
1486
+ i = ctx -> num_commit_graphs_before - 1 ;
1487
+ g = ctx -> r -> objects -> commit_graph ;
1488
+
1489
+ while (g ) {
1490
+ if (i < ctx -> num_commit_graphs_after )
1491
+ ctx -> commit_graph_hash_after [i ] = xstrdup (oid_to_hex (& g -> oid ));
1492
+
1493
+ i -- ;
1494
+ g = g -> base_graph ;
1495
+ }
1496
+ }
1497
+
1498
+ static void merge_commit_graph (struct write_commit_graph_context * ctx ,
1499
+ struct commit_graph * g )
1500
+ {
1501
+ uint32_t i ;
1502
+ uint32_t offset = g -> num_commits_in_base ;
1503
+
1504
+ ALLOC_GROW (ctx -> commits .list , ctx -> commits .nr + g -> num_commits , ctx -> commits .alloc );
1505
+
1506
+ for (i = 0 ; i < g -> num_commits ; i ++ ) {
1507
+ struct object_id oid ;
1508
+ struct commit * result ;
1509
+
1510
+ display_progress (ctx -> progress , i + 1 );
1511
+
1512
+ load_oid_from_graph (g , i + offset , & oid );
1513
+
1514
+ /* only add commits if they still exist in the repo */
1515
+ result = lookup_commit_reference_gently (ctx -> r , & oid , 1 );
1516
+
1517
+ if (result ) {
1518
+ ctx -> commits .list [ctx -> commits .nr ] = result ;
1519
+ ctx -> commits .nr ++ ;
1520
+ }
1521
+ }
1522
+ }
1523
+
1524
+ static int commit_compare (const void * _a , const void * _b )
1525
+ {
1526
+ const struct commit * a = * (const struct commit * * )_a ;
1527
+ const struct commit * b = * (const struct commit * * )_b ;
1528
+ return oidcmp (& a -> object .oid , & b -> object .oid );
1529
+ }
1530
+
1531
+ static void deduplicate_commits (struct write_commit_graph_context * ctx )
1532
+ {
1533
+ uint32_t i , num_parents , last_distinct = 0 , duplicates = 0 ;
1534
+ struct commit_list * parent ;
1535
+
1536
+ if (ctx -> report_progress )
1537
+ ctx -> progress = start_delayed_progress (
1538
+ _ ("De-duplicating merged commits" ),
1539
+ ctx -> commits .nr );
1540
+
1541
+ QSORT (ctx -> commits .list , ctx -> commits .nr , commit_compare );
1542
+
1543
+ ctx -> num_extra_edges = 0 ;
1544
+ for (i = 1 ; i < ctx -> commits .nr ; i ++ ) {
1545
+ display_progress (ctx -> progress , i );
1546
+
1547
+ if (oideq (& ctx -> commits .list [last_distinct ]-> object .oid ,
1548
+ & ctx -> commits .list [i ]-> object .oid )) {
1549
+ duplicates ++ ;
1550
+ } else {
1551
+ if (duplicates )
1552
+ ctx -> commits .list [last_distinct + 1 ] = ctx -> commits .list [i ];
1553
+ last_distinct ++ ;
1554
+
1555
+ num_parents = 0 ;
1556
+ for (parent = ctx -> commits .list [i ]-> parents ; parent ; parent = parent -> next )
1557
+ num_parents ++ ;
1558
+
1559
+ if (num_parents > 2 )
1560
+ ctx -> num_extra_edges += num_parents - 2 ;
1561
+ }
1562
+ }
1563
+
1564
+ ctx -> commits .nr -= duplicates ;
1565
+ stop_progress (& ctx -> progress );
1566
+ }
1567
+
1568
+ static void merge_commit_graphs (struct write_commit_graph_context * ctx )
1569
+ {
1570
+ struct commit_graph * g = ctx -> r -> objects -> commit_graph ;
1571
+ uint32_t current_graph_number = ctx -> num_commit_graphs_before ;
1572
+ struct strbuf progress_title = STRBUF_INIT ;
1573
+
1574
+ while (g && current_graph_number >= ctx -> num_commit_graphs_after ) {
1575
+ current_graph_number -- ;
1576
+
1577
+ if (ctx -> report_progress ) {
1578
+ if (current_graph_number )
1579
+ strbuf_addf (& progress_title ,
1580
+ _ ("Merging commit-graph-%d" ),
1581
+ current_graph_number );
1582
+ else
1583
+ strbuf_addstr (& progress_title ,
1584
+ _ ("Merging commit-graph" ));
1585
+ ctx -> progress = start_delayed_progress (progress_title .buf , 0 );
1586
+ }
1587
+
1588
+ merge_commit_graph (ctx , g );
1589
+ stop_progress (& ctx -> progress );
1590
+ strbuf_release (& progress_title );
1591
+
1592
+ g = g -> base_graph ;
1593
+ }
1594
+
1595
+ if (g ) {
1596
+ ctx -> new_base_graph = g ;
1597
+ ctx -> new_num_commits_in_base = g -> num_commits + g -> num_commits_in_base ;
1598
+ }
1599
+
1600
+ if (ctx -> new_base_graph )
1601
+ ctx -> base_graph_name = xstrdup (ctx -> new_base_graph -> filename );
1602
+
1603
+ deduplicate_commits (ctx );
1604
+ }
1605
+
1487
1606
int write_commit_graph (const char * obj_dir ,
1488
1607
struct string_list * pack_indexes ,
1489
1608
struct string_list * commit_hex ,
@@ -1529,6 +1648,9 @@ int write_commit_graph(const char *obj_dir,
1529
1648
ctx -> approx_nr_objects = approximate_object_count ();
1530
1649
ctx -> oids .alloc = ctx -> approx_nr_objects / 32 ;
1531
1650
1651
+ if (ctx -> split && ctx -> oids .alloc > split_strategy_max_commits )
1652
+ ctx -> oids .alloc = split_strategy_max_commits ;
1653
+
1532
1654
if (ctx -> append ) {
1533
1655
prepare_commit_graph_one (ctx -> r , ctx -> obj_dir );
1534
1656
if (ctx -> r -> objects -> commit_graph )
@@ -1582,9 +1704,11 @@ int write_commit_graph(const char *obj_dir,
1582
1704
if (!ctx -> commits .nr )
1583
1705
goto cleanup ;
1584
1706
1585
- if (ctx -> split )
1586
- init_commit_graph_chain (ctx );
1587
- else
1707
+ if (ctx -> split ) {
1708
+ split_graph_merge_strategy (ctx );
1709
+
1710
+ merge_commit_graphs (ctx );
1711
+ } else
1588
1712
ctx -> num_commit_graphs_after = 1 ;
1589
1713
1590
1714
compute_generation_numbers (ctx );
0 commit comments