@@ -27,7 +27,7 @@ final class VcsIgnoredFilterIterator extends \FilterIterator
27
27
28
28
public function __construct (\Iterator $ iterator , string $ baseDir )
29
29
{
30
- $ this ->baseDir = $ baseDir ;
30
+ $ this ->baseDir = $ this -> normalizePath ( $ baseDir) ;
31
31
32
32
parent ::__construct ($ iterator );
33
33
}
@@ -36,35 +36,65 @@ public function accept(): bool
36
36
{
37
37
$ file = $ this ->current ();
38
38
39
- $ fileRealPath = $ file ->getRealPath ();
40
- if ($ file ->isDir ()) {
39
+ $ fileRealPath = $ this -> normalizePath ( $ file ->getRealPath () );
40
+ if ($ file ->isDir () && ! str_ends_with ( $ fileRealPath , ' / ' ) ) {
41
41
$ fileRealPath .= '/ ' ;
42
42
}
43
43
44
- $ parentDirectory = $ fileRealPath ;
45
-
46
- do {
47
- $ parentDirectory = \dirname ($ parentDirectory );
48
- $ relativeFilePath = substr ($ fileRealPath , \strlen ($ parentDirectory ) + 1 );
44
+ foreach ($ this ->parentsDirectoryDownward ($ fileRealPath ) as $ parentDirectory ) {
45
+ $ fileRelativePath = substr ($ fileRealPath , \strlen ($ parentDirectory ) + 1 );
49
46
50
47
$ regex = $ this ->readGitignoreFile ("{$ parentDirectory }/.gitignore " );
51
48
52
- if (null !== $ regex && preg_match ($ regex , $ relativeFilePath )) {
49
+ if (null !== $ regex && preg_match ($ regex , $ fileRelativePath )) {
53
50
return false ;
54
51
}
55
- } while ($ parentDirectory !== $ this ->baseDir );
52
+
53
+ if (0 !== strpos ($ parentDirectory , $ this ->baseDir )) {
54
+ break ;
55
+ }
56
+ }
56
57
57
58
return true ;
58
59
}
59
60
61
+ /**
62
+ * @return list<string>
63
+ */
64
+ private function parentsDirectoryDownward (string $ fileRealPath ): array
65
+ {
66
+ $ parentDirectories = [];
67
+
68
+ $ parentDirectory = $ fileRealPath ;
69
+
70
+ while (true ) {
71
+ $ newParentDirectory = \dirname ($ parentDirectory );
72
+
73
+ // dirname('/') = '/'
74
+ if ($ newParentDirectory === $ parentDirectory ) {
75
+ break ;
76
+ }
77
+
78
+ $ parentDirectory = $ newParentDirectory ;
79
+
80
+ if (0 !== strpos ($ parentDirectory , $ this ->baseDir )) {
81
+ break ;
82
+ }
83
+
84
+ $ parentDirectories [] = $ parentDirectory ;
85
+ }
86
+
87
+ return array_reverse ($ parentDirectories );
88
+ }
89
+
60
90
private function readGitignoreFile (string $ path ): ?string
61
91
{
62
92
if (\array_key_exists ($ path , $ this ->gitignoreFilesCache )) {
63
93
return $ this ->gitignoreFilesCache [$ path ];
64
94
}
65
95
66
96
if (!file_exists ($ path )) {
67
- return null ;
97
+ return $ this -> gitignoreFilesCache [ $ path ] = null ;
68
98
}
69
99
70
100
if (!is_file ($ path ) || !is_readable ($ path )) {
@@ -73,4 +103,13 @@ private function readGitignoreFile(string $path): ?string
73
103
74
104
return $ this ->gitignoreFilesCache [$ path ] = Gitignore::toRegex (file_get_contents ($ path ));
75
105
}
106
+
107
+ private function normalizePath (string $ path ): string
108
+ {
109
+ if ('\\' === \DIRECTORY_SEPARATOR ) {
110
+ return str_replace ('\\' , '/ ' , $ path );
111
+ }
112
+
113
+ return $ path ;
114
+ }
76
115
}
0 commit comments