1
0
Fork 0

Merge branch 'master' into 2.0

pull/8684/head
Jordi Boggiano 2020-03-10 14:05:33 +01:00
commit d63eb8179e
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
21 changed files with 229 additions and 78 deletions

View File

@ -1,3 +1,11 @@
### [1.10.0] 2020-03-10
* Added `bearer` auth config to authenticate using `Authorization: Bearer <token>` headers
* Added `plugin-api-version` in composer.lock so future Composer versions know if they are running a lock file which was not built by the correct version
* Fixed composer fund command and funding info parsing to be more useful
* Fixed issue where --no-dev autoload generation was excluding some packages which should not have been excluded
* Fixed 1.10-RC regression in create project's handling of absolute paths
### [1.10.0-RC] 2020-02-14
* Breaking: `composer global exec ...` now executes the process in the current working directory instead of executing it in the global directory.
@ -811,6 +819,7 @@
* Initial release
[1.10.0]: https://github.com/composer/composer/compare/1.10.0-RC...1.10.0
[1.10.0-RC]: https://github.com/composer/composer/compare/1.9.3...1.10.0-RC
[1.9.3]: https://github.com/composer/composer/compare/1.9.2...1.9.3
[1.9.2]: https://github.com/composer/composer/compare/1.9.1...1.9.2

70
composer.lock generated
View File

@ -185,16 +185,16 @@
},
{
"name": "composer/xdebug-handler",
"version": "1.4.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "cbe23383749496fe0f373345208b79568e4bc248"
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/cbe23383749496fe0f373345208b79568e4bc248",
"reference": "cbe23383749496fe0f373345208b79568e4bc248",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7",
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7",
"shasum": ""
},
"require": {
@ -225,12 +225,13 @@
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/1.4.0"
},
"time": "2019-11-06T16:40:04+00:00"
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
}
],
"time": "2020-03-01T12:26:26+00:00"
},
{
"name": "justinrainbow/json-schema",
@ -935,6 +936,10 @@
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/master"
},
"time": "2015-06-14T21:17:01+00:00"
},
{
@ -978,26 +983,20 @@
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2016-01-25T08:17:30+00:00"
},
{
"name": "phpspec/prophecy",
"version": "v1.10.2",
"version": "v1.10.3",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9"
"reference": "451c3cd1418cf640de218914901e51b064abb093"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9",
"reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
"reference": "451c3cd1418cf640de218914901e51b064abb093",
"shasum": ""
},
"require": {
@ -1047,7 +1046,7 @@
"spy",
"stub"
],
"time": "2020-01-20T15:57:02+00:00"
"time": "2020-03-05T15:02:03+00:00"
},
{
"name": "sebastian/comparator",
@ -1287,23 +1286,23 @@
},
{
"name": "symfony/phpunit-bridge",
"version": "v3.4.37",
"version": "v3.4.38",
"source": {
"type": "git",
"url": "https://github.com/symfony/phpunit-bridge.git",
"reference": "ebfd1b428ffc14306e843092763f228bfba168d0"
"reference": "c02893ae43532b46a4f0e0f207d088b939f278d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/ebfd1b428ffc14306e843092763f228bfba168d0",
"reference": "ebfd1b428ffc14306e843092763f228bfba168d0",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/c02893ae43532b46a4f0e0f207d088b939f278d9",
"reference": "c02893ae43532b46a4f0e0f207d088b939f278d9",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"conflict": {
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0|<6.4,>=6.0"
},
"suggest": {
"symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
@ -1348,7 +1347,21 @@
],
"description": "Symfony PHPUnit Bridge",
"homepage": "https://symfony.com",
"time": "2020-01-14T14:27:59+00:00"
"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": "2020-02-21T08:01:47+00:00"
}
],
"aliases": [],
@ -1362,5 +1375,6 @@
"platform-dev": [],
"platform-overrides": {
"php": "5.3.9"
}
},
"plugin-api-version": "1.1.0"
}

