+int peel_ref(const char *ref, unsigned char *sha1)
+{
+ int flag;
+ unsigned char base[20];
+ struct object *o;
+
+ if (!resolve_ref(ref, base, 1, &flag))
+ return -1;
+
+ if ((flag & REF_ISPACKED)) {
+ struct ref_list *list = get_packed_refs();
+ int len = strlen(ref);
+
+ while (list) {
+ if ((list->flag & REF_ISPEELED) &&
+ !strncmp(list->name, ref, len) &&
+ strlen(list->name) == len + 3 &&
+ !strcmp(list->name + len, "^{}")) {
+ hashcpy(sha1, list->sha1);
+ return 0;
+ }
+ list = list->next;
+ }
+ /* older pack-refs did not leave peeled ones in */
+ }
+
+ /* otherwise ... */
+ o = parse_object(base);
+ if (o->type == OBJ_TAG) {
+ o = deref_tag(o, ref, 0);
+ if (o) {
+ hashcpy(sha1, o->sha1);
+ return 0;
+ }
+ }
+ return -1;
+}
+