Пример #1
0
 /**
  * parse a configuration for a PEAR2 installation
  *
  * @param string $pearDirectory This can be either a single path, or a
  *                              PATH_SEPARATOR-separated list of directories
  * @param string $userfile
  */
 public function __construct($snapshot, \Pyrus\Config $config = null)
 {
     self::constructDefaults();
     if (!$config) {
         $config = \Pyrus\Config::current();
     }
     $this->loadConfigFile($config->location, $snapshot);
     $this->pearDir = $config->location;
 }
Пример #2
0
 function isUpgradeable()
 {
     if (!isset(\Pyrus\Main::$options['upgrade'])) {
         // we don't attempt to upgrade a dep unless we're upgrading
         return false;
     }
     $reg = \Pyrus\Config::current()->registry;
     $version = $reg->info($this->name, $this->channel, 'version');
     if (version_compare($this->version['release'], $version, '<=')) {
         return !isset(\Pyrus\Main::$options['force']);
     }
     return true;
 }
Пример #3
0
 function __construct($coverage, $recursive)
 {
     $this->ini_overwrites[] = 'error_reporting=' . E_ALL;
     if ($coverage) {
         $this->_options['coverage'] = true;
     }
     if ($recursive) {
         $this->_options['recur'] = true;
     }
     $this->windows = substr(PHP_OS, 0, 3) == 'WIN';
     $this->_php = \Pyrus\Config::current()->php_bin;
     $this->xdebug_loaded = extension_loaded('xdebug');
 }
Пример #4
0
 function cloneRegistry(Base $registry)
 {
     try {
         $packageiterator = $registry->package;
         foreach (\Pyrus\Config::current()->channelregistry->listChannels() as $channel) {
             $packageiterator->setIteratorChannel($channel);
             foreach ($packageiterator as $package) {
                 if ($this->exists($package->name, $package->channel)) {
                     $old = $this->toPackageFile($package->name, $package->channel);
                     if ($old->date == $package->date && $old->time == $package->time) {
                         continue;
                     }
                 }
                 $this->replace($package);
             }
         }
     } catch (\Exception $e) {
         throw new Exception('Cannot clone registry', $e);
     }
 }
Пример #5
0
 /**
  * Get/Create a transaction.
  *
  * @param string|Pyrus\Installer\Role\Common $path The directory path.
  * @return Transaction A Pyrus\AtomicFileTransaction\Transaction instance
  */
 public function getTransaction($path)
 {
     if ($path instanceof \Pyrus\Installer\Role\Common) {
         $path = \Pyrus\Config::current()->{$path->getLocationConfig()};
     }
     $path = FS::path((string) $path);
     if (isset($this->transactions[$path])) {
         return $this->transactions[$path];
     }
     // Create new transaction object
     $class = $this->getTransactionClass();
     try {
         $this->transactions[$path] = new $class($path, $this);
         return $this->transactions[$path];
     } catch (\Exception $e) {
         $errs = new MultiErrors();
         $errs->E_ERROR[] = $e;
         $errs->merge($this->rollbackTransactions());
         throw new MultiException('Unable to begin transaction', $errs);
     }
 }
Пример #6
0
 function getRelativeLocation(\Pyrus\PackageFileInterface $pkg, \Pyrus\PackageFile\v2Iterator\FileTag $file, $retDir = false)
 {
     if ($this->md5 === null) {
         return parent::getRelativeLocation($pkg, $file, $retDir);
     }
     $info = parent::getRelativeLocation($pkg, $file, $retDir);
     $path = \Pyrus\Config::current()->cfg_dir . DIRECTORY_SEPARATOR;
     if ($retDir) {
         $filepath = $info[1];
     } else {
         $filepath = $info;
     }
     if (@file_exists($path . $filepath)) {
         // configuration has already been installed, check for modifications
         // made by the user
         $md5 = md5_file($path . $filepath);
         $newmd5 = $pkg->files[$file->packagedname]['attribs'];
         if (!isset($newmd5['md5sum'])) {
             $newmd5 = md5_file($pkg->getFilePath($file->packagedname));
         } else {
             $newmd5 = $newmd5['md5sum'];
         }
         // first check to see if the user modified the file
         // next check to see if the config file changed from the last installed version
         // if both tests are satisfied, install the new file under another name and display a warning
         if ($md5 !== $this->md5 && $md5 !== $newmd5) {
             // configuration has been modified, so save our version as
             // configfile.new-version
             $old = $filepath;
             $filepath .= '.new-' . $pkg->version['release'];
             \Pyrus\Logger::log(0, "WARNING: configuration file {$old} is being installed as {$filepath}, " . "you should manually merge in changes to the existing configuration file");
         }
     }
     if ($retDir) {
         $info[1] = $filepath;
     } else {
         $info = $filepath;
     }
     return $info;
 }
Пример #7
0
 function offsetUnset($offset)
 {
     $info = Config::current()->channelregistry->parseName($offset);
     $this->reg->uninstall($info['package'], $info['channel']);
 }
