files_pack_refs(): use reference iteration
Use reference iteration rather than `do_for_each_entry_in_dir()` in the definition of `files_pack_refs()`. This makes the code shorter and easier to follow, because the logic can be inline rather than spread between the main function and a callback function, and it removes the need to use `pack_refs_cb_data` to preserve intermediate state. This removes the last callers of `entry_resolves_to_object()` and `get_loose_ref_dir()`, so delete those functions. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Apr 16, 2017 at 08:41 UTC
50c2d8555bbc5b29625452fbcc92d4e3395e7366
1 file changed
+60
-83
refs/files-backend.c
+60
-83
@@ -32,17 +32,6 @@ static int ref_resolves_to_object(const char *refname,
32
return 1;
33
}
34
35
-/*
36
- * Return true if the reference described by entry can be resolved to
37
- * an object in the database; otherwise, emit a warning and return
38
- * false.
39
- */
40
-static int entry_resolves_to_object(struct ref_entry *entry)
41
-{
42
- return ref_resolves_to_object(entry->name,
43
- &entry->u.value.oid, entry->flag);
44
-}
45
-
35
struct packed_ref_cache {
36
struct ref_cache *cache;
37
@@ -547,11 +536,6 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
536
return refs->loose;
537
}
538
550
-static struct ref_dir *get_loose_ref_dir(struct files_ref_store *refs)
551
-{
552
- return get_ref_dir(get_loose_ref_cache(refs)->root);
553
-}
554
-
539
/*
540
* Return the ref_entry for the given refname from the packed
541
* references. If it does not exist, return NULL.
@@ -1408,65 +1392,6 @@ struct ref_to_prune {
1392
char name[FLEX_ARRAY];
1393
};
1394
1411
-struct pack_refs_cb_data {
1412
- unsigned int flags;
1413
- struct ref_dir *packed_refs;
1414
- struct ref_to_prune *ref_to_prune;
1415
-};
1416
-
1417
-/*
1418
- * An each_ref_entry_fn that is run over loose references only. If
1419
- * the loose reference can be packed, add an entry in the packed ref
1420
- * cache. If the reference should be pruned, also add it to
1421
- * ref_to_prune in the pack_refs_cb_data.
1422
- */
1423
-static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)
1424
-{
1425
- struct pack_refs_cb_data *cb = cb_data;
1426
- enum peel_status peel_status;
1427
- struct ref_entry *packed_entry;
1428
- int is_tag_ref = starts_with(entry->name, "refs/tags/");
1429
-
1430
- /* Do not pack per-worktree refs: */
1431
- if (ref_type(entry->name) != REF_TYPE_NORMAL)
1432
- return 0;
1433
-
1434
- /* ALWAYS pack tags */
1435
- if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref)
1436
- return 0;
1437
-
1438
- /* Do not pack symbolic or broken refs: */
1439
- if ((entry->flag & REF_ISSYMREF) || !entry_resolves_to_object(entry))
1440
- return 0;
1441
-
1442
- /* Add a packed ref cache entry equivalent to the loose entry. */
1443
- peel_status = peel_entry(entry, 1);
1444
- if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG)
1445
- die("internal error peeling reference %s (%s)",
1446
- entry->name, oid_to_hex(&entry->u.value.oid));
1447
- packed_entry = find_ref_entry(cb->packed_refs, entry->name);
1448
- if (packed_entry) {
1449
- /* Overwrite existing packed entry with info from loose entry */
1450
- packed_entry->flag = REF_ISPACKED | REF_KNOWS_PEELED;
1451
- oidcpy(&packed_entry->u.value.oid, &entry->u.value.oid);
1452
- } else {
1453
- packed_entry = create_ref_entry(entry->name, entry->u.value.oid.hash,
1454
- REF_ISPACKED | REF_KNOWS_PEELED, 0);
1455
- add_ref_entry(cb->packed_refs, packed_entry);
1456
- }
1457
- oidcpy(&packed_entry->u.value.peeled, &entry->u.value.peeled);
1458
-
1459
- /* Schedule the loose reference for pruning if requested. */
1460
- if ((cb->flags & PACK_REFS_PRUNE)) {
1461
- struct ref_to_prune *n;
1462
- FLEX_ALLOC_STR(n, name, entry->name);
1463
- hashcpy(n->sha1, entry->u.value.oid.hash);
1464
- n->next = cb->ref_to_prune;
1465
- cb->ref_to_prune = n;
1466
- }
1467
- return 0;
1468
-}
1469
-
1395
enum {
1396
REMOVE_EMPTY_PARENTS_REF = 0x01,
1397
REMOVE_EMPTY_PARENTS_REFLOG = 0x02
@@ -1556,21 +1481,73 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
1481
struct files_ref_store *refs =
1482
files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
1483
"pack_refs");
1559
- struct pack_refs_cb_data cbdata;
1560
-
1561
- memset(&cbdata, 0, sizeof(cbdata));
1562
- cbdata.flags = flags;
1484
+ struct ref_iterator *iter;
1485
+ struct ref_dir *packed_refs;
1486
+ int ok;
1487
+ struct ref_to_prune *refs_to_prune = NULL;
1488
1489
lock_packed_refs(refs, LOCK_DIE_ON_ERROR);
1565
- cbdata.packed_refs = get_packed_refs(refs);
1490
+ packed_refs = get_packed_refs(refs);
1491
+
1492
+ iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL, 0);
1493
+ while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
1494
+ /*
1495
+ * If the loose reference can be packed, add an entry
1496
+ * in the packed ref cache. If the reference should be
1497
+ * pruned, also add it to refs_to_prune.
1498
+ */
1499
+ struct ref_entry *packed_entry;
1500
+ int is_tag_ref = starts_with(iter->refname, "refs/tags/");
1501
+
1502
+ /* Do not pack per-worktree refs: */
1503
+ if (ref_type(iter->refname) != REF_TYPE_NORMAL)
1504
+ continue;
1505
+
1506
+ /* ALWAYS pack tags */
1507
+ if (!(flags & PACK_REFS_ALL) && !is_tag_ref)
1508
+ continue;
1509
+
1510
+ /* Do not pack symbolic or broken refs: */
1511
+ if (iter->flags & REF_ISSYMREF)
1512
+ continue;
1513
1567
- do_for_each_entry_in_dir(get_loose_ref_dir(refs),
1568
- pack_if_possible_fn, &cbdata);
1514
+ if (!ref_resolves_to_object(iter->refname, iter->oid, iter->flags))
1515
+ continue;
1516
+
1517
+ /*
1518
+ * Create an entry in the packed-refs cache equivalent
1519
+ * to the one from the loose ref cache, except that
1520
+ * we don't copy the peeled status, because we want it
1521
+ * to be re-peeled.
1522
+ */
1523
+ packed_entry = find_ref_entry(packed_refs, iter->refname);
1524
+ if (packed_entry) {
1525
+ /* Overwrite existing packed entry with info from loose entry */
1526
+ packed_entry->flag = REF_ISPACKED;
1527
+ oidcpy(&packed_entry->u.value.oid, iter->oid);
1528
+ } else {
1529
+ packed_entry = create_ref_entry(iter->refname, iter->oid->hash,
1530
+ REF_ISPACKED, 0);
1531
+ add_ref_entry(packed_refs, packed_entry);
1532
+ }
1533
+ oidclr(&packed_entry->u.value.peeled);
1534
+
1535
+ /* Schedule the loose reference for pruning if requested. */
1536
+ if ((flags & PACK_REFS_PRUNE)) {
1537
+ struct ref_to_prune *n;
1538
+ FLEX_ALLOC_STR(n, name, iter->refname);
1539
+ hashcpy(n->sha1, iter->oid->hash);
1540
+ n->next = refs_to_prune;
1541
+ refs_to_prune = n;
1542
+ }
1543
+ }
1544
+ if (ok != ITER_DONE)
1545
+ die("error while iterating over references");
1546
1547
if (commit_packed_refs(refs))
1548
die_errno("unable to overwrite old ref-pack file");
1549
1573
- prune_refs(refs, cbdata.ref_to_prune);
1550
+ prune_refs(refs, refs_to_prune);
1551
return 0;
1552
}
1553