1
0
Fork 0

Fix create-project to reuse the target folders permissions for files created (#12146)

* Fix create-project to reuse the target folders permissions for files created

Fixes #9039

* Fix issue when COMPOSER_VENDOR_DIR env is set

* Allow null in setBaseDir
pull/12152/head
Jordi Boggiano 2024-10-04 11:19:36 +02:00 committed by GitHub
parent 33ffd5abc3
commit ac2f89a05b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 17 deletions

View File

@ -319,14 +319,6 @@ EOT
$composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages); $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
chdir($oldCwd); chdir($oldCwd);
$vendorComposerDir = $config->get('vendor-dir').'/composer';
if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
Silencer::call('rmdir', $vendorComposerDir);
$vendorDir = $config->get('vendor-dir');
if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
Silencer::call('rmdir', $vendorDir);
}
}
return 0; return 0;
} }
@ -338,10 +330,6 @@ EOT
*/ */
protected function installRootPackage(InputInterface $input, IOInterface $io, Config $config, string $packageName, PlatformRequirementFilterInterface $platformRequirementFilter, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = false, bool $preferDist = false, bool $installDevPackages = false, ?array $repositories = null, bool $disablePlugins = false, bool $disableScripts = false, bool $noProgress = false, bool $secureHttp = true): bool protected function installRootPackage(InputInterface $input, IOInterface $io, Config $config, string $packageName, PlatformRequirementFilterInterface $platformRequirementFilter, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = false, bool $preferDist = false, bool $installDevPackages = false, ?array $repositories = null, bool $disablePlugins = false, bool $disableScripts = false, bool $noProgress = false, bool $secureHttp = true): bool
{ {
if (!$secureHttp) {
$config->merge(['config' => ['secure-http' => false]], Config::SOURCE_COMMAND);
}
$parser = new VersionParser(); $parser = new VersionParser();
$requirements = $parser->parseNameVersionPairs([$packageName]); $requirements = $parser->parseNameVersionPairs([$packageName]);
$name = strtolower($requirements[0]['name']); $name = strtolower($requirements[0]['name']);
@ -354,12 +342,22 @@ EOT
$parts = explode("/", $name, 2); $parts = explode("/", $name, 2);
$directory = Platform::getCwd() . DIRECTORY_SEPARATOR . array_pop($parts); $directory = Platform::getCwd() . DIRECTORY_SEPARATOR . array_pop($parts);
} }
$directory = rtrim($directory, '/\\');
$process = new ProcessExecutor($io); $process = new ProcessExecutor($io);
$fs = new Filesystem($process); $fs = new Filesystem($process);
if (!$fs->isAbsolutePath($directory)) { if (!$fs->isAbsolutePath($directory)) {
$directory = Platform::getCwd() . DIRECTORY_SEPARATOR . $directory; $directory = Platform::getCwd() . DIRECTORY_SEPARATOR . $directory;
} }
if ('' === $directory) {
throw new \UnexpectedValueException('Got an empty target directory, something went wrong');
}
// set the base dir to ensure $config->all() below resolves the correct absolute paths to vendor-dir etc
$config->setBaseDir($directory);
if (!$secureHttp) {
$config->merge(['config' => ['secure-http' => false]], Config::SOURCE_COMMAND);
}
$io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(Platform::getCwd(), $directory, true) . '"</info>'); $io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(Platform::getCwd(), $directory, true) . '"</info>');
@ -390,6 +388,8 @@ EOT
$composer = $this->createComposerInstance($input, $io, $config->all(), $disablePlugins, $disableScripts); $composer = $this->createComposerInstance($input, $io, $config->all(), $disablePlugins, $disableScripts);
$config = $composer->getConfig(); $config = $composer->getConfig();
// set the base dir here again on the new config instance, as otherwise in case the vendor dir is defined in an env var for example it would still override the value set above by $config->all()
$config->setBaseDir($directory);
$rm = $composer->getRepositoryManager(); $rm = $composer->getRepositoryManager();
$repositorySet = new RepositorySet($stability); $repositorySet = new RepositorySet($stability);
@ -424,16 +424,21 @@ EOT
throw new \InvalidArgumentException($errorMessage .'.'); throw new \InvalidArgumentException($errorMessage .'.');
} }
$oldCwd = Platform::getCwd();
// handler Ctrl+C aborts gracefully // handler Ctrl+C aborts gracefully
@mkdir($directory, 0777, true); @mkdir($directory, 0777, true);
if (false !== ($realDir = realpath($directory))) { if (false !== ($realDir = realpath($directory))) {
$signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use ($realDir) { $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use ($realDir, $oldCwd) {
chdir($oldCwd);
$this->getIO()->writeError('Received '.$signal.', aborting', true, IOInterface::DEBUG); $this->getIO()->writeError('Received '.$signal.', aborting', true, IOInterface::DEBUG);
$fs = new Filesystem(); $fs = new Filesystem();
$fs->removeDirectory($realDir); $fs->removeDirectory($realDir);
$handler->exitWithLastSignal(); $handler->exitWithLastSignal();
}); });
} }
if (!chdir($directory)) {
throw new \RuntimeException('Failed to chdir into the new project dir at '.$directory);
}
// avoid displaying 9999999-dev as version if default-branch was selected // avoid displaying 9999999-dev as version if default-branch was selected
if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
@ -467,7 +472,6 @@ EOT
$installedFromVcs = 'source' === $package->getInstallationSource(); $installedFromVcs = 'source' === $package->getInstallationSource();
$io->writeError('<info>Created project in ' . $directory . '</info>'); $io->writeError('<info>Created project in ' . $directory . '</info>');
chdir($directory);
// ensure that the env var being set does not interfere with create-project // ensure that the env var being set does not interfere with create-project
// as it is probably not meant to be used here, so we do not use it if a composer.json can be found // as it is probably not meant to be used here, so we do not use it if a composer.json can be found

View File

@ -98,7 +98,7 @@ class Config
/** @var array<string, mixed> */ /** @var array<string, mixed> */
private $config; private $config;
/** @var ?string */ /** @var ?non-empty-string */
private $baseDir; private $baseDir;
/** @var array<int|string, mixed> */ /** @var array<int|string, mixed> */
private $repositories; private $repositories;
@ -139,6 +139,18 @@ class Config
} }
} }
/**
* Changing this can break path resolution for relative config paths so do not call this without knowing what you are doing
*
* The $baseDir should be an absolute path and without trailing slash
*
* @param non-empty-string|null $baseDir
*/
public function setBaseDir(?string $baseDir): void
{
$this->baseDir = $baseDir;
}
public function setConfigSource(ConfigSourceInterface $source): void public function setConfigSource(ConfigSourceInterface $source): void
{ {
$this->configSource = $source; $this->configSource = $source;
@ -546,7 +558,7 @@ class Config
return $path; return $path;
} }
return $this->baseDir ? $this->baseDir . '/' . $path : $path; return $this->baseDir !== null ? $this->baseDir . '/' . $path : $path;
} }
/** /**

View File

@ -178,7 +178,7 @@ class RepositoryFactory
/** /**
* @param int|string $index * @param int|string $index
* @param array{url?: string} $repo * @param array{url?: string} $repo
* @param array<string, mixed> $existingRepos * @param array<int|string, mixed> $existingRepos
*/ */
public static function generateRepositoryName($index, array $repo, array $existingRepos): string public static function generateRepositoryName($index, array $repo, array $existingRepos): string
{ {