Browse Source

Added support for expanding environment variables in paths, and tilde expansion on Windows.

Niels Keurentjes 9 years ago
parent
commit
7e71b2bfbc
2 changed files with 36 additions and 18 deletions
  1. 24 17
      src/Composer/Util/Platform.php
  2. 12 1
      tests/Composer/Test/Util/PlatformTest.php

+ 24 - 17
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');
     }
- }
+}

+ 12 - 1
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());