View File

@ -129,11 +129,17 @@ A list of domain names and username/passwords to authenticate against them. For
example using `{"example.org": {"username": "alice", "password": "foo"}}` as the
value of this option will let Composer authenticate against example.org.
> **Note:** Authentication-related config options like `http-basic` and
> **Note:** Authentication-related config options like `http-basic`, `bearer` and
> `github-oauth` can also be specified inside a `auth.json` file that goes
> besides your `composer.json`. That way you can gitignore it and every
> developer can place their own credentials in there.
## bearer
A list of domain names and tokens to authenticate against them. For example using
`{"example.org": "foo"}` as the value of this option will let Composer authenticate
against example.org using an `Authorization: Bearer foo` header.
## platform
Lets you fake platform packages (PHP and extensions) so that you can emulate a

View File

@ -54,7 +54,7 @@ v2.0.2
Normally, Composer deals with tags (as opposed to branches -- if you don't
know what this means, read up on
[version control systems](https://en.wikipedia.org/wiki/Version_control#Common_vocabulary)).
[version control systems](https://en.wikipedia.org/wiki/Version_control#Common_terminology)).
When you write a version constraint, it may reference a specific tag (e.g.,
`1.1`) or it may reference a valid range of tags (e.g., `>=1.1 <2.0`, or
`~4.0`). To resolve these constraints, Composer first asks the VCS to list

View File

@ -140,7 +140,16 @@
"gitlab-token": {
"type": "object",
"description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
"additionalProperties": true
"additionalProperties": {
"type": "string"
}
},
"bearer": {
"type": "object",
"description": "A hash of domain name => bearer authentication token, for example {\"example.com\":\"<token>\"}.",
"additionalProperties": {
"type": "string"
}
},
"disable-tls": {
"type": "boolean",

View File

@ -236,6 +236,7 @@ EOF;
// flatten array
$classMap = array();
$ambiguousClasses = array();
if ($scanPsr0Packages) {
$namespacesToScan = array();
@ -256,14 +257,23 @@ EOF;
continue;
}
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespace, $group['type'], $classMap);
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespace, $group['type'], $classMap, $ambiguousClasses);
}
}
}
}
foreach ($autoloads['classmap'] as $dir) {
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, null, $classMap);
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, null, $classMap, $ambiguousClasses);
}
foreach ($ambiguousClasses as $className => $ambigiousPaths) {
$cleanPath = str_replace(array('$vendorDir . \'', '$baseDir . \'', "',\n"), array($vendorPath, $basePath, ''), $classMap[$className]);
$this->io->writeError(
'<warning>Warning: Ambiguous class resolution, "'.$className.'"'.
' was found '. (count($ambigiousPaths) + 1) .'x: in "'.$cleanPath.'" and "'. implode('", "', $ambigiousPaths) .'", the first will be used.</warning>'
);
}
ksort($classMap);
@ -326,17 +336,14 @@ EOF;
return 0;
}
private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, $autoloadType = null, array $classMap = array())
private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, $autoloadType = null, array $classMap, array &$ambiguousClasses)
{
foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType) as $class => $path) {
$pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
if (!isset($classMap[$class])) {
$classMap[$class] = $pathCode;
} elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
$this->io->writeError(
'<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
);
$ambiguousClasses[$class][] = $path;
}
}
@ -939,16 +946,23 @@ INITIALIZER;
{
$packages = array();
$include = array();
$replacedBy = array();
foreach ($packageMap as $item) {
$package = $item[0];
$name = $package->getName();
$packages[$name] = $package;
foreach ($package->getReplaces() as $replace) {
$replacedBy[$replace->getTarget()] = $name;
}
}
$add = function (PackageInterface $package) use (&$add, $packages, &$include) {
$add = function (PackageInterface $package) use (&$add, $packages, &$include, $replacedBy) {
foreach ($package->getRequires() as $link) {
$target = $link->getTarget();
if (isset($replacedBy[$target])) {
$target = $replacedBy[$target];
}
if (!isset($include[$target])) {
$include[$target] = true;
if (isset($packages[$target])) {

View File

@ -187,7 +187,7 @@ EOT
}
if ($input->getOption('global') && !$this->authConfigFile->exists()) {
touch($this->authConfigFile->getPath());
$this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
$this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject, 'bearer' => new \ArrayObject));
Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
}
@ -667,7 +667,7 @@ EOT
}
// handle auth
if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\.(.+)/', $settingKey, $matches)) {
if ($input->getOption('unset')) {
$this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
$this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
@ -681,7 +681,7 @@ EOT
}
$this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
$this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
} elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
} elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'), true)) {
if (1 !== count($values)) {
throw new \RuntimeException('Too many arguments, expected only one token');
}

