mirror of
https://github.com/php/php-src.git
synced 2024-11-25 02:44:58 +08:00
e07220ad03
(not yet in production)
308 lines
11 KiB
PHP
308 lines
11 KiB
PHP
<?php
|
|
//
|
|
// +----------------------------------------------------------------------+
|
|
// | PHP Version 4 |
|
|
// +----------------------------------------------------------------------+
|
|
// | Copyright (c) 1997-2003 The PHP Group |
|
|
// +----------------------------------------------------------------------+
|
|
// | This source file is subject to version 3.0 of the PHP license, |
|
|
// | that is bundled with this package in the file LICENSE, and is |
|
|
// | available through the world-wide-web at the following url: |
|
|
// | http://www.php.net/license/3_0.txt. |
|
|
// | If you did not receive a copy of the PHP license and are unable to |
|
|
// | obtain it through the world-wide-web, please send a note to |
|
|
// | license@php.net so we can mail you a copy immediately. |
|
|
// +----------------------------------------------------------------------+
|
|
// | Authors: Tomas V.V.Cox <cox@idecnet.com> |
|
|
// | |
|
|
// +----------------------------------------------------------------------+
|
|
//
|
|
// $Id$
|
|
|
|
/**
|
|
Experimental dependencies database handling functions (not yet in production)
|
|
|
|
<?php
|
|
include './DependencyDB.php';
|
|
PEAR::setErrorHandling(PEAR_ERROR_DIE);
|
|
$dep = PEAR_DependencyDB::singleton('./test.deps', '/home/cox/www/include/pear');
|
|
//$dep->rebuildDB();
|
|
$a = $dep->checkAction('uninstall', 'net_socket');
|
|
print_r($a);
|
|
?>
|
|
|
|
**/
|
|
|
|
require_once 'PEAR.php';
|
|
require_once 'PEAR/Registry.php';
|
|
require_once 'PEAR/Dependency.php';
|
|
|
|
class PEAR_DependencyDB extends PEAR
|
|
{
|
|
var $pear_reg = false;
|
|
var $pear_dep = false;
|
|
var $depdb_file = false;
|
|
var $lockfile = false;
|
|
var $lock_fp = false;
|
|
var $depdb_version = '1.0';
|
|
|
|
function &singleton($depdb_file, $reg_file)
|
|
{
|
|
$obj = new PEAR_DependencyDB;
|
|
$reg = &new PEAR_Registry($reg_file);
|
|
$obj->pear_reg = $reg;
|
|
$obj->lockfile = $reg->lockfile;
|
|
$obj->pear_dep = new PEAR_Dependency($reg);
|
|
$obj->depdb_file = $depdb_file;
|
|
$obj->assertDepsDB();
|
|
return $obj;
|
|
}
|
|
|
|
function assertDepsDB()
|
|
{
|
|
if (!is_file($this->depdb_file)) {
|
|
$this->rebuildDB();
|
|
} else {
|
|
$depdb = $this->_getDepDB();
|
|
// Datatype format has been changed, rebuild the Deps DB
|
|
if ($depdb['depdb_version'] != $this->depdb_version) {
|
|
$this->rebuildDB();
|
|
}
|
|
}
|
|
}
|
|
|
|
function _lock($mode = LOCK_EX)
|
|
{
|
|
if (!eregi('Windows 9', php_uname())) {
|
|
if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
|
|
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
|
|
return true;
|
|
}
|
|
$open_mode = 'w';
|
|
// XXX People reported problems with LOCK_SH and 'w'
|
|
if ($mode === LOCK_SH) {
|
|
if (@!is_file($this->lockfile)) {
|
|
touch($this->lockfile);
|
|
}
|
|
$open_mode = 'r';
|
|
}
|
|
|
|
$this->lock_fp = @fopen($this->lockfile, $open_mode);
|
|
|
|
if (!is_resource($this->lock_fp)) {
|
|
return $this->raiseError("could not create lock file" .
|
|
(isset($php_errormsg) ? ": " . $php_errormsg : ""));
|
|
}
|
|
if (!(int)flock($this->lock_fp, $mode)) {
|
|
switch ($mode) {
|
|
case LOCK_SH: $str = 'shared'; break;
|
|
case LOCK_EX: $str = 'exclusive'; break;
|
|
case LOCK_UN: $str = 'unlock'; break;
|
|
default: $str = 'unknown'; break;
|
|
}
|
|
return $this->raiseError("could not acquire $str lock ($this->lockfile)");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// }}}
|
|
// {{{ _unlock()
|
|
|
|
function _unlock()
|
|
{
|
|
$ret = $this->_lock(LOCK_UN);
|
|
$this->lock_fp = null;
|
|
return $ret;
|
|
}
|
|
|
|
// {{{ rebuildDepsFile()
|
|
|
|
function rebuildDB()
|
|
{
|
|
$depdb = array('depdb_version' => $this->depdb_version);
|
|
$packages = $this->pear_reg->listPackages();
|
|
foreach ($packages as $package) {
|
|
$deps = $this->pear_reg->packageInfo($package, 'release_deps');
|
|
$this->setPackageDep($depdb, $package, $deps);
|
|
}
|
|
print_r($depdb);
|
|
$error = $this->_writeDepDB($depdb);
|
|
if (PEAR::isError($error)) {
|
|
return $error;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function &_getDepDB()
|
|
{
|
|
if (!$fp = fopen($this->depdb_file, 'r')) {
|
|
return $this->raiseError("Could not open dependencies file `".$this->depdb_file."'");
|
|
}
|
|
$data = fread($fp, filesize($this->depdb_file));
|
|
fclose($fp);
|
|
return unserialize($data);
|
|
}
|
|
|
|
function _writeDepDB(&$deps)
|
|
{
|
|
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
|
|
return $e;
|
|
}
|
|
if (!$fp = fopen($this->depdb_file, 'wb')) {
|
|
$this->_unlock();
|
|
return $this->raiseError("Could not open dependencies file `".$this->depfile."' for writting");
|
|
}
|
|
fwrite($fp, serialize($deps));
|
|
fclose($fp);
|
|
$this->_unlock();
|
|
return true;
|
|
}
|
|
/*
|
|
function removePackageDep($package)
|
|
{
|
|
$data = &$this->_depGetDepDB();
|
|
if (PEAR::isError($data)) {
|
|
return $data;
|
|
}
|
|
// Other packages depends on this package, can't be removed
|
|
if (isset($data['deps'][$package])) {
|
|
return $data['deps'][$package];
|
|
}
|
|
// The package depends on others, remove those dependencies
|
|
if (isset($data['pkgs'][$package])) {
|
|
foreach ($data['pkgs'][$package] as $pkg => $key) {
|
|
// remove the dependency
|
|
unset($data['deps'][$pkg][$key]);
|
|
// if no more dependencies, remove the subject too
|
|
if (!count($data['deps'][$pkg])) {
|
|
unset($data['deps'][$pkg]);
|
|
}
|
|
}
|
|
// remove the package from the index list
|
|
unset($data['pkgs'][$package]);
|
|
}
|
|
return $this->_depWriteDepDB();
|
|
}
|
|
*/
|
|
|
|
function checkAction($action, $package, $new_version = null)
|
|
{
|
|
$depdb = &$this->_getDepDB();
|
|
if (PEAR::isError($depdb)) {
|
|
return $depdb;
|
|
}
|
|
$fails = '';
|
|
switch($action) {
|
|
case 'uninstall':
|
|
// Other packages depends on this package, can't be removed
|
|
if (isset($depdb['deps'][$package])) {
|
|
foreach ($depdb['deps'][$package] as $dep) {
|
|
$fails .= "Package '" . $dep['depend'] . "' depends on '$package'\n";
|
|
}
|
|
return $fails;
|
|
}
|
|
return true;
|
|
case 'install':
|
|
case 'upgrade':
|
|
// Other packages depend on this package, check deps. Ex:
|
|
// <dep type='pkg' rel='lt' version='1.0'>Foo</dep> and we are trying to
|
|
// update Foo to version 2.0
|
|
if (isset($depdb['deps'][$package])) {
|
|
foreach ($depdb['deps'][$package] as $dep) {
|
|
$relation = $dep['rel'];
|
|
if ($relation == 'not') {
|
|
$fails .= "Package '" . $dep['depend'] . "' conflicts with '$package'\n";
|
|
} elseif ($relation != 'has' && $new_version !== null) {
|
|
if (!version_compare("$new_version", "{$dep['version']}", $relation)) {
|
|
$fails .= "Package '" . $dep['depend'] . "' requires ".
|
|
"$package " . $this->pear_dep->signOperator($relation) .
|
|
" " . $dep['version'];
|
|
}
|
|
}
|
|
}
|
|
if (isset($fails)) {
|
|
return $fails;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function commitAction($action, $package)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* Update or insert a the dependencies of a package, prechecking
|
|
* that the package won't break any dependency in the process
|
|
|
|
The data structure is as follows:
|
|
$dep_db = array(
|
|
// Other packages depends on this packages
|
|
'deps' => array(
|
|
'Package Name' => array(
|
|
0 => array(
|
|
// This package depends on 'Package Name'
|
|
'depend' => 'Package',
|
|
// Which version 'Package' needs of 'Package Name'
|
|
'version' => '1.0',
|
|
// The requirement (version_compare() operator)
|
|
'rel' => 'ge'
|
|
),
|
|
),
|
|
)
|
|
// This packages are dependant on other packages
|
|
'pkgs' => array(
|
|
'Package Dependant' => array(
|
|
// This is a index list with paths over the 'deps' array for quick
|
|
// searching things like "what dependecies has this package?"
|
|
// $dep_db['deps']['Package Name'][3]
|
|
'Package Name' => 3 // key in array ['deps']['Package Name']
|
|
),
|
|
)
|
|
)
|
|
|
|
Note: It only supports package dependencies no other type
|
|
*/
|
|
|
|
function setPackageDep(&$data, $package, $rel_deps = array())
|
|
{
|
|
// This package has no dependencies
|
|
if (!is_array($rel_deps) || !count($rel_deps)) {
|
|
return true;
|
|
}
|
|
|
|
// The package depends on others, register that
|
|
foreach ($rel_deps as $dep) {
|
|
// We only support deps of type 'pkg's
|
|
if ($dep && $dep['type'] == 'pkg' && isset($dep['name'])) {
|
|
$dep_name = strtolower($dep['name']);
|
|
$write = array('depend' => $package,
|
|
'rel' => $dep['rel']);
|
|
if ($dep['rel'] != 'has') {
|
|
$write['version'] = $dep['version'];
|
|
}
|
|
settype($data['deps'][$dep_name], 'array');
|
|
|
|
// The dependency already exists, update it
|
|
if (isset($data['pkgs'][$package][$dep_name])) {
|
|
$key = $data['pkgs'][$package][$dep_name];
|
|
$data['deps'][$dep_name][$key] = $write;
|
|
|
|
// New dependency, insert it
|
|
} else {
|
|
$data['deps'][$dep_name][] = $write;
|
|
$key = key($data['deps'][$dep_name]);
|
|
settype($data['pkgs'][$package], 'array');
|
|
$data['pkgs'][$package][$dep_name] = $key;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
// }}}
|
|
}
|
|
?>
|