| 469 | } |
| 470 | |
| 471 | static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, |
| 472 | const char *refname, unsigned int flags) |
| 473 | { |
| 474 | struct cache_ref_iterator *iter = |
| 475 | (struct cache_ref_iterator *)ref_iterator; |
| 476 | |
| 477 | if (flags & REF_ITERATOR_SEEK_SET_PREFIX) { |
| 478 | return cache_ref_iterator_set_prefix(iter, refname); |
| 479 | } else if (refname && *refname) { |
| 480 | struct cache_ref_iterator_level *level; |
| 481 | const char *slash = refname; |
| 482 | struct ref_dir *dir; |
| 483 | |
| 484 | dir = get_ref_dir(iter->cache->root); |
| 485 | |
| 486 | if (iter->prime_dir) |
| 487 | prime_ref_dir(dir, refname); |
| 488 | |
| 489 | iter->levels_nr = 1; |
| 490 | level = &iter->levels[0]; |
| 491 | level->index = -1; |
| 492 | level->dir = dir; |
| 493 | |
| 494 | /* Unset any previously set prefix */ |
| 495 | FREE_AND_NULL(iter->prefix); |
| 496 | |
| 497 | /* |
| 498 | * Breakdown the provided seek path and assign the correct |
| 499 | * indexing to each level as needed. |
| 500 | */ |
| 501 | do { |
| 502 | int idx; |
| 503 | size_t len; |
| 504 | int cmp = 0; |
| 505 | |
| 506 | sort_ref_dir(dir); |
| 507 | |
| 508 | slash = strchr(slash, '/'); |
| 509 | len = slash ? (size_t)(slash - refname) : strlen(refname); |
| 510 | |
| 511 | for (idx = 0; idx < dir->nr; idx++) { |
| 512 | cmp = strncmp(refname, dir->entries[idx]->name, len); |
| 513 | if (cmp <= 0) |
| 514 | break; |
| 515 | } |
| 516 | /* don't overflow the index */ |
| 517 | idx = idx >= dir->nr ? dir->nr - 1 : idx; |
| 518 | |
| 519 | if (slash) |
| 520 | slash = slash + 1; |
| 521 | |
| 522 | level->index = idx; |
| 523 | if (dir->entries[idx]->flag & REF_DIR) { |
| 524 | /* push down a level */ |
| 525 | dir = get_ref_dir(dir->entries[idx]); |
| 526 | |
| 527 | ALLOC_GROW(iter->levels, iter->levels_nr + 1, |
| 528 | iter->levels_alloc); |
no test coverage detected