From 7e71b2bfbca85a8f07c41ace0f8e34248904b6d7 Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Tue, 12 Apr 2016 23:07:58 +0200 Subject: [PATCH] Added support for expanding environment variables in paths, and tilde expansion on Windows. --- src/Composer/Util/Platform.php | 41 +++++++++++++---------- tests/Composer/Test/Util/PlatformTest.php | 13 ++++++- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index cd936672e..530591064 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -20,29 +20,36 @@ namespace Composer\Util; class Platform { /** - * Parses magic constructs like tildes in paths. Right now only tildes are supported but we could add support for - * environment variables on various platforms. + * Parses tildes and environment variables in paths. * * @param string $path * @return string */ public static function expandPath($path) { - // Tilde expansion for *nix - if (!self::isWindows() && 0 === strpos($path, '~/')) { - if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) { - $info = posix_getpwuid(posix_getuid()); - $home = $info['dir']; - } else { - $home = getenv('HOME'); - } - // Cannot be empty or FALSE - if (!$home) { - throw new \RuntimeException(sprintf('No home folder found to expand ~ with in %s', $path)); - } - $path = $home . substr($path, 1); + if (preg_match('#^~[/\\\\]#', $path)) { + return self::getUserDirectory() . substr($path, 1); } - return $path; + return preg_replace_callback(self::isWindows() ? '#^(%(\\w+)%)[/\\\\]#' : '#^(\\$(\\w+))/#', function($matches) { + return getenv($matches[2]) . DIRECTORY_SEPARATOR; + }, $path); + } + + /** + * @return string The formal user home as detected from environment parameters + * @throws \RuntimeException If the user home could not reliably be determined + */ + public static function getUserDirectory() + { + if (false !== ($home = getenv('HOME'))) { + return $home; + } elseif (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) { + return $home; + } elseif (function_exists('posix_getuid') && function_exists('posix_getpwuid')) { + $info = posix_getpwuid(posix_getuid()); + return $info['dir']; + } + throw new \RuntimeException('Could not determine user directory'); } /** @@ -52,4 +59,4 @@ class Platform { return defined('PHP_WINDOWS_VERSION_BUILD'); } - } +} diff --git a/tests/Composer/Test/Util/PlatformTest.php b/tests/Composer/Test/Util/PlatformTest.php index 4cbe7ffe8..4b0491147 100644 --- a/tests/Composer/Test/Util/PlatformTest.php +++ b/tests/Composer/Test/Util/PlatformTest.php @@ -21,7 +21,18 @@ use Composer\Util\Platform; */ class PlatformTest extends \PHPUnit_Framework_TestCase { - public function testWindows() + public function testExpandPath() + { + putenv('TESTENV=/home/test'); + if (Platform::isWindows()) { + $this->assertEquals('/home/test/myPath', Platform::expandPath('%TESTENV%/myPath')); + } else { + $this->assertEquals('/home/test/myPath', Platform::expandPath('$TESTENV/myPath')); + } + $this->assertEquals((getenv('HOME') ?: getenv('USERPROFILE')) . DIRECTORY_SEPARATOR . 'test', Platform::expandPath('~/test')); + } + + public function testIsWindows() { // Compare 2 common tests for Windows to the built-in Windows test $this->assertEquals(('\\' === DIRECTORY_SEPARATOR), Platform::isWindows());