300
301
struct stat st;
302
int fd;
303
+ struct commit_graph *g;
304
int open_ok = open_commit_graph(graph_file, &fd, &st);
305
306
if (!open_ok)
307
return NULL;
308
308
- return load_commit_graph_one_fd_st(fd, &st);
309
+ g = load_commit_graph_one_fd_st(fd, &st);
310
+
311
+ if (g)
312
+ g->filename = xstrdup(graph_file);
313
+
314
+ return g;
315
}
316
317
static struct commit_graph *load_commit_graph_v1(struct repository *r, const char *obj_dir)
736
struct progress *progress;
737
int progress_done;
738
uint64_t progress_cnt;
739
+
740
+ char *base_graph_name;
741
+ int num_commit_graphs_before;
742
+ int num_commit_graphs_after;
743
+ char **commit_graph_filenames_before;
744
+ char **commit_graph_filenames_after;
745
+ char **commit_graph_hash_after;
746
+ uint32_t new_num_commits_in_base;
747
+ struct commit_graph *new_base_graph;
748
+
749
unsigned append:1,
734
- report_progress:1;
750
+ report_progress:1,
751
+ split:1;
752
};
753
754
static void write_graph_chunk_fanout(struct hashfile *f,
818
ctx->commits.nr,
819
commit_to_sha1);
820
821
+ if (edge_value >= 0)
822
+ edge_value += ctx->new_num_commits_in_base;
823
+ else {
824
+ uint32_t pos;
825
+ if (find_commit_in_graph(parent->item,
826
+ ctx->new_base_graph,
827
+ &pos))
828
+ edge_value = pos;
829
+ }
830
+
831
if (edge_value < 0)
832
BUG("missing parent %s for commit %s",
833
oid_to_hex(&parent->item->object.oid),
848
ctx->commits.list,
849
ctx->commits.nr,
850
commit_to_sha1);
851
+
852
+ if (edge_value >= 0)
853
+ edge_value += ctx->new_num_commits_in_base;
854
+ else {
855
+ uint32_t pos;
856
+ if (find_commit_in_graph(parent->item,
857
+ ctx->new_base_graph,
858
+ &pos))
859
+ edge_value = pos;
860
+ }
861
+
862
if (edge_value < 0)
863
BUG("missing parent %s for commit %s",
864
oid_to_hex(&parent->item->object.oid),
916
ctx->commits.nr,
917
commit_to_sha1);
918
919
+ if (edge_value >= 0)
920
+ edge_value += ctx->new_num_commits_in_base;
921
+ else {
922
+ uint32_t pos;
923
+ if (find_commit_in_graph(parent->item,
924
+ ctx->new_base_graph,
925
+ &pos))
926
+ edge_value = pos;
927
+ }
928
+
929
if (edge_value < 0)
930
BUG("missing parent %s for commit %s",
931
oid_to_hex(&parent->item->object.oid),
1017
display_progress(ctx->progress, i + 1);
1018
commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
1019
972
- if (commit && !parse_commit_no_graph(commit))
1020
+ if (!commit)
1021
+ continue;
1022
+ if (ctx->split) {
1023
+ if (!parse_commit(commit) &&
1024
+ commit->graph_pos == COMMIT_NOT_FROM_GRAPH)
1025
+ add_missing_parents(ctx, commit);
1026
+ } else if (!parse_commit_no_graph(commit))
1027
add_missing_parents(ctx, commit);
1028
}
1029
stop_progress(&ctx->progress);
1219
1220
for (i = 1; i < ctx->oids.nr; i++) {
1221
display_progress(ctx->progress, i + 1);
1168
- if (!oideq(&ctx->oids.list[i - 1], &ctx->oids.list[i]))
1222
+ if (!oideq(&ctx->oids.list[i - 1], &ctx->oids.list[i])) {
1223
+ if (ctx->split) {
1224
+ struct commit *c = lookup_commit(ctx->r, &ctx->oids.list[i]);
1225
+
1226
+ if (!c || c->graph_pos != COMMIT_NOT_FROM_GRAPH)
1227
+ continue;
1228
+ }
1229
+
1230
count_distinct++;
1231
+ }
1232
}
1233
stop_progress(&ctx->progress);
1234
1251
if (i > 0 && oideq(&ctx->oids.list[i - 1], &ctx->oids.list[i]))
1252
continue;
1253
1254
+ ALLOC_GROW(ctx->commits.list, ctx->commits.nr + 1, ctx->commits.alloc);
1255
ctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.list[i]);
1256
+
1257
+ if (ctx->split &&
1258
+ ctx->commits.list[ctx->commits.nr]->graph_pos != COMMIT_NOT_FROM_GRAPH)
1259
+ continue;
1260
+
1261
parse_commit_no_graph(ctx->commits.list[ctx->commits.nr]);
1262
1263
for (parent = ctx->commits.list[ctx->commits.nr]->parents;
1272
stop_progress(&ctx->progress);
1273
}
1274
1275
+static int write_graph_chunk_base_1(struct hashfile *f,
1276
+ struct commit_graph *g)
1277
+{
1278
+ int num = 0;
1279
+
1280
+ if (!g)
1281
+ return 0;
1282
+
1283
+ num = write_graph_chunk_base_1(f, g->base_graph);
1284
+ hashwrite(f, g->oid.hash, the_hash_algo->rawsz);
1285
+ return num + 1;
1286
+}
1287
+
1288
+static int write_graph_chunk_base(struct hashfile *f,
1289
+ struct write_commit_graph_context *ctx)
1290
+{
1291
+ int num = write_graph_chunk_base_1(f, ctx->new_base_graph);
1292
+
1293
+ if (num != ctx->num_commit_graphs_after - 1) {
1294
+ error(_("failed to write correct number of base graph ids"));
1295
+ return -1;
1296
+ }
1297
+
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
+
1331
static int write_commit_graph_file(struct write_commit_graph_context *ctx)
1332
{
1333
uint32_t i;
1334
+ int fd;
1335
struct hashfile *f;
1336
struct lock_file lk = LOCK_INIT;
1212
- uint32_t chunk_ids[5];
1213
- uint64_t chunk_offsets[5];
1337
+ uint32_t chunk_ids[6];
1338
+ uint64_t chunk_offsets[6];
1339
const unsigned hashsz = the_hash_algo->rawsz;
1340
struct strbuf progress_title = STRBUF_INIT;
1341
int num_chunks = 3;
1342
+ struct object_id file_hash;
1343
+
1344
+ if (ctx->split) {
1345
+ struct strbuf tmp_file = STRBUF_INIT;
1346
+
1347
+ strbuf_addf(&tmp_file,
1348
+ "%s/info/commit-graphs/tmp_graph_XXXXXX",
1349
+ ctx->obj_dir);
1350
+ ctx->graph_name = strbuf_detach(&tmp_file, NULL);
1351
+ } else {
1352
+ ctx->graph_name = get_commit_graph_filename(ctx->obj_dir);
1353
+ }
1354
1218
- ctx->graph_name = get_commit_graph_filename(ctx->obj_dir);
1355
if (safe_create_leading_directories(ctx->graph_name)) {
1356
UNLEAK(ctx->graph_name);
1357
error(_("unable to create leading directories of %s"),
1359
return -1;
1360
}
1361
1226
- hold_lock_file_for_update(&lk, ctx->graph_name, LOCK_DIE_ON_ERROR);
1227
- f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
1362
+ if (ctx->split) {
1363
+ char *lock_name = get_chain_filename(ctx->obj_dir);
1364
+
1365
+ hold_lock_file_for_update(&lk, lock_name, LOCK_DIE_ON_ERROR);
1366
+
1367
+ fd = git_mkstemp_mode(ctx->graph_name, 0444);
1368
+ if (fd < 0) {
1369
+ error(_("unable to create '%s'"), ctx->graph_name);
1370
+ return -1;
1371
+ }
1372
+
1373
+ f = hashfd(fd, ctx->graph_name);
1374
+ } else {
1375
+ hold_lock_file_for_update(&lk, ctx->graph_name, LOCK_DIE_ON_ERROR);
1376
+ fd = lk.tempfile->fd;
1377
+ f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
1378
+ }
1379
1380
chunk_ids[0] = GRAPH_CHUNKID_OIDFANOUT;
1381
chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
1384
chunk_ids[num_chunks] = GRAPH_CHUNKID_EXTRAEDGES;
1385
num_chunks++;
1386
}
1387
+ if (ctx->num_commit_graphs_after > 1) {
1388
+ chunk_ids[num_chunks] = GRAPH_CHUNKID_BASE;
1389
+ num_chunks++;
1390
+ }
1391
1392
chunk_ids[num_chunks] = 0;
1393
1402
4 * ctx->num_extra_edges;
1403
num_chunks++;
1404
}
1405
+ if (ctx->num_commit_graphs_after > 1) {
1406
+ chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
1407
+ hashsz * (ctx->num_commit_graphs_after - 1);
1408
+ num_chunks++;
1409
+ }
1410
1411
hashwrite_be32(f, GRAPH_SIGNATURE);
1412
1413
hashwrite_u8(f, GRAPH_VERSION);
1414
hashwrite_u8(f, oid_version());
1415
hashwrite_u8(f, num_chunks);
1256
- hashwrite_u8(f, 0);
1416
+ hashwrite_u8(f, ctx->num_commit_graphs_after - 1);
1417
1418
for (i = 0; i <= num_chunks; i++) {
1419
uint32_t chunk_write[3];
1439
write_graph_chunk_data(f, hashsz, ctx);
1440
if (ctx->num_extra_edges)
1441
write_graph_chunk_extra_edges(f, ctx);
1442
+ if (ctx->num_commit_graphs_after > 1 &&
1443
+ write_graph_chunk_base(f, ctx)) {
1444
+ return -1;
1445
+ }
1446
stop_progress(&ctx->progress);
1447
strbuf_release(&progress_title);
1448
1449
+ if (ctx->split && ctx->base_graph_name && ctx->num_commit_graphs_after > 1) {
1450
+ char *new_base_hash = xstrdup(oid_to_hex(&ctx->new_base_graph->oid));
1451
+ char *new_base_name = get_split_graph_filename(ctx->obj_dir, new_base_hash);
1452
+
1453
+ free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
1454
+ free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2]);
1455
+ ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2] = new_base_name;
1456
+ ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2] = new_base_hash;
1457
+ }
1458
+
1459
close_commit_graph(ctx->r->objects);
1286
- finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
1460
+ finalize_hashfile(f, file_hash.hash, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
1461
+
1462
+ if (ctx->split) {
1463
+ FILE *chainf = fdopen_lock_file(&lk, "w");
1464
+ char *final_graph_name;
1465
+ int result;
1466
+
1467
+ close(fd);
1468
+
1469
+ if (!chainf) {
1470
+ error(_("unable to open commit-graph chain file"));
1471
+ return -1;
1472
+ }
1473
+
1474
+ if (ctx->base_graph_name) {
1475
+ result = rename(ctx->base_graph_name,
1476
+ ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
1477
+
1478
+ if (result) {
1479
+ error(_("failed to rename base commit-graph file"));
1480
+ return -1;
1481
+ }
1482
+ } else {
1483
+ char *graph_name = get_commit_graph_filename(ctx->obj_dir);
1484
+ unlink(graph_name);
1485
+ }
1486
+
1487
+ ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(oid_to_hex(&file_hash));
1488
+ final_graph_name = get_split_graph_filename(ctx->obj_dir,
1489
+ ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
1490
+ ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1] = final_graph_name;
1491
+
1492
+ result = rename(ctx->graph_name, final_graph_name);
1493
+
1494
+ for (i = 0; i < ctx->num_commit_graphs_after; i++)
1495
+ fprintf(lk.tempfile->fp, "%s\n", ctx->commit_graph_hash_after[i]);
1496
+
1497
+ if (result) {
1498
+ error(_("failed to rename temporary commit-graph file"));
1499
+ return -1;
1500
+ }
1501
+ }
1502
+
1503
commit_lock_file(&lk);
1504
1505
return 0;
1522
ctx->obj_dir = obj_dir;
1523
ctx->append = flags & COMMIT_GRAPH_APPEND ? 1 : 0;
1524
ctx->report_progress = flags & COMMIT_GRAPH_PROGRESS ? 1 : 0;
1525
+ ctx->split = flags & COMMIT_GRAPH_SPLIT ? 1 : 0;
1526
+
1527
+ if (ctx->split) {
1528
+ struct commit_graph *g;
1529
+ prepare_commit_graph(ctx->r);
1530
+
1531
+ g = ctx->r->objects->commit_graph;
1532
+
1533
+ while (g) {
1534
+ ctx->num_commit_graphs_before++;
1535
+ g = g->base_graph;
1536
+ }
1537
+
1538
+ if (ctx->num_commit_graphs_before) {
1539
+ ALLOC_ARRAY(ctx->commit_graph_filenames_before, ctx->num_commit_graphs_before);
1540
+ i = ctx->num_commit_graphs_before;
1541
+ g = ctx->r->objects->commit_graph;
1542
+
1543
+ while (g) {
1544
+ ctx->commit_graph_filenames_before[--i] = xstrdup(g->filename);
1545
+ g = g->base_graph;
1546
+ }
1547
+ }
1548
+ }
1549
1550
ctx->approx_nr_objects = approximate_object_count();
1551
ctx->oids.alloc = ctx->approx_nr_objects / 32;
1600
goto cleanup;
1601
}
1602
1603
+ if (!ctx->commits.nr)
1604
+ goto cleanup;
1605
+
1606
+ if (ctx->split)
1607
+ init_commit_graph_chain(ctx);
1608
+ else
1609
+ ctx->num_commit_graphs_after = 1;
1610
+
1611
compute_generation_numbers(ctx);
1612
1613
res = write_commit_graph_file(ctx);
1616
free(ctx->graph_name);
1617
free(ctx->commits.list);
1618
free(ctx->oids.list);
1619
+
1620
+ if (ctx->commit_graph_filenames_after) {
1621
+ for (i = 0; i < ctx->num_commit_graphs_after; i++) {
1622
+ free(ctx->commit_graph_filenames_after[i]);
1623
+ free(ctx->commit_graph_hash_after[i]);
1624
+ }
1625
+
1626
+ for (i = 0; i < ctx->num_commit_graphs_before; i++)
1627
+ free(ctx->commit_graph_filenames_before[i]);
1628
+
1629
+ free(ctx->commit_graph_filenames_after);
1630
+ free(ctx->commit_graph_filenames_before);
1631
+ free(ctx->commit_graph_hash_after);
1632
+ }
1633
+
1634
free(ctx);
1635
1636
return res;
1818
g->data = NULL;
1819
close(g->graph_fd);
1820
}
1821
+ free(g->filename);
1822
free(g);
1823
}