@@ -625,6 +625,84 @@ static int get_dtype(struct dirent *de, const char *path, int len)
625625 return dtype ;
626626}
627627
628+ enum path_treatment {
629+ path_ignored ,
630+ path_handled ,
631+ path_recurse ,
632+ };
633+
634+ static enum path_treatment treat_path (struct dir_struct * dir ,
635+ struct dirent * de ,
636+ char * path , int path_max ,
637+ int baselen ,
638+ const struct path_simplify * simplify ,
639+ int * len )
640+ {
641+ int dtype , exclude ;
642+
643+ if (is_dot_or_dotdot (de -> d_name ) || !strcmp (de -> d_name , ".git" ))
644+ return path_ignored ;
645+ * len = strlen (de -> d_name );
646+ /* Ignore overly long pathnames! */
647+ if (* len + baselen + 8 > path_max )
648+ return path_ignored ;
649+ memcpy (path + baselen , de -> d_name , * len + 1 );
650+ * len += baselen ;
651+ if (simplify_away (path , * len , simplify ))
652+ return path_ignored ;
653+
654+ dtype = DTYPE (de );
655+ exclude = excluded (dir , path , & dtype );
656+ if (exclude && (dir -> flags & DIR_COLLECT_IGNORED )
657+ && in_pathspec (path , * len , simplify ))
658+ dir_add_ignored (dir , path , * len );
659+
660+ /*
661+ * Excluded? If we don't explicitly want to show
662+ * ignored files, ignore it
663+ */
664+ if (exclude && !(dir -> flags & DIR_SHOW_IGNORED ))
665+ return path_ignored ;
666+
667+ if (dtype == DT_UNKNOWN )
668+ dtype = get_dtype (de , path , * len );
669+
670+ /*
671+ * Do we want to see just the ignored files?
672+ * We still need to recurse into directories,
673+ * even if we don't ignore them, since the
674+ * directory may contain files that we do..
675+ */
676+ if (!exclude && (dir -> flags & DIR_SHOW_IGNORED )) {
677+ if (dtype != DT_DIR )
678+ return path_ignored ;
679+ }
680+
681+ switch (dtype ) {
682+ default :
683+ return path_ignored ;
684+ case DT_DIR :
685+ memcpy (path + * len , "/" , 2 );
686+ (* len )++ ;
687+ switch (treat_directory (dir , path , * len , simplify )) {
688+ case show_directory :
689+ if (exclude != !!(dir -> flags
690+ & DIR_SHOW_IGNORED ))
691+ return path_ignored ;
692+ break ;
693+ case recurse_into_directory :
694+ return path_recurse ;
695+ case ignore_directory :
696+ return path_ignored ;
697+ }
698+ break ;
699+ case DT_REG :
700+ case DT_LNK :
701+ break ;
702+ }
703+ return path_handled ;
704+ }
705+
628706/*
629707 * Read a directory tree. We currently ignore anything but
630708 * directories, regular files and symlinks. That's because git
@@ -634,7 +712,10 @@ static int get_dtype(struct dirent *de, const char *path, int len)
634712 * Also, we ignore the name ".git" (even if it is not a directory).
635713 * That likely will not change.
636714 */
637- static int read_directory_recursive (struct dir_struct * dir , const char * base , int baselen , int check_only , const struct path_simplify * simplify )
715+ static int read_directory_recursive (struct dir_struct * dir ,
716+ const char * base , int baselen ,
717+ int check_only ,
718+ const struct path_simplify * simplify )
638719{
639720 DIR * fdir = opendir (* base ? base : "." );
640721 int contents = 0 ;
@@ -645,70 +726,16 @@ static int read_directory_recursive(struct dir_struct *dir, const char *base, in
645726 memcpy (path , base , baselen );
646727
647728 while ((de = readdir (fdir )) != NULL ) {
648- int len , dtype ;
649- int exclude ;
650-
651- if (is_dot_or_dotdot (de -> d_name ) ||
652- !strcmp (de -> d_name , ".git" ))
653- continue ;
654- len = strlen (de -> d_name );
655- /* Ignore overly long pathnames! */
656- if (len + baselen + 8 > sizeof (path ))
729+ int len ;
730+ switch (treat_path (dir , de , path , sizeof (path ),
731+ baselen , simplify , & len )) {
732+ case path_recurse :
733+ contents += read_directory_recursive
734+ (dir , path , len , 0 , simplify );
657735 continue ;
658- memcpy (path + baselen , de -> d_name , len + 1 );
659- len = baselen + len ;
660- if (simplify_away (path , len , simplify ))
736+ case path_ignored :
661737 continue ;
662-
663- dtype = DTYPE (de );
664- exclude = excluded (dir , path , & dtype );
665- if (exclude && (dir -> flags & DIR_COLLECT_IGNORED )
666- && in_pathspec (path , len , simplify ))
667- dir_add_ignored (dir , path ,len );
668-
669- /*
670- * Excluded? If we don't explicitly want to show
671- * ignored files, ignore it
672- */
673- if (exclude && !(dir -> flags & DIR_SHOW_IGNORED ))
674- continue ;
675-
676- if (dtype == DT_UNKNOWN )
677- dtype = get_dtype (de , path , len );
678-
679- /*
680- * Do we want to see just the ignored files?
681- * We still need to recurse into directories,
682- * even if we don't ignore them, since the
683- * directory may contain files that we do..
684- */
685- if (!exclude && (dir -> flags & DIR_SHOW_IGNORED )) {
686- if (dtype != DT_DIR )
687- continue ;
688- }
689-
690- switch (dtype ) {
691- default :
692- continue ;
693- case DT_DIR :
694- memcpy (path + len , "/" , 2 );
695- len ++ ;
696- switch (treat_directory (dir , path , len , simplify )) {
697- case show_directory :
698- if (exclude != !!(dir -> flags
699- & DIR_SHOW_IGNORED ))
700- continue ;
701- break ;
702- case recurse_into_directory :
703- contents += read_directory_recursive (dir ,
704- path , len , 0 , simplify );
705- continue ;
706- case ignore_directory :
707- continue ;
708- }
709- break ;
710- case DT_REG :
711- case DT_LNK :
738+ case path_handled :
712739 break ;
713740 }
714741 contents ++ ;
0 commit comments