@@ -498,13 +498,14 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
498
498
* itself - the caller needs to do the final check for the cache
499
499
* entry having more data at the end!
500
500
*/
501
- static int do_compare_entry (const struct cache_entry * ce , const struct traverse_info * info , const struct name_entry * n )
501
+ static int do_compare_entry_piecewise (const struct cache_entry * ce , const struct traverse_info * info , const struct name_entry * n )
502
502
{
503
503
int len , pathlen , ce_len ;
504
504
const char * ce_name ;
505
505
506
506
if (info -> prev ) {
507
- int cmp = do_compare_entry (ce , info -> prev , & info -> name );
507
+ int cmp = do_compare_entry_piecewise (ce , info -> prev ,
508
+ & info -> name );
508
509
if (cmp )
509
510
return cmp ;
510
511
}
@@ -522,6 +523,39 @@ static int do_compare_entry(const struct cache_entry *ce, const struct traverse_
522
523
return df_name_compare (ce_name , ce_len , S_IFREG , n -> path , len , n -> mode );
523
524
}
524
525
526
+ static int do_compare_entry (const struct cache_entry * ce ,
527
+ const struct traverse_info * info ,
528
+ const struct name_entry * n )
529
+ {
530
+ int len , pathlen , ce_len ;
531
+ const char * ce_name ;
532
+ int cmp ;
533
+
534
+ /*
535
+ * If we have not precomputed the traverse path, it is quicker
536
+ * to avoid doing so. But if we have precomputed it,
537
+ * it is quicker to use the precomputed version.
538
+ */
539
+ if (!info -> traverse_path )
540
+ return do_compare_entry_piecewise (ce , info , n );
541
+
542
+ cmp = strncmp (ce -> name , info -> traverse_path , info -> pathlen );
543
+ if (cmp )
544
+ return cmp ;
545
+
546
+ pathlen = info -> pathlen ;
547
+ ce_len = ce_namelen (ce );
548
+
549
+ if (ce_len < pathlen )
550
+ return -1 ;
551
+
552
+ ce_len -= pathlen ;
553
+ ce_name = ce -> name + pathlen ;
554
+
555
+ len = tree_entry_len (n );
556
+ return df_name_compare (ce_name , ce_len , S_IFREG , n -> path , len , n -> mode );
557
+ }
558
+
525
559
static int compare_entry (const struct cache_entry * ce , const struct traverse_info * info , const struct name_entry * n )
526
560
{
527
561
int cmp = do_compare_entry (ce , info , n );
@@ -661,8 +695,19 @@ static int find_cache_pos(struct traverse_info *info,
661
695
++ o -> cache_bottom ;
662
696
continue ;
663
697
}
664
- if (!ce_in_traverse_path (ce , info ))
698
+ if (!ce_in_traverse_path (ce , info )) {
699
+ /*
700
+ * Check if we can skip future cache checks
701
+ * (because we're already past all possible
702
+ * entries in the traverse path).
703
+ */
704
+ if (info -> traverse_path ) {
705
+ if (strncmp (ce -> name , info -> traverse_path ,
706
+ info -> pathlen ) > 0 )
707
+ break ;
708
+ }
665
709
continue ;
710
+ }
666
711
ce_name = ce -> name + pfxlen ;
667
712
ce_slash = strchr (ce_name , '/' );
668
713
if (ce_slash )
0 commit comments