summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorMichael Haggerty <mhagger@alum.mit.edu>2013-04-22 21:52:37 +0200
committerJunio C Hamano <gitster@pobox.com>2013-05-01 15:33:11 -0700
commitf85354b5c7b800912743927f4abba022444163fd (patch)
treeb836e47afa80f313f7eff7d4800421b9b9d165d3 /refs.c
parent8d3725b96fa6878fabe5ec715ff7b9f263481ea1 (diff)
downloadgit-f85354b5c7b800912743927f4abba022444163fd.tar.gz
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>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/refs.c b/refs.c
index b1c15fda80..7e4aca95bb 100644
--- a/refs.c
+++ b/refs.c
@@ -1397,7 +1397,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
@@ -1405,13 +1407,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)
@@ -1430,7 +1438,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;
@@ -1450,7 +1458,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;
@@ -1999,7 +2007,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: */
@@ -2015,13 +2023,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)) {
@@ -2162,7 +2169,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);