@@ -362,9 +362,7 @@ struct cache_ref_iterator {
362362 struct ref_iterator base ;
363363
364364 /*
365- * The number of levels currently on the stack. This is always
366- * at least 1, because when it becomes zero the iteration is
367- * ended and this struct is freed.
365+ * The number of levels currently on the stack.
368366 */
369367 size_t levels_nr ;
370368
@@ -376,7 +374,7 @@ struct cache_ref_iterator {
376374 * The prefix is matched textually, without regard for path
377375 * component boundaries.
378376 */
379- const char * prefix ;
377+ char * prefix ;
380378
381379 /*
382380 * A stack of levels. levels[0] is the uppermost level that is
@@ -389,13 +387,19 @@ struct cache_ref_iterator {
389387 struct cache_ref_iterator_level * levels ;
390388
391389 struct repository * repo ;
390+ struct ref_cache * cache ;
391+
392+ int prime_dir ;
392393};
393394
394395static int cache_ref_iterator_advance (struct ref_iterator * ref_iterator )
395396{
396397 struct cache_ref_iterator * iter =
397398 (struct cache_ref_iterator * )ref_iterator ;
398399
400+ if (!iter -> levels_nr )
401+ return ITER_DONE ;
402+
399403 while (1 ) {
400404 struct cache_ref_iterator_level * level =
401405 & iter -> levels [iter -> levels_nr - 1 ];
@@ -444,6 +448,41 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
444448 }
445449}
446450
451+ static int cache_ref_iterator_seek (struct ref_iterator * ref_iterator ,
452+ const char * prefix )
453+ {
454+ struct cache_ref_iterator * iter =
455+ (struct cache_ref_iterator * )ref_iterator ;
456+ struct cache_ref_iterator_level * level ;
457+ struct ref_dir * dir ;
458+
459+ dir = get_ref_dir (iter -> cache -> root );
460+ if (prefix && * prefix )
461+ dir = find_containing_dir (dir , prefix );
462+ if (!dir ) {
463+ iter -> levels_nr = 0 ;
464+ return 0 ;
465+ }
466+
467+ if (iter -> prime_dir )
468+ prime_ref_dir (dir , prefix );
469+ iter -> levels_nr = 1 ;
470+ level = & iter -> levels [0 ];
471+ level -> index = -1 ;
472+ level -> dir = dir ;
473+
474+ if (prefix && * prefix ) {
475+ free (iter -> prefix );
476+ iter -> prefix = xstrdup (prefix );
477+ level -> prefix_state = PREFIX_WITHIN_DIR ;
478+ } else {
479+ FREE_AND_NULL (iter -> prefix );
480+ level -> prefix_state = PREFIX_CONTAINS_DIR ;
481+ }
482+
483+ return 0 ;
484+ }
485+
447486static int cache_ref_iterator_peel (struct ref_iterator * ref_iterator ,
448487 struct object_id * peeled )
449488{
@@ -456,12 +495,13 @@ static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
456495{
457496 struct cache_ref_iterator * iter =
458497 (struct cache_ref_iterator * )ref_iterator ;
459- free (( char * ) iter -> prefix );
498+ free (iter -> prefix );
460499 free (iter -> levels );
461500}
462501
463502static struct ref_iterator_vtable cache_ref_iterator_vtable = {
464503 .advance = cache_ref_iterator_advance ,
504+ .seek = cache_ref_iterator_seek ,
465505 .peel = cache_ref_iterator_peel ,
466506 .release = cache_ref_iterator_release ,
467507};
@@ -471,39 +511,22 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
471511 struct repository * repo ,
472512 int prime_dir )
473513{
474- struct ref_dir * dir ;
475514 struct cache_ref_iterator * iter ;
476515 struct ref_iterator * ref_iterator ;
477- struct cache_ref_iterator_level * level ;
478-
479- dir = get_ref_dir (cache -> root );
480- if (prefix && * prefix )
481- dir = find_containing_dir (dir , prefix );
482- if (!dir )
483- /* There's nothing to iterate over. */
484- return empty_ref_iterator_begin ();
485-
486- if (prime_dir )
487- prime_ref_dir (dir , prefix );
488516
489517 CALLOC_ARRAY (iter , 1 );
490518 ref_iterator = & iter -> base ;
491519 base_ref_iterator_init (ref_iterator , & cache_ref_iterator_vtable );
492520 ALLOC_GROW (iter -> levels , 10 , iter -> levels_alloc );
493521
494- iter -> levels_nr = 1 ;
495- level = & iter -> levels [0 ];
496- level -> index = -1 ;
497- level -> dir = dir ;
522+ iter -> repo = repo ;
523+ iter -> cache = cache ;
524+ iter -> prime_dir = prime_dir ;
498525
499- if (prefix && * prefix ) {
500- iter -> prefix = xstrdup (prefix );
501- level -> prefix_state = PREFIX_WITHIN_DIR ;
502- } else {
503- level -> prefix_state = PREFIX_CONTAINS_DIR ;
526+ if (cache_ref_iterator_seek (& iter -> base , prefix ) < 0 ) {
527+ ref_iterator_free (& iter -> base );
528+ return NULL ;
504529 }
505530
506- iter -> repo = repo ;
507-
508531 return ref_iterator ;
509532}
0 commit comments