diff --git a/README.md b/README.md index 5bf8dee..fe82a64 100644 --- a/README.md +++ b/README.md @@ -114,19 +114,13 @@ $iterator = new GlobFilterIterator( Relative globs such as `*.css` are not supported. Usually, such globs refer to paths relative to the current working directory. This utility, however, does not -want to make such assumptions. Hence you should always pass absolute globs. - -If you want to allow users to pass relative globs, I recommend to turn the globs -into absolute globs using the [Webmozart Path Utility]: +want to make such assumptions. Hence you should always pass absolute globs, so +usage of `__DIR__` is encouraged: ```php use Webmozart\Glob\Glob; -use Webmozart\PathUtil\Path; -// If $glob is absolute, that glob is used without modification. -// If $glob is relative, it is turned into an absolute path based on the current -// working directory. -$paths = Glob::glob(Path::makeAbsolute($glob, getcwd()); +$paths = Glob::glob(__DIR__ . '/*'); ``` ### Windows Compatibility diff --git a/composer.json b/composer.json index 2ade78e..4afd87e 100644 --- a/composer.json +++ b/composer.json @@ -9,8 +9,7 @@ } ], "require": { - "php": "^7.3 || ^8.0.0", - "webmozart/path-util": "^2.2" + "php": "^7.3 || ^8.0.0" }, "require-dev": { "symfony/filesystem": "^5.3", diff --git a/composer.lock b/composer.lock index 84cf3ea..4826a98 100644 --- a/composer.lock +++ b/composer.lock @@ -4,196 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f45c85c1eb6f4b5b7a54845334ad24d", - "packages": [ - { - "name": "symfony/polyfill-ctype", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-02-19T12:13:01+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" - }, - { - "name": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "time": "2015-12-17T08:42:14+00:00" - } - ], + "content-hash": "750fe9e270f2e5366054f2a69ce2001f", + "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", @@ -2162,6 +1974,85 @@ ], "time": "2021-07-21T12:40:44+00:00" }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, { "name": "symfony/polyfill-php80", "version": "v1.23.1", @@ -2294,6 +2185,64 @@ } ], "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], @@ -2308,5 +2257,5 @@ "platform-overrides": { "php": "7.3.0" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.3.0" } diff --git a/src/Glob.php b/src/Glob.php index e6b3dea..f1fa126 100644 --- a/src/Glob.php +++ b/src/Glob.php @@ -13,7 +13,6 @@ use InvalidArgumentException; use Webmozart\Glob\Iterator\GlobIterator; -use Webmozart\PathUtil\Path; /** * Searches and matches file paths using Ant-like globs. @@ -313,7 +312,7 @@ public static function getBasePath($glob, $flags = 0) */ public static function toRegEx($glob, $flags = 0, $delimiter = '~') { - if (!Path::isAbsolute($glob) && false === strpos($glob, '://')) { + if (!Path::isAbsolute((string) $glob) && false === strpos($glob, '://')) { throw new InvalidArgumentException(sprintf( 'The glob "%s" is not absolute and not a URI.', $glob @@ -458,7 +457,7 @@ public static function toRegEx($glob, $flags = 0, $delimiter = '~') */ public static function getStaticPrefix($glob, $flags = 0) { - if (!Path::isAbsolute($glob) && false === strpos($glob, '://')) { + if (!Path::isAbsolute((string) $glob) && false === strpos($glob, '://')) { throw new InvalidArgumentException(sprintf( 'The glob "%s" is not absolute and not a URI.', $glob diff --git a/src/Path.php b/src/Path.php new file mode 100644 index 0000000..faead48 --- /dev/null +++ b/src/Path.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webmozart\Glob; + +/** + * Contains utility methods for handling path strings. + * + * The methods in this class are able to deal with both UNIX and Windows paths + * with both forward and backward slashes. All methods return normalized parts + * containing only forward slashes and no excess "." and ".." segments. + * + * @author Bernhard Schussek + * @author Thomas Schulz + * + * @internal this class was introduced to remove an external dependency, but is + * not part of the public API of this package: do not use it directly. + */ +abstract class Path +{ + /** + * Returns whether a path is absolute. + * + * @param string $path A path string. + * + * @return bool Returns true if the path is absolute, false if it is + * relative or empty. + */ + public static function isAbsolute(string $path): bool + { + if ('' === $path) { + return false; + } + + // Strip scheme + if (false !== ($pos = strpos($path, '://'))) { + $path = substr($path, $pos + 3); + } + + // UNIX root "/" or "\" (Windows style) + if ('/' === $path[0] || '\\' === $path[0]) { + return true; + } + + // Windows root + if (strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + // Special case: "C:" + if (2 === strlen($path)) { + return true; + } + + // Normal case: "C:/ or "C:\" + if ('/' === $path[2] || '\\' === $path[2]) { + return true; + } + } + + return false; + } + + final private function __construct() + { + } +} diff --git a/src/Test/TestUtil.php b/src/Test/TestUtil.php index 5bfa348..f878a92 100644 --- a/src/Test/TestUtil.php +++ b/src/Test/TestUtil.php @@ -43,7 +43,7 @@ public static function makeTempDir($namespace, $className) // symlink to another directory (e.g. /var => /private/var on some Macs) // We want to know the real path to avoid comparison failures with // code that uses real paths only - $systemTempDir = Path::normalize(realpath(sys_get_temp_dir())); + $systemTempDir = realpath(sys_get_temp_dir()); $basePath = $systemTempDir.'/'.$namespace.'/'.$shortClass; while (false === @mkdir($tempDir = $basePath.rand(10000, 99999), 0777, true)) { diff --git a/tests/PathTest.php b/tests/PathTest.php new file mode 100644 index 0000000..2b5f7c9 --- /dev/null +++ b/tests/PathTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webmozart\Glob\Tests; + +use PHPUnit\Framework\TestCase; +use Webmozart\Glob\Path; + +/** * + * @author Bernhard Schussek + * @author Thomas Schulz + */ +final class PathTest extends TestCase +{ + private $storedEnv = array(); + + protected function setUp(): void + { + $this->storedEnv['HOME'] = getenv('HOME'); + $this->storedEnv['HOMEDRIVE'] = getenv('HOMEDRIVE'); + $this->storedEnv['HOMEPATH'] = getenv('HOMEPATH'); + + putenv('HOME=/home/webmozart'); + putenv('HOMEDRIVE='); + putenv('HOMEPATH='); + } + + protected function tearDown(): void + { + putenv('HOME='.$this->storedEnv['HOME']); + putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']); + putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']); + } + + public function provideIsAbsolutePathTests() + { + return array( + array('/css/style.css', true), + array('/', true), + array('css/style.css', false), + array('', false), + + array('\\css\\style.css', true), + array('\\', true), + array('css\\style.css', false), + + array('C:/css/style.css', true), + array('D:/', true), + + array('E:\\css\\style.css', true), + array('F:\\', true), + + array('phar:///css/style.css', true), + array('phar:///', true), + + // Windows special case + array('C:', true), + + // Not considered absolute + array('C:css/style.css', false), + ); + } + + /** + * @dataProvider provideIsAbsolutePathTests + */ + public function testIsAbsolute($path, $isAbsolute) + { + self::assertSame($isAbsolute, Path::isAbsolute($path)); + } +}