@@ -523,6 +523,28 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options)
523
523
}
524
524
}
525
525
526
+ struct name_stack {
527
+ const char * * names ;
528
+ size_t nr , alloc ;
529
+ };
530
+
531
+ static void name_stack_push (struct name_stack * stack , const char * name )
532
+ {
533
+ ALLOC_GROW (stack -> names , stack -> nr + 1 , stack -> alloc );
534
+ stack -> names [stack -> nr ++ ] = name ;
535
+ }
536
+
537
+ static const char * name_stack_pop (struct name_stack * stack )
538
+ {
539
+ return stack -> nr ? stack -> names [-- stack -> nr ] : NULL ;
540
+ }
541
+
542
+ static void name_stack_clear (struct name_stack * stack )
543
+ {
544
+ FREE_AND_NULL (stack -> names );
545
+ stack -> nr = stack -> alloc = 0 ;
546
+ }
547
+
526
548
/*
527
549
* The entries in a tree are ordered in the _path_ order,
528
550
* which means that a directory entry is ordered by adding
@@ -534,7 +556,14 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options)
534
556
#define TREE_UNORDERED (-1)
535
557
#define TREE_HAS_DUPS (-2)
536
558
537
- static int verify_ordered (unsigned mode1 , const char * name1 , unsigned mode2 , const char * name2 )
559
+ static int is_less_than_slash (unsigned char c )
560
+ {
561
+ return '\0' < c && c < '/' ;
562
+ }
563
+
564
+ static int verify_ordered (unsigned mode1 , const char * name1 ,
565
+ unsigned mode2 , const char * name2 ,
566
+ struct name_stack * candidates )
538
567
{
539
568
int len1 = strlen (name1 );
540
569
int len2 = strlen (name2 );
@@ -566,6 +595,41 @@ static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, con
566
595
c1 = '/' ;
567
596
if (!c2 && S_ISDIR (mode2 ))
568
597
c2 = '/' ;
598
+
599
+ /*
600
+ * There can be non-consecutive duplicates due to the implicitly
601
+ * add slash, e.g.:
602
+ *
603
+ * foo
604
+ * foo.bar
605
+ * foo.bar.baz
606
+ * foo.bar/
607
+ * foo/
608
+ *
609
+ * Record non-directory candidates (like "foo" and "foo.bar" in
610
+ * the example) on a stack and check directory candidates (like
611
+ * foo/" and "foo.bar/") against that stack.
612
+ */
613
+ if (!c1 && is_less_than_slash (c2 )) {
614
+ name_stack_push (candidates , name1 );
615
+ } else if (c2 == '/' && is_less_than_slash (c1 )) {
616
+ for (;;) {
617
+ const char * p ;
618
+ const char * f_name = name_stack_pop (candidates );
619
+
620
+ if (!f_name )
621
+ break ;
622
+ if (!skip_prefix (name2 , f_name , & p ))
623
+ break ;
624
+ if (!* p )
625
+ return TREE_HAS_DUPS ;
626
+ if (is_less_than_slash (* p )) {
627
+ name_stack_push (candidates , f_name );
628
+ break ;
629
+ }
630
+ }
631
+ }
632
+
569
633
return c1 < c2 ? 0 : TREE_UNORDERED ;
570
634
}
571
635
@@ -587,6 +651,7 @@ static int fsck_tree(const struct object_id *oid,
587
651
struct tree_desc desc ;
588
652
unsigned o_mode ;
589
653
const char * o_name ;
654
+ struct name_stack df_dup_candidates = { NULL };
590
655
591
656
if (init_tree_desc_gently (& desc , buffer , size )) {
592
657
retval += report (options , oid , OBJ_TREE , FSCK_MSG_BAD_TREE , "cannot be parsed as a tree" );
@@ -666,7 +731,8 @@ static int fsck_tree(const struct object_id *oid,
666
731
}
667
732
668
733
if (o_name ) {
669
- switch (verify_ordered (o_mode , o_name , mode , name )) {
734
+ switch (verify_ordered (o_mode , o_name , mode , name ,
735
+ & df_dup_candidates )) {
670
736
case TREE_UNORDERED :
671
737
not_properly_sorted = 1 ;
672
738
break ;
@@ -682,6 +748,8 @@ static int fsck_tree(const struct object_id *oid,
682
748
o_name = name ;
683
749
}
684
750
751
+ name_stack_clear (& df_dup_candidates );
752
+
685
753
if (has_null_sha1 )
686
754
retval += report (options , oid , OBJ_TREE , FSCK_MSG_NULL_SHA1 , "contains entries pointing to null sha1" );
687
755
if (has_full_path )
0 commit comments