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