Skip to content

Commit

Permalink
Fix support for writing into UNC paths, and comparing UNC paths corre…
Browse files Browse the repository at this point in the history
…ctly in InstalledVersions, fixes composer#9993
  • Loading branch information
Seldaek committed Jul 12, 2021
1 parent cc81f5b commit 2e3b328
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
11 changes: 8 additions & 3 deletions src/Composer/Factory.php
Expand Up @@ -385,7 +385,7 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
$composer->setPackage($package);

// load local repository
$this->addLocalRepository($io, $rm, $vendorDir, $package);
$this->addLocalRepository($io, $rm, $vendorDir, $package, $process);

// initialize installation manager
$im = $this->createInstallationManager($loop, $io, $dispatcher);
Expand Down Expand Up @@ -458,9 +458,14 @@ public static function createGlobal(IOInterface $io, $disablePlugins = false)
* @param Repository\RepositoryManager $rm
* @param string $vendorDir
*/
protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir, RootPackageInterface $rootPackage)
protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir, RootPackageInterface $rootPackage, ProcessExecutor $process = null)
{
$rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io), true, $rootPackage));
$fs = null;
if ($process) {
$fs = new Filesystem($process);
}

$rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io), true, $rootPackage, $fs));
}

/**
Expand Down
32 changes: 21 additions & 11 deletions src/Composer/Repository/FilesystemRepository.php
Expand Up @@ -31,6 +31,7 @@ class FilesystemRepository extends WritableArrayRepository
protected $file;
private $dumpVersions;
private $rootPackage;
private $filesystem;

/**
* Initializes filesystem repository.
Expand All @@ -39,12 +40,13 @@ class FilesystemRepository extends WritableArrayRepository
* @param bool $dumpVersions
* @param ?RootPackageInterface $rootPackage Must be provided if $dumpVersions is true
*/
public function __construct(JsonFile $repositoryFile, $dumpVersions = false, RootPackageInterface $rootPackage = null)
public function __construct(JsonFile $repositoryFile, $dumpVersions = false, RootPackageInterface $rootPackage = null, Filesystem $filesystem = null)
{
parent::__construct();
$this->file = $repositoryFile;
$this->dumpVersions = $dumpVersions;
$this->rootPackage = $rootPackage;
$this->filesystem = $filesystem ?: new Filesystem;
if ($dumpVersions && !$rootPackage) {
throw new \InvalidArgumentException('Expected a root package instance if $dumpVersions is true');
}
Expand Down Expand Up @@ -100,14 +102,24 @@ public function write($devMode, InstallationManager $installationManager)
{
$data = array('packages' => array(), 'dev' => $devMode, 'dev-package-names' => array());
$dumper = new ArrayDumper();
$fs = new Filesystem();
$repoDir = dirname($fs->normalizePath($this->file->getPath()));

// make sure the directory is created so we can realpath it
// as realpath() does some additional normalizations with network paths that normalizePath does not
// and we need to find shortest path correctly
$repoDir = dirname($this->file->getPath());
$this->filesystem->ensureDirectoryExists($repoDir);

$repoDir = $this->filesystem->normalizePath(realpath($repoDir));
$installPaths = array();

foreach ($this->getCanonicalPackages() as $package) {
$pkgArray = $dumper->dump($package);
$path = $installationManager->getInstallPath($package);
$installPath = ('' !== $path && null !== $path) ? $fs->findShortestPath($repoDir, $fs->isAbsolutePath($path) ? $path : getcwd() . '/' . $path, true) : null;
$installPath = null;
if ('' !== $path && null !== $path) {
$normalizedPath = $this->filesystem->normalizePath($this->filesystem->isAbsolutePath($path) ? $path : getcwd() . '/' . $path);
$installPath = $this->filesystem->findShortestPath($repoDir, $normalizedPath, true);
}
$installPaths[$package->getName()] = $installPath;

$pkgArray['install-path'] = $installPath;
Expand All @@ -130,9 +142,9 @@ public function write($devMode, InstallationManager $installationManager)
if ($this->dumpVersions) {
$versions = $this->generateInstalledVersions($installationManager, $installPaths, $devMode, $repoDir);

$fs->filePutContentsIfModified($repoDir.'/installed.php', '<?php return ' . $this->dumpToPhpCode($versions) . ';'."\n");
$this->filesystem->filePutContentsIfModified($repoDir.'/installed.php', '<?php return ' . $this->dumpToPhpCode($versions) . ';'."\n");
$installedVersionsClass = file_get_contents(__DIR__.'/../InstalledVersions.php');
$fs->filePutContentsIfModified($repoDir.'/InstalledVersions.php', $installedVersionsClass);
$this->filesystem->filePutContentsIfModified($repoDir.'/InstalledVersions.php', $installedVersionsClass);

\Composer\InstalledVersions::reload($versions);
}
Expand All @@ -154,8 +166,7 @@ private function dumpToPhpCode(array $array = array(), $level = 0)
$lines .= "array(),\n";
}
} elseif ($key === 'install_path' && is_string($value)) {
$fs = new Filesystem();
if ($fs->isAbsolutePath($value)) {
if ($this->filesystem->isAbsolutePath($value)) {
$lines .= var_export($value, true) . ",\n";
} else {
$lines .= "__DIR__ . " . var_export('/' . $value, true) . ",\n";
Expand Down Expand Up @@ -203,9 +214,8 @@ private function generateInstalledVersions(InstallationManager $installationMana
}

if ($package instanceof RootPackageInterface) {
$fs = new Filesystem();
$to = getcwd();
$installPath = $fs->findShortestPath($repoDir, $to, true);
$to = $this->filesystem->normalizePath(realpath(getcwd()));
$installPath = $this->filesystem->findShortestPath($repoDir, $to, true);
} else {
$installPath = $installPaths[$package->getName()];
}
Expand Down
9 changes: 7 additions & 2 deletions tests/Composer/Test/Repository/FilesystemRepositoryTest.php
Expand Up @@ -16,6 +16,7 @@
use Composer\Repository\FilesystemRepository;
use Composer\Test\TestCase;
use Composer\Json\JsonFile;
use Composer\Util\Filesystem;

class FilesystemRepositoryTest extends TestCase
{
Expand Down Expand Up @@ -83,13 +84,17 @@ public function testRepositoryWrite()
{
$json = $this->createJsonFileMock();

$repoDir = sys_get_temp_dir().'/repo_write_test/';
$fs = new Filesystem();
$fs->removeDirectory($repoDir);

$repository = new FilesystemRepository($json);
$im = $this->getMockBuilder('Composer\Installer\InstallationManager')
->disableOriginalConstructor()
->getMock();
$im->expects($this->exactly(2))
->method('getInstallPath')
->will($this->returnValue('/foo/bar/vendor/woop/woop'));
->will($this->returnValue($repoDir.'/vendor/woop/woop'));

$json
->expects($this->once())
Expand All @@ -98,7 +103,7 @@ public function testRepositoryWrite()
$json
->expects($this->once())
->method('getPath')
->will($this->returnValue('/foo/bar/vendor/composer/installed.json'));
->will($this->returnValue($repoDir.'/vendor/composer/installed.json'));
$json
->expects($this->once())
->method('exists')
Expand Down

0 comments on commit 2e3b328

Please sign in to comment.