diff --git a/src/Utils/Finder.php b/src/Utils/Finder.php index 1f3ea589c..2c9a3200f 100644 --- a/src/Utils/Finder.php +++ b/src/Utils/Finder.php @@ -99,16 +99,14 @@ public function directories(string|array $masks = ['*']): static private function addMask(array $masks, string $mode): static { foreach ($masks as $mask) { - $mask = FileSystem::unixSlashes($mask); + $orig = $mask; if ($mode === 'dir') { - $mask = rtrim($mask, '/'); + $mask = rtrim($mask, '/\\'); } - if ($mask === '' || ($mode === 'file' && str_ends_with($mask, '/'))) { + if ($mask === '' || ($mode === 'file' && $mask !== $orig)) { throw new Nette\InvalidArgumentException("Invalid mask '$mask'"); } - if (str_starts_with($mask, '**/')) { - $mask = substr($mask, 3); - } + $mask = preg_replace('~\*\*[/\\\\]~A', '', $mask); $this->find[] = [$mask, $mode]; } return $this; @@ -132,7 +130,7 @@ public function in(string|array $paths): static public function from(string|array $paths): static { $paths = is_array($paths) ? $paths : func_get_args(); // compatibility with variadic - $this->addLocation($paths, '/**'); + $this->addLocation($paths, DIRECTORY_SEPARATOR . '**'); return $this; } @@ -143,7 +141,7 @@ private function addLocation(array $paths, string $ext): void if ($path === '') { throw new Nette\InvalidArgumentException("Invalid directory '$path'"); } - $path = rtrim(FileSystem::unixSlashes($path), '/'); + $path = rtrim($path, '/\\'); $this->in[] = $path . $ext; } } @@ -329,7 +327,6 @@ public function getIterator(): \Generator if ($item instanceof self) { yield from $item->getIterator(); } else { - $item = FileSystem::platformSlashes($item); yield $item => new FileInfo($item); } } @@ -350,7 +347,7 @@ private function traverseDir(string $dir, array $searches, array $subdirs = []): } try { - $pathNames = new \FilesystemIterator($dir, \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::UNIX_PATHS); + $pathNames = new \FilesystemIterator($dir, \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME); } catch (\UnexpectedValueException $e) { if ($this->ignoreUnreadableDirs) { return; @@ -359,7 +356,7 @@ private function traverseDir(string $dir, array $searches, array $subdirs = []): } } - $files = $this->convertToFiles($pathNames, implode('/', $subdirs), FileSystem::isAbsolute($dir)); + $files = $this->convertToFiles($pathNames, implode(DIRECTORY_SEPARATOR, $subdirs), FileSystem::isAbsolute($dir)); if ($this->sort) { $files = iterator_to_array($files); @@ -405,9 +402,8 @@ private function convertToFiles(iterable $pathNames, string $relativePath, bool { foreach ($pathNames as $pathName) { if (!$absolute) { - $pathName = preg_replace('~\.?/~A', '', $pathName); + $pathName = preg_replace('~\.?[\\\\/]~A', '', $pathName); } - $pathName = FileSystem::platformSlashes($pathName); yield new FileInfo($pathName, $relativePath); } } @@ -441,7 +437,7 @@ private function buildPlan(): array } else { foreach ($this->in ?: ['.'] as $in) { $in = strtr($in, ['[' => '[[]', ']' => '[]]']); // in path, do not treat [ and ] as a pattern by glob() - $splits[] = self::splitRecursivePart($in . '/' . $mask); + $splits[] = self::splitRecursivePart($in . DIRECTORY_SEPARATOR . $mask); } } @@ -471,11 +467,11 @@ private function buildPlan(): array */ private static function splitRecursivePart(string $path): array { - $a = strrpos($path, '/'); - $parts = preg_split('~(?<=^|/)\*\*($|/)~', substr($path, 0, $a + 1), 2); + preg_match('~(.*[\\\\/])(.*)$~A', $path, $m); + $parts = preg_split('~(?<=^|[\\\\/])\*\*($|[\\\\/])~', $m[1], 2); return isset($parts[1]) - ? [$parts[0], $parts[1] . substr($path, $a + 1), true] - : [$parts[0], substr($path, $a + 1), false]; + ? [$parts[0], $parts[1] . $m[2], true] + : [$parts[0], $m[2], false]; } @@ -484,6 +480,7 @@ private static function splitRecursivePart(string $path): array */ private function buildPattern(string $mask): string { + $mask = FileSystem::unixSlashes($mask); if ($mask === '*') { return '##'; } elseif (str_starts_with($mask, './')) { diff --git a/tests/Utils/Finder.append.phpt b/tests/Utils/Finder.append.phpt index ea84efa79..bf8278a5c 100644 --- a/tests/Utils/Finder.append.phpt +++ b/tests/Utils/Finder.append.phpt @@ -30,7 +30,7 @@ test('append finder', function () { "fixtures.finder{$ds}file.txt", "fixtures.finder{$ds}subdir", "fixtures.finder{$ds}subdir{$ds}subdir2", - "fixtures.finder{$ds}subdir{$ds}subdir2{$ds}file.txt", + "fixtures.finder/subdir/subdir2{$ds}file.txt", ], array_map('strval', $finder->collect())); }); diff --git a/tests/Utils/Finder.errors.phpt b/tests/Utils/Finder.errors.phpt index f84897e0c..05b1f4dd1 100644 --- a/tests/Utils/Finder.errors.phpt +++ b/tests/Utils/Finder.errors.phpt @@ -35,6 +35,6 @@ test('globing', function () { Assert::exception( fn() => iterator_to_array(Finder::findFiles('fixtures.finder/*/unknown/*')), Nette\InvalidStateException::class, - "Directory './fixtures.finder/*/unknown' does not exist.", + "Directory '.%ds%fixtures.finder/*/unknown' does not exist.", ); });