@@ -774,8 +774,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
774
774
* traversal routine.
775
775
*
776
776
* 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
779
780
*
780
781
* Case 2: If we *already* have that directory name as a gitlink,
781
782
* 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)
789
790
* just a directory, unless "hide_empty_directories" is
790
791
* also true and the directory is empty, in which case
791
792
* 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.
792
796
* (b) if it looks like a git directory, and we don't have
793
797
* 'no_gitlinks' set we treat it as a gitlink, and show it
794
798
* as a directory.
@@ -801,12 +805,15 @@ enum directory_treatment {
801
805
};
802
806
803
807
static enum directory_treatment treat_directory (struct dir_struct * dir ,
804
- const char * dirname , int len ,
808
+ const char * dirname , int len , int exclude ,
805
809
const struct path_simplify * simplify )
806
810
{
807
811
/* The "len-1" is to strip the final '/' */
808
812
switch (directory_exists_in_index (dirname , len - 1 )) {
809
813
case index_directory :
814
+ if ((dir -> flags & DIR_SHOW_OTHER_DIRECTORIES ) && exclude )
815
+ break ;
816
+
810
817
return recurse_into_directory ;
811
818
812
819
case index_gitdir :
@@ -826,13 +833,72 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
826
833
}
827
834
828
835
/* 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 ))
830
853
return show_directory ;
831
854
if (!read_directory_recursive (dir , dirname , len , 1 , simplify ))
832
855
return ignore_directory ;
833
856
return show_directory ;
834
857
}
835
858
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
+
836
902
/*
837
903
* This is an inexact early pruning of any recursive directory
838
904
* 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,
971
1037
if (dtype == DT_UNKNOWN )
972
1038
dtype = get_dtype (de , path -> buf , path -> len );
973
1039
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
-
985
1040
switch (dtype ) {
986
1041
default :
987
1042
return path_ignored ;
988
1043
case DT_DIR :
989
1044
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 )) {
991
1047
case show_directory :
992
- if (exclude != !!(dir -> flags
993
- & DIR_SHOW_IGNORED ))
994
- return path_ignored ;
995
1048
break ;
996
1049
case recurse_into_directory :
997
1050
return path_recurse ;
@@ -1001,7 +1054,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
1001
1054
break ;
1002
1055
case DT_REG :
1003
1056
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
+ }
1005
1063
}
1006
1064
return path_handled ;
1007
1065
}
0 commit comments