View File

@ -303,13 +303,16 @@ EOT
// if no directory was specified, use the 2nd part of the package name
if (null === $directory) {
$parts = explode("/", $name, 2);
$directory = array_pop($parts);
$directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
}
$directory = getcwd() . DIRECTORY_SEPARATOR . $directory;
$io->writeError('<info>Creating a "' . $packageName . '" project at "' . $directory . '"</info>');
$fs = new Filesystem();
if (!$fs->isAbsolutePath($directory)) {
$directory = getcwd() . DIRECTORY_SEPARATOR . $directory;
}
$io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(getcwd(), $directory, true) . '"</info>');
if (file_exists($directory)) {
if (!is_dir($directory)) {
throw new \InvalidArgumentException('Cannot create project directory at "'.$directory.'", it exists as a file.');

View File

@ -14,6 +14,7 @@ namespace Composer\Command;
use Composer\Package\CompletePackageInterface;
use Composer\Package\AliasPackage;
use Composer\Repository\CompositeRepository;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -36,20 +37,19 @@ class FundCommand extends BaseCommand
$composer = $this->getComposer();
$repo = $composer->getRepositoryManager()->getLocalRepository();
$remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
$fundings = array();
foreach ($repo->getPackages() as $package) {
if ($package instanceof AliasPackage) {
continue;
}
if ($package instanceof CompletePackageInterface && $funding = $package->getFunding()) {
foreach ($funding as $fundingOption) {
list($vendor, $packageName) = explode('/', $package->getPrettyName());
$url = $fundingOption['url'];
if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && preg_match('{^https://github.com/([^/]+)$}', $url, $match)) {
$url = 'https://github.com/sponsors/'.$match[1];
}
$fundings[$vendor][$url][] = $packageName;
$latest = $remoteRepos->findPackage($package->getName(), 'dev-master');
if ($latest instanceof CompletePackageInterface && $latest->getFunding()) {
$fundings = $this->insertFundingData($fundings, $latest);
continue;
}
if ($package instanceof CompletePackageInterface && $package->getFunding()) {
$fundings = $this->insertFundingData($fundings, $package);
}
}
@ -86,4 +86,18 @@ class FundCommand extends BaseCommand
return 0;
}
private function insertFundingData(array $fundings, CompletePackageInterface $package)
{
foreach ($package->getFunding() as $fundingOption) {
list($vendor, $packageName) = explode('/', $package->getPrettyName());
$url = $fundingOption['url'];
if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && preg_match('{^https://github.com/([^/]+)$}', $url, $match)) {
$url = 'https://github.com/sponsors/'.$match[1];
}
$fundings[$vendor][$url][] = $packageName;
}
return $fundings;
}
}

View File

@ -495,7 +495,7 @@ EOT
}
$io->write('');
if (isset($package['warning'])) {
$io->writeError('<warning>' . $package['warning'] . '</warning>');
$io->write('<warning>' . $package['warning'] . '</warning>');
}
}

View File

