Update PEAR Package Extractor to use 'task:replace', 'phprelease' commands and install role='script' files
Add PearInstaller Change PEAR packages type from 'library' to 'pear-library' and dist type from 'pear' to 'file' Remove PearDownloader Refactor Channel Installerpull/831/head
parent
0117108efb
commit
ac3cebc633
|
@ -1,52 +0,0 @@
|
||||||
<?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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downloader for pear packages
|
|
||||||
*
|
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
|
||||||
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
|
||||||
*/
|
|
||||||
class PearDownloader extends FileDownloader
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function download(PackageInterface $package, $path)
|
|
||||||
{
|
|
||||||
parent::download($package, $path);
|
|
||||||
|
|
||||||
$fileName = $this->getFileName($package, $path);
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
$this->io->write(' Installing PEAR package');
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$pearExtractor = new PearPackageExtractor($fileName);
|
|
||||||
$pearExtractor->extractTo($path);
|
|
||||||
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
$this->io->write(' Cleaning up');
|
|
||||||
}
|
|
||||||
unlink($fileName);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// clean up
|
|
||||||
$this->filesystem->removeDirectory($path);
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->io->write('');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,22 +35,22 @@ class PearPackageExtractor
|
||||||
throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
|
throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->filesystem = new Filesystem();
|
||||||
$this->file = $file;
|
$this->file = $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs PEAR source files according to package.xml definitions and removes extracted files
|
* Installs PEAR source files according to package.xml definitions and removes extracted files
|
||||||
*
|
*
|
||||||
* @param $file string path to downloaded PEAR archive file
|
* @param string $target target install location. all source installation would be performed relative to target path.
|
||||||
* @param $target string target install location. all source installation would be performed relative to target path.
|
* @param array $roles types of files to install. default role for PEAR source files are 'php'.
|
||||||
* @param $role string type of files to install. default role for PEAR source files are 'php'.
|
* @param array $vars used for replacement tasks
|
||||||
*
|
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
|
* @throws \UnexpectedValueException
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function extractTo($target, $role = 'php')
|
public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
|
||||||
{
|
{
|
||||||
$this->filesystem = new Filesystem();
|
|
||||||
|
|
||||||
$extractionPath = $target.'/tarball';
|
$extractionPath = $target.'/tarball';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -61,8 +61,8 @@ class PearPackageExtractor
|
||||||
throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
|
throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fileCopyActions = $this->buildCopyActions($extractionPath, $role);
|
$fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
|
||||||
$this->copyFiles($fileCopyActions, $extractionPath, $target);
|
$this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
|
||||||
$this->filesystem->removeDirectory($extractionPath);
|
$this->filesystem->removeDirectory($extractionPath);
|
||||||
} catch (\Exception $exception) {
|
} catch (\Exception $exception) {
|
||||||
throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
|
throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
|
||||||
|
@ -72,20 +72,24 @@ class PearPackageExtractor
|
||||||
/**
|
/**
|
||||||
* Perform copy actions on files
|
* Perform copy actions on files
|
||||||
*
|
*
|
||||||
* @param $files array array('from', 'to') with relative paths
|
* @param array $files array of copy actions ('from', 'to') with relative paths
|
||||||
* @param $source string path to source dir.
|
* @param $source string path to source dir.
|
||||||
* @param $target string path to destination dir
|
* @param $target string path to destination dir
|
||||||
|
* @param array $roles array [role => roleRoot] relative root for files having that role
|
||||||
|
* @param array $vars list of values can be used for replacement tasks
|
||||||
*/
|
*/
|
||||||
private function copyFiles($files, $source, $target)
|
private function copyFiles($files, $source, $target, $roles, $vars)
|
||||||
{
|
{
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$from = $this->combine($source, $file['from']);
|
$from = $this->combine($source, $file['from']);
|
||||||
$to = $this->combine($target, $file['to']);
|
$to = $this->combine($target, $roles[$file['role']]);
|
||||||
$this->copyFile($from, $to);
|
$to = $this->combine($to, $file['to']);
|
||||||
|
$tasks = $file['tasks'];
|
||||||
|
$this->copyFile($from, $to, $tasks, $vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function copyFile($from, $to)
|
private function copyFile($from, $to, $tasks, $vars)
|
||||||
{
|
{
|
||||||
if (!is_file($from)) {
|
if (!is_file($from)) {
|
||||||
throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
|
throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
|
||||||
|
@ -93,7 +97,24 @@ class PearPackageExtractor
|
||||||
|
|
||||||
$this->filesystem->ensureDirectoryExists(dirname($to));
|
$this->filesystem->ensureDirectoryExists(dirname($to));
|
||||||
|
|
||||||
if (!copy($from, $to)) {
|
if (0 == count($tasks)) {
|
||||||
|
$copied = copy($from, $to);
|
||||||
|
} else {
|
||||||
|
$content = file_get_contents($from);
|
||||||
|
$replacements = array();
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
$pattern = $task['from'];
|
||||||
|
$varName = $task['to'];
|
||||||
|
if (isset($vars[$varName])) {
|
||||||
|
$replacements[$pattern] = $vars[$varName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$content = strtr($content, $replacements);
|
||||||
|
|
||||||
|
$copied = file_put_contents($to, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $copied) {
|
||||||
throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
|
throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +128,7 @@ class PearPackageExtractor
|
||||||
* path, and target is destination of file (also relative to $source path)
|
* path, and target is destination of file (also relative to $source path)
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
private function buildCopyActions($source, $role)
|
private function buildCopyActions($source, array $roles, $vars)
|
||||||
{
|
{
|
||||||
/** @var $package \SimpleXmlElement */
|
/** @var $package \SimpleXmlElement */
|
||||||
$package = simplexml_load_file($this->combine($source, 'package.xml'));
|
$package = simplexml_load_file($this->combine($source, 'package.xml'));
|
||||||
|
@ -120,13 +141,18 @@ class PearPackageExtractor
|
||||||
$packageName = (string) $package->name;
|
$packageName = (string) $package->name;
|
||||||
$packageVersion = (string) $package->release->version;
|
$packageVersion = (string) $package->release->version;
|
||||||
$sourceDir = $packageName . '-' . $packageVersion;
|
$sourceDir = $packageName . '-' . $packageVersion;
|
||||||
$result = $this->buildSourceList10($children, $role, $sourceDir);
|
$result = $this->buildSourceList10($children, $roles, $sourceDir);
|
||||||
} elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
|
} elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
|
||||||
$children = $package->contents->children();
|
$children = $package->contents->children();
|
||||||
$packageName = (string) $package->name;
|
$packageName = (string) $package->name;
|
||||||
$packageVersion = (string) $package->version->release;
|
$packageVersion = (string) $package->version->release;
|
||||||
$sourceDir = $packageName . '-' . $packageVersion;
|
$sourceDir = $packageName . '-' . $packageVersion;
|
||||||
$result = $this->buildSourceList20($children, $role, $sourceDir);
|
$result = $this->buildSourceList20($children, $roles, $sourceDir);
|
||||||
|
|
||||||
|
$namespaces = $package->getNamespaces();
|
||||||
|
$package->registerXPathNamespace('ns', $namespaces['']);
|
||||||
|
$releaseNodes = $package->xpath('ns:phprelease');
|
||||||
|
$this->applyRelease($result, $releaseNodes, $vars);
|
||||||
} else {
|
} else {
|
||||||
throw new \RuntimeException('Unsupported schema version of package definition file.');
|
throw new \RuntimeException('Unsupported schema version of package definition file.');
|
||||||
}
|
}
|
||||||
|
@ -134,7 +160,34 @@ class PearPackageExtractor
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildSourceList10($children, $targetRole, $source = '', $target = '', $role = null)
|
private function applyRelease(&$actions, $releaseNodes, $vars)
|
||||||
|
{
|
||||||
|
foreach ($releaseNodes as $releaseNode) {
|
||||||
|
$requiredOs = (string) ($releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name) ?: '';
|
||||||
|
if ($requiredOs && $vars['os'] != $requiredOs)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ($releaseNode->filelist) {
|
||||||
|
foreach ($releaseNode->filelist->children() as $action) {
|
||||||
|
if ('install' == $action->getName()) {
|
||||||
|
$name = (string) $action['name'];
|
||||||
|
$as = (string) $action['as'];
|
||||||
|
if (isset($actions[$name])) {
|
||||||
|
$actions[$name]['to'] = $as;
|
||||||
|
}
|
||||||
|
} elseif ('ignore' == $action->getName()) {
|
||||||
|
$name = (string) $action['name'];
|
||||||
|
unset($actions[$name]);
|
||||||
|
} else {
|
||||||
|
// unknown action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildSourceList10($children, $targetRoles, $source = '', $target = '', $role = null)
|
||||||
{
|
{
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
|
@ -145,14 +198,15 @@ class PearPackageExtractor
|
||||||
$dirSource = $this->combine($source, (string) $child['name']);
|
$dirSource = $this->combine($source, (string) $child['name']);
|
||||||
$dirTarget = $child['baseinstalldir'] ? : $target;
|
$dirTarget = $child['baseinstalldir'] ? : $target;
|
||||||
$dirRole = $child['role'] ? : $role;
|
$dirRole = $child['role'] ? : $role;
|
||||||
$dirFiles = $this->buildSourceList10($child->children(), $targetRole, $dirSource, $dirTarget, $dirRole);
|
$dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole);
|
||||||
$result = array_merge($result, $dirFiles);
|
$result = array_merge($result, $dirFiles);
|
||||||
} elseif ($child->getName() == 'file') {
|
} elseif ($child->getName() == 'file') {
|
||||||
if (($child['role'] ? : $role) == $targetRole) {
|
$fileRole = (string) $child['role'] ? : $role;
|
||||||
|
if (isset($targetRoles[$fileRole])) {
|
||||||
$fileName = (string) ($child['name'] ? : $child[0]); // $child[0] means text content
|
$fileName = (string) ($child['name'] ? : $child[0]); // $child[0] means text content
|
||||||
$fileSource = $this->combine($source, $fileName);
|
$fileSource = $this->combine($source, $fileName);
|
||||||
$fileTarget = $this->combine((string) $child['baseinstalldir'] ? : $target, $fileName);
|
$fileTarget = $this->combine((string) $child['baseinstalldir'] ? : $target, $fileName);
|
||||||
$result[] = array('from' => $fileSource, 'to' => $fileTarget);
|
$result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,24 +214,31 @@ class PearPackageExtractor
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildSourceList20($children, $targetRole, $source = '', $target = '', $role = null)
|
private function buildSourceList20($children, $targetRoles, $source = '', $target = '', $role = null)
|
||||||
{
|
{
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
// enumerating files
|
// enumerating files
|
||||||
foreach ($children as $child) {
|
foreach ($children as $child) {
|
||||||
/** @var $child \SimpleXMLElement */
|
/** @var $child \SimpleXMLElement */
|
||||||
if ($child->getName() == 'dir') {
|
if ('dir' == $child->getName()) {
|
||||||
$dirSource = $this->combine($source, $child['name']);
|
$dirSource = $this->combine($source, $child['name']);
|
||||||
$dirTarget = $child['baseinstalldir'] ? : $target;
|
$dirTarget = $child['baseinstalldir'] ? : $target;
|
||||||
$dirRole = $child['role'] ? : $role;
|
$dirRole = $child['role'] ? : $role;
|
||||||
$dirFiles = $this->buildSourceList20($child->children(), $targetRole, $dirSource, $dirTarget, $dirRole);
|
$dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole);
|
||||||
$result = array_merge($result, $dirFiles);
|
$result = array_merge($result, $dirFiles);
|
||||||
} elseif ($child->getName() == 'file') {
|
} elseif ('file' == $child->getName()) {
|
||||||
if (($child['role'] ? : $role) == $targetRole) {
|
$fileRole = (string) $child['role'] ? : $role;
|
||||||
|
if (isset($targetRoles[$fileRole])) {
|
||||||
$fileSource = $this->combine($source, (string) $child['name']);
|
$fileSource = $this->combine($source, (string) $child['name']);
|
||||||
$fileTarget = $this->combine((string) ($child['baseinstalldir'] ? : $target), (string) $child['name']);
|
$fileTarget = $this->combine((string) ($child['baseinstalldir'] ? : $target), (string) $child['name']);
|
||||||
$result[] = array('from' => $fileSource, 'to' => $fileTarget);
|
$fileTasks = array();
|
||||||
|
foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
|
||||||
|
if ('replace' == $taskNode->getName()) {
|
||||||
|
$fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,6 @@ class Factory
|
||||||
$dm->setDownloader('git', new Downloader\GitDownloader($io));
|
$dm->setDownloader('git', new Downloader\GitDownloader($io));
|
||||||
$dm->setDownloader('svn', new Downloader\SvnDownloader($io));
|
$dm->setDownloader('svn', new Downloader\SvnDownloader($io));
|
||||||
$dm->setDownloader('hg', new Downloader\HgDownloader($io));
|
$dm->setDownloader('hg', new Downloader\HgDownloader($io));
|
||||||
$dm->setDownloader('pear', new Downloader\PearDownloader($io));
|
|
||||||
$dm->setDownloader('zip', new Downloader\ZipDownloader($io));
|
$dm->setDownloader('zip', new Downloader\ZipDownloader($io));
|
||||||
$dm->setDownloader('tar', new Downloader\TarDownloader($io));
|
$dm->setDownloader('tar', new Downloader\TarDownloader($io));
|
||||||
$dm->setDownloader('phar', new Downloader\PharDownloader($io));
|
$dm->setDownloader('phar', new Downloader\PharDownloader($io));
|
||||||
|
@ -251,6 +250,7 @@ class Factory
|
||||||
protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
|
protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
|
||||||
{
|
{
|
||||||
$im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
|
$im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
|
||||||
|
$im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
|
||||||
$im->addInstaller(new Installer\InstallerInstaller($io, $composer));
|
$im->addInstaller(new Installer\InstallerInstaller($io, $composer));
|
||||||
$im->addInstaller(new Installer\MetapackageInstaller($io));
|
$im->addInstaller(new Installer\MetapackageInstaller($io));
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
$this->removeBinaries($package);
|
$this->removeBinaries($package);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->downloadManager->download($package, $downloadPath);
|
$this->installCode($package);
|
||||||
$this->installBinaries($package);
|
$this->installBinaries($package);
|
||||||
if (!$repo->hasPackage($package)) {
|
if (!$repo->hasPackage($package)) {
|
||||||
$repo->addPackage(clone $package);
|
$repo->addPackage(clone $package);
|
||||||
|
@ -102,7 +102,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
$downloadPath = $this->getInstallPath($initial);
|
$downloadPath = $this->getInstallPath($initial);
|
||||||
|
|
||||||
$this->removeBinaries($initial);
|
$this->removeBinaries($initial);
|
||||||
$this->downloadManager->update($initial, $target, $downloadPath);
|
$this->updateCode($initial, $target, $downloadPath);
|
||||||
$this->installBinaries($target);
|
$this->installBinaries($target);
|
||||||
$repo->removePackage($initial);
|
$repo->removePackage($initial);
|
||||||
if (!$repo->hasPackage($target)) {
|
if (!$repo->hasPackage($target)) {
|
||||||
|
@ -123,7 +123,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
|
|
||||||
$downloadPath = $this->getInstallPath($package);
|
$downloadPath = $this->getInstallPath($package);
|
||||||
|
|
||||||
$this->downloadManager->remove($package, $downloadPath);
|
$this->removeCode($package);
|
||||||
$this->removeBinaries($package);
|
$this->removeBinaries($package);
|
||||||
$repo->removePackage($package);
|
$repo->removePackage($package);
|
||||||
|
|
||||||
|
@ -146,12 +146,36 @@ class LibraryInstaller implements InstallerInterface
|
||||||
return ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
|
return ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function installCode(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$downloadPath = $this->getInstallPath($package);
|
||||||
|
$this->downloadManager->download($package, $downloadPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function updateCode(PackageInterface $initial, PackageInterface $target)
|
||||||
|
{
|
||||||
|
$downloadPath = $this->getInstallPath($initial);
|
||||||
|
$this->downloadManager->update($initial, $target, $downloadPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeCode(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$downloadPath = $this->getInstallPath($package);
|
||||||
|
$this->downloadManager->remove($package, $downloadPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBinaries(PackageInterface $package)
|
||||||
|
{
|
||||||
|
return $package->getBinaries();
|
||||||
|
}
|
||||||
|
|
||||||
protected function installBinaries(PackageInterface $package)
|
protected function installBinaries(PackageInterface $package)
|
||||||
{
|
{
|
||||||
if (!$package->getBinaries()) {
|
$binaries = $this->getBinaries($package);
|
||||||
|
if (!$binaries) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
foreach ($package->getBinaries() as $bin) {
|
foreach ($binaries as $bin) {
|
||||||
$this->initializeBinDir();
|
$this->initializeBinDir();
|
||||||
$link = $this->binDir.'/'.basename($bin);
|
$link = $this->binDir.'/'.basename($bin);
|
||||||
if (file_exists($link)) {
|
if (file_exists($link)) {
|
||||||
|
@ -193,10 +217,11 @@ class LibraryInstaller implements InstallerInterface
|
||||||
|
|
||||||
protected function removeBinaries(PackageInterface $package)
|
protected function removeBinaries(PackageInterface $package)
|
||||||
{
|
{
|
||||||
if (!$package->getBinaries()) {
|
$binaries = $this->getBinaries($package);
|
||||||
|
if (!$binaries) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
foreach ($package->getBinaries() as $bin) {
|
foreach ($binaries as $bin) {
|
||||||
$link = $this->binDir.'/'.basename($bin);
|
$link = $this->binDir.'/'.basename($bin);
|
||||||
if (!file_exists($link)) {
|
if (!file_exists($link)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?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\Installer;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
use Composer\Composer;
|
||||||
|
use Composer\Downloader\PearPackageExtractor;
|
||||||
|
use Composer\Downloader\DownloadManager;
|
||||||
|
use Composer\Repository\InstalledRepositoryInterface;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Util\Filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package installation manager.
|
||||||
|
*
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
|
*/
|
||||||
|
class PearInstaller extends LibraryInstaller
|
||||||
|
{
|
||||||
|
private $filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes library installer.
|
||||||
|
*
|
||||||
|
* @param string $vendorDir relative path for packages home
|
||||||
|
* @param string $binDir relative path for binaries
|
||||||
|
* @param DownloadManager $dm download manager
|
||||||
|
* @param IOInterface $io io instance
|
||||||
|
* @param string $type package type that this installer handles
|
||||||
|
*/
|
||||||
|
public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
|
||||||
|
{
|
||||||
|
$this->filesystem = new Filesystem();
|
||||||
|
parent::__construct($io, $composer, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
|
||||||
|
{
|
||||||
|
$this->uninstall($repo, $initial);
|
||||||
|
$this->install($repo, $target);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function installCode(PackageInterface $package)
|
||||||
|
{
|
||||||
|
parent::installCode($package);
|
||||||
|
|
||||||
|
$isWindows = defined('PHP_WINDOWS_VERSION_BUILD') ? true : false;
|
||||||
|
|
||||||
|
$vars = array(
|
||||||
|
'os' => $isWindows ? 'windows' : 'linux',
|
||||||
|
'php_bin' => ($isWindows ? getenv('PHPRC') .'php.exe' : `which php`),
|
||||||
|
'pear_php' => $this->getInstallPath($package),
|
||||||
|
'bin_dir' => $this->getInstallPath($package) . '/bin',
|
||||||
|
'php_dir' => $this->getInstallPath($package),
|
||||||
|
'data_dir' => '@DATA_DIR@',
|
||||||
|
'version' => $package->getPrettyVersion(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
|
||||||
|
$pearExtractor = new PearPackageExtractor($packageArchive);
|
||||||
|
$pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin'), $vars);
|
||||||
|
|
||||||
|
if ($this->io->isVerbose()) {
|
||||||
|
$this->io->write(' Cleaning up');
|
||||||
|
}
|
||||||
|
unlink($packageArchive);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBinaries(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$binariesPath = $this->getInstallPath($package) . '/bin/';
|
||||||
|
$binaries = array();
|
||||||
|
if (file_exists($binariesPath)) {
|
||||||
|
foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME) as $fileName => $value) {
|
||||||
|
$binaries[] = 'bin/'.$fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $binaries;
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ abstract class BaseChannelReader
|
||||||
|
|
||||||
if (false == $xml) {
|
if (false == $xml) {
|
||||||
$url = rtrim($origin, '/') . '/' . ltrim($path, '/');
|
$url = rtrim($origin, '/') . '/' . ltrim($path, '/');
|
||||||
throw new \UnexpectedValueException('The PEAR channel at ' . $origin . ' is broken.');
|
throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $xml;
|
return $xml;
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
namespace Composer\Repository\Pear;
|
namespace Composer\Repository\Pear;
|
||||||
|
|
||||||
use Composer\Util\RemoteFilesystem;
|
use Composer\Util\RemoteFilesystem;
|
||||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
|
||||||
use Composer\Package\Link;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PEAR Channel package reader.
|
* PEAR Channel package reader.
|
||||||
|
|
|
@ -33,6 +33,7 @@ class PackageDependencyParser
|
||||||
if (!$this->isHash($depArray)) {
|
if (!$this->isHash($depArray)) {
|
||||||
return new DependencyInfo($this->buildDependency10Info($depArray), array());
|
return new DependencyInfo($this->buildDependency10Info($depArray), array());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->buildDependency20Info($depArray);
|
return $this->buildDependency20Info($depArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ class PearRepository extends ArrayRepository
|
||||||
$channelInfo = $reader->read($this->url);
|
$channelInfo = $reader->read($this->url);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->io->write('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
|
$this->io->write('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
|
$packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
|
||||||
|
@ -146,9 +147,9 @@ class PearRepository extends ArrayRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
$package = new MemoryPackage($composerPackageName, $normalizedVersion, $version);
|
$package = new MemoryPackage($composerPackageName, $normalizedVersion, $version);
|
||||||
$package->setType('library');
|
$package->setType('pear-library');
|
||||||
$package->setDescription($packageDefinition->getDescription());
|
$package->setDescription($packageDefinition->getDescription());
|
||||||
$package->setDistType('pear');
|
$package->setDistType('file');
|
||||||
$package->setDistUrl($distUrl);
|
$package->setDistUrl($distUrl);
|
||||||
$package->setAutoload(array('classmap' => array('')));
|
$package->setAutoload(array('classmap' => array('')));
|
||||||
$package->setIncludePaths(array('/'));
|
$package->setIncludePaths(array('/'));
|
||||||
|
@ -178,7 +179,7 @@ class PearRepository extends ArrayRepository
|
||||||
/**
|
/**
|
||||||
* Softened version parser.
|
* Softened version parser.
|
||||||
*
|
*
|
||||||
* @param string $version
|
* @param string $version
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
private function parseVersion($version)
|
private function parseVersion($version)
|
||||||
|
|
|
@ -19,7 +19,17 @@
|
||||||
<dir name="/">
|
<dir name="/">
|
||||||
<file role="php" name="php/Zend/Authentication/Storage/StorageInterface.php"/>
|
<file role="php" name="php/Zend/Authentication/Storage/StorageInterface.php"/>
|
||||||
<file role="php" name="php/Zend/Authentication/Result.php"/>
|
<file role="php" name="php/Zend/Authentication/Result.php"/>
|
||||||
|
<file role="script" name="php/Test.php">
|
||||||
|
<tasks:replace from='@version@' to='version' />
|
||||||
|
</file>
|
||||||
|
<file role="php" name="renamedFile.php"/>
|
||||||
|
<file role="php" name="ignoredFile.php"/>
|
||||||
</dir>
|
</dir>
|
||||||
</contents>
|
</contents>
|
||||||
<phprelease/>
|
<phprelease>
|
||||||
|
<filelist>
|
||||||
|
<install name='renamedFile.php' as='correctFile.php' />
|
||||||
|
<ignore name='ignoredFile.php' />
|
||||||
|
</filelist>
|
||||||
|
</phprelease>
|
||||||
</package>
|
</package>
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?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\Test\Downloader;
|
|
||||||
|
|
||||||
use Composer\Downloader\PearDownloader;
|
|
||||||
|
|
||||||
class PearDownloaderTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testErrorMessages()
|
|
||||||
{
|
|
||||||
$packageMock = $this->getMock('Composer\Package\PackageInterface');
|
|
||||||
$packageMock->expects($this->any())
|
|
||||||
->method('getDistUrl')
|
|
||||||
->will($this->returnValue('file://'.__FILE__))
|
|
||||||
;
|
|
||||||
|
|
||||||
$io = $this->getMock('Composer\IO\IOInterface');
|
|
||||||
$downloader = new PearDownloader($io);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$downloader->download($packageMock, sys_get_temp_dir().'/composer-pear-test');
|
|
||||||
$this->fail('Download of invalid pear packages should throw an exception');
|
|
||||||
} catch (\UnexpectedValueException $e) {
|
|
||||||
$this->assertContains('Failed to extract PEAR package', $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -22,20 +22,26 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase
|
||||||
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
|
|
||||||
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v1.0', 'php');
|
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v1.0', array('php' => '/'), array());
|
||||||
|
|
||||||
$expectedFileActions = array(
|
$expectedFileActions = array(
|
||||||
0 => Array(
|
'Gtk.php' => Array(
|
||||||
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk.php',
|
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk.php',
|
||||||
'to' => 'PEAR/Frontend/Gtk.php',
|
'to' => 'PEAR/Frontend/Gtk.php',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
),
|
),
|
||||||
1 => Array(
|
'Gtk/Config.php' => Array(
|
||||||
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk/Config.php',
|
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk/Config.php',
|
||||||
'to' => 'PEAR/Frontend/Gtk/Config.php',
|
'to' => 'PEAR/Frontend/Gtk/Config.php',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
),
|
),
|
||||||
2 => Array(
|
'Gtk/xpm/black_close_icon.xpm' => Array(
|
||||||
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk/xpm/black_close_icon.xpm',
|
'from' => 'PEAR_Frontend_Gtk-0.4.0/Gtk/xpm/black_close_icon.xpm',
|
||||||
'to' => 'PEAR/Frontend/Gtk/xpm/black_close_icon.xpm',
|
'to' => 'PEAR/Frontend/Gtk/xpm/black_close_icon.xpm',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertSame($expectedFileActions, $fileActions);
|
$this->assertSame($expectedFileActions, $fileActions);
|
||||||
|
@ -47,12 +53,14 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase
|
||||||
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
|
|
||||||
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v2.0', 'php');
|
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v2.0', array('php' => '/'), array());
|
||||||
|
|
||||||
$expectedFileActions = array(
|
$expectedFileActions = array(
|
||||||
0 => Array(
|
'URL.php' => Array(
|
||||||
'from' => 'Net_URL-1.0.15/URL.php',
|
'from' => 'Net_URL-1.0.15/URL.php',
|
||||||
'to' => 'Net/URL.php',
|
'to' => 'Net/URL.php',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertSame($expectedFileActions, $fileActions);
|
$this->assertSame($expectedFileActions, $fileActions);
|
||||||
|
@ -64,18 +72,62 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase
|
||||||
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
$method = new \ReflectionMethod($extractor, 'buildCopyActions');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
|
|
||||||
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v2.1', 'php');
|
$fileActions = $method->invoke($extractor, __DIR__ . '/Fixtures/Package_v2.1', array('php' => '/', 'script' => '/bin'), array());
|
||||||
|
|
||||||
$expectedFileActions = array(
|
$expectedFileActions = array(
|
||||||
0 => Array(
|
'php/Zend/Authentication/Storage/StorageInterface.php' => Array(
|
||||||
'from' => 'Zend_Authentication-2.0.0beta4/php/Zend/Authentication/Storage/StorageInterface.php',
|
'from' => 'Zend_Authentication-2.0.0beta4/php/Zend/Authentication/Storage/StorageInterface.php',
|
||||||
'to' => '/php/Zend/Authentication/Storage/StorageInterface.php',
|
'to' => '/php/Zend/Authentication/Storage/StorageInterface.php',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
),
|
),
|
||||||
1 => Array(
|
'php/Zend/Authentication/Result.php' => Array(
|
||||||
'from' => 'Zend_Authentication-2.0.0beta4/php/Zend/Authentication/Result.php',
|
'from' => 'Zend_Authentication-2.0.0beta4/php/Zend/Authentication/Result.php',
|
||||||
'to' => '/php/Zend/Authentication/Result.php',
|
'to' => '/php/Zend/Authentication/Result.php',
|
||||||
)
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
|
),
|
||||||
|
'php/Test.php' => array (
|
||||||
|
'from' => 'Zend_Authentication-2.0.0beta4/php/Test.php',
|
||||||
|
'to' => '/php/Test.php',
|
||||||
|
'role' => 'script',
|
||||||
|
'tasks' => array (
|
||||||
|
array (
|
||||||
|
'from' => '@version@',
|
||||||
|
'to' => 'version',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'renamedFile.php' => Array(
|
||||||
|
'from' => 'Zend_Authentication-2.0.0beta4/renamedFile.php',
|
||||||
|
'to' => 'correctFile.php',
|
||||||
|
'role' => 'php',
|
||||||
|
'tasks' => array(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
$this->assertSame($expectedFileActions, $fileActions);
|
$this->assertSame($expectedFileActions, $fileActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testShouldPerformReplacements()
|
||||||
|
{
|
||||||
|
$from = tempnam(sys_get_temp_dir(), 'pear-extract');
|
||||||
|
$to = $from.'-to';
|
||||||
|
|
||||||
|
$original = 'replaced: @placeholder@; not replaced: @another@; replaced again: @placeholder@';
|
||||||
|
$expected = 'replaced: value; not replaced: @another@; replaced again: value';
|
||||||
|
|
||||||
|
file_put_contents($from, $original);
|
||||||
|
|
||||||
|
$extractor = new PearPackageExtractor($from);
|
||||||
|
$method = new \ReflectionMethod($extractor, 'copyFile');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
|
||||||
|
$method->invoke($extractor, $from, $to, array(array('from' => '@placeholder@', 'to' => 'variable')), array('variable' => 'value'));
|
||||||
|
$result = file_get_contents($to);
|
||||||
|
|
||||||
|
unlink($to);
|
||||||
|
unlink($from);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ class LibraryInstallerTest extends TestCase
|
||||||
$package = $this->createPackageMock();
|
$package = $this->createPackageMock();
|
||||||
|
|
||||||
$package
|
$package
|
||||||
->expects($this->once())
|
->expects($this->any())
|
||||||
->method('getPrettyName')
|
->method('getPrettyName')
|
||||||
->will($this->returnValue('some/package'));
|
->will($this->returnValue('some/package'));
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ class LibraryInstallerTest extends TestCase
|
||||||
$target = $this->createPackageMock();
|
$target = $this->createPackageMock();
|
||||||
|
|
||||||
$initial
|
$initial
|
||||||
->expects($this->once())
|
->expects($this->any())
|
||||||
->method('getPrettyName')
|
->method('getPrettyName')
|
||||||
->will($this->returnValue('package1'));
|
->will($this->returnValue('package1'));
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ class LibraryInstallerTest extends TestCase
|
||||||
$package = $this->createPackageMock();
|
$package = $this->createPackageMock();
|
||||||
|
|
||||||
$package
|
$package
|
||||||
->expects($this->once())
|
->expects($this->any())
|
||||||
->method('getPrettyName')
|
->method('getPrettyName')
|
||||||
->will($this->returnValue('pkg'));
|
->will($this->returnValue('pkg'));
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
->will($this->returnValue('pkg1'));
|
->will($this->returnValue('pkg1'));
|
||||||
$package1
|
$package1
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getPrettyVersion')
|
->method('getVersion')
|
||||||
->will($this->returnValue('1.0.0-beta'));
|
->will($this->returnValue('1.0.0-beta'));
|
||||||
|
|
||||||
$package2
|
$package2
|
||||||
|
@ -147,7 +147,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
->will($this->returnValue('pkg2'));
|
->will($this->returnValue('pkg2'));
|
||||||
$package2
|
$package2
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getPrettyVersion')
|
->method('getVersion')
|
||||||
->will($this->returnValue('0.1.10'));
|
->will($this->returnValue('0.1.10'));
|
||||||
|
|
||||||
$json
|
$json
|
||||||
|
|
|
@ -118,8 +118,8 @@ class ChannelReaderTest extends TestCase
|
||||||
$packages = $ref->invoke($reader, $channelInfo, new VersionParser());
|
$packages = $ref->invoke($reader, $channelInfo, new VersionParser());
|
||||||
|
|
||||||
$expectedPackage = new MemoryPackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1');
|
$expectedPackage = new MemoryPackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1');
|
||||||
$expectedPackage->setType('library');
|
$expectedPackage->setType('pear-library');
|
||||||
$expectedPackage->setDistType('pear');
|
$expectedPackage->setDistType('file');
|
||||||
$expectedPackage->setDescription('description');
|
$expectedPackage->setDescription('description');
|
||||||
$expectedPackage->setDistUrl("http://test.loc/get/sample-1.0.0.1.tgz");
|
$expectedPackage->setDistUrl("http://test.loc/get/sample-1.0.0.1.tgz");
|
||||||
$expectedPackage->setAutoload(array('classmap' => array('')));
|
$expectedPackage->setAutoload(array('classmap' => array('')));
|
||||||
|
|
|
@ -10,5 +10,7 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
$loader = require __DIR__.'/../src/bootstrap.php';
|
$loader = require __DIR__.'/../src/bootstrap.php';
|
||||||
$loader->add('Composer\Test', __DIR__);
|
$loader->add('Composer\Test', __DIR__);
|
||||||
|
|
Loading…
Reference in New Issue