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 <mhag...@alum.mit.edu>
---
 refs.c | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/refs.c b/refs.c
index f78e955..f2d83f3 100644
--- a/refs.c
+++ b/refs.c
@@ -1396,7 +1396,9 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
 }
 
 /*
- * Peel the entry (if possible) and return its new peel_status.
+ * Peel the entry (if possible) and return its new peel_status.  If
+ * repeel is true, re-peel the entry even if there is an old peeled
+ * value that is already stored in it.
  *
  * It is OK to call this function with a packed reference entry that
  * might be stale and might even refer to an object that has since
@@ -1404,13 +1406,19 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
  * REF_KNOWS_PEELED then leave the status unchanged and return
  * PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
  */
-static enum peel_status peel_entry(struct ref_entry *entry)
+static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
 {
        enum peel_status status;
 
-       if (entry->flag & REF_KNOWS_PEELED)
-               return is_null_sha1(entry->u.value.peeled) ?
-                       PEEL_NON_TAG : PEEL_PEELED;
+       if (entry->flag & REF_KNOWS_PEELED) {
+               if (repeel) {
+                       entry->flag &= ~REF_KNOWS_PEELED;
+                       hashclr(entry->u.value.peeled);
+               } else {
+                       return is_null_sha1(entry->u.value.peeled) ?
+                               PEEL_NON_TAG : PEEL_PEELED;
+               }
+       }
        if (entry->flag & REF_ISBROKEN)
                return PEEL_BROKEN;
        if (entry->flag & REF_ISSYMREF)
@@ -1429,7 +1437,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
 
        if (current_ref && (current_ref->name == refname
                            || !strcmp(current_ref->name, refname))) {
-               if (peel_entry(current_ref))
+               if (peel_entry(current_ref, 0))
                        return -1;
                hashcpy(sha1, current_ref->u.value.peeled);
                return 0;
@@ -1449,7 +1457,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
        if (flag & REF_ISPACKED) {
                struct ref_entry *r = get_packed_ref(refname);
                if (r) {
-                       if (peel_entry(r))
+                       if (peel_entry(r, 0))
                                return -1;
                        hashcpy(sha1, r->u.value.peeled);
                        return 0;
@@ -1998,7 +2006,7 @@ struct pack_refs_cb_data {
 static int pack_one_ref(struct ref_entry *entry, void *cb_data)
 {
        struct pack_refs_cb_data *cb = cb_data;
-       struct object *o;
+       enum peel_status peel_status;
        int is_tag_ref;
 
        /* Do not pack symbolic or broken refs: */
@@ -2014,13 +2022,12 @@ static int pack_one_ref(struct ref_entry *entry, void 
*cb_data)
        fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(entry->u.value.sha1),
                entry->name);
 
-       o = parse_object_or_die(entry->u.value.sha1, entry->name);
-       if (o->type == OBJ_TAG) {
-               o = deref_tag(o, entry->name, 0);
-               if (o)
-                       fprintf(cb->refs_file, "^%s\n",
-                               sha1_to_hex(o->sha1));
-       }
+       peel_status = peel_entry(entry, 1);
+       if (peel_status == PEEL_PEELED)
+               fprintf(cb->refs_file, "^%s\n", 
sha1_to_hex(entry->u.value.peeled));
+       else if (peel_status != PEEL_NON_TAG)
+               die("internal error peeling reference %s (%s)",
+                   entry->name, sha1_to_hex(entry->u.value.sha1));
 
        /* If the ref was already packed, there is no need to prune it. */
        if ((cb->flags & PACK_REFS_PRUNE) && !(entry->flag & REF_ISPACKED)) {
@@ -2161,7 +2168,7 @@ static int repack_ref_fn(struct ref_entry *entry, void 
*cb_data)
                return 0;
        }
 
-       peel_status = peel_entry(entry);
+       peel_status = peel_entry(entry, 0);
        write_packed_entry(*fd, entry->name, entry->u.value.sha1,
                           peel_status == PEEL_PEELED ?
                           entry->u.value.peeled : NULL);
-- 
1.8.2.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to