Пример #8
0
 /**
  * @param \Pyrus\PackageFile\v2
  * @param int
  */
 function validate(\Pyrus\PackageInterface $pf, $state = \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 = \Pyrus\Main::getDataPath() . '/package-2.1.xsd';
         } else {
             $schema = \Pyrus\Main::getDataPath() . '/package-2.0.xsd';
         }
         // libxml can't process these from within a phar (pity)
         if (strpos($schema, 'phar://') === 0) {
             if (!file_exists($temp = \Pyrus\Config::current()->temp_dir . DIRECTORY_SEPARATOR . 'schema')) {
                 mkdir($temp, 0755, true);
             }
             $tmpschema = $temp . DIRECTORY_SEPARATOR . basename($schema);
             copy($schema, $tmpschema);
             $dom->schemaValidate($tmpschema);
         } else {
             $dom->schemaValidate($schema);
         }
         $causes = array();
         foreach (libxml_get_errors() as $error) {
             $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception("Line " . $error->line . ': ' . $error->message);
         }
         if (count($this->errors)) {
             throw new \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 \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 \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 = \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 \Pyrus\PackageFile\Exception($msg);
                     }
                 }
             }
             $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception('File "' . $name . '" has invalid role "' . $file->role . '", should be one of ' . implode(', ', \Pyrus\Installer\Role::getValidRoles($this->_pf->getPackageType())));
         }
         if (count($file->tasks) && $this->_curState != \Pyrus\Validate::DOWNLOADING) {
             // has tasks
             $save = $file->getArrayCopy();
             foreach ($file->tasks as $task => $value) {
                 if ($tagClass = \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 (\Pyrus\Task\Exception $e) {
                             $this->errors->E_ERROR[] = new \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 = \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 \Pyrus\PackageFile\Exception($msg);
                             }
                         }
                     }
                     $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception('Unknown task "' . $task . '" passed in file <file name="' . $name . '">');
                 }
             }
         }
     }
     $this->_validateRelease();
     if (count($this->errors->E_ERROR)) {
         throw new \Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors);
     }
     try {
         $validator = \Pyrus\Config::current()->channelregistry[$this->_pf->channel]->getValidationObject($this->_pf->name);
     } catch (\Pyrus\Config\Exception $e) {
         throw new \Pyrus\PackageFile\Exception('Unable to process channel-specific configuration for channel ' . $this->_pf->getChannel(), $e);
     } catch (\Exception $e) {
         $valpack = \Pyrus\Config::current()->channelregistry[$this->_pf->channel]->getValidationPackage();
         $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception('Unknown channel ' . $this->_pf->channel);
         $this->errors->E_ERROR[] = new \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(\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 \Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors);
     }
     if ($state == \Pyrus\Validate::PACKAGING) {
         if ($this->_pf->type == 'bundle') {
             if (!$this->_analyzeBundledPackages()) {
                 throw new \Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors);
             }
         } else {
             if (!$this->_analyzePhpFiles()) {
                 throw new \Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors);
             }
         }
     }
     return $state;
 }
