PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/build/agavi/script/agavi.php

https://github.com/enixu/agavi-src
PHP | 343 lines | 242 code | 64 blank | 37 comment | 19 complexity | 0aa2e7c0760632fb705f2e09b90be054 MD5 | raw file
  1. #! /usr/bin/env php
  2. <?php
  3. // +---------------------------------------------------------------------------+
  4. // | This file is part of the Agavi package. |
  5. // | Copyright (c) 2005-2010 the Agavi Project. |
  6. // | |
  7. // | For the full copyright and license information, please view the LICENSE |
  8. // | file that was distributed with this source code. You can also view the |
  9. // | LICENSE file online at http://www.agavi.org/LICENSE.txt |
  10. // | vi: set noexpandtab: |
  11. // | Local Variables: |
  12. // | indent-tabs-mode: t |
  13. // | End: |
  14. // +---------------------------------------------------------------------------+
  15. /**
  16. * Command-line script for the build system.
  17. *
  18. * @package agavi
  19. * @subpackage build
  20. *
  21. * @author Noah Fontes <noah.fontes@bitextender.com>
  22. * @copyright Authors
  23. * @copyright The Agavi Project
  24. *
  25. * @since 1.0.0
  26. *
  27. * @version $Id$
  28. */
  29. define('BUILD_DIRECTORY', realpath(dirname(__FILE__) . '/../..'));
  30. define('START_DIRECTORY', getcwd());
  31. define('MIN_PHING_VERSION', '2.4.0');
  32. require('phing/Phing.php');
  33. require(dirname(__FILE__) . '/../build.php');
  34. AgaviBuild::bootstrap();
  35. require(dirname(__FILE__) . '/AgaviOptionParser.class.php');
  36. $GLOBALS['OUTPUT'] = new OutputStream(fopen('php://stdout', 'w'));
  37. $GLOBALS['ERROR'] = new OutputStream(fopen('php://stderr', 'w'));
  38. $GLOBALS['INPUT'] = new InputStream(fopen('php://stdin', 'r'));
  39. /* Initialize Phing. */
  40. try {
  41. Phing::startup();
  42. Phing::setProperty('phing.home', getenv('PHING_HOME'));
  43. try {
  44. if(!version_compare(preg_replace('/^Phing(?:\s*version)?\s*([0-9\.]+)/i', '$1', Phing::getPhingVersion()), MIN_PHING_VERSION, 'ge')) {
  45. $GLOBALS['ERROR']->write(sprintf('Error: Phing version %s or later required', MIN_PHING_VERSION) . PHP_EOL);
  46. exit(1);
  47. }
  48. } catch(Exception $e) {
  49. $GLOBALS['ERROR']->write(sprintf('Error: Phing version could not be determined; Phing %s or later required', MIN_PHING_VERSION) . PHP_EOL);
  50. exit(1);
  51. }
  52. } catch(Exception $e) {
  53. $GLOBALS['ERROR']->write($e->getMessage() . PHP_EOL);
  54. exit(1);
  55. }
  56. $GLOBALS['PROPERTIES'] = array();
  57. $GLOBALS['SHOW_LIST'] = false;
  58. $GLOBALS['VERBOSE'] = false;
  59. $GLOBALS['LOGGER'] = 'phing.listener.AnsiColorLogger';
  60. $GLOBALS['BUILD'] = new PhingFile(BUILD_DIRECTORY . '/build.xml');
  61. /* Define parser callbacks. */
  62. function input_help_display()
  63. {
  64. $GLOBALS['OUTPUT']->write(sprintf('Usage: %s [options] [target...]', basename($_SERVER['argv'][0])) . PHP_EOL);
  65. $GLOBALS['OUTPUT']->write('Options:' . PHP_EOL);
  66. $GLOBALS['OUTPUT']->write(' -h -? --help Displays the help for this utility' . PHP_EOL);
  67. $GLOBALS['OUTPUT']->write(' -v --version Displays relevant version information' . PHP_EOL);
  68. $GLOBALS['OUTPUT']->write(' -l --list --targets Displays the list of available targets' . PHP_EOL);
  69. $GLOBALS['OUTPUT']->write(' -D --define <property> <value> Defines a configuration property' . PHP_EOL);
  70. $GLOBALS['OUTPUT']->write(' --verbose Provides more verbose configuration information' . PHP_EOL);
  71. $GLOBALS['OUTPUT']->write(' --agavi-source-directory <path> Sets the Agavi source directory to <path>' . PHP_EOL);
  72. $GLOBALS['OUTPUT']->write(' --include-path <path> Appends <path> to the PHP include path' . PHP_EOL);
  73. $GLOBALS['OUTPUT']->write(' --logger <class> Sets the configuration logger class to <class>' . PHP_EOL);
  74. }
  75. function input_help(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  76. {
  77. input_help_display();
  78. exit(0);
  79. }
  80. function input_version(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  81. {
  82. $GLOBALS['OUTPUT']->write('Agavi project configuration system, script version $Id$' . PHP_EOL);
  83. $GLOBALS['OUTPUT']->write(Phing::getPhingVersion() . PHP_EOL);
  84. exit(0);
  85. }
  86. function input_list(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  87. {
  88. $GLOBALS['SHOW_LIST'] = true;
  89. }
  90. function input_define(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  91. {
  92. $name = $arguments[0];
  93. $value = $arguments[1];
  94. $GLOBALS['PROPERTIES'][$name] = $value;
  95. }
  96. function input_verbose(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  97. {
  98. $GLOBALS['VERBOSE'] = true;
  99. }
  100. function input_agavi_source_directory(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  101. {
  102. $path = new PhingFile($arguments[0]);
  103. $path = $path->isAbsolute() ? $path : new PhingFile(START_DIRECTORY, (string)$path);
  104. $GLOBALS['PROPERTIES']['agavi.directory.src'] = $path;
  105. }
  106. function input_include_path(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  107. {
  108. $path = new PhingFile($arguments[0]);
  109. $path = $path->isAbsolute() ? $path : new PhingFile(START_DIRECTORY, (string)$path);
  110. set_include_path($path->getAbsolutePath() . PATH_SEPARATOR . get_include_path());
  111. }
  112. function input_logger(AgaviOptionParser $parser, $name, $arguments, $scriptArguments)
  113. {
  114. $logger = $arguments[0];
  115. $GLOBALS['LOGGER'] = $logger;
  116. }
  117. /* Parse incoming arguments. */
  118. $parser = new AgaviOptionParser(array_slice($_SERVER['argv'], 1));
  119. $parser->addOption('help', array('h', '?'), array('help'), 'input_help');
  120. $parser->addOption('version', array('v'), array('version'), 'input_version');
  121. $parser->addOption('list', array('l'), array('list', 'targets'), 'input_list');
  122. $parser->addOption('define', array('D'), array('define'), 'input_define', 2);
  123. $parser->addOption('verbose', array(), array('verbose'), 'input_verbose');
  124. $parser->addOption('agavi_source_directory', array(), array('agavi-source-directory'), 'input_agavi_source_directory', 1);
  125. $parser->addOption('include_path', array(), array('include-path'), 'input_include_path', 1);
  126. $parser->addOption('logger', array(), array('logger'), 'input_logger', 1);
  127. try {
  128. $parser->parse();
  129. } catch(AgaviOptionException $aae) {
  130. $GLOBALS['ERROR']->write('Error: ' . $aae->getMessage() . PHP_EOL);
  131. $GLOBALS['ERROR']->write(PHP_EOL);
  132. input_help_display();
  133. exit(1);
  134. }
  135. $GLOBALS['TARGETS'] = $parser->getPassedArguments();
  136. if(!isset($GLOBALS['PROPERTIES']['agavi.directory.src'])) {
  137. $GLOBALS['PROPERTIES']['agavi.directory.src'] = new PhingFile(realpath(dirname(__FILE__) . '/../../..'));
  138. }
  139. if(!is_dir($GLOBALS['PROPERTIES']['agavi.directory.src']) || !is_file($GLOBALS['PROPERTIES']['agavi.directory.src'] . DIRECTORY_SEPARATOR . 'agavi.php')) {
  140. $GLOBALS['ERROR']->write(sprintf('Error: Agavi source directory expected at %s, but is not present', $GLOBALS['PROPERTIES']['agavi.directory.src']) . PHP_EOL);
  141. $GLOBALS['ERROR']->write(PHP_EOL);
  142. input_help_display();
  143. exit(1);
  144. }
  145. $GLOBALS['PROJECT_DIRECTORY'] = null;
  146. try {
  147. $project = new Project();
  148. $project->setBasedir(BUILD_DIRECTORY);
  149. foreach($GLOBALS['PROPERTIES'] as $name => $value) {
  150. $project->setUserProperty($name, $value);
  151. }
  152. $project->init();
  153. ProjectConfigurator::configureProject($project, new PhingFile(BUILD_DIRECTORY . '/build.xml'));
  154. Phing::setCurrentProject($project);
  155. try {
  156. $project->fireBuildStarted();
  157. $task = $project->createTask('agavi.locate-project');
  158. $task->setProperty('project.directory');
  159. $task->setPath(new PhingFile($project->getProperty('application.startdir')));
  160. $task->setIgnoreIfSet(true);
  161. $task->init();
  162. $task->perform();
  163. if($project->getProperty('project.directory') !== null) {
  164. $task = $project->createTask('agavi.check-project');
  165. $task->setProperty('project.available');
  166. $task->setPath(new PhingFile($project->getProperty('project.directory')));
  167. $task->init();
  168. $task->perform();
  169. } elseif(is_link($_SERVER['argv'][0])) {
  170. /* The script is a symlink. */
  171. $task = $project->createTask('agavi.locate-project');
  172. $task->setProperty('project.directory');
  173. $path = new PhingFile(dirname($_SERVER['argv'][0]));
  174. $path = $path->isAbsolute() ? $path : new PhingFile(START_DIRECTORY, (string)$path);
  175. $task->setPath($path);
  176. $task->setIgnoreIfSet(true);
  177. $task->init();
  178. $task->perform();
  179. if($project->getProperty('project.directory') !== null) {
  180. $task = $project->createTask('agavi.check-project');
  181. $task->setProperty('project.available');
  182. $task->setPath(new PhingFile($project->getProperty('project.directory')));
  183. $task->init();
  184. $task->perform();
  185. }
  186. }
  187. } catch(BuildException $be) {
  188. $project->fireBuildFinished($be);
  189. throw $be;
  190. }
  191. $project->fireBuildFinished(null);
  192. if($project->getProperty('project.available')) {
  193. $GLOBALS['PROJECT_DIRECTORY'] = $project->getProperty('project.directory');
  194. }
  195. } catch(Exception $e) {
  196. /* This failed. Can't figure out project directory. Forget it. */
  197. }
  198. /* Switch to whichever project directory the script determined. */
  199. $GLOBALS['PROPERTIES']['project.directory'] = $GLOBALS['PROJECT_DIRECTORY'];
  200. /* Execute Phing. */
  201. try {
  202. $project = new Project();
  203. // hax for Mac OS X 10.5 Leopard, where "dim" ANSI colors are broken...
  204. if(
  205. PHP_OS == 'Darwin' &&
  206. (
  207. (isset($_SERVER['TERM_PROGRAM']) && $_SERVER['TERM_PROGRAM'] == 'Apple_Terminal') ||
  208. (isset($_ENV['TERM_PROGRAM']) && $_ENV['TERM_PROGRAM'] == 'Apple_Terminal')
  209. ) &&
  210. version_compare(preg_replace('/^ProductVersion:\s*([0-9]+\.[0-9]+)/ms', '$1', shell_exec('sw_vers')), '10.5', 'eq') &&
  211. !Phing::getProperty('phing.logger.defaults')
  212. ) {
  213. Phing::setProperty('phing.logger.defaults', new PhingFile(BUILD_DIRECTORY . '/agavi/phing/ansicolorlogger_osxleopard.properties'));
  214. }
  215. // hax for Windows, which doesn't support ANSI colors at all
  216. elseif(stripos(PHP_OS, 'Win') === 0) {
  217. $GLOBALS['LOGGER'] = 'phing.listener.DefaultLogger';
  218. }
  219. $GLOBALS['LOGGER'] = Phing::import($GLOBALS['LOGGER']);
  220. $logger = new $GLOBALS['LOGGER']();
  221. $logger->setMessageOutputLevel($GLOBALS['VERBOSE'] ? Project::MSG_VERBOSE : Project::MSG_INFO);
  222. $logger->setOutputStream($GLOBALS['OUTPUT']);
  223. $logger->setErrorStream($GLOBALS['ERROR']);
  224. $project->addBuildListener($logger);
  225. $project->setInputHandler(new DefaultInputHandler());
  226. $project->setUserProperty('phing.file', $GLOBALS['BUILD']->getAbsolutePath());
  227. $project->setUserProperty('phing.version', Phing::getPhingVersion());
  228. /* Phing fucks with the cwd. Really, brilliant. */
  229. $project->setUserProperty('application.startdir', START_DIRECTORY);
  230. foreach($GLOBALS['PROPERTIES'] as $name => $value) {
  231. $project->setUserProperty($name, $value);
  232. }
  233. $project->init();
  234. ProjectConfigurator::configureProject($project, $GLOBALS['BUILD']);
  235. Phing::setCurrentProject($project);
  236. if($GLOBALS['SHOW_LIST'] === true) {
  237. input_help_display();
  238. $GLOBALS['OUTPUT']->write(PHP_EOL);
  239. $GLOBALS['OUTPUT']->write('Targets:' . PHP_EOL);
  240. $size = 0;
  241. $targets = array();
  242. foreach($project->getTargets() as $target) {
  243. $name = $target->getName();
  244. $nameSize = strlen($name);
  245. $description = $target->getDescription();
  246. if($description !== null) {
  247. $size = $nameSize > $size ? $nameSize : $size;
  248. $targets[$name] = $description;
  249. }
  250. }
  251. $formatter = ' %-' . $size . 's %s';
  252. foreach($targets as $name => $description) {
  253. $GLOBALS['OUTPUT']->write(sprintf($formatter, $name, $description) . PHP_EOL);
  254. }
  255. $defaultTarget = $project->getDefaultTarget();
  256. if($defaultTarget !== null && $defaultTarget !== '') {
  257. $GLOBALS['OUTPUT']->write(PHP_EOL);
  258. $GLOBALS['OUTPUT']->write('Default target: ' . $defaultTarget . PHP_EOL);
  259. }
  260. exit(0);
  261. }
  262. try {
  263. $project->fireBuildStarted();
  264. $GLOBALS['TARGETS'] = count($GLOBALS['TARGETS']) === 0
  265. ? array($project->getDefaultTarget())
  266. : $GLOBALS['TARGETS'];
  267. $project->executeTargets($GLOBALS['TARGETS']);
  268. } catch(Exception $e) {
  269. $project->fireBuildFinished($e);
  270. throw $e;
  271. }
  272. $project->fireBuildFinished(null);
  273. } catch(Exception $e) {
  274. $GLOBALS['ERROR']->write(PHP_EOL);
  275. $GLOBALS['ERROR']->write(sprintf('%s:%d: %s', $e->getFile(), $e->getLine(), $e->getMessage()) . PHP_EOL);
  276. exit(1);
  277. }
  278. exit(0);
  279. ?>