Git fork

refs: keep track of unresolved reference value in iterators

Since ref iterators do not hold onto the direct value of a reference
without resolving it, the only way to get ahold of a direct value of a
symbolic ref is to make a separate call to refs_read_symbolic_ref.

To make accessing the direct value of a symbolic ref more efficient,
let's save the direct value of the ref in the iterators for both the
files backend and the reftable backend.

Signed-off-by: John Cai <johncai86@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

John Cai and committed by
Junio C Hamano
cfd97152 39bf06ad

+30 -5
+12 -3
refs/files-backend.c
··· 245 245 { 246 246 struct object_id oid; 247 247 int flag; 248 + const char *referent = refs_resolve_ref_unsafe(&refs->base, 249 + refname, 250 + RESOLVE_REF_READING, 251 + &oid, &flag); 248 252 249 - if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING, 250 - &oid, &flag)) { 253 + if (!referent) { 251 254 oidclr(&oid, the_repository->hash_algo); 252 255 flag |= REF_ISBROKEN; 253 256 } else if (is_null_oid(&oid)) { ··· 268 271 oidclr(&oid, the_repository->hash_algo); 269 272 flag |= REF_BAD_NAME | REF_ISBROKEN; 270 273 } 271 - add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag)); 274 + 275 + if (!(flag & REF_ISSYMREF)) 276 + referent = NULL; 277 + 278 + add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag)); 272 279 } 273 280 274 281 /* ··· 886 893 iter->base.refname = iter->iter0->refname; 887 894 iter->base.oid = iter->iter0->oid; 888 895 iter->base.flags = iter->iter0->flags; 896 + iter->base.referent = iter->iter0->referent; 897 + 889 898 return ITER_OK; 890 899 } 891 900
+2
refs/iterator.c
··· 29 29 { 30 30 iter->vtable = vtable; 31 31 iter->refname = NULL; 32 + iter->referent = NULL; 32 33 iter->oid = NULL; 33 34 iter->flags = 0; 34 35 } ··· 199 200 } 200 201 201 202 if (selection & ITER_YIELD_CURRENT) { 203 + iter->base.referent = (*iter->current)->referent; 202 204 iter->base.refname = (*iter->current)->refname; 203 205 iter->base.oid = (*iter->current)->oid; 204 206 iter->base.flags = (*iter->current)->flags;
+5
refs/ref-cache.c
··· 34 34 } 35 35 36 36 struct ref_entry *create_ref_entry(const char *refname, 37 + const char *referent, 37 38 const struct object_id *oid, int flag) 38 39 { 39 40 struct ref_entry *ref; ··· 41 42 FLEX_ALLOC_STR(ref, name, refname); 42 43 oidcpy(&ref->u.value.oid, oid); 43 44 ref->flag = flag; 45 + ref->u.value.referent = xstrdup_or_null(referent); 46 + 44 47 return ref; 45 48 } 46 49 ··· 66 69 */ 67 70 clear_ref_dir(&entry->u.subdir); 68 71 } 72 + free(entry->u.value.referent); 69 73 free(entry); 70 74 } 71 75 ··· 431 435 level->index = -1; 432 436 } else { 433 437 iter->base.refname = entry->name; 438 + iter->base.referent = entry->u.value.referent; 434 439 iter->base.oid = &entry->u.value.oid; 435 440 iter->base.flags = entry->flag; 436 441 return ITER_OK;
+2
refs/ref-cache.h
··· 42 42 * referred to by the last reference in the symlink chain. 43 43 */ 44 44 struct object_id oid; 45 + char *referent; 45 46 }; 46 47 47 48 /* ··· 173 174 const char *dirname, size_t len); 174 175 175 176 struct ref_entry *create_ref_entry(const char *refname, 177 + const char *referent, 176 178 const struct object_id *oid, int flag); 177 179 178 180 /*
+1
refs/refs-internal.h
··· 299 299 struct ref_iterator { 300 300 struct ref_iterator_vtable *vtable; 301 301 const char *refname; 302 + const char *referent; 302 303 const struct object_id *oid; 303 304 unsigned int flags; 304 305 };
+8 -2
refs/reftable-backend.c
··· 455 455 struct reftable_ref_iterator *iter = 456 456 (struct reftable_ref_iterator *)ref_iterator; 457 457 struct reftable_ref_store *refs = iter->refs; 458 + const char *referent = NULL; 458 459 459 460 while (!iter->err) { 460 461 int flags = 0; ··· 494 495 the_repository->hash_algo); 495 496 break; 496 497 case REFTABLE_REF_SYMREF: 497 - if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, 498 - RESOLVE_REF_READING, &iter->oid, &flags)) 498 + referent = refs_resolve_ref_unsafe(&iter->refs->base, 499 + iter->ref.refname, 500 + RESOLVE_REF_READING, 501 + &iter->oid, 502 + &flags); 503 + if (!referent) 499 504 oidclr(&iter->oid, the_repository->hash_algo); 500 505 break; 501 506 default: ··· 523 528 continue; 524 529 525 530 iter->base.refname = iter->ref.refname; 531 + iter->base.referent = referent; 526 532 iter->base.oid = &iter->oid; 527 533 iter->base.flags = flags; 528 534