@ -70,6 +70,7 @@ class Config
// gitlab-oauth
// gitlab-token
// http-basic
// bearer
);
public static $defaultRepositories = array(
@ -133,7 +134,7 @@ class Config
// override defaults with given config
if (!empty($config['config']) && is_array($config['config'])) {
foreach ($config['config'] as $key => $val) {
if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer')) && isset($this->config[$key])) {
$this->config[$key] = array_merge($this->config[$key], $val);
} elseif ('preferred-install' === $key && isset($this->config[$key])) {
if (is_array($val) || is_array($this->config[$key])) {

View File

@ -96,7 +96,7 @@ class JsonConfigSource implements ConfigSourceInterface
{
$authConfig = $this->authConfig;
$this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
list($key, $host) = explode('.', $key, 2);
if ($authConfig) {
$config[$key][$host] = $val;
@ -116,7 +116,7 @@ class JsonConfigSource implements ConfigSourceInterface
{
$authConfig = $this->authConfig;
$this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
list($key, $host) = explode('.', $key, 2);
if ($authConfig) {
unset($config[$key][$host]);

View File

@ -131,7 +131,8 @@ class Application extends BaseApplication
if ($input->hasParameterOption('--no-cache')) {
$io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
putenv('COMPOSER_CACHE_DIR='.(Platform::isWindows() ? 'nul' : '/dev/null'));
$_SERVER['COMPOSER_CACHE_DIR'] = Platform::isWindows() ? 'nul' : '/dev/null';
putenv('COMPOSER_CACHE_DIR='.$_SERVER['COMPOSER_CACHE_DIR']);
}
// switch working dir

View File

@ -243,7 +243,8 @@ class EventDispatcher
$finder = new PhpExecutableFinder();
$phpPath = $finder->find(false);
if ($phpPath) {
putenv('PHP_BINARY=' . $phpPath);
$_SERVER['PHP_BINARY'] = $phpPath;
putenv('PHP_BINARY=' . $_SERVER['PHP_BINARY']);
}
}

View File

@ -115,6 +115,7 @@ abstract class BaseIO implements IOInterface
$gitlabOauth = $config->get('gitlab-oauth') ?: array();
$gitlabToken = $config->get('gitlab-token') ?: array();
$httpBasic = $config->get('http-basic') ?: array();
$bearerToken = $config->get('bearer') ?: array();
// reload oauth tokens from config if available
@ -142,6 +143,10 @@ abstract class BaseIO implements IOInterface
$this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
}
foreach ($bearerToken as $domain => $token) {
$this->checkAndSetAuthentication($domain, $token, 'bearer');
}
// setup process timeout
ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
}

View File

@ -219,8 +219,8 @@ class Installer
}
if ($this->runScripts) {
$devMode = (int) $this->devMode;
putenv("COMPOSER_DEV_MODE=$devMode");
$_SERVER['COMPOSER_DEV_MODE'] = (int) $this->devMode;
putenv('COMPOSER_DEV_MODE='.$_SERVER['COMPOSER_DEV_MODE']);
// dispatch pre event
// should we treat this more strictly as running an update and then running an install, triggering events multiple times?

View File

@ -23,6 +23,7 @@ use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\ProcessExecutor;
use Composer\Util\HttpDownloader;
use Composer\Util\Url;
use Composer\Semver\Constraint\Constraint;
use Composer\IO\IOInterface;
use Composer\Config;
@ -381,7 +382,12 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
private function validateBranch($branch)
{
try {
return $this->versionParser->normalizeBranch($branch);
$normalizedBranch = $this->versionParser->normalizeBranch($branch);
// validate that the branch name has no weird characters conflicting with constraints
$this->versionParser->parseConstraints($normalizedBranch);
return $normalizedBranch;
} catch (\Exception $e) {
}
@ -421,7 +427,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
$this->io->overwriteError($msg, false);
}
if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
if ($existingPackage = $this->findPackage($cachedPackage['name'], new Constraint('=', $cachedPackage['version_normalized']))) {
if ($isVeryVerbose) {
$this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
}

View File

@ -117,7 +117,7 @@ class AuthHelper
$message = "\n".'Could not fetch '.$url.', enter your ' . $origin . ' credentials ' .($statusCode === 401 ? 'to access private repos' : 'to go over the API rate limit');
$gitLabUtil = new GitLab($this->io, $this->config, null);
if ($this->io->hasAuthentication($origin) && ($auth = $this->io->getAuthentication($origin)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token'), true)) {
if ($this->io->hasAuthentication($origin) && ($auth = $this->io->getAuthentication($origin)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token', 'oauth2'), true)) {
throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
}
@ -196,7 +196,9 @@ class AuthHelper
if ($this->io->hasAuthentication($origin)) {
$authenticationDisplayMessage = null;
$auth = $this->io->getAuthentication($origin);
if ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) {
if ($auth['password'] === 'bearer') {
$headers[] = 'Authorization: Bearer '.$auth['username'];
} elseif ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) {
$headers[] = 'Authorization: token '.$auth['username'];
$authenticationDisplayMessage = 'Using GitHub token authentication';
} elseif (in_array($origin, $this->config->get('gitlab-domains'), true)) {

View File

@ -312,7 +312,9 @@ class Filesystem
}
if (!function_exists('proc_open')) {
return $this->copyThenRemove($source, $target);
$this->copyThenRemove($source, $target);
return;
}
if (Platform::isWindows()) {
@ -342,7 +344,7 @@ class Filesystem
}
}
return $this->copyThenRemove($source, $target);
$this->copyThenRemove($source, $target);
}
/**

View File

@ -486,6 +486,58 @@ class AutoloadGeneratorTest extends TestCase
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
}
public function testNonDevAutoloadReplacesNestedRequirements()
{
$package = new Package('a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a')
));
$packages = array();
$packages[] = $a = new Package('a/a', '1.0', '1.0');
$packages[] = $b = new Package('b/b', '1.0', '1.0');
$packages[] = $c = new Package('c/c', '1.0', '1.0');
$packages[] = $d = new Package('d/d', '1.0', '1.0');
$packages[] = $e = new Package('e/e', '1.0', '1.0');
$a->setAutoload(array('classmap' => array('src/A.php')));
$a->setRequires(array(
new Link('a/a', 'b/b')
));
$b->setAutoload(array('classmap' => array('src/B.php')));
$b->setRequires(array(
new Link('b/b', 'e/e')
));
$c->setAutoload(array('classmap' => array('src/C.php')));
$c->setReplaces(array(
new Link('c/c', 'b/b')
));
$c->setRequires(array(
new Link('c/c', 'd/d')
));
$d->setAutoload(array('classmap' => array('src/D.php')));
$e->setAutoload(array('classmap' => array('src/E.php')));
$this->repository->expects($this->once())
->method('getCanonicalPackages')
->will($this->returnValue($packages));
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/c/c/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/d/d/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/e/e/src');
file_put_contents($this->vendorDir.'/a/a/src/A.php', '<?php class A {}');
file_put_contents($this->vendorDir.'/b/b/src/B.php', '<?php class B {}');
file_put_contents($this->vendorDir.'/c/c/src/C.php', '<?php class C {}');
file_put_contents($this->vendorDir.'/d/d/src/D.php', '<?php class D {}');
file_put_contents($this->vendorDir.'/e/e/src/E.php', '<?php class E {}');
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_5');
$this->assertAutoloadFiles('classmap9', $this->vendorDir.'/composer', 'classmap');
}
public function testPharAutoload()
{
$package = new Package('a', '1.0', '1.0');

View File

@ -0,0 +1,12 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'A' => $vendorDir . '/a/a/src/A.php',
'C' => $vendorDir . '/c/c/src/C.php',
'D' => $vendorDir . '/d/d/src/D.php',
);