Skip to content

Commit f85354b

Browse files
mhaggergitster
authored andcommitted
pack_one_ref(): use function peel_entry()
Change pack_one_ref() to call peel_entry() rather than using its own code for peeling references. Aside from sharing code, this lets it take advantage of the optimization introduced by 6c4a060. Please note that we *could* use any peeled values that happen to already be stored in the ref_entries, which would avoid some object lookups for references that were already packed. But doing so would also propagate any peeling errors across runs of "git pack-refs" and give no way to recover from such errors. And "git pack-refs" isn't run often enough that the performance cost is a problem. So instead, add a new option to peel_entry() to force the entry to be re-peeled, and call it with that option set. Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8d3725b commit f85354b

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

refs.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,21 +1397,29 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh
13971397
}
13981398

13991399
/*
1400-
* Peel the entry (if possible) and return its new peel_status.
1400+
* Peel the entry (if possible) and return its new peel_status. If
1401+
* repeel is true, re-peel the entry even if there is an old peeled
1402+
* value that is already stored in it.
14011403
*
14021404
* It is OK to call this function with a packed reference entry that
14031405
* might be stale and might even refer to an object that has since
14041406
* been garbage-collected. In such a case, if the entry has
14051407
* REF_KNOWS_PEELED then leave the status unchanged and return
14061408
* PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
14071409
*/
1408-
static enum peel_status peel_entry(struct ref_entry *entry)
1410+
static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
14091411
{
14101412
enum peel_status status;
14111413

1412-
if (entry->flag & REF_KNOWS_PEELED)
1413-
return is_null_sha1(entry->u.value.peeled) ?
1414-
PEEL_NON_TAG : PEEL_PEELED;
1414+
if (entry->flag & REF_KNOWS_PEELED) {
1415+
if (repeel) {
1416+
entry->flag &= ~REF_KNOWS_PEELED;
1417+
hashclr(entry->u.value.peeled);
1418+
} else {
1419+
return is_null_sha1(entry->u.value.peeled) ?
1420+
PEEL_NON_TAG : PEEL_PEELED;
1421+
}
1422+
}
14151423
if (entry->flag & REF_ISBROKEN)
14161424
return PEEL_BROKEN;
14171425
if (entry->flag & REF_ISSYMREF)
@@ -1430,7 +1438,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
14301438

14311439
if (current_ref && (current_ref->name == refname
14321440
|| !strcmp(current_ref->name, refname))) {
1433-
if (peel_entry(current_ref))
1441+
if (peel_entry(current_ref, 0))
14341442
return -1;
14351443
hashcpy(sha1, current_ref->u.value.peeled);
14361444
return 0;
@@ -1450,7 +1458,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
14501458
if (flag & REF_ISPACKED) {
14511459
struct ref_entry *r = get_packed_ref(refname);
14521460
if (r) {
1453-
if (peel_entry(r))
1461+
if (peel_entry(r, 0))
14541462
return -1;
14551463
hashcpy(sha1, r->u.value.peeled);
14561464
return 0;
@@ -1999,7 +2007,7 @@ struct pack_refs_cb_data {
19992007
static int pack_one_ref(struct ref_entry *entry, void *cb_data)
20002008
{
20012009
struct pack_refs_cb_data *cb = cb_data;
2002-
struct object *o;
2010+
enum peel_status peel_status;
20032011
int is_tag_ref;
20042012

20052013
/* Do not pack symbolic or broken refs: */
@@ -2015,13 +2023,12 @@ static int pack_one_ref(struct ref_entry *entry, void *cb_data)
20152023
fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(entry->u.value.sha1),
20162024
entry->name);
20172025

2018-
o = parse_object_or_die(entry->u.value.sha1, entry->name);
2019-
if (o->type == OBJ_TAG) {
2020-
o = deref_tag(o, entry->name, 0);
2021-
if (o)
2022-
fprintf(cb->refs_file, "^%s\n",
2023-
sha1_to_hex(o->sha1));
2024-
}
2026+
peel_status = peel_entry(entry, 1);
2027+
if (peel_status == PEEL_PEELED)
2028+
fprintf(cb->refs_file, "^%s\n", sha1_to_hex(entry->u.value.peeled));
2029+
else if (peel_status != PEEL_NON_TAG)
2030+
die("internal error peeling reference %s (%s)",
2031+
entry->name, sha1_to_hex(entry->u.value.sha1));
20252032

20262033
/* If the ref was already packed, there is no need to prune it. */
20272034
if ((cb->flags & PACK_REFS_PRUNE) && !(entry->flag & REF_ISPACKED)) {
@@ -2162,7 +2169,7 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
21622169
return 0;
21632170
}
21642171

2165-
peel_status = peel_entry(entry);
2172+
peel_status = peel_entry(entry, 0);
21662173
write_packed_entry(*fd, entry->name, entry->u.value.sha1,
21672174
peel_status == PEEL_PEELED ?
21682175
entry->u.value.peeled : NULL);

0 commit comments

Comments
 (0)