/** * @param string * @param string file name of the channel.xml * * @return \PEAR2\Pyrus\ChannelFile\v1 */ function parse($data, $file = false, $class = 'PEAR2\Pyrus\ChannelFile\v1') { $ret = new $class; if (!$ret instanceof \PEAR2\Pyrus\ChannelFile\v1) { throw new \PEAR2\Pyrus\ChannelFile\Exception('Class ' . $class . ' passed to parse() must be a child class of \PEAR2\Pyrus\ChannelFile\v1'); } $schema = \PEAR2\Pyrus\Main::getDataPath() . '/channel-1.0.xsd'; // for running out of svn if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/channel-1.0.xsd'; } try { if ($file) { $ret->fromArray(parent::parse($data, $schema)); } else { $ret->fromArray(parent::parseString($data, $schema)); } } catch (\Exception $e) { throw new \PEAR2\Pyrus\ChannelFile\Exception('Invalid channel.xml', null, $e); } return $ret; }
protected function __construct($rolepath) { if (isset(Main::$options['packagingroot'])) { $rolepath = Main::prepend(Main::$options['packagingroot'], $rolepath); } $rolepath = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $rolepath); $this->rolepath = $rolepath; $path = dirname($rolepath) . DIRECTORY_SEPARATOR; $this->backuppath = $path . '.old-' . basename($rolepath); $this->journalpath = $path . '.journal-' . basename($rolepath); $this->defaultMode = 0777 & ~octdec(Config::current()->umask); }
function validate(\PEAR2\Pyrus\PackageInterface $package, array $file) { $parser = new \PEAR2\Pyrus\XMLParser(); $schemapath = \PEAR2\Pyrus\Main::getDataPath(); if (!file_exists(\PEAR2\Pyrus\Main::getDataPath() . '/customcommand-2.0.xsd')) { $schemapath = realpath(__DIR__ . '/../../../../../data'); } $taskschema = $schemapath . '/customcommand-2.0.xsd'; try { $taskinfo = $parser->parse($package->getFilePath($file['attribs']['name']), $taskschema); } catch (\Exception $e) { throw new \PEAR2\Pyrus\Installer\Role\Exception('Invalid custom command definition file,' . ' file does not conform to the schema', $e); } }
/** * Initialize the registry * * @param string $path */ function __construct($path, $readonly = false) { $this->readonly = $readonly; if (isset(Main::$options['packagingroot'])) { $path = Main::prepend(Main::$options['packagingroot'], $path); } $this->path = $path; $this->channelpath = $path . DIRECTORY_SEPARATOR . '.xmlregistry' . DIRECTORY_SEPARATOR . 'channels'; if (1 === $this->exists('pear.php.net')) { $this->initialized = false; } else { $this->initialized = true; } }
function __construct($path, $readonly = false) { $this->readonly = $readonly; if (!file_exists($path . '/.registry') && basename($path) !== 'php') { $path = $path . DIRECTORY_SEPARATOR . 'php'; } $this->path = $path; if (isset(\PEAR2\Pyrus\Main::$options['packagingroot'])) { $path = \PEAR2\Pyrus\Main::prepend(\PEAR2\Pyrus\Main::$options['packagingroot'], $path); } $this->_channelPath = $path . DIRECTORY_SEPARATOR . '.channels'; $this->_aliasPath = $this->_channelPath . DIRECTORY_SEPARATOR . '.alias'; if (!file_exists($this->_channelPath) || !is_dir($this->_channelPath)) { if ($readonly) { throw new Exception('Cannot initialize PEAR1 channel registry, directory' . ' does not exist and registry is read-only'); } if (!@mkdir($this->_channelPath, 0755, true)) { throw new Exception('Cannot initialize PEAR1 channel registry, channel' . ' directory could not be initialized'); } } if (!file_exists($this->_aliasPath) || !is_dir($this->_aliasPath)) { if ($readonly) { throw new Exception('Cannot initialize PEAR1 channel registry, aliasdirectory ' . 'does not exist and registry is read-only'); } if (!@mkdir($this->_aliasPath, 0755, true)) { throw new Exception('Cannot initialize PEAR1 channel registry, channel ' . 'aliasdirectory could not be initialized'); } } if (1 === $this->exists('pear.php.net')) { $this->initialized = false; } else { $this->initialized = true; } }
static private function _init($path, $readonly) { if (!$path) { $path = ':memory:'; } else { $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); } if (static::existsRegistry($path)) { return; } $dbpath = $path; if ($path != ':memory:' && isset(Main::$options['packagingroot'])) { $dbpath = Main::prepend(Main::$options['packagingroot'], $path); } if ($path != ':memory:' && !file_exists(dirname($dbpath))) { if ($readonly) { throw new Exception('Cannot create SQLite3 registry, registry is read-only'); } @mkdir(dirname($dbpath), 0755, true); } if ($readonly && $path != ':memory:' && !file_exists($dbpath)) { throw new Exception('Cannot create SQLite3 registry, registry is read-only'); } static::$databases[$path] = new \SQLite3($dbpath); // ScottMac needs to fix sqlite3 FIXME if (static::$databases[$path]->lastErrorCode()) { $error = static::$databases[$path]->lastErrorMsg(); throw new Exception('Cannot open SQLite3 registry: ' . $error); } $sql = 'SELECT version FROM pearregistryversion'; if (@static::getRegistry($path)->querySingle($sql) == '1.0.0') { return; } if ($readonly) { throw new Exception('Cannot create SQLite3 registry, registry is read-only'); } $a = new Sqlite3\Creator; try { $a->create(static::$databases[$path]); } catch (\Exception $e) { unset(static::$databases[$path]); $a = get_class($e); throw new $a('Database initialization failed', 0, $e); } }
/** * @param \PEAR2\Pyrus\PackageFile\v2 * @param int */ function validate(\PEAR2\Pyrus\PackageInterface $pf, $state = \PEAR2\Pyrus\Validate::NORMAL) { $this->errors = new \PEAR2\MultiErrors; if (!$pf->schemaOK) { // this package.xml was created from scratch, not loaded from an existing // package.xml $dom = new \DOMDocument; libxml_use_internal_errors(true); libxml_clear_errors(); $dom->loadXML($pf); $a = $pf->toArray(); if ($a['package']['attribs']['version'] == '2.1') { $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.1.xsd'; // for running out of cvs if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/package-2.1.xsd'; } } else { $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.0.xsd'; // for running out of cvs if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/package-2.0.xsd'; } } $dom->schemaValidate($schema); $causes = array(); foreach (libxml_get_errors() as $error) { $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception("Line " . $error->line . ': ' . $error->message); } if (count($this->errors)) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml, does' . ' not validate against schema', $this->errors); } } $this->_pf = $pf; $this->_curState = $state; $this->_packageInfo = $this->_pf->toArray(); $this->_packageInfo = $this->_packageInfo['package']; if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { return false; } $myversion = self::VERSION; if ($myversion === '@PACKAGE_VERSION@') { // we're running from CVS, assume we're 2.0.0 $myversion = '2.0.0'; } $test = $this->_packageInfo; if (isset($test['dependencies']) && isset($test['dependencies']['required']) && isset($test['dependencies']['required']['pearinstaller']) && isset($test['dependencies']['required']['pearinstaller']['min']) && version_compare($myversion, $test['dependencies']['required']['pearinstaller']['min'], '<')) { $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception( 'This package.xml requires PEAR version ' . $test['dependencies']['required']['pearinstaller']['min'] . ' to parse properly, we are version ' . $myversion); } $fail = false; foreach ($pf->contents as $file) { // leverage the hidden iterators to do our validation $name = $file->dir . $file->name; if ($name[0] == '.' && $name[1] == '/') { // name is something like "./doc/whatever.txt" $this->errors->E_ERROR[] = new \PEAR2\Pyrus\Package\Exception( 'File "' . $name . '" cannot begin with "."'); continue; } if (!$this->_validateRole($file->role)) { if (isset($this->_packageInfo['usesrole'])) { $roles = $this->_packageInfo['usesrole']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['role'] = $file->role) { if (isset($role['uri'])) { $package = $role['uri']; } else { $package = \PEAR2\Pyrus\Config:: parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true); } $msg = 'This package contains role "' . $file->role . '" and requires package "' . $package . '" to be used'; $this->errors->E_WARNING[] = new \PEAR2\Pyrus\PackageFile\Exception($msg); } } } $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception( 'File "' . $name . '" has invalid role "' . $file->role . '", should be one of ' . implode(', ', \PEAR2\Pyrus\Installer\Role::getValidRoles($this->_pf->getPackageType()))); } if (count($file->tasks) && $this->_curState != \PEAR2\Pyrus\Validate::DOWNLOADING) { // has tasks $save = $file->getArrayCopy(); foreach ($file->tasks as $task => $value) { if ($tagClass = \PEAR2\Pyrus\Task\Common::getTask($task)) { if (!is_array($value) || !isset($value[0])) { $value = array($value); } foreach ($value as $v) { try { $ret = $tagClass::validateXml($this->_pf, $v, $save['attribs'], $file->name); } catch (\PEAR2\Pyrus\Task\Exception $e) { $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception('Invalid task $task', $e); } } } else { if (isset($this->_packageInfo['usestask'])) { $roles = $this->_packageInfo['usestask']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['task'] = $task) { if (isset($role['uri'])) { $package = $role['uri']; } else { $package = \PEAR2\Pyrus\Config:: parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true); } $msg = 'This package contains task "' . str_replace($this->_pf->getTasksNs() . ':', '', $task) . '" and requires package "' . $package . '" to be used'; $this->errors->E_WARNING[] = new \PEAR2\Pyrus\PackageFile\Exception($msg); } } } $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception( 'Unknown task "' . $task . '" passed in file <file name="' . $name . '">'); } } } } $this->_validateRelease(); if (count($this->errors->E_ERROR)) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors); } try { $validator = \PEAR2\Pyrus\Config::current() ->channelregistry[$this->_pf->channel] ->getValidationObject($this->_pf->name); } catch (\PEAR2\Pyrus\Config\Exception $e) { throw new \PEAR2\Pyrus\PackageFile\Exception( 'Unable to process channel-specific configuration for channel ' . $this->_pf->getChannel(), $e); } catch (\Exception $e) { $valpack = \PEAR2\Pyrus\Config::current() ->channelregistry[$this->_pf->channel]->getValidationPackage(); $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception( 'Unknown channel ' . $this->_pf->channel); $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception( 'package "' . $this->_pf->channel . '/' . $this->_pf->name . '" cannot be properly validated without validation package "' . $this->_pf->channel . '/' . $valpack['name'] . '-' . $valpack['version'] . '"'); } try { $validator->setPackageFile($this->_pf); $validator->setChannel(\PEAR2\Pyrus\Config::current() ->channelregistry[$this->_pf->channel]); $validator->validate($state); // merge in errors from channel-specific validation $this->errors[] = $validator->getFailures(); } catch (\Exception $e) { $this->errors->E_ERROR[] = $e; } if (count($this->errors->E_ERROR)) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors); } if ($state == \PEAR2\Pyrus\Validate::PACKAGING) { if ($this->_pf->type == 'bundle') { if (!$this->_analyzeBundledPackages()) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors); } } else { if (!$this->_analyzePhpFiles()) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors); } } } return $state; }
/** * Scan through the Command directory looking for classes * and see what commands they implement. * @param string which directory to look for classes, defaults to * the Installer/Roles subdirectory of * the directory from where this file (__FILE__) is * included. * * @return bool TRUE on success, a PEAR error on failure * @access public * @static */ static function registerRoles($dir = null) { self::$_roles = array(); $parser = new \PEAR2\Pyrus\XMLParser; if ($dir === null) { $dir = __DIR__ . '/Role'; } if (!file_exists($dir) || !is_dir($dir)) { throw new Role\Exception("registerRoles: opendir($dir) failed"); } $dp = @opendir($dir); if (empty($dp)) { throw new Role\Exception("registerRoles: opendir($dir) failed"); } $schemapath = \PEAR2\Pyrus\Main::getDataPath() . '/customrole-2.0.xsd'; if (!file_exists($schemapath)) { $schemapath = realpath(__DIR__ . '/../../../data/customrole-2.0.xsd'); } while ($entry = readdir($dp)) { if ($entry{0} == '.' || substr($entry, -4) != '.xml') { continue; } $role = strtolower(basename($entry, '.xml')); // List of roles if (!isset(self::$_roles[$role])) { $file = "$dir/$entry"; $data = $parser->parse($file, $schemapath); $data = $data['role']; if (!is_array($data['releasetypes'])) { $data['releasetypes'] = array($data['releasetypes']); } self::$_roles[$role] = $data; } } closedir($dp); $roles = self::$_roles; ksort($roles); self::$_roles = $roles; self::getBaseinstallRoles(true); self::getInstallableRoles(true); self::getValidRoles('****', true); return true; }
/** * This method acts as a controller which dispatches the request to the * correct command/method. * * <code> * $cli = \PEAR2\Pyrus\ScriptFrontend\Commands(); * $cli->run($args = array (0 => 'install', * 1 => 'PEAR2/Pyrus_Developer/package.xml')); * </code> * * The above code will dispatch to the install command * * @param array $args An array of command line arguments. * * @return void */ function run($args) { try { $sig = \PEAR2\Pyrus\Main::getSignature(); if ($sig) { echo "Pyrus version ", \PEAR2\Pyrus\Main::VERSION, ' ', $sig['hash_type'], ': ', $sig['hash'], "\n"; } $this->_findPEAR($args); $this->verbose = \PEAR2\Pyrus\Config::current()->verbose; // scan for custom commands/roles/tasks \PEAR2\Pyrus\Config::current()->pluginregistry->scan(); if (!isset(static::$commandParser->commands['make'])) { $this->addDeveloperCommands('developer'); } if (!isset(static::$commandParser->commands['scs-update'])) { $this->addDeveloperCommands('scs'); } $result = static::$commandParser->parse(count($args) + 1, array_merge(array('cruft'), $args)); if ($result->options['verbose']) { $this->verbose = $result->options['verbose']; } if ($result->options['paranoid']) { \PEAR2\Pyrus\Main::$paranoid = $result->options['paranoid']; } if ($info = \PEAR2\Pyrus\PluginRegistry::getCommandInfo($result->command_name)) { if ($this instanceof $info['class']) { if ($info['function'] == 'dummyStub' || $info['function'] == 'scsDummyStub') { $this->{$info['function']}($result); } else { $this->{$info['function']}($result->command->args, $result->command->options); } } else { $class = new $info['class'](); $class->{$info['function']}($this, $result->command->args, $result->command->options); } } else { $this->help(array('command' => isset($args[0]) ? $args[0] : null)); } } catch (\PEAR2\Console\CommandLine\Exception $e) { static::$commandParser->displayError($e->getMessage(), false); static::$commandParser->displayUsage(false); } }
/** * remotely connect to a channel server and grab the channel information, * then add it to the current pyrus managed repo * * @param array $args $args[0] should be the channel name, eg:pear.unl.edu */ function channelDiscover($args) { // try secure first $chan = 'https://' . $args['channel'] . '/channel.xml'; try { $response = \PEAR2\Pyrus\Main::download($chan); if ($response->code != 200) { throw new \PEAR2\Pyrus\Exception('Download of channel.xml failed'); } } catch (\Exception $e) { try { $chan = 'http://' . $args['channel'] . '/channel.xml'; $response = \PEAR2\Pyrus\Main::download($chan); if ($response->code != 200) { throw new \PEAR2\Pyrus\Exception('Download of channel.xml failed'); } } catch (\Exception $e) { // failed, re-throw original error echo "Discovery of channel ", $args['channel'], " failed: ", $e->getMessage(), "\n"; return; } } $chan = new \PEAR2\Pyrus\Channel(new \PEAR2\Pyrus\ChannelFile($response->body, true)); \PEAR2\Pyrus\Config::current()->channelregistry->add($chan); echo "Discovery of channel ", $chan->name, " successful\n"; }
/** * Parses a string containing package xml and returns an object * * @param string $data data to parse * @param string|false $file name of the archive this package.xml came from, if any * @param string $class class name to instantiate and return. * This must be PEAR2\Pyrus\PackageFile\v2 or a subclass * @param int $state what state we are currently in * * @return \PEAR2\Pyrus\PackageFile\v2 */ function parse($data, $file = false, $class = 'PEAR2\\Pyrus\\PackageFile\\v2', $state = \PEAR2\Pyrus\Validate::NORMAL) { $this->_inContents = false; $this->_path = ''; $this->_files = array(); $this->_lastDepth = $this->_lastFileDepth = 0; $this->_inFile = 0; $ret = new $class(); if (!$ret instanceof \PEAR2\Pyrus\PackageFile\v2) { throw new \PEAR2\Pyrus\PackageFile\Exception('Class ' . $class . ' passed to parse() must be a child class of \\PEAR2\\Pyrus\\PackageFile\\v2'); } if (preg_match('/<package[^>]+version="2.1"/', $data)) { $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.1.xsd'; // for running out of cvs if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/data/package-2.1.xsd'; } } elseif (preg_match('/<package[^>]+version="2.0"/', $data)) { $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.0.xsd'; // for running out of cvs if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/data/package-2.0.xsd'; } } else { throw new \PEAR2\Pyrus\PackageFile\Exception('Cannot process package.xml version 1.0', -3); } try { $ret->fromArray(parent::parseString($data, $schema)); } catch (\Exception $e) { throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $e); } $ret->setFileList($this->_files); $ret->setBaseInstallDirs($this->_baseinstalldirs); $ret->setPackagefile($file); return $ret; }
/** * Returns a list of registries present in the PEAR installation at $path * @param string * @return array */ public static function detectRegistries($path) { if (isset(Main::$options['packagingroot'])) { $path = Main::prepend(Main::$options['packagingroot'], $path); } if (file_exists($path . '/.registry') || is_dir($path . '/.registry')) { return array('Pear1'); } if (basename($path) !== 'php') { $path = $path . DIRECTORY_SEPARATOR . 'php'; } if (file_exists($path . '/.registry') || is_dir($path . '/.registry')) { return array('Pear1'); } return array(); }
protected function fromUrl($param, $saveparam = '') { $this->type = 'url'; $dir = Config::current()->download_dir; try { $response = \PEAR2\Pyrus\Main::downloadWithProgress($param); if ($response->code != '200') { throw new Exception('Download failed, received ' . $response->code); } $info = parse_url($param); $name = urldecode(basename($info['path'])); if (isset($response->headers['content-disposition'])) { if (preg_match('/filename="(.+)"/', $response->headers['content-disposition'], $match)) { $name = $match[1]; } } if (!@file_exists($dir)) { mkdir($dir, 0755, true); } if (false === file_put_contents($dir . DIRECTORY_SEPARATOR . $name, $response->body)) { throw new Exception('Unable to save package '.$name.' to downloads directory, '.$dir.'. Do we have permission to write there?'); } // whew, download worked! $a = new \PEAR2\Pyrus\Package($dir . DIRECTORY_SEPARATOR . $name); return $a->getInternalPackage(); } catch (\PEAR2\Pyrus\HTTPException $e) { throw $e; // pass it along } catch (\Exception $e) { if (!empty($saveparam)) { $saveparam = ", cannot download \"$saveparam\""; } throw new Exception('Could not download from "' . $param . '"' . $saveparam, $e); } }
/** @todo Consider simply injecting the Package object as appropriate */ function package($frontend, $args, $options) { $path = getcwd() . DIRECTORY_SEPARATOR; $package = new \PEAR2\Pyrus\Package(null); if (!isset($args['packagexml']) && !file_exists($path . 'package.xml') && !file_exists($path . 'package2.xml')) { throw new \PEAR2\Pyrus\PackageFile\Exception("No package.xml or package2.xml found in " . $path); } if (isset($args['packagexml'])) { $package = new \PEAR2\Pyrus\Package($args['packagexml']); } else { // first try ./package.xml if (file_exists($path . 'package.xml')) { try { $package = new \PEAR2\Pyrus\Package($path . 'package.xml'); } catch (\PEAR2\Pyrus\PackageFile\Exception $e) { if ($e->getCode() != -3) { throw $e; } if (!file_exists($path . 'package2.xml')) { throw $e; } $package = new \PEAR2\Pyrus\Package($path . 'package2.xml'); // now the creator knows to do the magic of package2.xml/package.xml $package->thisIsOldAndCrustyCompatible(); } } // Alternatively; there's only a package2.xml if (file_exists($path . 'package2.xml') && !file_exists($path . 'package.xml')) { $package = new \PEAR2\Pyrus\Package($path . 'package2.xml'); } } if ($package->isNewPackage()) { if (!$options['phar'] && !$options['zip'] && !$options['tar'] && !$options['tgz']) { // try tgz first if (extension_loaded('zlib')) { $options['tgz'] = true; } else { $options['tar'] = true; } } if ($options['phar'] && ini_get('phar.readonly')) { throw new \PEAR2\Pyrus\Developer\Creator\Exception("Cannot create phar archive, pass -dphar.readonly=0"); } } else { if ($options['zip'] || $options['phar']) { echo "Zip and Phar archives can only be created for PEAR2 packages, ignoring\n"; } if (extension_loaded('zlib')) { $options['tgz'] = true; } else { $options['tar'] = true; } } // get openssl cert if set, and password if (\PEAR2\Pyrus\Config::current()->openssl_cert) { if ('yes' == $frontend->ask('Sign package?', array('yes', 'no'), 'yes')) { $cert = \PEAR2\Pyrus\Config::current()->openssl_cert; if (!file_exists($cert)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('OpenSSL certificate ' . $cert . ' does not exist'); } $releaser = \PEAR2\Pyrus\Config::current()->handle; $maintainers = array(); foreach ($package->maintainer as $maintainer) { $maintainers[] = $maintainer->user; } if (!strlen($releaser)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('handle configuration variable must be from ' . 'package.xml (one of ' . implode(', ', $maintainers) . ')'); } if (!in_array($releaser, $maintainers)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('handle configuration variable must be from ' . 'package.xml (one of ' . implode(', ', $maintainers) . ')'); } $passphrase = $frontend->ask('passphrase for OpenSSL PKCS#12 certificate?'); if (!$passphrase) { $passphrase = ''; } } else { $releaser = $cert = null; $passphrase = ''; } } else { $releaser = $cert = null; $passphrase = ''; } $sourcepath = \PEAR2\Pyrus\Main::getSourcePath(); if (0 !== strpos($sourcepath, 'phar://')) { // running from svn, assume we're in a standard package layout with a vendor dir // TODO: Improve this to automatically find latest releases from pear2.php.net $exceptionpath = $autoloadpath = $multierrorspath = realpath($sourcepath . '/../../vendor/php') . '/PEAR2'; if (!file_exists($exceptionpath . '/Exception.php')) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('Cannot locate PEAR2/Exception in a local vendor/ dir. ' . 'It is best to install the latest versions of these locally.'); } } else { $exceptionpath = $autoloadpath = $multierrorspath = dirname($sourcepath) . '/PEAR2'; } $extras = array(); $stub = false; if ($options['tgz'] && extension_loaded('zlib')) { $mainfile = $package->name . '-' . $package->version['release'] . '.tgz'; $mainformat = \Phar::TAR; $maincompress = \Phar::GZ; } elseif ($options['tgz']) { $options['tar'] = true; } if ($options['tar']) { if (isset($mainfile)) { $extras[] = array('tar', \Phar::TAR, \Phar::NONE); } else { $mainfile = $package->name . '-' . $package->version['release'] . '.tar'; $mainformat = \Phar::TAR; $maincompress = \Phar::NONE; } } if ($options['phar']) { if (isset($mainfile)) { $extras[] = array('phar', \Phar::PHAR, \Phar::GZ); } else { $mainfile = $package->name . '-' . $package->version['release'] . '.phar'; $mainformat = \Phar::PHAR; $maincompress = \Phar::NONE; } if (!$options['stub'] && file_exists(dirname($package->archivefile) . '/stub.php')) { $stub = file_get_contents(dirname($package->archivefile) . '/stub.php'); } elseif ($options['stub'] && file_exists($options['stub'])) { $stub = file_get_contents($options['stub']); } $stub = str_replace('@PACKAGE_VERSION' . '@', $package->version['release'], $stub); } if ($options['zip']) { if (isset($mainfile)) { $extras[] = array('zip', \Phar::ZIP, \Phar::NONE); } else { $mainfile = $package->name . '-' . $package->version['release'] . '.zip'; $mainformat = \Phar::ZIP; $maincompress = \Phar::NONE; } } if (isset($options['outputfile'])) { $mainfile = $options['outputfile']; } echo "Creating ", $mainfile, "\n"; if (null == $cert) { $cloner = new \PEAR2\Pyrus\Package\Cloner($mainfile); $clone = $extras; $extras = array(); } else { foreach ($extras as $stuff) { echo "Creating ", $package->name, '-', $package->version['release'], '.', $stuff[0], "\n"; } $clone = array(); } $creator = new \PEAR2\Pyrus\Package\Creator(array(new \PEAR2\Pyrus\Developer\Creator\Phar($mainfile, $stub, $mainformat, $maincompress, $extras, $releaser, $package, $cert, $passphrase)), $exceptionpath, $autoloadpath, $multierrorspath); if (!$options['extrasetup'] && file_exists(dirname($package->archivefile) . '/extrasetup.php')) { $options['extrasetup'] = 'extrasetup.php'; } if ($options['extrasetup']) { // encapsulate the extrafiles inside a closure so there is no access to the variables in this function $getinfo = function () use($options, $package) { $file = $options['extrasetup']; if (!file_exists(dirname($package->archivefile) . '/' . $file)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file must be in the same directory as package.xml'); } include dirname($package->archivefile) . '/' . $file; if (!isset($extrafiles)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file must set $extrafiles variable to an array of files'); } if (!is_array($extrafiles)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file must set $extrafiles variable to an array of files'); } foreach ($extrafiles as $path => $file) { if (is_object($file)) { if ($file instanceof \PEAR2\Pyrus\PackageInterface || $file instanceof \PEAR2\Pyrus\PackageFileInterface) { continue; } throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file object must implement \\PEAR2\\Pyrus\\PackageInterface or \\PEAR2\\Pyrus\\PackageFileInterface'); } if (!file_exists($file)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file ' . $file . ' does not exist'); } if (!is_string($path)) { throw new \PEAR2\Pyrus\Developer\Creator\Exception('extrasetup file ' . $file . ' index should be the path to save in the' . ' release'); } } return $extrafiles; }; $extrafiles = $getinfo(); } else { $extrafiles = array(); } $creator->render($package, $extrafiles); if (count($clone)) { foreach ($clone as $extra) { echo "Creating ", $package->name, '-', $package->version['release'], '.', $extra[0], "\n"; $cloner->{'to' . $extra[0]}(); } } echo "done\n"; }
/** * Figure out which version is best, and use this, or error out if none work * @param \PEAR2\Pyrus\PackageFile\v2\Dependencies\Package $compositeDep * the composite of all dependencies on this package, as calculated * by {@link \PEAR2\Pyrus\Package\Dependency::getCompositeDependency()} */ function figureOutBestVersion(\PEAR2\Pyrus\PackageFile\v2\Dependencies\Package $compositeDep, $versions = null, \PEAR2\Pyrus\PackageFile\v2\Dependencies\Package $compositeConflictingDep = null) { // set up release list if not done yet $this->rewind(); $ok = \PEAR2\Pyrus\Installer::betterStates($this->minimumStability, true); $v = $this->explicitVersion; $n = $this->channel . '/' . $this->name; $failIfExplicit = function ($versioninfo) use($v, $n) { if ($v && $versioninfo['v'] == $v) { throw new Exception($n . ' Cannot be installed, it does not satisfy ' . 'all dependencies'); } }; foreach ($this->releaseList as $versioninfo) { if (isset(\PEAR2\Pyrus\Main::$options['force'])) { // found one if ($this->versionSet && $versioninfo['v'] != $this->version['release']) { // inform the installer we need to reset dependencies $this->version['release'] = $versioninfo['v']; return true; } $this->version['release'] = $versioninfo['v']; return; } if ($versions && !in_array($versioninfo['v'], $versions)) { continue; } if (!isset(\PEAR2\Pyrus\Main::$options['force']) && isset($versioninfo['m'])) { // minimum PHP version required if (version_compare($versioninfo['m'], $this->getPHPVersion(), '>')) { $failIfExplicit($versioninfo); continue; } } if (!in_array($versioninfo['s'], $ok) && !isset(\PEAR2\Pyrus\Main::$options['force'])) { // release is not stable enough continue; } if ($this->explicitVersion && $versioninfo['v'] != $this->explicitVersion) { continue; } if (!$compositeDep->satisfied($versioninfo['v'])) { $failIfExplicit($versioninfo); continue; } if ($compositeConflictingDep && !$compositeConflictingDep->satisfied($versioninfo['v'])) { $failIfExplicit($versioninfo); continue; } $paranoia = \PEAR2\Pyrus\Main::getParanoiaLevel(); if (!$this->explicitVersion && $paranoia > 1) { // first, we check to see if we are upgrading if (isset(\PEAR2\Pyrus\Main::$options['upgrade'])) { // now we check to see if we are installed if (isset(Config::current()->registry->package[$n])) { $installed = Config::current()->registry->info($this->name, $this->channel, 'apiversion'); $installed = explode('.', $installed); if (count($installed) == 2) { $installed[] = '0'; } if (count($installed) == 1) { $installed[] = '0'; $installed[] = '0'; } if (isset($this->parent->protocols->rest['REST1.3'])) { $api = $this->rest->retrieveCacheFirst($this->parent->protocols->rest['REST1.3']->baseurl . 'r/' . strtolower($this->name) . '/v2.' . $versioninfo['v'] . '.xml'); } else { throw new Exception('Channel ' . $this->channel . ' does not support ' . 'a paranoia greater than 1'); } $api = explode('.', $api['a']); if (count($api) == 2) { $api[] = '0'; } if (count($api) == 1) { $api[] = '0'; $api[] = '0'; } if ($paranoia > 4) { $paranoia = 4; } switch ($paranoia) { case 4: if ($installed != $api) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API has changed'); continue 2; } break; case 3: if ($installed[0] == $api[0] && $installed[1] != $api[1]) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API has added' . ' new features'); continue 2; } // break intentionally omitted // break intentionally omitted case 2: if ($installed[0] != $api[0]) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API breaks' . ' backwards compatibility'); continue 2; } break; } } } } // found one if ($this->versionSet && $versioninfo['v'] != $this->version['release']) { // inform the installer we need to reset dependencies $this->version['release'] = $versioninfo['v']; return true; } $this->version['release'] = $versioninfo['v']; return; } throw new Exception('Unable to locate a package release for ' . $this->channel . '/' . $this->name . ' that can satisfy all dependencies'); }
/** * Returns a list of registries present in the PEAR installation at $path * @param string * @return array */ public static function detectRegistries($path) { if (isset(Main::$options['packagingroot'])) { $path = Main::prepend(Main::$options['packagingroot'], $path); } if (file_exists($path . '/.xmlregistry') || is_dir($path . '/.xmlregistry')) { return array('Xml'); } return array(); }
protected function getDefaultChannel($channel) { $xml = \PEAR2\Pyrus\Main::getDataPath() . '/default_channels/' . $channel . '.xml'; if (!file_exists($xml)) { $xml = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/default_channels/' . $channel . '.xml'; } $parser = new \PEAR2\Pyrus\ChannelFile\Parser\v1(); $info = $parser->parse($xml, true); return new Channel($this, $info->getArray()); }
/** * Validate the xml against the channel schema. * */ function validate() { if (!isset($this->_xml)) { $this->__toString(); } $a = new \PEAR2\Pyrus\XMLParser(); $schema = \PEAR2\Pyrus\Main::getDataPath() . '/channel-1.0.xsd'; // for running out of svn if (!file_exists($schema)) { $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/channel-1.0.xsd'; } try { $a->parseString($this->_xml, $schema); return true; } catch (\Exception $e) { throw new \PEAR2\Pyrus\Channel\Exception('Invalid channel.xml', $e); } }