Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial import of development tools.

This first import contains a functional module package builder.
  • Loading branch information...
commit 4b949784d3a70c78d0db902964ac47cbd10f9856 0 parents
@mmakaay mmakaay authored
98 bin/build_phorum_module
@@ -0,0 +1,98 @@
+#!/usr/bin/env php
+<?php
+
+require_once dirname(__FILE__) . '/../lib/Phorum/ModuleBuilder.php';
+
+// ----------------------------------------------------------------------
+// Parse arguments
+// ----------------------------------------------------------------------
+
+$args = array();
+
+$verbose = FALSE;
+$build_dir = "/tmp";
+
+for ($i = 1; $i < $_SERVER['argc']; $i++)
+{
+ $opt = $_SERVER['argv'][$i];
+
+ // Gather non-options.
+ if ($opt[0] != '-') {
+ $args[] = $opt;
+ continue;
+ }
+
+ // Process options.
+ switch ($opt)
+ {
+ case "-h":
+ usage();
+ exit;
+ break;
+
+ case "-v":
+ $verbose = TRUE;
+ break;
+
+ case "-b":
+ if (!isset($_SERVER['argv'][++$i])) {
+ die("Missing value for option -b!\n");
+ }
+ $build_dir = $_SERVER['argv'][$i];
+ break;
+
+ default:
+ die("Unknown option: $opt\n");
+ }
+}
+
+$count = count($args);
+switch ($count)
+{
+ case 0 : $module_dir = getcwd(); break;
+ case 1 : $module_dir = $args[0]; break;
+ default : die("Only one module dir expected, but got $count!\n");
+}
+
+// ----------------------------------------------------------------------
+// Generate the module package
+// ----------------------------------------------------------------------
+
+try
+{
+ $builder = new Phorum_ModuleBuilder($module_dir, $build_dir);
+ if ($verbose) $builder->enableScreenLogger();
+ $output = $builder->build();
+ if (!$verbose) {
+ print "Package archives created:\n";
+ foreach ($output as $file) {
+ print "> $file\n";
+ }
+ }
+}
+catch (Exception $e)
+{
+ die("Error: " . $e->getMessage() . "\n");
+}
+
+// ----------------------------------------------------------------------
+// Utility functions
+// ----------------------------------------------------------------------
+
+function usage()
+{
+ $program = basename($_SERVER['argv'][0]);
+
+ print "\n";
+ print "Usage: $program [OPTIONS] [MODULE DIR]\n";
+ print "\n";
+ print " -h : Show this help.\n";
+ print " -v : Enable verbose output.\n";
+ print " -b <path> : The working directory for building the module\n";
+ print " package. By default, /tmp is used.\n";
+ print "\n";
+ print " MODULE DIR : The path to the Phorum module for which to\n";
+ print " build a distribution package. By default,\n";
+ print " the active working directory is used.\n";
+ print "\n";
+}
109 lib/Phorum/ModuleBuilder.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * This script implements the Phorum_ModuleBuilder class.
+ *
+ * @author Maurice Makaay
+ * @copyright Phorum
+ * @package Phorum
+ * @category DevTools
+ */
+
+require_once dirname(__FILE__) . "/ModuleInfo.php";
+require_once dirname(__FILE__) . "/PackageBuilder.php";
+
+/**
+ * The Phorum_ModuleBuilder class.
+ *
+ * This class provides functionality for packaging a Phorum module
+ * into a format that can be used for distribution.
+ *
+ * @package Phorum
+ */
+class Phorum_ModuleBuilder extends Phorum_PackageBuilder
+{
+ /**
+ * An object that contains information about the Phorum module.
+ *
+ * @var Phorum_ModuleInfo
+ */
+ protected $_module_info;
+
+ /**
+ * Create a new Phorum ModuleBuilder object.
+ *
+ * @param string $path
+ * The path for the directory where the module code is stored (this is
+ * the directory with the info.txt in it).
+ *
+ * @param string $build_dir
+ * The working directory for building the package (default is "/tmp").
+ *
+ * @throws Exception
+ * when illegal parameters are used.
+ */
+ public function __construct($path, $build_dir = "/tmp")
+ {
+ if (!is_dir($path)) throw new Exception(
+ "Illegal module source dir '$path' provided: " .
+ "not a directory"
+ );
+
+ $info_file = realpath("$path/info.txt");
+ if (!file_exists($info_file)) throw new Exception(
+ "Illegal module source dir '$path' provided: " .
+ "no info.txt file found"
+ );
+
+ if (!is_dir($build_dir)) throw new Exception(
+ "Illegal build dir '$build_dir' provided: not a directory"
+ );
+
+ // Initialize a module info object, used for gathering information
+ // about the module. We will use this object at various places during
+ // building the package.
+ $this->_module_info = new Phorum_ModuleInfo();
+ $this->_module_info->load($info_file);
+
+ parent::__construct($this->_module_info->getID(), $path, $build_dir);
+ }
+
+ /**
+ * Retrieve the version of the package.
+ * This version is read from the module info.txt file.
+ *
+ * @return string
+ */
+ protected function _getPackageVersion()
+ {
+ return $this->_module_info->getVersion();
+ }
+
+ /**
+ * Retrieve the directory where the package is built.
+ *
+ * Overridden from Phorum_PackageBuilder to keep out the
+ * version number of the directory. For Phorum modules, it's
+ * easiest to not have the version number included in the
+ * packaged directory.
+ *
+ * @return string
+ */
+ protected function _getBuildPackageDir()
+ {
+ return $this->_build_dir . '/' . $this->_package_name;
+ }
+
+ protected function _substituteTags($data)
+ {
+ $data = str_replace('@TITLE@', $this->_module_info->getTitle(), $data);
+ $data = str_replace('@MODULE_ID@', $this->_module_info->getId(), $data);
+
+ $description = wordwrap(
+ strip_tags($this->_module_info->getDescription()), 72
+ );
+ $data = str_replace('@DESCRIPTION@', $description, $data);
+
+ return parent::_substituteTags($data);
+ }
+}
+
382 lib/Phorum/ModuleInfo.php
@@ -0,0 +1,382 @@
+<?php
+/**
+ * This script implements the Phorum_ModuleInfo class.
+ *
+ * @author Maurice Makaay
+ * @copyright Phorum
+ * @package Phorum
+ * @category DevTools
+ */
+
+/**
+ * The Phorum_PackageBuilder class.
+ *
+ * This class provides functionality for packaging an application
+ * into a format that can be used for distribution.
+ *
+ * @package Phorum
+ */
+class Phorum_ModuleInfo
+{
+ /**
+ * The id for the module. This determines the directory in which
+ * the module will be stored (phorumdir/mods/<id>) and the
+ * name of the PHP script that implements the module
+ * (phorumdir/mods/<id>/<id>.php).
+ *
+ * @var string
+ */
+ protected $_id;
+
+ /**
+ * The title of the module (info.txt "title" field).
+ *
+ * @var string
+ */
+ protected $_title;
+
+ /**
+ * A description of the module (info.txt "desc" field).
+ *
+ * @var string
+ */
+ protected $_description;
+
+ /**
+ * The author of the module (info.txt "author" field).
+ *
+ * @var string
+ */
+ protected $_author;
+
+ /**
+ * The URL for the module project (info.txt "url" field).
+ *
+ * @var string
+ */
+ protected $_url;
+
+ /**
+ * The version of the module (info.txt "version" field).
+ *
+ * @var string
+ */
+ protected $_version;
+
+ /**
+ * The required version of Phorum for the module
+ * (info.txt "required_version" field).
+ *
+ * @var string
+ */
+ protected $_required_version;
+
+ /**
+ * The categories for the module (info.txt "category" fields).
+ *
+ * @var array
+ */
+ protected $_categories;
+
+ /**
+ * The hooks for the module (info.txt "hook" fields).
+ *
+ * @var array
+ */
+ protected $_hooks;
+
+ /**
+ * The compatibility hooks for the module (info.txt "compat" fields).
+ *
+ * @var array
+ */
+ protected $_compat;
+
+ /**
+ * The priorities for the module (info.txt "priority" fields).
+ *
+ * @var array
+ */
+ protected $_priorities;
+
+ /**
+ * The version of the dblayer for the module (info.txt "dbversion" field).
+ *
+ * @var string
+ */
+ protected $_dbversion;
+
+ /**
+ * Create a new Phorum ModuleInfo object.
+ */
+ public function __construct()
+ {
+ ini_set('track_errors', TRUE);
+
+ $this->reset();
+ }
+
+ /**
+ * Reset all module information data.
+ */
+ public function reset()
+ {
+ $this->_id = NULL;
+ $this->_title = NULL;
+ $this->_description = NULL;
+ $this->_version = NULL;
+ $this->_required_version = NULL;
+ $this->_dbversion = NULL;
+ $this->_categories = array();
+ $this->_hooks = array();
+ $this->_compat = array();
+ $this->_priorities = array(
+ "hook" => array(),
+ "module" => array()
+ );
+ }
+
+ /**
+ * Load module info from a module's info.txt file.
+ *
+ * @param string $info_file
+ * The path for a module's info.txt file.
+ */
+ public function load($info_file)
+ {
+ $fp = @fopen($info_file, "r");
+ if ($fp === FALSE) throw new Exception(
+ "Cannot read module info: $php_errormsg"
+ );
+
+ $line_nr = 0;
+ while (!feof($fp))
+ {
+ $line = fgets($fp);
+ $line_nr ++;
+
+ if (trim($line) == '' || preg_match('/^\s*#/', $line)) {
+ continue;
+ }
+ elseif (preg_match('/^(\w+)\s*:\s*(.*?)\s*$/', $line, $m))
+ {
+ $directive = strtolower($m[1]);
+ $value = $m[2];
+
+ $where = "at line $line_nr of $info_file";
+
+ switch ($directive)
+ {
+ case "id":
+ $this->_id = $value;
+ break;
+
+ case "title":
+ $this->_title = $value;
+ break;
+
+ case "desc":
+ $this->_description = $value;
+ break;
+
+ case "author":
+ $this->_author = $value;
+ break;
+
+ case "url":
+ $this->_url = $value;
+ break;
+
+ case "version":
+ $this->_version = $value;
+ break;
+
+ case "require_version":
+ case "required_version":
+ $this->required_version = $value;
+ break;
+
+ case "category":
+ $categories = preg_split('/\s*,\s*/', $value);
+ foreach ($categories as $category) {
+ $this->_categories[$category] = $category;
+ }
+ break;
+
+ case "priority":
+ if (preg_match('/^run\s+hook\s+(.+)\s+(before|after)\s(.+)$/i', $value, $m)) {
+ $this->_priorities['hook'][$m[1]][] = $m;
+ } elseif (preg_match('/^run\s+module\s+(before|after)\s(.+)$/i', $value, $m)) {
+ $this->_priorities['module'][] = $m;
+ } else {
+ throw new Exception(
+ "Invalid $directive $where: " .
+ "cannot parse priority '$value'"
+ );
+ }
+
+ break;
+
+ case "hook":
+ case "compat":
+ if ($directive == 'hook') {
+ $store =& $this->_hooks;
+ } else {
+ $store =& $this->_compat;
+ }
+ if (preg_match('/^(\w+)\|(.*)$/', $value, $m))
+ {
+ if (trim($m[2]) == '' &&
+ ($directive != 'hook' || $m[1] != 'lang')) {
+ throw new Exception(
+ "Invalid $directive directive $where: " .
+ "missing value after the '|' character"
+ );
+ }
+ if (isset($store[$m[1]])) throw new Exception(
+ "Duplicate $directive directive '$m[1]' $where"
+ );
+ $store[$m[1]] = $m[2];
+ }
+ else throw new Exception(
+ "Illegal value for $directive directive $where"
+ );
+ break;
+
+ case "dbversion":
+ if (!preg_match('/^\d{8}$/', $value)) throw new Exception(
+ "Invalid $directive directive $where: " .
+ "expected 8 numbers (format YYYYMMDDXX)"
+ );
+ $this->_dbversion = $value;
+ break;
+
+ default:
+ throw new Exception(
+ "Unknown directive '$directive' $where"
+ );
+ break;
+ }
+ }
+ else
+ {
+ throw new Exception(
+ "Cannot parse line $line_nr of $info_file: $line"
+ );
+ }
+ }
+
+ fclose($fp);
+
+ // Determine the directory in which the info.txt is stored.
+ $parent_dir = dirname(realpath($info_file));
+
+ // If no id is provided in the info.txt, then try to derive the id.
+ if (trim($this->_id) == '')
+ {
+ // The id is assumed to match this directory (this matches the
+ // normal directory layout for modules when installed in the
+ // Phorum tree: phorumdir/mods/<id>).
+ $id = basename($parent_dir);
+
+ // Allow a directory format like "Module-<id>" (this is the format
+ // that we use for the repositories on github). We strip the
+ // directory name down to <id> alone.
+ $id = preg_replace('/^.*-/', '', $id);
+
+ // Check if the id is likely to be the module id.
+ if (!preg_match('/^\w+$/', $id)) throw new Exception(
+ "Cannot autodetect the module id: based on the directory " .
+ "where info.txt is stored, we guessed '$id', but that " .
+ "module id does not match the required format (letters, " .
+ "numbers, underscores). Either rename the directory or " .
+ "provide the 'id' directive in the module's info.txt."
+ );
+ if (!file_exists("$parent_dir/$id.php")) throw new Exception(
+ "Cannot autodetect the module id: based on the directory " .
+ "where info.txt is stored, we guessed '$id', but the " .
+ "expected module script '$parent_dir/$id.php' does not exist." .
+ "Either rename the directory, create the module script or " .
+ "provide the 'id' directive in the module's info.txt."
+ );
+
+ $this->_id = $id;
+ }
+ else
+ {
+ $id = $this->_id;
+ if (!file_exists("$parent_dir/$id.php")) throw new Exception(
+ "Based on the module id '$id' from info.txt, the module " .
+ "script '$parent_dir/$id.php' is expected, however it does " .
+ "not exist. Either rename the directory, create the module " .
+ "script or provide the correct 'id' directive in the " .
+ "module's info.txt."
+ );
+ }
+
+ $this->validate();
+ }
+
+ /**
+ * Validate the module data.
+ *
+ * @throws Exception
+ * when the module data is invalid.
+ */
+ public function validate()
+ {
+ }
+
+ /**
+ * Retrieve the module id.
+ *
+ * @return string
+ */
+ public function getID()
+ {
+ if (trim($this->_id) == '') throw new Exception(
+ "No id is set for the module."
+ );
+ return $this->_id;
+ }
+
+ /**
+ * Retrieve the module version.
+ *
+ * @return string
+ */
+ public function getVersion()
+ {
+ if (trim($this->_version) == '') throw new Exception(
+ "No version is set for the module."
+ );
+ return $this->_version;
+ }
+
+ /**
+ * Retrieve the module title.
+ *
+ * @return string
+ */
+ public function getTitle()
+ {
+ if (trim($this->_title) == '') throw new Exception(
+ "No title is set for the module."
+ );
+ return $this->_title;
+ }
+
+ /**
+ * Retrieve the module description.
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ if (trim($this->_description) == '') throw new Exception(
+ "No description is set for the module."
+ );
+ return $this->_description;
+ }
+}
+
577 lib/Phorum/PackageBuilder.php
@@ -0,0 +1,577 @@
+<?php
+/**
+ * This script implements the Phorum_PackageBuilder class.
+ *
+ * @author Maurice Makaay
+ * @copyright Phorum
+ * @package Phorum
+ * @category DevTools
+ */
+
+define('PHORUM_ZIP_ARCHIVE', 1);
+define('PHORUM_TARGZ_ARCHIVE', 2);
+
+/**
+ * The Phorum_PackageBuilder class.
+ *
+ * This class provides base functionality for packaging an application
+ * into formats that can be used for distribution. This is an abstract
+ * class. Dedicated build classes are derived from this class.
+ *
+ * @package Phorum
+ */
+abstract class Phorum_PackageBuilder
+{
+ /**
+ * The name of the package to build.
+ *
+ * @var string
+ */
+ protected $_package_name;
+
+ /**
+ * The directory where the sources for the package to build are located.
+ *
+ * @var string
+ */
+ protected $_package_dir;
+
+ /**
+ * The working directory for building the package.
+ *
+ * @var string
+ */
+ protected $_build_dir;
+
+ /**
+ * The version of the package to build.
+ * This property is filled by the getPackageVersion() method.
+ *
+ * @var string
+ */
+ protected $_version = NULL;
+
+ /**
+ * A callback that can be used for logging packaging operations.
+ *
+ * @var callback
+ */
+ protected $_log_callback = NULL;
+
+ /**
+ * A list of files to exclude from the package.
+ * Files to exclude can be added to this list using the
+ * registerExclude() method.
+ *
+ * @var array
+ */
+ protected $_exclude_files = array();
+
+ /**
+ * A list of directories to exclude from the package.
+ * Directories to exclude can be added to this list using the
+ * registerExclude() method.
+ *
+ * @var array
+ */
+ protected $_exclude_dirs = array();
+
+ /**
+ * Create a new Phorum PackageBuilder object.
+ *
+ * @param string $package_name
+ * The name for the package. This name is used in the resulting
+ * package file (<package_name>-<version>.tar.gz).
+ *
+ * @param string $package_dir
+ * The directory where the sources for the package to build are located.
+ *
+ * @param string $build_dir
+ * The working directory for building the package (default is "/tmp").
+ *
+ * @throws Exception
+ * when illegal parameters are used.
+ */
+ public function __construct(
+ $package_name,
+ $package_dir,
+ $build_dir = "/tmp")
+ {
+ $this->_package_name = $package_name;
+ $this->_package_dir = realpath($package_dir);
+ $this->_build_dir = realpath($build_dir);
+
+ // The build dir cannot be below the package dir. It would
+ // result in an endless file copying loop.
+ $check = substr($this->_build_dir, 0, strlen($this->_package_dir));
+ if ($check == $this->_package_dir) {
+ throw new Exception(
+ "The module build dir cannot be at or below the " .
+ "package source dir."
+ );
+ }
+
+ if (!preg_match('/^[\w\-]+$/', $this->_package_name)) {
+ throw new Exception(
+ "Illegal format used for package_name '$this->_package_name' " .
+ "(expected only letters, numbers, underscores and minus signs)"
+ );
+ }
+
+ if (!is_dir($this->_package_dir)) throw new Exception(
+ "Illegal package source dir '$package_dir' provided: not a directory"
+ );
+
+ if (!is_dir($this->_build_dir)) throw new Exception(
+ "Illegal build dir '$this->_build_dir' provided: not a directory"
+ );
+
+ $this->_getPackageVersion();
+
+ // Register some globally skipped files and directories.
+ $this->registerExclude('.svn');
+ $this->registerExclude('.git');
+
+ ini_set('track_errors', TRUE);
+ }
+
+ /**
+ * Setup the built-in screen logger as logging output.
+ */
+ public function enableScreenLogger()
+ {
+ $this->setLogger(array('Phorum_PackageBuilder', 'screenLogger'));
+ }
+
+ /**
+ * Set a callback for logging purposes.
+ * The callback will be called with information about the
+ * packaging process.
+ *
+ * @param callable $callback
+ */
+ public function setLogger($callback)
+ {
+ if (!is_callable($callback)) throw new Exception(
+ "The callback must be a callable object."
+ );
+ $this->_log_callback = $callback;
+ }
+
+ /**
+ * A logger that can be used for the setLogger() method, which outputs
+ * the log messages to the screen.
+ *
+ * @param string $message
+ * @param integer $level
+ */
+ static public function screenLogger($message, $level)
+ {
+ if ($level) {
+ print str_repeat(" ", 2 * ($level - 1));
+ print "> ";
+ }
+
+ print "$message\n";
+ }
+
+ /**
+ * Register one or more files to exclude from the package.
+ *
+ * It is possible to feed this method multiple files at once by
+ * using multiple arguments or an array argument.
+ *
+ * @param string $file
+ * The relative path (below the package source directory) of the
+ * file to exclude.
+ */
+ public function registerExclude()
+ {
+ $args = func_get_args();
+ foreach ($args as $arg)
+ {
+ if (is_array($arg)) {
+ foreach ($arg as $subarg) {
+ $this->_registerExclude($subarg);
+ }
+ } else {
+ $this->_registerExclude($arg);
+ }
+ }
+ }
+
+ protected function _registerExclude($path)
+ {
+ $full = "$this->_package_dir/$path";
+
+ // If the exclude file does not exist, then we won't have to do
+ // any further handling. The file will not be in the resulting
+ // package anyway.
+ if (!file_exists($full)) return;
+
+ // Check if the excluded path is below the package source dir.
+ $full = realpath($full);
+ $a = substr($full, 0, strlen($this->_package_dir));
+ $b = $this->_package_dir;
+ if ($a !== $b) {
+ throw new Exception(
+ "Exclude path '$path' is not below the package source dir."
+ );
+ }
+
+ $exclude = '.' . substr($full, strlen($this->_package_dir));
+
+ if (is_dir($full)) {
+ $this->_exclude_dirs[$exclude] = TRUE;
+ } else {
+ $this->_exclude_files[$exclude] = TRUE;
+ }
+ }
+
+ /**
+ * Build the distribution package in the build directory.
+ *
+ * @return array
+ * An array of paths to the built packages (zip and tar.gz).
+ *
+ * @throws Exception
+ * in case building fails for some reason.
+ */
+ public function build()
+ {
+ $package_id = $this->_getPackageId();
+ $this->_log("");
+ $this->_log("Building package $package_id");
+
+ $this->_initializeBuildPackageDir();
+
+ $this->_copyPackageFiles();
+
+ $this->_updateDocumentationFiles();
+
+ $output = array();
+ $output[] = $this->_createPackageArchive(PHORUM_ZIP_ARCHIVE);
+ $output[] = $this->_createPackageArchive(PHORUM_TARGZ_ARCHIVE);
+
+ $this->_cleanupBuildPackageDir();
+
+ $this->_log("");
+ $this->_log("Package archives created:");
+ foreach ($output as $file) {
+ $this->_log($file, 1);
+ }
+ $this->_log("");
+
+ return $output;
+ }
+
+ /**
+ * Write a log message.
+ *
+ * @param string $message
+ * The message to log.
+ *
+ * @param integer $level
+ * The level for the message. This can be used to indicate
+ * sub, sub-sub, etc. messages. A logger can use this to
+ * display the log information hierarchically.
+ * Level 0 (the default) indicates a top-level message.
+ */
+ protected function _log($message, $level = 0)
+ {
+ if ($this->_log_callback !== NULL) {
+ $cb = $this->_log_callback;
+ call_user_func($cb, $message, $level);
+ }
+ }
+
+ /**
+ * Retrieve the version of the package.
+ *
+ * @return string
+ */
+ abstract protected function _getPackageVersion();
+
+ /**
+ * Retrieve the directory where the package is built.
+ *
+ * @return string
+ */
+ protected function _getBuildPackageDir()
+ {
+ $package_id = $this->_getPackageId();
+ return $this->_build_dir . '/' . $package_id;
+ }
+
+ /**
+ * Retrieve the package ID, which is a combination of the package
+ * name and the package version.
+ *
+ * @return string
+ */
+ protected function _getPackageId()
+ {
+ return $this->_package_name . '-' . $this->_getPackageVersion();
+ }
+
+ /**
+ * Retrieve the file name of the package archive to create.
+ *
+ * @param integer $type
+ * One of PHORUM_ZIP_ARCHIVE or PHORUM_TARGZ_ARCHIVE
+ * @return string
+ */
+ protected function _getOutputArchive($type)
+ {
+ $package_id = $this->_getPackageId();
+ $output = "$this->_build_dir/{$package_id}";
+
+ switch ($type) {
+ case PHORUM_ZIP_ARCHIVE : $output .= '.zip'; break;
+ case PHORUM_TARGZ_ARCHIVE : $output .= '.tar.gz'; break;
+ default: throw new Exception("Unknown archive type: $type");
+ }
+
+ return $output;
+ }
+
+ protected function _initializeBuildPackageDir()
+ {
+ $build_package_dir = $this->_getBuildPackageDir();
+ $this->_log("Initializing build dir: $build_package_dir ...", 1);
+
+ $this->_rmtree($build_package_dir);
+
+ if (!@mkdir($build_package_dir, 0750)) throw new Exception(
+ "Unable to create build directory: $php_errormsg"
+ );
+
+ // Match the file permissions for the target directory with those
+ // of the source directory.
+ $perms = fileperms($this->_package_dir) & 511;
+ if (!@chmod($build_package_dir, $perms)) {
+ throw new Exception($php_errormsg);
+ }
+ }
+
+ protected function _copyPackageFiles()
+ {
+ $build_package_dir = $this->_getBuildPackageDir();
+ $this->_log("Copying package files to the build dir ...", 1);
+
+ $cur_dir = getcwd();
+ if ($cur_dir === FALSE) throw new Exception(
+ "Unable to determine the current working directory."
+ );
+
+ try
+ {
+ if (!@chdir($this->_package_dir)) throw new Exception(
+ "Unable to access the package sources directory: " .
+ $php_errormsg
+ );
+
+ $files = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator(
+ '.', FilesystemIterator::SKIP_DOTS
+ ),
+ RecursiveIteratorIterator::SELF_FIRST
+ );
+
+ foreach ($files as $file)
+ {
+ $file = $file->getPathname();
+
+ // Skip files that are related to subversion.
+ if (preg_match('!/\.svn[$/]?!', $file)) {
+ continue;
+ }
+
+ if (isset($this->_exclude_files[$file])) {
+ $this->_log("Skipped excluded file: $file", 2);
+ continue;
+ }
+
+ foreach ($this->_exclude_dirs as $dir => $dummy)
+ {
+ // Skip directory.
+ if ($file == $dir) {
+ $this->_log("Skipped excluded directory: $file", 2);
+ continue 2;
+ }
+
+ // Skip files below the skipped directory.
+ if (substr($file, 0, strlen($dir) + 1) == "$dir/") {
+ continue 2;
+ }
+ }
+
+ // Copy the file to the target build directory.
+ if (is_dir($file)) {
+ if (!@mkdir("$build_package_dir/$file")) {
+ throw new Exception($php_errormsg);
+ }
+ } else {
+ if (!@copy($file, "$build_package_dir/$file")) {
+ throw new Exception($php_errormsg);
+ }
+ }
+
+ // Match the file permissions for the copied file with those
+ // of the source file.
+ $perms = fileperms($file) & 511;
+ if (!@chmod("$build_package_dir/$file", $perms)) {
+ throw new Exception($php_errormsg);
+ }
+ }
+ }
+ catch (Exception $e)
+ {
+ chdir($cur_dir);
+ throw $e;
+ }
+ }
+
+ protected function _updateDocumentationFiles()
+ {
+ $build_package_dir = $this->_getBuildPackageDir();
+
+ foreach (array(
+ 'README',
+ 'INSTALL',
+ 'UPGRADE',
+ 'COPYING',
+ 'AUTHORS',
+ 'info.txt',
+ 'ChangeLog',
+ 'Changelog',
+ 'NEWS') as $doc_file)
+ {
+ $file = "$build_package_dir/$doc_file";
+ if (file_exists($file))
+ {
+ $data = $orig_data = @file_get_contents($file);
+ if ($data === FALSE) throw new Exception(
+ "Unable to read $doc_file: $php_errormsg"
+ );
+
+ $data = $this->_substituteTags($data);
+
+ if ($data !== $orig_data) {
+ if (!@file_put_contents($file, $data)) {
+ throw new Exception(
+ "Unable to write $doc_file: $php_errormsg"
+ );
+ }
+ $this->_log("Updated $doc_file", 2);
+ }
+ }
+ }
+ }
+
+ protected function _substituteTags($data)
+ {
+ $data = str_replace('@VERSION@', $this->_getPackageVersion(), $data);
+ $data = str_replace('@PACKAGE@', $this->_getPackageId(), $data);
+
+ return $data;
+ }
+
+ /**
+ * Create a packaged archive.
+ *
+ * @param integer $type
+ * One of PHORUM_ZIP_ARCHIVE or PHORUM_TARGZ_ARCHIVE
+ *
+ * @return string
+ * The filename of the created archive.
+ */
+ protected function _createPackageArchive($type)
+ {
+ $output = $this->_getOutputArchive($type);
+ $build_pkg_dir = $this->_getBuildPackageDir();
+ $build_dir = dirname($build_pkg_dir);
+ $pkg_dir = basename($build_pkg_dir);
+
+ $this->_log("Creating the package archive ...", 1);
+
+ if (file_exists($output)) {
+ if (!@unlink($output)) throw new Exception($php_errormsg);
+ }
+
+ $path = getenv("PATH");
+ putenv("PATH=/bin:/usr/bin");
+ switch ($type)
+ {
+ case PHORUM_TARGZ_ARCHIVE:
+ system("tar -C $build_dir -zcf $output $pkg_dir", $exit);
+ if ($exit != 0) throw new Exception(
+ "The tar program exited with a non-zero exit code."
+ );
+ break;
+
+ case PHORUM_ZIP_ARCHIVE:
+ system("cd $build_dir; zip -qr $output $pkg_dir", $exit);
+ if ($exit != 0) throw new Exception(
+ "The zip program exited with a non-zero exit code."
+ );
+ break;
+
+ default:
+ throw new Exception("Unknown archive type: $type");
+ break;
+ }
+ putenv("PATH=$path");
+
+ return $output;
+ }
+
+ protected function _cleanupBuildPackageDir()
+ {
+ $build_package_dir = $this->_getBuildPackageDir();
+ $this->_log("Cleaning up build dir ...", 1);
+
+ $this->_rmtree($build_package_dir);
+ }
+
+ /**
+ * Delete a directory tree recursively.
+ *
+ * @param string $path
+ * The path for the directory to delete.
+ */
+ protected function _rmtree($path)
+ {
+ if (!is_dir($path)) return;
+
+ $files = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator(
+ $path,
+ FilesystemIterator::SKIP_DOTS
+ ),
+ RecursiveIteratorIterator::CHILD_FIRST
+ );
+
+ foreach ($files as $file)
+ {
+ if (is_dir($file)) {
+ if (!@rmdir($file)) throw new Exception(
+ "Unable to delete directory: " .
+ $php_errormsg
+ );
+ }
+ else {
+ if (!@unlink($file)) throw new Exception(
+ "Unable to delete file: " .
+ $php_errormsg
+ );
+ }
+ }
+
+ if (!@rmdir($path)) throw new Exception(
+ "Unable to delete directory: " .
+ $php_errormsg
+ );
+ }
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.