Пример #9
0
ini_set('display_errors', true);
// Get the autoloader
require __DIR__ . '/../../../autoload.php';
/*
$channel = new PEAR2\SimpleChannelServer('pear2.php.net','/Library/WebServer/Documents/pearserver', null, '/Users/bbieber/pyrus', array('saltybeagle','cellog'));
if (!@unserialize(file_get_contents('/tmp/categories.inf'))) {
      $cat = PEAR2_SimpleChannelServer_Categories::create('Name1',
          'Description 1', 'Alias1')->
          create('Name2', 'Description 2')->
          create('Name3', 'Description 3', 'Alias3')->
          create('Name4', 'Description 4');
      file_put_contents('/tmp/categories.inf', serialize($cat));
}

$categories = PEAR2_SimpleChannelServer_Categories::getCategories();
$categories = $channel->listCategories();
foreach($categories as $category) {
    var_dump($category);
}
*/
$channel = new PEAR2\SimpleChannelServer\Channel('pear2.php.net', 'Brett Bieber\'s PEAR Channel', 'salty');
//$scs = new PEAR2\SimpleChannelServer($channel,'/Library/WebServer/Documents/pearserver','/home/bbieber/pyrus/php');
$scs = new PEAR2\SimpleChannelServer($channel, '/home/cellog/testapache/htdocs', \Pyrus\Config::current()->path);
$categories = PEAR2\SimpleChannelServer\Categories::create('Default', 'This is the default category');
$scs->saveChannel();
$scs->saveRelease(new \Pyrus\Package(__DIR__ . '/../package.xml'), 'cellog');
echo 'did it' . PHP_EOL;
/*
$manager = new PEAR2\SimpleChannelServer\REST\Manager('/Library/WebServer/Documents/pearserver','pear2.php.net','rest/',array('cellog'));
var_dump($manager->saveRelease(new \Pyrus\Package(__DIR__ . '/../package.xml'),'cellog'));
*/
Пример #10
0
 /** @todo Consider simply injecting the Package object as appropriate */
 function package($frontend, $args, $options)
 {
     $path = getcwd() . DIRECTORY_SEPARATOR;
     $package = new \Pyrus\Package(null);
     if (!isset($args['packagexml']) && !file_exists($path . 'package.xml') && !file_exists($path . 'package2.xml')) {
         throw new \Pyrus\PackageFile\Exception("No package.xml or package2.xml found in " . $path);
     }
     if (isset($args['packagexml'])) {
         $package = new \Pyrus\Package($args['packagexml']);
     } else {
         // first try ./package.xml
         if (file_exists($path . 'package.xml')) {
             try {
                 $package = new \Pyrus\Package($path . 'package.xml');
             } catch (\Pyrus\PackageFile\Exception $e) {
                 if ($e->getCode() != -3) {
                     throw $e;
                 }
                 if (!file_exists($path . 'package2.xml')) {
                     throw $e;
                 }
                 $package = new \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 \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 \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 (\Pyrus\Config::current()->openssl_cert) {
         if ('yes' == $frontend->ask('Sign package?', array('yes', 'no'), 'yes')) {
             $cert = \Pyrus\Config::current()->openssl_cert;
             if (!file_exists($cert)) {
                 throw new \Pyrus\Developer\Creator\Exception('OpenSSL certificate ' . $cert . ' does not exist');
             }
             $releaser = \Pyrus\Config::current()->handle;
             $maintainers = array();
             foreach ($package->maintainer as $maintainer) {
                 $maintainers[] = $maintainer->user;
             }
             if (!strlen($releaser)) {
                 throw new \Pyrus\Developer\Creator\Exception('handle configuration variable must be from ' . 'package.xml (one of ' . implode(', ', $maintainers) . ')');
             }
             if (!in_array($releaser, $maintainers)) {
                 throw new \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 = \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 \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 \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 \Pyrus\Package\Creator(array(new \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 \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 \Pyrus\Developer\Creator\Exception('extrasetup file must set $extrafiles variable to an array of files');
             }
             if (!is_array($extrafiles)) {
                 throw new \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 \Pyrus\PackageInterface || $file instanceof \Pyrus\PackageFileInterface) {
                         continue;
                     }
                     throw new \Pyrus\Developer\Creator\Exception('extrasetup file object must implement \\Pyrus\\PackageInterface or \\Pyrus\\PackageFileInterface');
                 }
                 if (!file_exists($file)) {
                     throw new \Pyrus\Developer\Creator\Exception('extrasetup file ' . $file . ' does not exist');
                 }
                 if (!is_string($path)) {
                     throw new \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";
 }
Пример #11
0
 /**
  * Rebuild the dependency DB by reading registry entries.
  */
 function rebuildDB()
 {
     $depdb = array('_version' => $this->_version);
     if (!$this->hasWriteAccess()) {
         // allow startup for read-only with older Registry
         return $depdb;
     }
     $reg = \Pyrus\Config::current()->registry;
     foreach (\Pyrus\Config::current()->channelregistry as $channel) {
         foreach ($reg->listPackages($channel->name) as $package) {
             $package = $reg->package[$channel->name . '/' . $package];
             $depdb = $this->_setPackageDeps($depdb, $package);
         }
     }
     $this->_writeDepDB($depdb);
 }
Пример #12
0
<?php

/**
 * This file generates the pyrus.phar file and PEAR2 package for Pyrus.
 */
$current = \Pyrus\Config::current();
$config = \Pyrus\Config::singleton(__DIR__ . '/vendor');
$extrafiles = array($config->registry->toPackage('PEAR2_HTTP_Request', 'pear2.php.net'), $config->registry->toPackage('PEAR2_Console_CommandLine', 'pear2.php.net'), $config->registry->toPackage('PEAR2_Exception', 'pear2.php.net'), $config->registry->toPackage('PEAR2_MultiErrors', 'pear2.php.net'));
\Pyrus\Config::setCurrent($current->path);
Пример #13
0
 /**
  * @param array output of {@link parsePackageName()}
  * @return \Pyrus\Channel\RemotePackage
  * @access private
  */
 function getRemotePackage($parr)
 {
     // getDownloadURL returns an array.  On error, it only contains information
     // on the latest release as array(version, info).  On success it contains
     // array(version, info, download url string)
     $state = isset($parr['state']) ? $parr['state'] : Config::current()->preferred_state;
     if (!isset(Config::current()->channelregistry[$parr['channel']])) {
         throw new Exception('Unknown remote channel: ' . $parr['channel']);
     }
     try {
         $chan = Config::current()->channelregistry[$parr['channel']];
     } catch (\Exception $e) {
         throw new Exception('Cannot retrieve download information ' . 'for remote abstract package ' . $parr['channel'] . '/' . $parr['package'], $e);
     }
     $p_mirror = Config::current()->preferred_mirror;
     $mirror = isset($chan->mirrors[$p_mirror]) ? $chan->mirrors[$p_mirror] : $chan;
     return $mirror->remotepackage[$parr['package']];
 }
Пример #14
0
 /**
  * Detect any files already installed that would be overwritten by
  * files inside the package represented by $package
  */
 public function detectFileConflicts(\Pyrus\PackageFileInterface $package)
 {
     // construct list of all installed files
     $filesByPackage = $allfiles = array();
     $config = \Pyrus\Config::current();
     foreach ($config->channelregistry as $channel) {
         foreach ($this->listPackages($channel->name) as $packagename) {
             $files = $this->info($packagename, $channel->name, 'installedfiles');
             $newfiles = array();
             foreach ($files as $file) {
                 $newfiles[$file['installed_as']] = $file;
             }
             $filesByPackage[$channel->name . '/' . $packagename] = $newfiles;
             $allfiles = array_merge($allfiles, $newfiles);
         }
     }
     // now iterate over each file in the package, and note all the conflicts
     $roles = array();
     foreach (Role::getValidRoles($package->getPackageType()) as $role) {
         // set up a list of file role => configuration variable
         // for storing in the registry
         $roles[$role] = Role::factory($package->getPackageType(), $role);
     }
     $ret = array();
     foreach ($package->installcontents as $file) {
         $relativepath = $roles[$file->role]->getRelativeLocation($package, $file);
         if (!$relativepath) {
             continue;
         }
         $testpath = $config->{$roles[$file->role]->getLocationConfig()} . DIRECTORY_SEPARATOR . $relativepath;
         if (isset($allfiles[$testpath])) {
             foreach ($filesByPackage as $pname => $files) {
                 if (isset($files[$testpath])) {
                     $ret[] = array($relativepath => $pname);
                     break;
                 }
             }
         }
     }
     return $ret;
 }
Пример #15
0
 protected function getPackage($package)
 {
     $releases = array();
     if (isset($package['a']) && $package['a']) {
         $releases = $package['a']['r'];
         if (!isset($releases[0])) {
             $releases = array($releases);
         }
         foreach ($releases as $i => $release) {
             if (!isset($release['m'])) {
                 $releases[$i]['m'] = '5.2.0';
             }
         }
     }
     $pxml = new RemotePackage($this->parent, $releases);
     $pxml->channel = $package['p']['c'];
     $pxml->name = $package['p']['n'];
     $pxml->license = $package['p']['l'];
     $pxml->summary = $package['p']['s'];
     $pxml->description = $package['p']['d'];
     $reg = \Pyrus\Config::current()->registry;
     if ($reg->exists($package['p']['n'], $package['p']['c'])) {
         $pxml->setExplicitState($version = $reg->info($package['p']['n'], $package['p']['c'], 'version'));
         $found = false;
         foreach ($pxml as $remoteversion => $rinfo) {
             if (version_compare($remoteversion, $version, '<=')) {
                 continue;
             }
             if (version_compare($rinfo['minimumphp'], phpversion(), '>')) {
                 continue;
             }
             // found one, so upgrade is possible if dependencies pass
             $found = true;
             break;
         }
         // the installed package version satisfies this dependency, don't do anything
         if ($found) {
             $pxml->setUpgradeable();
         }
     } else {
         $pxml->setExplicitState($this->minimumStability);
     }
     return $pxml;
 }
Пример #16
0
 /**
  * Unlike other tasks, the installed file name is passed in instead of the file contents,
  * because this task is handled post-installation
  * @param \Pyrus\PackageInterface
  * @param string path to the post-install script
  * @return bool false to skip this file
  */
 function setupPostInstall()
 {
     $files = \Pyrus\Config::current()->registry->info($this->pkg->name, $this->pkg->channel, 'installedfiles');
     foreach ($files as $path => $info) {
         if ($info['name'] == $this->_filename) {
             break;
         }
     }
     Logger::log(0, 'Including external post-installation script "' . $path . '" - any errors are in this script');
     include $path;
     if (class_exists($this->scriptClass) === false) {
         throw new Exception('init of post-install script class "' . $this->scriptClass . '" failed');
     }
     Logger::log(0, 'Inclusion succeeded');
     $this->obj = new $this->scriptClass();
     Logger::log(1, 'running post-install script "' . $this->scriptClass . '->init()"');
     try {
         $this->obj->init2($this->pkg, $this->lastVersion);
     } catch (\Exception $e) {
         throw new Exception('init of post-install script "' . $this->scriptClass . '->init()" failed', $e);
     }
     Logger::log(0, 'init succeeded');
     return true;
 }
Пример #17
0
 /**
  * Render packages from the creators passed into the constructor.
  *
  * This will take any package source and an array mapping internal
  * path => file name and create new packages in the formats requested.
  *
  * All files in package.xml will have the string @PACKAGE_VERSION@
  * automatically replaced with the current package's version
  * @param \Pyrus\Package $package
  * @param array $extrafiles
  */
 function render(\Pyrus\Package $package, array $extrafiles = array())
 {
     foreach ($this->_creators as $creator) {
         $creator->init();
     }
     $this->prepend = $prepend = $package->name . '-' . $package->version['release'];
     if ($package->isNewPackage()) {
         $packagexml = $prepend . '/.xmlregistry/packages/' . str_replace('/', '!', $package->channel) . '/' . $package->name . '/' . $package->version['release'] . '-info.xml';
     } else {
         if ($package->isOldAndCrustyCompatible()) {
             $packagexml = 'package2.xml';
             $old = file_get_contents('package.xml');
         } else {
             $packagexml = 'package.xml';
         }
     }
     if (self::VERSION === '@' . 'PACKAGE_VERSION@') {
         // we're running straight from SVN, so pretend to be 2.0.0
         $package->packagerversion = '2.0.0';
     } else {
         $package->packagerversion = self::VERSION;
     }
     // get packaging package.xml
     $packageingstr = (string) new \Pyrus\XMLWriter($package->toArray(true));
     foreach ($this->_creators as $creator) {
         $creator->addFile($packagexml, $packageingstr);
     }
     if ($package->isOldAndCrustyCompatible()) {
         foreach ($this->_creators as $creator) {
             $creator->addFile('package.xml', $old);
         }
     }
     if ($package->getInternalPackage() instanceof Xml) {
         // check for package_compatible.xml
         if ($package->isNewPackage() && file_exists($package->getFilePath('package_compatible.xml'))) {
             foreach ($this->_creators as $creator) {
                 $creator->addFile('package.xml', file_get_contents($package->getFilePath('package_compatible.xml')));
             }
         }
     }
     $packagingloc = \Pyrus\Config::current()->temp_dir . DIRECTORY_SEPARATOR . 'pyrpackage';
     if (file_exists($packagingloc)) {
         \Pyrus\Filesystem::rmrf($packagingloc, false, false);
     }
     mkdir($packagingloc, 0777, true);
     // $packageat is the relative path within the archive
     // $info is an array of format:
     // array('attribs' => array('name' => ...)[, 'tasks:blah' ...])
     $alreadyPackaged = array();
     $globalreplace = array('attribs' => array('from' => '@' . 'PACKAGE_VERSION@', 'to' => 'version', 'type' => 'package-info'));
     foreach ($package->packagingcontents as $packageat => $info) {
         $role = \Pyrus\Installer\Role::factory($package->getPackageType(), $info['attribs']['role']);
         try {
             $role->packageTimeValidate($package, $info);
         } catch (\Exception $e) {
             throw new Creator\Exception('Invalid file ' . $packageat . ': ' . $e->getMessage(), $e);
         }
         $packageat = str_replace('\\', '/', $packageat);
         $packageat = str_replace('//', '/', $packageat);
         if ($packageat[0] === '/' || strlen($packageat) > 2 && ($packageat[1] === ':' && $packageat[2] == '/')) {
             throw new Creator\Exception('Invalid path, cannot save a root path ' . $packageat);
         }
         if (preg_match('@^\\.\\.?/|/\\.\\.?\\z|/\\.\\./@', $packageat)) {
             throw new Creator\Exception('Invalid path, cannot use directory ' . 'reference . or .. ' . $packageat);
         }
         $alreadyPackaged[$packageat] = true;
         $packageat = $prepend . '/' . $packageat;
         $contents = $package->getFileContents($info['attribs']['name'], true);
         if (!file_exists(dirname($packagingloc . DIRECTORY_SEPARATOR . $packageat))) {
             mkdir(dirname($packagingloc . DIRECTORY_SEPARATOR . $packageat), 0777, true);
         }
         $fp = fopen($packagingloc . DIRECTORY_SEPARATOR . $packageat, 'wb+');
         ftruncate($fp, 0);
         stream_copy_to_stream($contents, $fp);
         fclose($contents);
         rewind($fp);
         if ($package->isNewPackage() && $info['attribs']['role'] == 'php') {
             if (isset($info['tasks:replace'])) {
                 if (isset($info['tasks:replace'][0])) {
                     $info['tasks:replace'][] = $globalreplace;
                 } else {
                     $info['tasks:replace'] = array($info['tasks:replace'], $globalreplace);
                 }
             } else {
                 $info['tasks:replace'] = $globalreplace;
             }
         }
         if (isset(\Pyrus\Config::current()->registry->package[$package->channel . '/' . $package->name])) {
             $version = \Pyrus\Config::current()->registry->info($package->name, $package->channel, 'version');
         } else {
             $version = null;
         }
         foreach (new Creator\TaskIterator($info, $package, \Pyrus\Task\Common::PACKAGE, $version) as $task) {
             // do pre-processing of file contents
             try {
                 $task->startSession($fp, $packageat);
             } catch (\Exception $e) {
                 // TODO: handle exceptions
             }
         }
         fclose($fp);
     }
     foreach ($this->_creators as $creator) {
         $creator->addDir($packagingloc);
     }
     if ($package->isNewPackage()) {
         $this->addPEAR2Stuff($alreadyPackaged);
     }
     $this->addExtraFiles($extrafiles);
     foreach ($this->_creators as $creator) {
         $creator->close();
     }
     \Pyrus\Filesystem::rmrf($packagingloc, false, false);
 }
Пример #18
0
 function getDependenciesOn($info)
 {
     $name = $info->name;
     $channel = $info->channel;
     $packages = \Pyrus\Config::current()->registry->getDependentPackages($info->getPackageFileObject());
     $ret = array();
     foreach ($packages as $package) {
         $deps = $package->dependencies;
         foreach (array('package', 'subpackage') as $type) {
             foreach (array('required', 'optional') as $required) {
                 foreach ($deps[$required]->{$type} as $dep) {
                     if ($dep->channel != $channel || $dep->name != $name) {
                         continue;
                     }
                     $ret[] = $dep;
                 }
             }
         }
     }
     return $ret;
 }
Пример #19
0
 /**
  * Detect any files already installed that would be overwritten by
  * files inside the package represented by $package
  */
 public function detectFileConflicts(\Pyrus\PackageFileInterface $package)
 {
     if (!static::existsRegistry($this->_path)) {
         throw new \Pyrus\ChannelRegistry\Exception('Error: no existing SQLite3 channel registry for ' . $this->_path);
     }
     $database = static::getRegistry($this->_path);
     $ret = array();
     $sql = 'SELECT
                 packages_channel, packages_name
             FROM files
             WHERE
                 packagepath = :path
             ORDER BY packages_channel, packages_name';
     $stmt = $database->prepare($sql);
     // now iterate over each file in the package, and note all the conflicts
     $roles = array();
     foreach (Role::getValidRoles($package->getPackageType()) as $role) {
         // set up a list of file role => configuration variable
         // for storing in the registry
         $roles[$role] = Role::factory($package->getPackageType(), $role);
     }
     $ret = array();
     $config = Config::current();
     foreach ($package->installcontents as $file) {
         $stmt->reset();
         $relativepath = $roles[$file->role]->getRelativeLocation($package, $file);
         if (!$relativepath) {
             continue;
         }
         $testpath = $config->{$roles[$file->role]->getLocationConfig()} . DIRECTORY_SEPARATOR . $relativepath;
         $stmt->bindValue(':path', $testpath, SQLITE3_TEXT);
         $result = $stmt->execute();
         while ($res = $result->fetchArray(SQLITE3_ASSOC)) {
             $pn = $this->info($res['packages_name'], $res['packages_channel'], 'name');
             $ret[] = array($relativepath => $res['packages_channel'] . '/' . $pn);
         }
     }
     return $ret;
 }
Пример #20
0
 /**
  * validate a downloaded package against installed packages
  *
  * @param $pkg downloaded package package.xml object
  * @param array $params full list of packages to install
  * @return bool
  */
 function validateDownloadedPackage(\Pyrus\PackageFileInterface $pkg, $params = array())
 {
     $me = $pkg->channel . '/' . $pkg->name;
     $reg = Config::current()->registry;
     $deppackages = $reg->getDependentPackages($pkg);
     $fail = false;
     if ($deppackages) {
         $actual = array();
         // first, remove packages that will be installed
         foreach ($deppackages as $package) {
             foreach ($params as $packd) {
                 if (strtolower($packd->name) == strtolower($package->name) && $packd->channel == $package->channel) {
                     \Pyrus\Logger::log(3, 'skipping installed package check of "' . Config::parsedPackageNameToString(array('channel' => $package->channel, 'package' => $package->name), true) . '", version "' . $packd->version['release'] . '" will be ' . 'downloaded and installed');
                     continue 2;
                 }
             }
             $actual[] = $package;
         }
         foreach ($actual as $package) {
             $checker = new \Pyrus\Dependency\Validator(array('channel' => $package->channel, 'package' => $package->name), $this->_state, $this->errs);
             foreach ($params as $packd) {
                 $deps = $package->dependencies['required']->package;
                 if (isset($deps[$me])) {
                     $ret = $checker->_validatePackageDownload($deps[$me], array($pkg, $package));
                 }
                 $deps = $package->dependencies['required']->subpackage;
                 if (isset($deps[$me])) {
                     $ret = $checker->_validatePackageDownload($deps[$me], array($pkg));
                 }
                 $deps = $package->dependencies['optional']->package;
                 if (isset($deps[$me])) {
                     $ret = $checker->_validatePackageDownload($deps[$me], array($pkg, $package));
                 }
                 $deps = $package->dependencies['optional']->subpackage;
                 if (isset($deps[$me])) {
                     $ret = $checker->_validatePackageDownload($deps[$me], array($pkg));
                 }
             }
         }
     }
     if (count($this->errs->E_ERROR)) {
         return $this->raiseError('%s cannot be installed, conflicts with installed packages');
     }
     return true;
 }
Пример #21
0
 function listAll($args, $options)
 {
     $reg = \Pyrus\Config::current()->registry;
     echo "Remote packages for channel ", $args['channel'], ":\n";
     if ($options['basic']) {
         foreach (\Pyrus\Config::current()->channelregistry[$args['channel']]->remotecategories as $category) {
             echo $category->name, ":\n";
             foreach ($category->basiclist as $package) {
                 $installed = $reg->exists($package['package'], $args['channel']) ? '  *' : '   ';
                 echo $installed, $package['package'], ' latest stable: ', $package['stable'], ', latest release: ', $package['latest']['v'], ' (', $package['latest']['s'], ")\n";
             }
         }
         return;
     }
     foreach (\Pyrus\Config::current()->channelregistry[$args['channel']]->remotecategories as $category) {
         echo $category->name, ":\n";
         $pnames = array();
         $summaries = array();
         $pnameinfo = array();
         $versions = array();
         try {
             foreach ($category as $package) {
                 $installed = ' ';
                 if ($package->isUpgradeable()) {
                     $installed = '!';
                 } elseif ($reg->exists($package->name, $args['channel'])) {
                     $installed = '*';
                 }
                 $found = false;
                 foreach ($package as $version => $latest) {
                     $found = true;
                     break;
                 }
                 $pnames[] = $package->name;
                 $summaries[] = $package->summary;
                 if (!$found) {
                     $versions[] = '--';
                     $pnameinfo[$package->name] = array('installed' => $installed, 'summary' => $package->summary, 'latest' => 'n/a');
                     continue;
                 }
                 $versions[] = $version;
                 $latest['v'] = $version;
                 $pnameinfo[$package->name] = array('installed' => $installed, 'summary' => $package->summary, 'latest' => $latest);
             }
         } catch (\Exception $e) {
             echo "Error: Category has broken REST (", $e->getMessage(), ")\n";
             continue;
         }
         $widths = array(1, 25, 8, 51);
         foreach ($pnameinfo as $package => $info) {
             if (is_string($info['latest'])) {
                 $text = array($info['installed'], $package, $info['latest'], $info['summary']);
             } else {
                 $text = array($info['installed'], $package, $info['latest']['v'], $info['summary']);
             }
             echo $this->wrapMultiColumns($text, $widths) . "\n";
         }
         echo "Key: * = installed, ! = upgrades available\n";
     }
 }
Пример #22
0
 function pyrusRelease($frontend, $args)
 {
     $this->getSCS();
     if (null !== $frontend) {
         $chan = \Pyrus\Config::current()->default_channel;
         \Pyrus\Config::current()->default_channel = $this->channel->name;
         $args['maintainer'] = \Pyrus\Config::current()->handle;
         \Pyrus\Config::current()->default_channel = $chan;
     }
     $this->scs->saveRelease($args['path'], $args['maintainer']);
     echo 'Release successfully saved.' . PHP_EOL;
 }
Пример #23
0
 protected function getMode($mode = null)
 {
     if ($mode === null) {
         return 0777 & ~octdec(\Pyrus\Config::current()->umask);
     }
     return $mode & 0777;
 }
Пример #24
0
 /**
  * Do a package.xml 1.0 replacement, with additional package-info fields available
  *
  * See validateXml() source for the complete list of allowed fields
  * @param \Pyrus\PackageInterface
  * @param resource open file pointer, set to the beginning of the file
  * @param string the eventual final file location (informational only)
  * @return string|false
  */
 function startSession($fp, $dest)
 {
     $contents = stream_get_contents($fp);
     $subst_from = $subst_to = array();
     foreach ($this->_replacements as $a) {
         $a = $a['attribs'];
         $to = '';
         if ($a['type'] == 'pear-config') {
             if ($this->installphase == Common::PACKAGE) {
                 return false;
             }
             $to = \Pyrus\Config::current()->{$a['to']};
             if (is_null($to)) {
                 \Pyrus\Logger::log(0, "{$dest}: invalid pear-config replacement: {$a['to']}");
                 return false;
             }
         } elseif ($a['type'] == 'php-const') {
             if ($this->installphase == Common::PACKAGE) {
                 return false;
             }
             if (defined($a['to'])) {
                 $to = constant($a['to']);
             } else {
                 \Pyrus\Logger::log(0, "{$dest}: invalid php-const replacement: {$a['to']}");
                 return false;
             }
         } else {
             if ($t = $this->pkg->{$a['to']}) {
                 if ($a['to'] == 'version') {
                     $t = $t['release'];
                 }
                 $to = $t;
             } else {
                 \Pyrus\Logger::log(0, "{$dest}: invalid package-info replacement: {$a['to']}");
                 return false;
             }
         }
         if (!is_null($to)) {
             $subst_from[] = $a['from'];
             $subst_to[] = $to;
         }
     }
     \Pyrus\Logger::log(3, "doing " . sizeof($subst_from) . " substitution(s) for {$dest}");
     if (sizeof($subst_from)) {
         $contents = str_replace($subst_from, $subst_to, $contents);
     }
     rewind($fp);
     ftruncate($fp, 0);
     fwrite($fp, $contents);
     return true;
 }
ini_set('display_errors', true);
// Get the autoloader
require __DIR__ . '/../../../autoload.php';
/*
$channel = new Pyrus_SimpleChannelServer('pear2.php.net','/Library/WebServer/Documents/pearserver', null, '/Users/bbieber/pyrus', array('saltybeagle','cellog'));
if (!@unserialize(file_get_contents('/tmp/categories.inf'))) {
      $cat = Pyrus_SimpleChannelServer_Categories::create('Name1',
          'Description 1', 'Alias1')->
          create('Name2', 'Description 2')->
          create('Name3', 'Description 3', 'Alias3')->
          create('Name4', 'Description 4');
      file_put_contents('/tmp/categories.inf', serialize($cat));
}

$categories = Pyrus_SimpleChannelServer_Categories::getCategories();
$categories = $channel->listCategories();
foreach($categories as $category) {
    var_dump($category);
}
*/
$channel = new Pyrus\SimpleChannelServer\Channel('pear2.php.net', 'Brett Bieber\'s PEAR Channel', 'salty');
//$scs = new Pyrus\SimpleChannelServer\Main($channel,'/Library/WebServer/Documents/pearserver','/home/bbieber/pyrus/php');
$scs = new Pyrus\SimpleChannelServer\Main($channel, '/home/cellog/testapache/htdocs', \Pyrus\Config::current()->location);
$categories = Pyrus\SimpleChannelServer\Categories::create('Default', 'This is the default category');
$scs->saveChannel();
$scs->saveRelease(new \Pyrus\Package(dirname(__FILE__) . '/../package.xml'), 'cellog');
echo 'did it' . PHP_EOL;
/*
$manager = new Pyrus\SimpleChannelServer\REST_Manager('/Library/WebServer/Documents/pearserver','pear2.php.net','rest/',array('cellog'));
var_dump($manager->saveRelease(new \Pyrus\Package(dirname(__FILE__) . '/../package.xml'),'cellog'));
*/
Пример #26
0
 static function registerCustomRole($info)
 {
     if (!isset(self::$_roles)) {
         self::registerRoles();
     }
     self::$_roles[$info['name']] = $info;
     $roles = self::$_roles;
     ksort($roles);
     self::$_roles = $roles;
     self::getBaseinstallRoles(true);
     self::getInstallableRoles(true);
     self::getValidRoles('****', true);
     if (isset($info['configvar'])) {
         if (!isset($info['configvar'][0])) {
             $info['configvar'] = array($info['configvar']);
         }
         foreach ($info['configvar'] as $configvar) {
             if ($configvar['configtype'] == 'system' && in_array($configvar['name'], Config::current()->customsystemvars) || $configvar['configtype'] == 'user' && in_array($configvar['name'], Config::current()->customuservars) || $configvar['configtype'] == 'channel' && in_array($configvar['name'], Config::current()->customchannelvars)) {
                 continue;
             }
             $default = $configvar['default'];
             if (false !== strpos($default, '<?php')) {
                 $tmp = Config::current()->temp_dir . DIRECTORY_SEPARATOR . '.configdefault.php';
                 if (!file_exists(dirname($tmp))) {
                     mkdir(dirname($tmp), 0755, true);
                 }
                 if (file_put_contents($tmp, $default) === false) {
                     throw new Role\Exception("Cannot create custom role configuration file {$tmp}");
                 }
                 $getDefault = function () use($tmp) {
                     include $tmp;
                     return $default;
                 };
                 $default = $getDefault();
             }
             Config::addConfigValue($configvar['name'], $default, $configvar['configtype']);
         }
     }
 }
Пример #27
0
 /**
  * Check to see if any packages in the list of packages to be installed
  * satisfy this dependency, and return one if found, otherwise
  * instantiate a new dependency package object
  * @return \Pyrus\PackageInterface|NULL
  */
 function retrieve(\Pyrus\PackageFile\v2\Dependencies\Package $info)
 {
     if (isset(self::$localPackages[$info->channel . '/' . $info->name]) || $this->childProcessed($info->channel . '/' . $info->name)) {
         // we can safely ignore this dependency, an explicit local
         // package is being installed, and we will use it
         // or the dependency has been previously processed, and we will
         // simply result in a duplicate
         return;
     }
     $reg = Config::current()->registry;
     // first check to see if the dependency is installed
     $canupgrade = false;
     if (isset($reg->package[$info->channel . '/' . $info->name])) {
         if (!isset(\Pyrus\Main::$options['upgrade'])) {
             // we don't attempt to upgrade a dep unless we're upgrading
             return;
         }
         $version = $reg->info($info->name, $info->channel, 'version');
         $stability = $reg->info($info->name, $info->channel, 'state');
         if ($this->node->isRemote() && $this->node->getExplicitState()) {
             $installedstability = \Pyrus\Installer::betterStates($stability);
             $parentstability = \Pyrus\Installer::betterStates($this->node->getExplicitState());
             if (count($parentstability) > count($installedstability)) {
                 $stability = $this->node->getExplicitState();
             }
         } else {
             $installedstability = \Pyrus\Installer::betterStates($stability);
             $prefstability = \Pyrus\Installer::betterStates(Config::current()->preferred_state);
             if (count($prefstability) > count($installedstability)) {
                 $stability = Config::current()->preferred_state;
             }
         }
         // see if there are new versions in our stability or better
         if (isset($info->uri)) {
             return;
         }
         $remote = new \Pyrus\Channel\RemotePackage(Config::current()->channelregistry[$info->channel], $stability);
         $found = false;
         foreach ($remote[$info->name] as $remoteversion => $rinfo) {
             if (version_compare($remoteversion, $version, '<=')) {
                 continue;
             }
             if (version_compare($rinfo['minimumphp'], static::getPHPversion(), '>')) {
                 continue;
             }
             // found one, so upgrade is possible if dependencies pass
             $found = true;
             break;
         }
         // the installed package version satisfies this dependency, don't do anything
         if (!$found) {
             return;
         }
         $canupgrade = true;
     }
     if (isset($info->uri)) {
         $ret = new \Pyrus\Package\Remote($info->uri);
         // set up the basics
         $ret->name = $info->name;
         $ret->uri = $info->uri;
         $this->addChild($ret);
         return;
     }
     if ($this->node->isRemote() && $this->node->getExplicitState()) {
         // pass the same explicit state to the child dependency
         $ret = new \Pyrus\Package\Remote($info->channel . '/' . $info->name . '-' . $this->node->getExplicitState());
         if ($canupgrade) {
             $ret->setUpgradeable();
         }
         $this->addChild($ret);
         return;
     }
     $ret = new \Pyrus\Package\Remote($info->channel . '/' . $info->name);
     if ($canupgrade) {
         $ret->setUpgradeable();
     }
     $this->addChild($ret);
     return;
 }
Пример #28
0
 /**
  * Figure out which version is best, and use this, or error out if none work
  * @param \Pyrus\PackageFile\v2\Dependencies\Package $compositeDep
  *        the composite of all dependencies on this package, as calculated
  *        by {@link \Pyrus\Package\Dependency::getCompositeDependency()}
  */
 function figureOutBestVersion(\Pyrus\PackageFile\v2\Dependencies\Package $compositeDep, $versions = null, \Pyrus\PackageFile\v2\Dependencies\Package $compositeConflictingDep = null)
 {
     // set up release list if not done yet
     $this->rewind();
     $ok = \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(\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(\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(\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 = \Pyrus\Main::getParanoiaLevel();
         if (!$this->explicitVersion && $paranoia > 1) {
             // first, we check to see if we are upgrading
             if (isset(\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', false, false, 'text/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');
 }
Пример #29
0
 public function info($package, $channel, $field)
 {
     if (!$this->exists($package, $channel)) {
         throw new Exception('Unknown package ' . $channel . '/' . $package);
     }
     $pf = $this->toPackageFile($package, $channel);
     if ($field === null) {
         return $pf;
     }
     if ($field == 'version') {
         $field = 'release-version';
     }
     if ($field != 'installedfiles' && $field != 'dirtree') {
         return $pf->{$field};
     }
     $packagefile = $this->_namePath($channel, $package) . '.reg';
     if (!$packagefile || !isset($packagefile[0])) {
         throw new Exception('Cannot find registry for package ' . $channel . '/' . $package);
     }
     $packagecontents = file_get_contents($packagefile);
     $data = @unserialize($packagecontents);
     if ($data === false) {
         throw new Exception('Cannot retrieve package file object for package ' . $channel . '/' . $package . ', PEAR 1.x registry file might be corrupt!');
     }
     if ($field == 'dirtree') {
         $ret = $data['filelist']['dirtree'];
         usort($ret, 'strnatcasecmp');
         return array_reverse($ret);
     }
     $configpaths = $roles = array();
     $config = \Pyrus\Config::current();
     foreach (Role::getValidRoles($pf->getPackageType()) as $role) {
         // set up a list of file role => configuration variable
         // for storing in the registry
         $roles[$role] = Role::factory($pf->getPackageType(), $role);
         $configpaths[$role] = $config->{$roles[$role]->getLocationConfig()};
     }
     $ret = array();
     foreach ($data['filelist'] as $file) {
         if (!isset($file['installed_as']) || !isset($configpaths[$file['role']])) {
             continue;
         }
         if (0 !== strpos($file['installed_as'], $configpaths[$file['role']])) {
             // this was installed with a different configuration, so don't guess
             $file['relativepath'] = basename($file['installed_as']);
             $file['configpath'] = dirname($file['installed_as']);
         } else {
             $file['relativepath'] = substr($file['installed_as'], strlen($configpaths[$file['role']]) + 1);
             $file['configpath'] = $configpaths[$file['role']];
         }
         $ret[$file['installed_as']] = $file;
     }
     return $ret;
 }
Пример #30
0
 /**
  * Repair from a previously failed transaction cut off mid-transaction
  */
 public static function repair()
 {
     if (static::inTransaction()) {
         throw new AtomicFileTransaction\RuntimeException('Cannot repair while in a transaction');
     }
     static::$instance = null;
     $config = Config::current();
     $remove = array();
     foreach ($config->systemvars as $var) {
         if (!strpos($var, '_dir')) {
             continue;
         }
         $path = FS::path($config->{$var});
         $backuppath = dirname($path) . DIRECTORY_SEPARATOR . '.old-' . basename($path);
         if (file_exists($backuppath) && is_dir($backuppath)) {
             if (file_exists($path)) {
                 if (!is_dir($path)) {
                     throw new AtomicFileTransaction\RuntimeException('Repair failed - ' . $var . ' path ' . $path . ' is not a directory.  Move this file out of the way and ' . 'try the repair again');
                 }
                 // this is the new stuff from journal path, so move it out of the way
                 $journalpath = dirname($path) . DIRECTORY_SEPARATOR . '.journal-' . basename($path);
                 $remove[] = $journalpath;
                 rename($path, $journalpath);
             }
             // restore backup
             rename($backuppath, $path);
         }
     }
     foreach ($remove as $path) {
         FS::rmrf($path);
     }
 }