@@ -49,7 +49,7 @@ struct cached_dir {
49
49
static enum path_treatment read_directory_recursive (struct dir_struct * dir ,
50
50
struct index_state * istate , const char * path , int len ,
51
51
struct untracked_cache_dir * untracked ,
52
- int check_only , const struct pathspec * pathspec );
52
+ int check_only , int stop_at_first_file , const struct pathspec * pathspec );
53
53
static int get_dtype (struct dirent * de , struct index_state * istate ,
54
54
const char * path , int len );
55
55
@@ -1404,8 +1404,13 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
1404
1404
1405
1405
untracked = lookup_untracked (dir -> untracked , untracked ,
1406
1406
dirname + baselen , len - baselen );
1407
+
1408
+ /*
1409
+ * If this is an excluded directory, then we only need to check if
1410
+ * the directory contains any files.
1411
+ */
1407
1412
return read_directory_recursive (dir , istate , dirname , len ,
1408
- untracked , 1 , pathspec );
1413
+ untracked , 1 , exclude , pathspec );
1409
1414
}
1410
1415
1411
1416
/*
@@ -1633,7 +1638,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
1633
1638
* with check_only set.
1634
1639
*/
1635
1640
return read_directory_recursive (dir , istate , path -> buf , path -> len ,
1636
- cdir -> ucd , 1 , pathspec );
1641
+ cdir -> ucd , 1 , 0 , pathspec );
1637
1642
/*
1638
1643
* We get path_recurse in the first run when
1639
1644
* directory_exists_in_index() returns index_nonexistent. We
@@ -1793,12 +1798,20 @@ static void close_cached_dir(struct cached_dir *cdir)
1793
1798
* Also, we ignore the name ".git" (even if it is not a directory).
1794
1799
* That likely will not change.
1795
1800
*
1801
+ * If 'stop_at_first_file' is specified, 'path_excluded' is returned
1802
+ * to signal that a file was found. This is the least significant value that
1803
+ * indicates that a file was encountered that does not depend on the order of
1804
+ * whether an untracked or exluded path was encountered first.
1805
+ *
1796
1806
* Returns the most significant path_treatment value encountered in the scan.
1807
+ * If 'stop_at_first_file' is specified, `path_excluded` is the most
1808
+ * significant path_treatment value that will be returned.
1797
1809
*/
1810
+
1798
1811
static enum path_treatment read_directory_recursive (struct dir_struct * dir ,
1799
1812
struct index_state * istate , const char * base , int baselen ,
1800
1813
struct untracked_cache_dir * untracked , int check_only ,
1801
- const struct pathspec * pathspec )
1814
+ int stop_at_first_file , const struct pathspec * pathspec )
1802
1815
{
1803
1816
struct cached_dir cdir ;
1804
1817
enum path_treatment state , subdir_state , dir_state = path_none ;
@@ -1832,12 +1845,34 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1832
1845
subdir_state =
1833
1846
read_directory_recursive (dir , istate , path .buf ,
1834
1847
path .len , ud ,
1835
- check_only , pathspec );
1848
+ check_only , stop_at_first_file , pathspec );
1836
1849
if (subdir_state > dir_state )
1837
1850
dir_state = subdir_state ;
1838
1851
}
1839
1852
1840
1853
if (check_only ) {
1854
+ if (stop_at_first_file ) {
1855
+ /*
1856
+ * If stopping at first file, then
1857
+ * signal that a file was found by
1858
+ * returning `path_excluded`. This is
1859
+ * to return a consistent value
1860
+ * regardless of whether an ignored or
1861
+ * excluded file happened to be
1862
+ * encountered 1st.
1863
+ *
1864
+ * In current usage, the
1865
+ * `stop_at_first_file` is passed when
1866
+ * an ancestor directory has matched
1867
+ * an exclude pattern, so any found
1868
+ * files will be excluded.
1869
+ */
1870
+ if (dir_state >= path_excluded ) {
1871
+ dir_state = path_excluded ;
1872
+ break ;
1873
+ }
1874
+ }
1875
+
1841
1876
/* abort early if maximum state has been reached */
1842
1877
if (dir_state == path_untracked ) {
1843
1878
if (cdir .fdir )
@@ -2108,7 +2143,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
2108
2143
*/
2109
2144
dir -> untracked = NULL ;
2110
2145
if (!len || treat_leading_path (dir , istate , path , len , pathspec ))
2111
- read_directory_recursive (dir , istate , path , len , untracked , 0 , pathspec );
2146
+ read_directory_recursive (dir , istate , path , len , untracked , 0 , 0 , pathspec );
2112
2147
QSORT (dir -> entries , dir -> nr , cmp_dir_entry );
2113
2148
QSORT (dir -> ignored , dir -> ignored_nr , cmp_dir_entry );
2114
2149
0 commit comments