1
0
Fork 0

Merge remote-tracking branch 'curry684/home-expansion'

pull/5238/head
Jordi Boggiano 2016-04-22 20:37:05 +01:00
commit d8c94c2640
6 changed files with 60 additions and 11 deletions

View File

@ -609,8 +609,8 @@ update to the latest version.
### Path ### Path
In addition to the artifact repository, you can use the path one, which allows In addition to the artifact repository, you can use the path one, which allows
you to depend on a relative directory. This can be especially useful when dealing you to depend on a local directory, either absolute or relative. This can be
with monolith repositories. especially useful when dealing with monolithic repositories.
For instance, if you have the following directory structure in your repository: For instance, if you have the following directory structure in your repository:
``` ```
@ -649,8 +649,8 @@ the console will read `Symlinked from ../../packages/my-package`. If symlinking
is _not_ possible the package will be copied. In that case, the console will is _not_ possible the package will be copied. In that case, the console will
output `Mirrored from ../../packages/my-package`. output `Mirrored from ../../packages/my-package`.
Instead of default fallback strategy you can force to use symlink with `"symlink": true` or Instead of default fallback strategy you can force to use symlink with `"symlink": true`
mirroring with `"symlink": false` option. or mirroring with `"symlink": false` option.
Forcing mirroring can be useful when deploying or generating package from a monolithic repository. Forcing mirroring can be useful when deploying or generating package from a monolithic repository.
```json ```json
@ -667,9 +667,11 @@ Forcing mirroring can be useful when deploying or generating package from a mono
} }
``` ```
Leading tildes are expanded to the current user's home folder, and environment
variables are parsed in both Windows and Linux/Mac notations. For example
Instead of using a relative path, an absolute path can also be used. `~/git/mypackage` will automatically load the mypackage clone from
`/home/<username>/git/mypackage`, equivalent to `$HOME/git/mypackage` or
`%USERPROFILE%/git/mypackage`.
> **Note:** Repository paths can also contain wildcards like ``*`` and ``?``. > **Note:** Repository paths can also contain wildcards like ``*`` and ``?``.
> For details, see the [PHP glob function](http://php.net/glob). > For details, see the [PHP glob function](http://php.net/glob).

View File

@ -15,6 +15,7 @@ namespace Composer;
use Composer\Config\ConfigSourceInterface; use Composer\Config\ConfigSourceInterface;
use Composer\Downloader\TransportException; use Composer\Downloader\TransportException;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Util\Platform;
/** /**
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
@ -210,7 +211,7 @@ class Config
$env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_')); $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
$val = rtrim($this->process($this->getComposerEnv($env) ?: $this->config[$key], $flags), '/\\'); $val = rtrim($this->process($this->getComposerEnv($env) ?: $this->config[$key], $flags), '/\\');
$val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $val); $val = Platform::expandPath($val);
if (substr($key, -4) !== '-dir') { if (substr($key, -4) !== '-dir') {
return $val; return $val;

View File

@ -18,6 +18,7 @@ use Composer\Json\JsonFile;
use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionParser;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor; use Composer\Util\ProcessExecutor;
/** /**
@ -101,7 +102,7 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
} }
$this->loader = new ArrayLoader(null, true); $this->loader = new ArrayLoader(null, true);
$this->url = $repoConfig['url']; $this->url = Platform::expandPath($repoConfig['url']);
$this->process = new ProcessExecutor($io); $this->process = new ProcessExecutor($io);
$this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser()); $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
$this->repoConfig = $repoConfig; $this->repoConfig = $repoConfig;

View File

@ -19,6 +19,43 @@ namespace Composer\Util;
*/ */
class Platform class Platform
{ {
/**
* Parses tildes and environment variables in paths.
*
* @param string $path
* @return string
*/
public static function expandPath($path)
{
if (preg_match('#^~[/\\\\]#', $path)) {
return self::getUserDirectory() . substr($path, 1);
}
return preg_replace_callback('#^([\\$%])(\\w+)\\1?(([/\\\\].*)?)#', function($matches) {
// Treat HOME as an alias for USERPROFILE on Windows for legacy reasons
if (Platform::isWindows() && $matches[2] == 'HOME') {
return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches[3];
}
return getenv($matches[2]) . $matches[3];
}, $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');
}
/** /**
* @return bool Whether the host machine is running a Windows OS * @return bool Whether the host machine is running a Windows OS
*/ */

View File

@ -150,7 +150,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
$home = rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '\\/'); $home = rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '\\/');
$this->assertEquals('b', $config->get('c')); $this->assertEquals('b', $config->get('c'));
$this->assertEquals($home.'/', $config->get('bin-dir')); $this->assertEquals($home, $config->get('bin-dir'));
$this->assertEquals($home.'/foo', $config->get('cache-dir')); $this->assertEquals($home.'/foo', $config->get('cache-dir'));
} }

View File

@ -21,7 +21,15 @@ use Composer\Util\Platform;
*/ */
class PlatformTest extends \PHPUnit_Framework_TestCase class PlatformTest extends \PHPUnit_Framework_TestCase
{ {
public function testWindows() public function testExpandPath()
{
putenv('TESTENV=/home/test');
$this->assertEquals('/home/test/myPath', Platform::expandPath('%TESTENV%/myPath'));
$this->assertEquals('/home/test/myPath', Platform::expandPath('$TESTENV/myPath'));
$this->assertEquals((getenv('HOME') ?: getenv('USERPROFILE')) . '/test', Platform::expandPath('~/test'));
}
public function testIsWindows()
{ {
// Compare 2 common tests for Windows to the built-in Windows test // Compare 2 common tests for Windows to the built-in Windows test
$this->assertEquals(('\\' === DIRECTORY_SEPARATOR), Platform::isWindows()); $this->assertEquals(('\\' === DIRECTORY_SEPARATOR), Platform::isWindows());