📄 installer.php
字号:
/** * Add a file operation to the current file transaction. * * @see startFileTransaction() * @var string $type This can be one of: * - rename: rename a file ($data has 2 values) * - chmod: change permissions on a file ($data has 2 values) * - delete: delete a file ($data has 1 value) * - rmdir: delete a directory if empty ($data has 1 value) * - installed_as: mark a file as installed ($data has 4 values). * @var array $data For all file operations, this array must contain the * full path to the file or directory that is being operated on. For * the rename command, the first parameter must be the file to rename, * the second its new name. * * The installed_as operation contains 4 elements in this order: * 1. Filename as listed in the filelist element from package.xml * 2. Full path to the installed file * 3. Full path from the php_dir configuration variable used in this * installation * 4. Relative path from the php_dir that this file is installed in */ function addFileOperation($type, $data) { if (!is_array($data)) { return $this->raiseError('Internal Error: $data in addFileOperation' . ' must be an array, was ' . gettype($data)); } if ($type == 'chmod') { $octmode = decoct($data[0]); $this->log(3, "adding to transaction: $type $octmode $data[1]"); } else { $this->log(3, "adding to transaction: $type " . implode(" ", $data)); } $this->file_operations[] = array($type, $data); } // }}} // {{{ startFileTransaction() function startFileTransaction($rollback_in_case = false) { if (count($this->file_operations) && $rollback_in_case) { $this->rollbackFileTransaction(); } $this->file_operations = array(); } // }}} // {{{ commitFileTransaction() function commitFileTransaction() { $n = count($this->file_operations); $this->log(2, "about to commit $n file operations"); // {{{ first, check permissions and such manually $errors = array(); foreach ($this->file_operations as $tr) { list($type, $data) = $tr; switch ($type) { case 'rename': if (!file_exists($data[0])) { $errors[] = "cannot rename file $data[0], doesn't exist"; } // check that dest dir. is writable if (!is_writable(dirname($data[1]))) { $errors[] = "permission denied ($type): $data[1]"; } break; case 'chmod': // check that file is writable if (!is_writable($data[1])) { $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); } break; case 'delete': if (!file_exists($data[0])) { $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); } // check that directory is writable if (file_exists($data[0]) && !is_writable(dirname($data[0]))) { $errors[] = "permission denied ($type): $data[0]"; } break; } } // }}} $m = sizeof($errors); if ($m > 0) { foreach ($errors as $error) { $this->log(1, $error); } return false; } // {{{ really commit the transaction foreach ($this->file_operations as $tr) { list($type, $data) = $tr; switch ($type) { case 'rename': @unlink($data[1]); @rename($data[0], $data[1]); $this->log(3, "+ mv $data[0] $data[1]"); break; case 'chmod': @chmod($data[1], $data[0]); $octmode = decoct($data[0]); $this->log(3, "+ chmod $octmode $data[1]"); break; case 'delete': @unlink($data[0]); $this->log(3, "+ rm $data[0]"); break; case 'rmdir': @rmdir($data[0]); $this->log(3, "+ rmdir $data[0]"); break; case 'installed_as': $this->pkginfo['filelist'][$data[0]]['installed_as'] = $data[1]; if (!isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { $this->pkginfo['filelist']['dirtree'][dirname($data[1])] = true; while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' && $data[3] != '.') { $this->pkginfo['filelist']['dirtree'] [$this->_prependPath($data[3], $data[2])] = true; $data[3] = dirname($data[3]); } } break; } } // }}} $this->log(2, "successfully committed $n file operations"); $this->file_operations = array(); return true; } // }}} // {{{ rollbackFileTransaction() function rollbackFileTransaction() { $n = count($this->file_operations); $this->log(2, "rolling back $n file operations"); foreach ($this->file_operations as $tr) { list($type, $data) = $tr; switch ($type) { case 'rename': @unlink($data[0]); $this->log(3, "+ rm $data[0]"); break; case 'mkdir': @rmdir($data[0]); $this->log(3, "+ rmdir $data[0]"); break; case 'chmod': break; case 'delete': break; case 'installed_as': if (isset($this->pkginfo['filelist'])) { unset($this->pkginfo['filelist'][$data[0]]['installed_as']); } if (isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { unset($this->pkginfo['filelist']['dirtree'][dirname($data[1])]); while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' && $data[3] != '.') { unset($this->pkginfo['filelist']['dirtree'] [$this->_prependPath($data[3], $data[2])]); $data[3] = dirname($data[3]); } } if (isset($this->pkginfo['filelist']['dirtree']) && !count($this->pkginfo['filelist']['dirtree'])) { unset($this->pkginfo['filelist']['dirtree']); } break; } } $this->file_operations = array(); } // }}} // {{{ mkDirHier($dir) function mkDirHier($dir) { $this->addFileOperation('mkdir', array($dir)); return parent::mkDirHier($dir); } // }}} // {{{ download() /** * Download any files and their dependencies, if necessary * * @param array a mixed list of package names, local files, or package.xml * @param PEAR_Config * @param array options from the command line * @param array this is the array that will be populated with packages to * install. Format of each entry: * * <code> * array('pkg' => 'package_name', 'file' => '/path/to/local/file', * 'info' => array() // parsed package.xml * ); * </code> * @param array this will be populated with any error messages * @param false private recursion variable * @param false private recursion variable * @param false private recursion variable * @deprecated in favor of PEAR_Downloader */ function download($packages, $options, &$config, &$installpackages, &$errors, $installed = false, $willinstall = false, $state = false) { // trickiness: initialize here parent::PEAR_Downloader($this->ui, $options, $config); $ret = parent::download($packages); $errors = $this->getErrorMsgs(); $installpackages = $this->getDownloadedPackages(); trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " . "in favor of PEAR_Downloader class", E_USER_WARNING); return $ret; } // }}} // {{{ install() /** * Installs the files within the package file specified. * * @param string $pkgfile path to the package file * @param array $options * recognized options: * - installroot : optional prefix directory for installation * - force : force installation * - register-only : update registry but don't install files * - upgrade : upgrade existing install * - soft : fail silently * - nodeps : ignore dependency conflicts/missing dependencies * - alldeps : install all dependencies * - onlyreqdeps : install only required dependencies * * @return array|PEAR_Error package info if successful */ function install($pkgfile, $options = array()) { $php_dir = $this->config->get('php_dir'); if (isset($options['installroot'])) { if (substr($options['installroot'], -1) == DIRECTORY_SEPARATOR) { $options['installroot'] = substr($options['installroot'], 0, -1); } $php_dir = $this->_prependPath($php_dir, $options['installroot']); $this->installroot = $options['installroot']; } else { $this->installroot = ''; } $this->registry = &new PEAR_Registry($php_dir); // ==> XXX should be removed later on $flag_old_format = false; if (substr($pkgfile, -4) == '.xml') { $descfile = $pkgfile; } else { // {{{ Decompress pack in tmp dir ------------------------------------- // To allow relative package file names $pkgfile = realpath($pkgfile); if (PEAR::isError($tmpdir = System::mktemp('-d'))) { return $tmpdir; } $this->log(3, '+ tmp dir created at ' . $tmpdir); $tar = new Archive_Tar($pkgfile); if (!@$tar->extract($tmpdir)) { return $this->raiseError("unable to unpack $pkgfile"); } // {{{ Look for existing package file $descfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; if (!is_file($descfile)) { // ----- Look for old package archive format // In this format the package.xml file was inside the // Package-n.n directory $dp = opendir($tmpdir); do { $pkgdir = readdir($dp); } while ($pkgdir{0} == '.'); $descfile = $tmpdir . DIRECTORY_SEPARATOR . $pkgdir . DIRECTORY_SEPARATOR . 'package.xml'; $flag_old_format = true; $this->log(0, "warning : you are using an archive with an old format"); } // }}} // <== XXX This part should be removed later on // }}} } if (!is_file($descfile)) { return $this->raiseError("no package.xml file after extracting the archive"); } // Parse xml file ----------------------------------------------- $pkginfo = $this->infoFromDescriptionFile($descfile); if (PEAR::isError($pkginfo)) { return $pkginfo; } $this->validatePackageInfo($pkginfo, $errors, $warnings); // XXX We allow warnings, do we have to do it? if (count($errors)) { if (empty($options['force'])) { return $this->raiseError("The following errors where found (use force option to install anyway):\n". implode("\n", $errors)); } else { $this->log(0, "warning : the following errors were found:\n". implode("\n", $errors)); } } $pkgname = $pkginfo['package']; // {{{ Check dependencies ------------------------------------------- if (isset($pkginfo['release_deps']) && empty($options['nodeps'])) { $dep_errors = ''; $error = $this->checkDeps($pkginfo, $dep_errors); if ($error == true) { if (empty($options['soft'])) { $this->log(0, substr($dep_errors, 1)); } return $this->raiseError("$pkgname: Dependencies failed"); } else if (!empty($dep_errors)) { // Print optional dependencies if (empty($options['soft'])) { $this->log(0, $dep_errors); } } } // }}} // {{{ checks to do when not in "force" mode if (empty($options['force'])) { $test = $this->registry->checkFileMap($pkginfo); if (sizeof($test)) { $tmp = $test; foreach ($tmp as $file => $pkg) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -