@@ -774,8 +774,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
774774 * traversal routine.
775775 *
776776 * Case 1: If we *already* have entries in the index under that
777- * directory name, we always recurse into the directory to see
778- * all the files.
777+ * directory name, we recurse into the directory to see all the files,
778+ * unless the directory is excluded and we want to show ignored
779+ * directories
779780 *
780781 * Case 2: If we *already* have that directory name as a gitlink,
781782 * we always continue to see it as a gitlink, regardless of whether
@@ -789,6 +790,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
789790 * just a directory, unless "hide_empty_directories" is
790791 * also true and the directory is empty, in which case
791792 * we just ignore it entirely.
793+ * if we are looking for ignored directories, look if it
794+ * contains only ignored files to decide if it must be shown as
795+ * ignored or not.
792796 * (b) if it looks like a git directory, and we don't have
793797 * 'no_gitlinks' set we treat it as a gitlink, and show it
794798 * as a directory.
@@ -801,12 +805,15 @@ enum directory_treatment {
801805};
802806
803807static enum directory_treatment treat_directory (struct dir_struct * dir ,
804- const char * dirname , int len ,
808+ const char * dirname , int len , int exclude ,
805809 const struct path_simplify * simplify )
806810{
807811 /* The "len-1" is to strip the final '/' */
808812 switch (directory_exists_in_index (dirname , len - 1 )) {
809813 case index_directory :
814+ if ((dir -> flags & DIR_SHOW_OTHER_DIRECTORIES ) && exclude )
815+ break ;
816+
810817 return recurse_into_directory ;
811818
812819 case index_gitdir :
@@ -826,13 +833,72 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
826833 }
827834
828835 /* This is the "show_other_directories" case */
829- if (!(dir -> flags & DIR_HIDE_EMPTY_DIRECTORIES ))
836+
837+ /*
838+ * We are looking for ignored files and our directory is not ignored,
839+ * check if it contains only ignored files
840+ */
841+ if ((dir -> flags & DIR_SHOW_IGNORED ) && !exclude ) {
842+ int ignored ;
843+ dir -> flags &= ~DIR_SHOW_IGNORED ;
844+ dir -> flags |= DIR_HIDE_EMPTY_DIRECTORIES ;
845+ ignored = read_directory_recursive (dir , dirname , len , 1 , simplify );
846+ dir -> flags &= ~DIR_HIDE_EMPTY_DIRECTORIES ;
847+ dir -> flags |= DIR_SHOW_IGNORED ;
848+
849+ return ignored ? ignore_directory : show_directory ;
850+ }
851+ if (!(dir -> flags & DIR_SHOW_IGNORED ) &&
852+ !(dir -> flags & DIR_HIDE_EMPTY_DIRECTORIES ))
830853 return show_directory ;
831854 if (!read_directory_recursive (dir , dirname , len , 1 , simplify ))
832855 return ignore_directory ;
833856 return show_directory ;
834857}
835858
859+ /*
860+ * Decide what to do when we find a file while traversing the
861+ * filesystem. Mostly two cases:
862+ *
863+ * 1. We are looking for ignored files
864+ * (a) File is ignored, include it
865+ * (b) File is in ignored path, include it
866+ * (c) File is not ignored, exclude it
867+ *
868+ * 2. Other scenarios, include the file if not excluded
869+ *
870+ * Return 1 for exclude, 0 for include.
871+ */
872+ static int treat_file (struct dir_struct * dir , struct strbuf * path , int exclude , int * dtype )
873+ {
874+ struct path_exclude_check check ;
875+ int exclude_file = 0 ;
876+
877+ if (exclude )
878+ exclude_file = !(dir -> flags & DIR_SHOW_IGNORED );
879+ else if (dir -> flags & DIR_SHOW_IGNORED ) {
880+ /*
881+ * Optimization:
882+ * Don't spend time on indexed files, they won't be
883+ * added to the list anyway
884+ */
885+ struct cache_entry * ce = index_name_exists (& the_index ,
886+ path -> buf , path -> len , ignore_case );
887+
888+ if (ce )
889+ return 1 ;
890+
891+ path_exclude_check_init (& check , dir );
892+
893+ if (!path_excluded (& check , path -> buf , path -> len , dtype ))
894+ exclude_file = 1 ;
895+
896+ path_exclude_check_clear (& check );
897+ }
898+
899+ return exclude_file ;
900+ }
901+
836902/*
837903 * This is an inexact early pruning of any recursive directory
838904 * reading - if the path cannot possibly be in the pathspec,
@@ -971,27 +1037,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
9711037 if (dtype == DT_UNKNOWN )
9721038 dtype = get_dtype (de , path -> buf , path -> len );
9731039
974- /*
975- * Do we want to see just the ignored files?
976- * We still need to recurse into directories,
977- * even if we don't ignore them, since the
978- * directory may contain files that we do..
979- */
980- if (!exclude && (dir -> flags & DIR_SHOW_IGNORED )) {
981- if (dtype != DT_DIR )
982- return path_ignored ;
983- }
984-
9851040 switch (dtype ) {
9861041 default :
9871042 return path_ignored ;
9881043 case DT_DIR :
9891044 strbuf_addch (path , '/' );
990- switch (treat_directory (dir , path -> buf , path -> len , simplify )) {
1045+
1046+ switch (treat_directory (dir , path -> buf , path -> len , exclude , simplify )) {
9911047 case show_directory :
992- if (exclude != !!(dir -> flags
993- & DIR_SHOW_IGNORED ))
994- return path_ignored ;
9951048 break ;
9961049 case recurse_into_directory :
9971050 return path_recurse ;
@@ -1001,7 +1054,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10011054 break ;
10021055 case DT_REG :
10031056 case DT_LNK :
1004- break ;
1057+ switch (treat_file (dir , path , exclude , & dtype )) {
1058+ case 1 :
1059+ return path_ignored ;
1060+ default :
1061+ break ;
1062+ }
10051063 }
10061064 return path_handled ;
10071065}
0 commit comments