On Mon, May 22, 2017 at 04:17:55PM +0200, Michael Haggerty wrote: > So: > > * Move the responsibility for doing the prefix check directly to > `cache_ref_iterator`. This means that `cache_ref_iterator_begin()` > never has to wrap its return value in a `prefix_ref_iterator`. > > * Teach `cache_ref_iterator_begin()` (and `prime_ref_dir()`) to be > stricter about what they iterate over and what directories they > prime. > > * Teach `cache_ref_iterator` to keep track of whether the current > `cache_ref_iterator_level` is fully within the prefix. If so, skip > the prefix checks entirely. As promised, I came back to this one with a more careful eye. These changes all make sense to me, and the implementation matches. My only question is: > @@ -511,9 +582,12 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, > level->index = -1; > level->dir = dir; > > - if (prefix && *prefix) > - ref_iterator = prefix_ref_iterator_begin(ref_iterator, > - prefix, 0); > + if (prefix && *prefix) { > + iter->prefix = xstrdup(prefix); > + level->prefix_state = PREFIX_WITHIN_DIR; > + } else { > + level->prefix_state = PREFIX_CONTAINS_DIR; > + } Who frees the prefix? Does this need: diff --git a/refs/ref-cache.c b/refs/ref-cache.c index fda3942db..a3efc5c51 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -542,6 +542,7 @@ static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator) struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; + free(iter->prefix); free(iter->levels); base_ref_iterator_free(ref_iterator); return ITER_DONE; -Peff