diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2013-04-22 21:52:22 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-05-01 15:33:10 -0700 |
commit | 9a489f3c17d6c974b18c47cf406404ca2a721c87 (patch) | |
tree | 2a498f1c399ef6a01e440b706e6075c8dfcda16b /refs.c | |
parent | 2312a7932080f17c2847ec3ce5dddbc65c2e0b41 (diff) | |
download | git-9a489f3c17d6c974b18c47cf406404ca2a721c87.tar.gz |
refs: extract a function peel_entry()
Peel the entry, and as a side effect store the peeled value in the
entry. Use this function from two places in peel_ref(); a third
caller will be added soon.
Please note that this change can lead to ref_entries for unpacked refs
being peeled. This has no practical benefit but is harmless.
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.c | 63 |
1 files changed, 49 insertions, 14 deletions
@@ -1286,7 +1286,17 @@ enum peel_status { PEEL_INVALID = -1, /* object cannot be peeled because it is not a tag: */ - PEEL_NON_TAG = -2 + PEEL_NON_TAG = -2, + + /* ref_entry contains no peeled value because it is a symref: */ + PEEL_IS_SYMREF = -3, + + /* + * ref_entry cannot be peeled because it is broken (i.e., the + * symbolic reference cannot even be resolved to an object + * name): + */ + PEEL_BROKEN = -4 }; /* @@ -1318,31 +1328,56 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh return PEEL_PEELED; } +/* + * Peel the entry (if possible) and return its new peel_status. + */ +static enum peel_status peel_entry(struct ref_entry *entry) +{ + 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_ISBROKEN) + return PEEL_BROKEN; + if (entry->flag & REF_ISSYMREF) + return PEEL_IS_SYMREF; + + status = peel_object(entry->u.value.sha1, entry->u.value.peeled); + if (status == PEEL_PEELED || status == PEEL_NON_TAG) + entry->flag |= REF_KNOWS_PEELED; + return status; +} + int peel_ref(const char *refname, unsigned char *sha1) { int flag; unsigned char base[20]; if (current_ref && (current_ref->name == refname - || !strcmp(current_ref->name, refname))) { - if (current_ref->flag & REF_KNOWS_PEELED) { - if (is_null_sha1(current_ref->u.value.peeled)) - return -1; - hashcpy(sha1, current_ref->u.value.peeled); - return 0; - } - return peel_object(current_ref->u.value.sha1, sha1); + || !strcmp(current_ref->name, refname))) { + if (peel_entry(current_ref)) + return -1; + hashcpy(sha1, current_ref->u.value.peeled); + return 0; } if (read_ref_full(refname, base, 1, &flag)) return -1; - if ((flag & REF_ISPACKED)) { + /* + * If the reference is packed, read its ref_entry from the + * cache in the hope that we already know its peeled value. + * We only try this optimization on packed references because + * (a) forcing the filling of the loose reference cache could + * be expensive and (b) loose references anyway usually do not + * have REF_KNOWS_PEELED. + */ + if (flag & REF_ISPACKED) { struct ref_entry *r = get_packed_ref(refname); - - if (r && (r->flag & REF_KNOWS_PEELED)) { - if (is_null_sha1(r->u.value.peeled)) - return -1; + if (r) { + if (peel_entry(r)) + return -1; hashcpy(sha1, r->u.value.peeled); return 0; } |