@@ -732,7 +732,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
732732
733733static struct dir_entry * dir_add_name (struct dir_struct * dir , const char * pathname , int len )
734734{
735- if (cache_name_exists (pathname , len , ignore_case ))
735+ if (!(dir -> flags & DIR_SHOW_IGNORED ) &&
736+ cache_name_exists (pathname , len , ignore_case ))
736737 return NULL ;
737738
738739 ALLOC_GROW (dir -> entries , dir -> nr + 1 , dir -> alloc );
@@ -834,8 +835,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
834835 * traversal routine.
835836 *
836837 * Case 1: If we *already* have entries in the index under that
837- * directory name, we always recurse into the directory to see
838- * all the files.
838+ * directory name, we recurse into the directory to see all the files,
839+ * unless the directory is excluded and we want to show ignored
840+ * directories
839841 *
840842 * Case 2: If we *already* have that directory name as a gitlink,
841843 * we always continue to see it as a gitlink, regardless of whether
@@ -849,6 +851,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
849851 * just a directory, unless "hide_empty_directories" is
850852 * also true and the directory is empty, in which case
851853 * we just ignore it entirely.
854+ * if we are looking for ignored directories, look if it
855+ * contains only ignored files to decide if it must be shown as
856+ * ignored or not.
852857 * (b) if it looks like a git directory, and we don't have
853858 * 'no_gitlinks' set we treat it as a gitlink, and show it
854859 * as a directory.
@@ -861,12 +866,15 @@ enum directory_treatment {
861866};
862867
863868static enum directory_treatment treat_directory (struct dir_struct * dir ,
864- const char * dirname , int len ,
869+ const char * dirname , int len , int exclude ,
865870 const struct path_simplify * simplify )
866871{
867872 /* The "len-1" is to strip the final '/' */
868873 switch (directory_exists_in_index (dirname , len - 1 )) {
869874 case index_directory :
875+ if ((dir -> flags & DIR_SHOW_OTHER_DIRECTORIES ) && exclude )
876+ break ;
877+
870878 return recurse_into_directory ;
871879
872880 case index_gitdir :
@@ -886,13 +894,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
886894 }
887895
888896 /* This is the "show_other_directories" case */
889- if (!(dir -> flags & DIR_HIDE_EMPTY_DIRECTORIES ))
897+
898+ /*
899+ * We are looking for ignored files and our directory is not ignored,
900+ * check if it contains only ignored files
901+ */
902+ if ((dir -> flags & DIR_SHOW_IGNORED ) && !exclude ) {
903+ int ignored ;
904+ dir -> flags &= ~DIR_SHOW_IGNORED ;
905+ dir -> flags |= DIR_HIDE_EMPTY_DIRECTORIES ;
906+ ignored = read_directory_recursive (dir , dirname , len , 1 , simplify );
907+ dir -> flags &= ~DIR_HIDE_EMPTY_DIRECTORIES ;
908+ dir -> flags |= DIR_SHOW_IGNORED ;
909+
910+ return ignored ? ignore_directory : show_directory ;
911+ }
912+ if (!(dir -> flags & DIR_SHOW_IGNORED ) &&
913+ !(dir -> flags & DIR_HIDE_EMPTY_DIRECTORIES ))
890914 return show_directory ;
891915 if (!read_directory_recursive (dir , dirname , len , 1 , simplify ))
892916 return ignore_directory ;
893917 return show_directory ;
894918}
895919
920+ /*
921+ * Decide what to do when we find a file while traversing the
922+ * filesystem. Mostly two cases:
923+ *
924+ * 1. We are looking for ignored files
925+ * (a) File is ignored, include it
926+ * (b) File is in ignored path, include it
927+ * (c) File is not ignored, exclude it
928+ *
929+ * 2. Other scenarios, include the file if not excluded
930+ *
931+ * Return 1 for exclude, 0 for include.
932+ */
933+ static int treat_file (struct dir_struct * dir , struct strbuf * path , int exclude , int * dtype )
934+ {
935+ struct path_exclude_check check ;
936+ int exclude_file = 0 ;
937+
938+ if (exclude )
939+ exclude_file = !(dir -> flags & DIR_SHOW_IGNORED );
940+ else if (dir -> flags & DIR_SHOW_IGNORED ) {
941+ /* Always exclude indexed files */
942+ struct cache_entry * ce = index_name_exists (& the_index ,
943+ path -> buf , path -> len , ignore_case );
944+
945+ if (ce )
946+ return 1 ;
947+
948+ path_exclude_check_init (& check , dir );
949+
950+ if (!path_excluded (& check , path -> buf , path -> len , dtype ))
951+ exclude_file = 1 ;
952+
953+ path_exclude_check_clear (& check );
954+ }
955+
956+ return exclude_file ;
957+ }
958+
896959/*
897960 * This is an inexact early pruning of any recursive directory
898961 * reading - if the path cannot possibly be in the pathspec,
@@ -1031,27 +1094,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10311094 if (dtype == DT_UNKNOWN )
10321095 dtype = get_dtype (de , path -> buf , path -> len );
10331096
1034- /*
1035- * Do we want to see just the ignored files?
1036- * We still need to recurse into directories,
1037- * even if we don't ignore them, since the
1038- * directory may contain files that we do..
1039- */
1040- if (!exclude && (dir -> flags & DIR_SHOW_IGNORED )) {
1041- if (dtype != DT_DIR )
1042- return path_ignored ;
1043- }
1044-
10451097 switch (dtype ) {
10461098 default :
10471099 return path_ignored ;
10481100 case DT_DIR :
10491101 strbuf_addch (path , '/' );
1050- switch (treat_directory (dir , path -> buf , path -> len , simplify )) {
1102+
1103+ switch (treat_directory (dir , path -> buf , path -> len , exclude , simplify )) {
10511104 case show_directory :
1052- if (exclude != !!(dir -> flags
1053- & DIR_SHOW_IGNORED ))
1054- return path_ignored ;
10551105 break ;
10561106 case recurse_into_directory :
10571107 return path_recurse ;
@@ -1061,7 +1111,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10611111 break ;
10621112 case DT_REG :
10631113 case DT_LNK :
1064- break ;
1114+ switch (treat_file (dir , path , exclude , & dtype )) {
1115+ case 1 :
1116+ return path_ignored ;
1117+ default :
1118+ break ;
1119+ }
10651120 }
10661121 return path_handled ;
10671122}
0 commit comments