From ac3cebc633c64d52b02a60f8f1fe48904ae293e6 Mon Sep 17 00:00:00 2001 From: Alexey Prilipko Date: Wed, 27 Jun 2012 16:27:01 +1100 Subject: [PATCH] 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 Installer --- src/Composer/Downloader/PearDownloader.php | 52 -------- .../Downloader/PearPackageExtractor.php | 117 +++++++++++++----- src/Composer/Factory.php | 2 +- src/Composer/Installer/LibraryInstaller.php | 39 ++++-- src/Composer/Installer/PearInstaller.php | 95 ++++++++++++++ .../Repository/Pear/BaseChannelReader.php | 2 +- .../Repository/Pear/ChannelReader.php | 2 - .../Pear/PackageDependencyParser.php | 1 + src/Composer/Repository/PearRepository.php | 7 +- .../Fixtures/Package_v2.1/package.xml | 12 +- .../Test/Downloader/PearDownloaderTest.php | 38 ------ .../Downloader/PearPackageExtractorTest.php | 72 +++++++++-- .../Test/Installer/LibraryInstallerTest.php | 6 +- tests/Composer/Test/Package/LockerTest.php | 4 +- .../Repository/Pear/ChannelReaderTest.php | 4 +- tests/bootstrap.php | 2 + 16 files changed, 305 insertions(+), 150 deletions(-) delete mode 100644 src/Composer/Downloader/PearDownloader.php create mode 100644 src/Composer/Installer/PearInstaller.php delete mode 100644 tests/Composer/Test/Downloader/PearDownloaderTest.php diff --git a/src/Composer/Downloader/PearDownloader.php b/src/Composer/Downloader/PearDownloader.php deleted file mode 100644 index 6f250abd3..000000000 --- a/src/Composer/Downloader/PearDownloader.php +++ /dev/null @@ -1,52 +0,0 @@ - - * Jordi Boggiano - * - * 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 - * @author Kirill chEbba Chebunin - */ -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(''); - } -} diff --git a/src/Composer/Downloader/PearPackageExtractor.php b/src/Composer/Downloader/PearPackageExtractor.php index 3a83a91dd..eeb88806c 100644 --- a/src/Composer/Downloader/PearPackageExtractor.php +++ b/src/Composer/Downloader/PearPackageExtractor.php @@ -35,22 +35,22 @@ class PearPackageExtractor throw new \UnexpectedValueException('PEAR package file is not found at '.$file); } + $this->filesystem = new Filesystem(); $this->file = $file; } /** * Installs PEAR source files according to package.xml definitions and removes extracted files * - * @param $file string path to downloaded PEAR archive file - * @param $target string target install location. all source installation would be performed relative to target path. - * @param $role string type of files to install. default role for PEAR source files are 'php'. - * + * @param string $target 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 array $vars used for replacement tasks * @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'; try { @@ -61,8 +61,8 @@ class PearPackageExtractor throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.'); } - $fileCopyActions = $this->buildCopyActions($extractionPath, $role); - $this->copyFiles($fileCopyActions, $extractionPath, $target); + $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars); + $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars); $this->filesystem->removeDirectory($extractionPath); } catch (\Exception $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 * - * @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 $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) { $from = $this->combine($source, $file['from']); - $to = $this->combine($target, $file['to']); - $this->copyFile($from, $to); + $to = $this->combine($target, $roles[$file['role']]); + $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)) { 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)); - 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)); } } @@ -107,7 +128,7 @@ class PearPackageExtractor * path, and target is destination of file (also relative to $source path) * @throws \RuntimeException */ - private function buildCopyActions($source, $role) + private function buildCopyActions($source, array $roles, $vars) { /** @var $package \SimpleXmlElement */ $package = simplexml_load_file($this->combine($source, 'package.xml')); @@ -120,13 +141,18 @@ class PearPackageExtractor $packageName = (string) $package->name; $packageVersion = (string) $package->release->version; $sourceDir = $packageName . '-' . $packageVersion; - $result = $this->buildSourceList10($children, $role, $sourceDir); + $result = $this->buildSourceList10($children, $roles, $sourceDir); } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) { $children = $package->contents->children(); $packageName = (string) $package->name; $packageVersion = (string) $package->version->release; $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 { throw new \RuntimeException('Unsupported schema version of package definition file.'); } @@ -134,7 +160,34 @@ class PearPackageExtractor 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(); @@ -145,14 +198,15 @@ class PearPackageExtractor $dirSource = $this->combine($source, (string) $child['name']); $dirTarget = $child['baseinstalldir'] ? : $target; $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); } 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 $fileSource = $this->combine($source, $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; } - private function buildSourceList20($children, $targetRole, $source = '', $target = '', $role = null) + private function buildSourceList20($children, $targetRoles, $source = '', $target = '', $role = null) { $result = array(); // enumerating files foreach ($children as $child) { /** @var $child \SimpleXMLElement */ - if ($child->getName() == 'dir') { + if ('dir' == $child->getName()) { $dirSource = $this->combine($source, $child['name']); $dirTarget = $child['baseinstalldir'] ? : $target; $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); - } elseif ($child->getName() == 'file') { - if (($child['role'] ? : $role) == $targetRole) { + } elseif ('file' == $child->getName()) { + $fileRole = (string) $child['role'] ? : $role; + if (isset($targetRoles[$fileRole])) { $fileSource = $this->combine($source, (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); } } } diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 18567c14b..75b47f790 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -225,7 +225,6 @@ class Factory $dm->setDownloader('git', new Downloader\GitDownloader($io)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io)); $dm->setDownloader('hg', new Downloader\HgDownloader($io)); - $dm->setDownloader('pear', new Downloader\PearDownloader($io)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io)); $dm->setDownloader('tar', new Downloader\TarDownloader($io)); $dm->setDownloader('phar', new Downloader\PharDownloader($io)); @@ -251,6 +250,7 @@ class Factory protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io) { $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\MetapackageInstaller($io)); } diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 6652edec8..2c3facad7 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -82,7 +82,7 @@ class LibraryInstaller implements InstallerInterface $this->removeBinaries($package); } - $this->downloadManager->download($package, $downloadPath); + $this->installCode($package); $this->installBinaries($package); if (!$repo->hasPackage($package)) { $repo->addPackage(clone $package); @@ -102,7 +102,7 @@ class LibraryInstaller implements InstallerInterface $downloadPath = $this->getInstallPath($initial); $this->removeBinaries($initial); - $this->downloadManager->update($initial, $target, $downloadPath); + $this->updateCode($initial, $target, $downloadPath); $this->installBinaries($target); $repo->removePackage($initial); if (!$repo->hasPackage($target)) { @@ -123,7 +123,7 @@ class LibraryInstaller implements InstallerInterface $downloadPath = $this->getInstallPath($package); - $this->downloadManager->remove($package, $downloadPath); + $this->removeCode($package); $this->removeBinaries($package); $repo->removePackage($package); @@ -146,12 +146,36 @@ class LibraryInstaller implements InstallerInterface 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) { - if (!$package->getBinaries()) { + $binaries = $this->getBinaries($package); + if (!$binaries) { return; } - foreach ($package->getBinaries() as $bin) { + foreach ($binaries as $bin) { $this->initializeBinDir(); $link = $this->binDir.'/'.basename($bin); if (file_exists($link)) { @@ -193,10 +217,11 @@ class LibraryInstaller implements InstallerInterface protected function removeBinaries(PackageInterface $package) { - if (!$package->getBinaries()) { + $binaries = $this->getBinaries($package); + if (!$binaries) { return; } - foreach ($package->getBinaries() as $bin) { + foreach ($binaries as $bin) { $link = $this->binDir.'/'.basename($bin); if (!file_exists($link)) { continue; diff --git a/src/Composer/Installer/PearInstaller.php b/src/Composer/Installer/PearInstaller.php new file mode 100644 index 000000000..75f8d0008 --- /dev/null +++ b/src/Composer/Installer/PearInstaller.php @@ -0,0 +1,95 @@ + + * Jordi Boggiano + * + * 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 + * @author Konstantin Kudryashov + */ +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; + } +} diff --git a/src/Composer/Repository/Pear/BaseChannelReader.php b/src/Composer/Repository/Pear/BaseChannelReader.php index 3533a0e26..2f586ad87 100644 --- a/src/Composer/Repository/Pear/BaseChannelReader.php +++ b/src/Composer/Repository/Pear/BaseChannelReader.php @@ -73,7 +73,7 @@ abstract class BaseChannelReader if (false == $xml) { $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; diff --git a/src/Composer/Repository/Pear/ChannelReader.php b/src/Composer/Repository/Pear/ChannelReader.php index e9e316f0b..7beb37d3c 100644 --- a/src/Composer/Repository/Pear/ChannelReader.php +++ b/src/Composer/Repository/Pear/ChannelReader.php @@ -13,8 +13,6 @@ namespace Composer\Repository\Pear; use Composer\Util\RemoteFilesystem; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\Link; /** * PEAR Channel package reader. diff --git a/src/Composer/Repository/Pear/PackageDependencyParser.php b/src/Composer/Repository/Pear/PackageDependencyParser.php index 75ee27acc..aa198ceb4 100644 --- a/src/Composer/Repository/Pear/PackageDependencyParser.php +++ b/src/Composer/Repository/Pear/PackageDependencyParser.php @@ -33,6 +33,7 @@ class PackageDependencyParser if (!$this->isHash($depArray)) { return new DependencyInfo($this->buildDependency10Info($depArray), array()); } + return $this->buildDependency20Info($depArray); } diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 7c7d3ffae..180ee5584 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -71,6 +71,7 @@ class PearRepository extends ArrayRepository $channelInfo = $reader->read($this->url); } catch (\Exception $e) { $this->io->write('PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().''); + return; } $packages = $this->buildComposerPackages($channelInfo, $this->versionParser); @@ -146,9 +147,9 @@ class PearRepository extends ArrayRepository } $package = new MemoryPackage($composerPackageName, $normalizedVersion, $version); - $package->setType('library'); + $package->setType('pear-library'); $package->setDescription($packageDefinition->getDescription()); - $package->setDistType('pear'); + $package->setDistType('file'); $package->setDistUrl($distUrl); $package->setAutoload(array('classmap' => array(''))); $package->setIncludePaths(array('/')); @@ -178,7 +179,7 @@ class PearRepository extends ArrayRepository /** * Softened version parser. * - * @param string $version + * @param string $version * @return null|string */ private function parseVersion($version) diff --git a/tests/Composer/Test/Downloader/Fixtures/Package_v2.1/package.xml b/tests/Composer/Test/Downloader/Fixtures/Package_v2.1/package.xml index e49f38bfe..80a8eb686 100644 --- a/tests/Composer/Test/Downloader/Fixtures/Package_v2.1/package.xml +++ b/tests/Composer/Test/Downloader/Fixtures/Package_v2.1/package.xml @@ -19,7 +19,17 @@ + + + + + - + + + + + + diff --git a/tests/Composer/Test/Downloader/PearDownloaderTest.php b/tests/Composer/Test/Downloader/PearDownloaderTest.php deleted file mode 100644 index d3cc8d0fd..000000000 --- a/tests/Composer/Test/Downloader/PearDownloaderTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Jordi Boggiano - * - * 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()); - } - } - -} diff --git a/tests/Composer/Test/Downloader/PearPackageExtractorTest.php b/tests/Composer/Test/Downloader/PearPackageExtractorTest.php index 42010a39c..fa393833d 100644 --- a/tests/Composer/Test/Downloader/PearPackageExtractorTest.php +++ b/tests/Composer/Test/Downloader/PearPackageExtractorTest.php @@ -22,20 +22,26 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase $method = new \ReflectionMethod($extractor, 'buildCopyActions'); $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( - 0 => Array( + 'Gtk.php' => Array( 'from' => 'PEAR_Frontend_Gtk-0.4.0/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', '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', 'to' => 'PEAR/Frontend/Gtk/xpm/black_close_icon.xpm', + 'role' => 'php', + 'tasks' => array(), ) ); $this->assertSame($expectedFileActions, $fileActions); @@ -47,12 +53,14 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase $method = new \ReflectionMethod($extractor, 'buildCopyActions'); $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( - 0 => Array( + 'URL.php' => Array( 'from' => 'Net_URL-1.0.15/URL.php', 'to' => 'Net/URL.php', + 'role' => 'php', + 'tasks' => array(), ) ); $this->assertSame($expectedFileActions, $fileActions); @@ -64,18 +72,62 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase $method = new \ReflectionMethod($extractor, 'buildCopyActions'); $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( - 0 => Array( + 'php/Zend/Authentication/Storage/StorageInterface.php' => Array( 'from' => 'Zend_Authentication-2.0.0beta4/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', '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); } + + 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); + } } diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 4badc2f37..496092dc6 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -106,7 +106,7 @@ class LibraryInstallerTest extends TestCase $package = $this->createPackageMock(); $package - ->expects($this->once()) + ->expects($this->any()) ->method('getPrettyName') ->will($this->returnValue('some/package')); @@ -136,7 +136,7 @@ class LibraryInstallerTest extends TestCase $target = $this->createPackageMock(); $initial - ->expects($this->once()) + ->expects($this->any()) ->method('getPrettyName') ->will($this->returnValue('package1')); @@ -175,7 +175,7 @@ class LibraryInstallerTest extends TestCase $package = $this->createPackageMock(); $package - ->expects($this->once()) + ->expects($this->any()) ->method('getPrettyName') ->will($this->returnValue('pkg')); diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 2f93d77e2..8136651b2 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -138,7 +138,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue('pkg1')); $package1 ->expects($this->once()) - ->method('getPrettyVersion') + ->method('getVersion') ->will($this->returnValue('1.0.0-beta')); $package2 @@ -147,7 +147,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue('pkg2')); $package2 ->expects($this->once()) - ->method('getPrettyVersion') + ->method('getVersion') ->will($this->returnValue('0.1.10')); $json diff --git a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php index a1ce4f7c6..8a93a60aa 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php @@ -118,8 +118,8 @@ class ChannelReaderTest extends TestCase $packages = $ref->invoke($reader, $channelInfo, new VersionParser()); $expectedPackage = new MemoryPackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1'); - $expectedPackage->setType('library'); - $expectedPackage->setDistType('pear'); + $expectedPackage->setType('pear-library'); + $expectedPackage->setDistType('file'); $expectedPackage->setDescription('description'); $expectedPackage->setDistUrl("http://test.loc/get/sample-1.0.0.1.tgz"); $expectedPackage->setAutoload(array('classmap' => array(''))); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a4f2e7cec..1974415d3 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -10,5 +10,7 @@ * file that was distributed with this source code. */ +error_reporting(E_ALL); + $loader = require __DIR__.'/../src/bootstrap.php'; $loader->add('Composer\Test', __DIR__);