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 6c4a060d7d. 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 <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Apr 22, 2013 at 21:52 UTC f85354b5c7b800912743927f4abba022444163fd
1 file changed +23 -16
refs.c
+23 -16
@@ -1397,7 +1397,9 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh
1397 }
1398
1399 /*
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.
1403 *
1404 * It is OK to call this function with a packed reference entry that
1405 * might be stale and might even refer to an object that has since
@@ -1405,13 +1407,19 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh
1407 * REF_KNOWS_PEELED then leave the status unchanged and return
1408 * PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
1409 */
1408 -static enum peel_status peel_entry(struct ref_entry *entry)
1410 +static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
1411 {
1412 enum peel_status status;
1413
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 + }
1423 if (entry->flag & REF_ISBROKEN)
1424 return PEEL_BROKEN;
1425 if (entry->flag & REF_ISSYMREF)
@@ -1430,7 +1438,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
1438
1439 if (current_ref && (current_ref->name == refname
1440 || !strcmp(current_ref->name, refname))) {
1433 - if (peel_entry(current_ref))
1441 + if (peel_entry(current_ref, 0))
1442 return -1;
1443 hashcpy(sha1, current_ref->u.value.peeled);
1444 return 0;
@@ -1450,7 +1458,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
1458 if (flag & REF_ISPACKED) {
1459 struct ref_entry *r = get_packed_ref(refname);
1460 if (r) {
1453 - if (peel_entry(r))
1461 + if (peel_entry(r, 0))
1462 return -1;
1463 hashcpy(sha1, r->u.value.peeled);
1464 return 0;
@@ -1999,7 +2007,7 @@ struct pack_refs_cb_data {
2007 static int pack_one_ref(struct ref_entry *entry, void *cb_data)
2008 {
2009 struct pack_refs_cb_data *cb = cb_data;
2002 - struct object *o;
2010 + enum peel_status peel_status;
2011 int is_tag_ref;
2012
2013 /* Do not pack symbolic or broken refs: */
@@ -2015,13 +2023,12 @@ static int pack_one_ref(struct ref_entry *entry, void *cb_data)
2023 fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(entry->u.value.sha1),
2024 entry->name);
2025
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));
2032
2033 /* If the ref was already packed, there is no need to prune it. */
2034 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)
2169 return 0;
2170 }
2171
2165 - peel_status = peel_entry(entry);
2172 + peel_status = peel_entry(entry, 0);
2173 write_packed_entry(*fd, entry->name, entry->u.value.sha1,
2174 peel_status == PEEL_PEELED ?
2175 entry->u.value.peeled : NULL);