/usr/share/php/Composer/Downloader/PathDownloader.php is in composer 1.0.0~beta2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | <?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Downloader;
use Composer\Package\PackageInterface;
use Composer\Util\Platform;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
/**
* Download a package from a local path.
*
* @author Samuel Roze <samuel.roze@gmail.com>
* @author Johann Reinke <johann.reinke@gmail.com>
*/
class PathDownloader extends FileDownloader
{
const STRATEGY_SYMLINK = 10;
const STRATEGY_MIRROR = 20;
/**
* {@inheritdoc}
*/
public function download(PackageInterface $package, $path)
{
$url = $package->getDistUrl();
$realUrl = realpath($url);
if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
throw new \RuntimeException(sprintf(
'Source path "%s" is not found for package %s', $url, $package->getName()
));
}
if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
throw new \RuntimeException(sprintf(
'Package %s cannot install to "%s" inside its source at "%s"',
$package->getName(), realpath($path), $realUrl
));
}
// Get the transport options with default values
$transportOptions = $package->getTransportOptions() + array('symlink' => null);
// When symlink transport option is null, both symlink and mirror are allowed
$currentStrategy = self::STRATEGY_SYMLINK;
$allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
if (true === $transportOptions['symlink']) {
$currentStrategy = self::STRATEGY_SYMLINK;
$allowedStrategies = array(self::STRATEGY_SYMLINK);
} elseif (false === $transportOptions['symlink']) {
$currentStrategy = self::STRATEGY_MIRROR;
$allowedStrategies = array(self::STRATEGY_MIRROR);
}
$fileSystem = new Filesystem();
$this->filesystem->removeDirectory($path);
$this->io->writeError(sprintf(
' - Installing <info>%s</info> (<comment>%s</comment>)',
$package->getName(),
$package->getFullPrettyVersion()
));
if (self::STRATEGY_SYMLINK == $currentStrategy) {
try {
if (Platform::isWindows()) {
// Implement symlinks as NTFS junctions on Windows
$this->filesystem->junction($realUrl, $path);
$this->io->writeError(sprintf(' Junctioned from %s', $url));
} else {
$absolutePath = $path;
if ( ! $this->filesystem->isAbsolutePath($absolutePath)) {
$absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
}
$shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
$fileSystem->symlink($shortestPath, $path);
$this->io->writeError(sprintf(' Symlinked from %s', $url));
}
} catch (IOException $e) {
if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
$this->io->writeError(' <error>Symlink failed, fallback to use mirroring!</error>');
$currentStrategy = self::STRATEGY_MIRROR;
} else {
throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
}
}
}
// Fallback if symlink failed or if symlink is not allowed for the package
if (self::STRATEGY_MIRROR == $currentStrategy) {
$fileSystem->mirror($realUrl, $path);
$this->io->writeError(sprintf(' Mirrored from %s', $url));
}
$this->io->writeError('');
}
/**
* {@inheritDoc}
*/
public function remove(PackageInterface $package, $path)
{
/**
* For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process
* inadvertently locks the file the removal will fail, but it would fall back to recursive delete which
* is disastrous within a junction. So in that case we have no other real choice but to fail hard.
*/
if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
$this->io->writeError(" - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
if (!$this->filesystem->removeJunction($path)) {
$this->io->writeError("<warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
}
} else {
parent::remove($package, $path);
}
}
}
|