PageRenderTime 33ms CodeModel.GetById 15ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/pear/XincPEARPackageTask.php

http://xinc.googlecode.com/
PHP | 431 lines | 237 code | 48 blank | 146 comment | 7 complexity | 15f5884391f00adda5287f49663ac04d MD5 | raw file
  1<?php
  2/**
  3 * Xinc - Continuous Integration.
  4 * Pear Package Task taken from phing http://phing.info
  5 *
  6 * PHP version 5
  7 *
  8 * @category Development
  9 * @package  Xinc
 10 * @author   Arno Schneider <username@example.org>
 11 * @author   Hans Lellelid <hans@xmpl.org>
 12 * @author   Alexander Opitz <opitz.alexander@gmail.com>
 13 * @license  http://www.gnu.org/copyleft/lgpl.html GNU/LGPL, see license.php
 14 *           This file is part of Xinc.
 15 *           Xinc is free software; you can redistribute it and/or modify
 16 *           it under the terms of the GNU Lesser General Public License as
 17 *           published by the Free Software Foundation; either version 2.1 of
 18 *           the License, or (at your option) any later version.
 19 *
 20 *           Xinc is distributed in the hope that it will be useful,
 21 *           but WITHOUT ANY WARRANTY; without even the implied warranty of
 22 *           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 23 *           GNU Lesser General Public License for more details.
 24 *
 25 *           You should have received a copy of the GNU Lesser General Public
 26 *           License along with Xinc, write to the Free Software Foundation,
 27 *           Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 28 * @link     http://code.google.com/p/xinc
 29 */
 30
 31require_once 'phing/tasks/ext/pearpackage/Fileset.php';
 32require_once 'PEAR.php';
 33require_once 'PEAR/Frontend.php';
 34require_once 'PEAR/Task/Postinstallscript/rw.php';
 35
 36/**
 37 * The package task.
 38 *
 39 * @category Development
 40 * @package  Xinc
 41 * @author   Arno Schneider <username@example.org>
 42 * @author   Hans Lellelid <hans@xmpl.org>
 43 * @author   Alexander Opitz <opitz.alexander@gmail.com>
 44 * @license  http://www.gnu.org/copyleft/lgpl.html GNU/LGPL, see license.php
 45 * @link     http://code.google.com/p/xinc
 46 */
 47class XincPEARPackageTask extends MatchingTask
 48{
 49    /** @var PhingFile Base directory for reading files. */
 50    private $dir;
 51
 52    /** @var string Versionnumber for this build. */
 53    private $version;
 54
 55    /** @var string Version state for this build. */
 56    private $state = 'beta';
 57
 58    /** @var string . */
 59    private $notes;
 60
 61    /** @var array of FileSet. */
 62    private $arFilesets = array();
 63
 64    /** @var PhingFile Package file */
 65    private $packageFile;
 66
 67    public function init()
 68    {
 69        $ret = @include_once 'PEAR/PackageFileManager2.php';
 70        if (false === $ret) {
 71            throw new BuildException(
 72                'You must have installed PEAR_PackageFileManager2'
 73                . 'in order to create a PEAR package.xml file.'
 74            );
 75        }
 76    }
 77
 78    /**
 79     * Main entry point.
 80     *
 81     * @return void
 82     * @throws BuildException
 83     */
 84     public function main()
 85     {
 86        $this->checkPreConditions();
 87
 88        // @var PEAR_PackageFileManager2
 89        $package = new PEAR_PackageFileManager2();
 90
 91        $package->setOptions($this->getOptions());
 92
 93        // the hard-coded stuff
 94        $package->setPackage('Xinc');
 95        $package->setSummary('Xinc - Continuous Integration Server');
 96        $package->setDescription(
 97            'Xinc is a continuous integration server written in PHP 5.'
 98            . ' It has built-in support for Subversion and Phing (and therefore'
 99            . ' PHPUnit), and can be easily extended to work with alternative'
100            . ' version control or build tools.'
101        );
102        $package->setChannel('pear.elektrischeslicht.de');
103        $package->setPackageType('php');
104
105        $package->setReleaseVersion($this->version);
106        $package->setAPIVersion($this->version);
107
108        $package->setReleaseStability($this->state);
109        $package->setAPIStability($this->state);
110
111        $package->setNotes($this->notes);
112
113        $package->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html');
114
115        // Add package maintainers
116        $package->addMaintainer('lead', 'arnoschn', 'Arno Schneider', 'arnoschn@gmail.com');
117        $package->addMaintainer('lead', 'opi', 'Alexander Opitz', 'opitz.alexander@gmail.com');
118        $package->addMaintainer('lead', 'gavinleefoster', 'Gavin Foster', 'gavinleefoster@gmail.com', 'no');
119
120        // (wow ... this is a poor design ...)
121        //
122        // note that the order of the method calls below is creating
123        // sub-"release" sections which have specific rules.  This replaces
124        // the platformexceptions system in the older version of PEAR's package.xml
125        //
126        // Programmatically, I feel the need to re-iterate that this API for PEAR_PackageFileManager
127        // seems really wrong.  Sub-sections should be encapsulated in objects instead of having
128        // a "flat" API that does not represent the structure being created....
129
130        $this->addSubsectionWindows($package);
131        $this->addSubsectionOthers($package);
132
133        // "core" dependencies
134        $package->setPhpDep('5.2.7');
135        $package->setPearinstallerDep('1.4.0');
136
137        // "package" dependencies
138        $package->addExtensionDep('required', 'xsl');
139        $package->addExtensionDep('required', 'xml');
140        $package->addPackageDepWithChannel('required', 'phing', 'pear.phing.info', '2.4.0');
141        $package->addPackageDepWithChannel('required', 'Base', 'components.ez.no', '1.4.1');
142        $package->addPackageDepWithChannel('required', 'Graph', 'components.ez.no', '1.2.1');
143        $package->addPackageDepWithChannel('optional', 'VersionControl_SVN', 'pear.php.net', '0.5.0');
144        $package->addPackageDepWithChannel('optional', 'VersionControl_Git', 'pear.php.net', '0.4.4');
145        $package->addPackageDepWithChannel('optional', 'Mail', 'pear.php.net', '1.2.0');
146        $package->addPackageDepWithChannel('optional', 'PHPUnit', 'pear.phpunit.de', '3.5.0');
147        $package->addPackageDepWithChannel('optional', 'PhpDocumentor', 'pear.php.net', '1.4.0');
148        $package->addPackageDepWithChannel('optional', 'PHP_CodeSniffer', 'pear.php.net', '1.3.0');
149        $package->addPackageDepWithChannel('optional', 'Xdebug', 'pecl.php.net', '2.0.0');
150        $package->addPackageDepWithChannel('optional', 'Archive_Tar', 'pear.php.net', '1.3.0');
151        $package->addPackageDepWithChannel('optional', 'PEAR_PackageFileManager2', 'pear.php.net', '1.0.2');
152
153        // now add the replacements ....
154        $package->addReplacement('bin/xinc.bat', 'pear-config', '@PHP_BIN@', 'php_bin');
155        $package->addReplacement('bin/xinc-settings.bat', 'pear-config', '@PHP_BIN@', 'php_bin');
156        $package->addReplacement('bin/xinc-settings.bat', 'pear-config', '@BIN_DIR@', 'bin_dir');
157        $package->addReplacement('Xinc.php', 'package-info', '@VERSION@', 'version');
158        $package->addReplacement('xinc.ini.tpl', 'package-info', '@VERSION@', 'version');
159        $package->addReplacement('bin/xinc.bat', 'pear-config', '@BIN_DIR@', 'bin_dir');
160        $package->addReplacement('scripts/xinc-uninstall', 'pear-config', '@PHP_BIN@', 'php_bin');
161        $package->addReplacement('scripts/xinc-uninstall.bat', 'pear-config', '@PHP_BIN@', 'php_bin');
162        $package->addReplacement('scripts/xinc-uninstall', 'pear-config', '@BIN_DIR@', 'bin_dir');
163        $package->addReplacement('scripts/xinc-uninstall.bat', 'pear-config', '@BIN_DIR@', 'bin_dir');
164        $package->addReplacement('etc/init.d/xinc.bat', 'pear-config', '@BIN_DIR@', 'bin_dir');
165        $package->addReplacement('etc/init.d/xinc', 'pear-config', '@BIN_DIR@', 'bin_dir');
166        $package->addReplacement('bin/xinc', 'pear-config', '@PHP_BIN@', 'php_bin');
167        $package->addReplacement('bin/xinc-settings', 'pear-config', '@PHP_BIN@', 'php_bin');
168        $package->addReplacement('bin/xinc-builds', 'pear-config', '@PHP_BIN@', 'php_bin');
169        $package->addReplacement('Xinc/scripts/pear-install.sh', 'pear-config', '@data-dir@','data_dir');
170
171        $config = PEAR_Config::singleton();
172        $log = PEAR_Frontend::singleton();
173        $task = new PEAR_Task_Postinstallscript_rw(
174            $package, $config, $log,
175            array('name' => 'Xinc/Postinstall/Nix.php', 'role' => 'php')
176        );
177        $task->addParamGroup(
178            'daemoninstall',
179            array(
180                $task->getParam('etc_dir', 'Directory to keep the Xinc config files', 'string', '/etc/xinc'),
181                $task->getParam('xinc_dir', 'Directory to keep the Xinc Projects and Status information', 'string', '/var/xinc'),
182                $task->getParam('log_dir', 'Directory to keep the Xinc log files', 'string', '/var/log'),
183                $task->getParam('initd_dir', 'Directory to install the Xinc start/stop daemon', 'string', '/etc/init.d'),
184                $task->getParam('tmp_dir', 'Directory for xinc`s temporary files', 'string', '/tmp/xinc'),
185                $task->getParam('install_examples', 'Do you want to install the SimpleProject example', 'string', 'yes'),
186                $task->getParam('www_dir', 'Directory to install the Xinc web-application', 'string', '/var/www/xinc'),
187                $task->getParam('www_ip', 'IP of Xinc web-application', 'string', '127.0.0.1'),
188                $task->getParam('www_port', 'Port of Xinc web-application', 'string', '8080'),
189            )
190        );
191        $package->addPostinstallTask($task, 'Xinc/Postinstall/Nix.php');
192
193        $taskWin = new PEAR_Task_Postinstallscript_rw(
194            $package, $config, $log,
195            array('name' => 'Xinc/Postinstall/Win.php', 'role' => 'php')
196        );
197        $taskWin->addParamGroup(
198            'daemoninstall',
199            array(
200                $taskWin->getParam('etc_dir', 'Directory to keep the Xinc config files', 'string', 'C:\\xinc\\etc'),
201                $taskWin->getParam('xinc_dir', 'Directory to keep the Xinc Projects and Status information', 'string', 'C:\\xinc'),
202                $taskWin->getParam('log_dir', 'Directory to keep the Xinc log files', 'string', 'C:\\xinc\\log'),
203                $taskWin->getParam('initd_dir', 'Directory to install the Xinc start/stop script', 'string', 'C:\\xinc\\init.d'),
204                $taskWin->getParam('tmp_dir', 'Directory for xinc`s temporary files', 'string', 'C:\\xinc\\temp'),
205                $taskWin->getParam('install_examples', 'Do you want to install the SimpleProject example', 'string', 'yes'),
206                $taskWin->getParam('www_dir', 'Directory to install the Xinc web-application', 'string', 'C:\\xinc\\www'),
207                $taskWin->getParam('www_ip', 'IP of Xinc web-application', 'string', '127.0.0.1'),
208                $taskWin->getParam('www_port', 'Port of Xinc web-application', 'string', '8080'),
209            )
210        );
211        $package->addPostinstallTask($taskWin, 'Xinc/Postinstall/Win.php');
212
213        // now we run this weird generateContents() method that apparently
214        // is necessary before we can add replacements ... ?
215        $package->generateContents();
216
217        $e = $package->writePackageFile();
218
219        if (PEAR::isError($e)) {
220            throw new BuildException(
221                'Unable to write package file.',
222                new Exception($e->getMessage())
223            );
224        }
225    }
226
227    /**
228     * Checks if needed parts are available. If not it throws an exception.
229     *
230     * @return void
231     * @throws BuildException
232     */
233    private function checkPreConditions()
234    {
235        if (empty($this->arFilesets)) {
236            throw new BuildException(
237                'You must use a <fileset> tag to specify the files'
238                . 'to include in the package.xml'
239            );
240        }
241
242        if ($this->dir === null) {
243            throw new BuildException(
244                'You must specify the "dir" attribute for PEAR package task.'
245            );
246        }
247
248        if ($this->version === null) {
249            throw new BuildException(
250                'You must specify the "version" attribute for PEAR package task.'
251            );
252        }
253    }
254
255    /**
256     * Sets the options in the package manager
257     *
258     * @return array Option array for package manager.
259     */
260    private function getOptions()
261    {
262        $arOptions = array(
263            'baseinstalldir' => '/',
264            'packagedirectory' => $this->dir->getAbsolutePath(),
265            'filelistgenerator' => 'Fileset',
266            'dir_roles' => array(
267                'bin'       => 'script',
268                'templates' => 'data',
269                'examples'  => 'data',
270                'resources' => 'data',
271                'etc'       => 'data',
272                'scripts'   => 'data',
273                'web'       => 'data',
274                'tests'     => 'test',
275            ),
276            // options needed by phing Fileset reader
277            'phing_project' => $this->getProject(),
278            'phing_filesets' => $this->arFilesets,
279        );
280
281        if ($this->packageFile !== null) {
282            // create one w/ full path
283            $f = new PhingFile($this->packageFile->getAbsolutePath());
284            $arOptions['packagefile'] = $f->getName();
285            // must end in trailing slash
286            $arOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
287            $this->log("Creating package file: " . $f->getPath(), PROJECT_MSG_INFO);
288        } else {
289            $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO);
290        }
291
292        return $arOptions;
293    }
294
295    /**
296     * Adds Windows release to the package manager
297     *
298     * @param PEAR_PackageFileManager2 $package The package manager.
299     *
300     * @return void
301     */
302    private function addSubsectionWindows(PEAR_PackageFileManager2 $package)
303    {
304        // windows release
305        $package->addRelease();
306        $package->setOSInstallCondition('windows');
307
308        $package->addInstallAs('bin/xinc.bat', 'xinc.bat');
309        $package->addInstallAs('bin/xinc.php', 'xinc.php');
310        $package->addInstallAs('bin/xinc-settings.bat', 'xinc-settings.bat');
311        $package->addInstallAs('bin/xinc-settings.php', 'xinc-settings.php');
312
313        $package->addIgnoreToRelease('Xinc/Postinstall/Nix.php');
314        $package->addIgnoreToRelease('bin/xinc');
315        $package->addIgnoreToRelease('bin/xinc-settings');
316        $package->addIgnoreToRelease('scripts/xinc-uninstall');
317        $package->addIgnoreToRelease('bin/xinc-builds');
318        $package->addIgnoreToRelease('etc/init.d/xinc');
319    }
320
321
322    /**
323     * Adds Others release to the package manager
324     *
325     * @param PEAR_PackageFileManager2 $package The package manager.
326     *
327     * @return void
328     */
329    private function addSubsectionOthers(PEAR_PackageFileManager2 $package)
330    {
331        // Linux release
332        $package->addRelease();
333
334        $package->addInstallAs('bin/xinc', 'xinc');
335        $package->addInstallAs('bin/xinc-settings', 'xinc-settings');
336        $package->addInstallAs('bin/xinc-builds', 'xinc-builds');
337
338        $package->addIgnoreToRelease('Xinc/Postinstall/Win.php');
339        $package->addIgnoreToRelease('bin/xinc.bat');
340        $package->addIgnoreToRelease('bin/xinc.php');
341        $package->addIgnoreToRelease('etc/init.d/xinc.bat');
342        $package->addIgnoreToRelease('scripts/winserv.exe');
343        $package->addIgnoreToRelease('scripts/xinc-uninstall.bat');
344    }
345
346    /**
347     * Used by the PEAR_PackageFileManager_FileSet lister.
348     *
349     * @return array FileSet[]
350     */
351    public function getFileSets()
352    {
353        return $this->arFilesets;
354    }
355
356    // -------------------------------
357    // Set properties from XML
358    // -------------------------------
359
360    /**
361     * Nested creator, creates a FileSet for this task
362     *
363     * @return FileSet The created fileset object
364     */
365    function createFileSet()
366    {
367        $fileset = new FileSet();
368        array_push($this->arFilesets, $fileset);
369        return $fileset;
370    }
371
372    /**
373     * Set the version we are building.
374     *
375     * @param string $v
376     *
377     * @return void
378     */
379    public function setVersion($v)
380    {
381        $this->version = $v;
382    }
383
384    /**
385     * Set the state we are building.
386     *
387     * @param string $v
388     *
389     * @return void
390     */
391    public function setState($v)
392    {
393        $this->state = $v;
394    }
395
396    /**
397     * Sets release notes field.
398     *
399     * @param string $v
400     *
401     * @return void
402     */
403    public function setNotes($v)
404    {
405        $this->notes = $v;
406    }
407
408    /**
409     * Sets "dir" property from XML.
410     *
411     * @param PhingFile $f
412     *
413     * @return void
414     */
415    public function setDir(PhingFile $f)
416    {
417        $this->dir = $f;
418    }
419
420    /**
421     * Sets the file to use for generated package.xml
422     *
423     * @param PhingFile $f
424     *
425     * @return void
426     */
427    public function setDestFile(PhingFile $f)
428    {
429        $this->packageFile = $f;
430    }
431}