PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/build/install.php

https://bitbucket.org/ndj/piecrust
PHP | 412 lines | 384 code | 23 blank | 5 comment | 17 complexity | d1ea118a94bce195a9e558b79a149383 MD5 | raw file
  1. #!/usr/bin/env php
  2. <?php
  3. install($argv);
  4. class CheckEnvironmentResult
  5. {
  6. public $errors;
  7. public function __construct()
  8. {
  9. $this->errors = array();
  10. }
  11. public function hasError($key)
  12. {
  13. return in_array($key, $this->errors);
  14. }
  15. public function isOk()
  16. {
  17. return (count($this->errors) == 0);
  18. }
  19. public function getExitCode()
  20. {
  21. return $this->isOk() ? 0 : 1;
  22. }
  23. }
  24. class Logger
  25. {
  26. public function __construct()
  27. {
  28. $this->hasColors = (DIRECTORY_SEPARATOR != '\\' || (getenv('ANSICON') !== false));
  29. $this->colorFormats = array(
  30. 'success' => "\033[0;32m%s\033[0m",
  31. 'error' => "\033[31;31m%s\033[0m",
  32. 'warning' => "\033[33;33m%s\033[0m"
  33. );
  34. }
  35. public function log($level, $message)
  36. {
  37. $messageFormat = "%s";
  38. if ($this->hasColors && isset($this->colorFormats[$level]))
  39. $messageFormat = $this->colorFormats[$level];
  40. printf($messageFormat, $message);
  41. printf(PHP_EOL);
  42. }
  43. public function error($message)
  44. {
  45. $this->log('error', $message);
  46. }
  47. public function success($message)
  48. {
  49. $this->log('success', $message);
  50. }
  51. public function warning($message)
  52. {
  53. $this->log('warning', $message);
  54. }
  55. public function info($message)
  56. {
  57. $this->log('info', $message);
  58. }
  59. }
  60. function install($argv)
  61. {
  62. $checkOnly = false;
  63. $helpOnly = false;
  64. $quiet = false;
  65. $installDir = getcwd();
  66. $version = 'stable';
  67. $skipNextArg = false;
  68. foreach ($argv as $i => $arg)
  69. {
  70. if ($skipNextArg)
  71. {
  72. $skipNextArg = false;
  73. continue;
  74. }
  75. if ($arg == '--check')
  76. {
  77. $checkOnly = true;
  78. }
  79. elseif ($arg == '--quiet')
  80. {
  81. $quiet = true;
  82. }
  83. elseif ($arg == '--help' or $arg == '-h')
  84. {
  85. $helpOnly = true;
  86. }
  87. elseif ($arg == '--install-dir')
  88. {
  89. $skipNextArg = true;
  90. $installDir = trim($argv[$i + 1]);
  91. }
  92. elseif ($arg == '--version')
  93. {
  94. $skipNextArg = true;
  95. $version = trim($argv[$i + 1]);
  96. if ($version == 'master')
  97. $version = 'default';
  98. }
  99. }
  100. if ($helpOnly)
  101. {
  102. showHelp();
  103. exit(0);
  104. }
  105. $checkResult = checkEnvironment($installDir);
  106. reportProblems($checkResult, ($checkOnly && !$quiet));
  107. if ($checkOnly || !$checkResult->isOk())
  108. {
  109. exit($checkResult->getExitCode());
  110. }
  111. $exitCode = installPieCrust($version, $installDir, $quiet);
  112. exit($exitCode);
  113. }
  114. function showHelp()
  115. {
  116. echo <<<EOF
  117. PieCrust Installer
  118. Usage: install.php <options>
  119. Options:
  120. --help
  121. Show this help.
  122. --check
  123. Only check the environment.
  124. --install-dir PATH
  125. Where to install PieCrust.
  126. (defaults to current directory)
  127. --version VERSION
  128. The version to install.
  129. Can be:
  130. - 'stable': the head of the stable branch.
  131. - 'master': the head of the dev branch.
  132. - 'default': same as 'master'.
  133. - 'x.y.z': a version number (e.g. 0.9.1)
  134. (defaults to 'stable')
  135. EOF;
  136. }
  137. function checkEnvironment($installDir)
  138. {
  139. $result = new CheckEnvironmentResult();
  140. if (version_compare(PHP_VERSION, '5.3.15', '<'))
  141. {
  142. $result->errors[] = 'php_version';
  143. }
  144. if (!extension_loaded('Phar'))
  145. {
  146. $result->errors[] = 'phar';
  147. }
  148. if (!extension_loaded('sockets'))
  149. {
  150. $result->errors[] = 'sockets';
  151. }
  152. return $result;
  153. }
  154. function reportProblems($result, $reportOk = false)
  155. {
  156. $logger = new Logger();
  157. if ($result->hasError('php_version'))
  158. {
  159. $logger->error("Your PHP is too old. You need version 5.3.15 or higher.");
  160. }
  161. if ($result->hasError('phar'))
  162. {
  163. $logger->error("The phar extension is missing.");
  164. $logger->error(" - install it or recompile PHP without `--disable-phar`.");
  165. }
  166. if ($result->hasError('sockets'))
  167. {
  168. $logger->error("The sockets extension is missing.");
  169. if (DIRECTORY_SEPARATOR == '\\')
  170. {
  171. $logger->error(" - open your `php.ini` configuration file and enable it with:\n".
  172. " extension=php_sockets.dll\n".
  173. " this line most likely exists, but is commented with a `;`.");
  174. $logger->error(" otherwise, install the extension, or recompile PHP with `--enable-sockets`.");
  175. }
  176. else
  177. {
  178. $logger->error(" - install it or recompile PHP with `--enable-sockets`.");
  179. }
  180. }
  181. if ($result->isOk() and $reportOk)
  182. {
  183. $logger->success("PieCrust is compatible with your environment.");
  184. }
  185. }
  186. function installPieCrust($version, $installDir, $quiet)
  187. {
  188. $logger = new Logger();
  189. // Figure out the destination file.
  190. if (!is_dir($installDir) || !is_writable($installDir))
  191. {
  192. $logger->error("Can't install in: {$installDir}\n".
  193. "Directory doesn't exist or is not writable.");
  194. return 1;
  195. }
  196. $installDir = rtrim($installDir, '/\\') . DIRECTORY_SEPARATOR;
  197. $destination = $installDir . 'piecrust.phar';
  198. // Remove existing destination.
  199. if (is_readable($destination))
  200. {
  201. if (!$quiet)
  202. $logger->warning("Removing existing file: {$destination}");
  203. @unlink($destination);
  204. }
  205. // Download Phar file from the server.
  206. $source = 'http://backend.bolt80.com/piecrust/'.$version.'/piecrust.phar';
  207. $streamContextOptions = array('http' => array());
  208. $streamContext = stream_context_create($streamContextOptions);
  209. if (!$quiet)
  210. $logger->info("Downloading from: {$source}");
  211. $data = file_get_contents($source, false, $streamContext);
  212. if ($data === false)
  213. {
  214. $logger->error("Could not download file from: {$source}");
  215. return 3;
  216. }
  217. $destFd = fopen($destination, 'w');
  218. if ($destFd === false)
  219. {
  220. $logger->error("Could not create destination file: {$destination}");
  221. return 2;
  222. }
  223. if (fwrite($destFd, $data) === false)
  224. {
  225. $logger->error("Could not write data to destination file: {$destination}");
  226. fclose($destFd);
  227. return 3;
  228. }
  229. fclose($destFd);
  230. // Test the Phar file.
  231. try
  232. {
  233. $archive = new Phar($destination);
  234. unset($archive);
  235. }
  236. catch (Exception $e)
  237. {
  238. $logger->error("Could not open downloaded file: {$destination}");
  239. $logger->error(" - {$e->getMessage()}");
  240. $logger->error(" - the downloaded file is most likely corrupted, please try again.");
  241. @unlink($destination);
  242. return 4;
  243. }
  244. // Make it an executable.
  245. chmod($destination, 0755);
  246. // Create a `chef` bootstrap script.
  247. if (DIRECTORY_SEPARATOR == '\\')
  248. {
  249. $chefPath = $installDir . 'chef.cmd';
  250. if (file_put_contents($chefPath, getChefBootstrapWindows()) === false)
  251. {
  252. $logger->error("Could not create the bootstrap script at: {$chefPath}");
  253. return 5;
  254. }
  255. }
  256. else
  257. {
  258. $chefPath = $installDir . 'chef';
  259. if (file_put_contents($chefPath, getChefBootstrapUnix()) === false)
  260. {
  261. $logger->error("Could not create the bootstrap script at: {$chefPath}");
  262. return 5;
  263. }
  264. }
  265. // Done!
  266. if (!$quiet)
  267. {
  268. $logger->success("PieCrust was successfully installed at: {$destination}");
  269. if (isset($chefPath))
  270. {
  271. $logger->success("You can run `{$chefPath}` now.");
  272. }
  273. else
  274. {
  275. $logger->success("You can run `php {$destination}` now.");
  276. }
  277. }
  278. }
  279. // W A R N I N G
  280. // -------------
  281. //
  282. // Below is slightly modified code from the `bin` scripts.
  283. // Any changes in those scripts should be ported here.
  284. function getChefBootstrapUnix()
  285. {
  286. return <<<'EOD'
  287. #!/bin/sh
  288. POSSIBLES="/usr/bin/php-5.3 /usr/local/bin/php-5.3 /usr/bin/php /usr/local/bin/php"
  289. for CUR in $POSSIBLES; do
  290. if [ -x $CUR ]; then
  291. PHP=$CUR
  292. break
  293. fi
  294. done
  295. if [ -z "$PHP" ]; then
  296. echo "Couldn't find PHP in any of the known locations."
  297. exit 1
  298. fi
  299. CHEF_DIR=`dirname $0`
  300. if `hash readlink 2>&-`; then
  301. LINKED_EXE=`readlink $0`
  302. if [ -n "$LINKED_EXE" ]; then
  303. CHEF_DIR=`dirname $LINKED_EXE`
  304. fi
  305. fi
  306. $PHP $CHEF_DIR/piecrust.phar $@
  307. EOD;
  308. }
  309. function getChefBootstrapWindows()
  310. {
  311. return <<<'EOD'
  312. @echo off
  313. setlocal
  314. :: First see if there's a pre-defined PHP executable path.
  315. if defined PHPEXE goto RunChef
  316. :: Then see if the PHP executable is in the PATH.
  317. for %%i in (php.exe) do (
  318. if not "%%~dp$PATH:i"=="" (
  319. set PHPEXE="%%~dp$PATH:i\php.exe"
  320. goto RunChef
  321. )
  322. )
  323. :: Ok, let's look for a standard PHP install.
  324. if defined PHPRC (
  325. set PHPEXE="%PHPRC%php.exe"
  326. goto RunChef
  327. )
  328. :: Or maybe a PEAR install?
  329. if defined PHP_PEAR_BIN_DIR (
  330. set PHPEXE="%PHP_PEAR_BIN_DIR%\php.exe"
  331. goto RunChef
  332. )
  333. :: Or maybe a XAMPP install? (on 32 and 64 bits Windows)
  334. FOR /F "tokens=3" %%G IN ('"reg query HKLM\SOFTWARE\xampp /v Install_Dir 2> nul"') DO (
  335. set PHPEXE="%%G\php\php.exe"
  336. goto RunChef
  337. )
  338. FOR /F "tokens=3" %%G IN ('"reg query HKLM\SOFTWARE\Wow6432Node\xampp /v Install_Dir 2> nul"') DO (
  339. set PHPEXE="%%G\php\php.exe"
  340. goto RunChef
  341. )
  342. :: Nope. Can't find it.
  343. echo.
  344. echo.Can't find the PHP executable. Is it installed somewhere?
  345. echo.
  346. echo.* If you're using a portable version, please define a PHPEXE environment
  347. echo. variable pointing to it.
  348. echo.* If you're using EsayPHP, add the EasyPHP's PHP sub-directory to your
  349. echo. PATH environment variable.
  350. echo.
  351. exit /b 1
  352. goto :eof
  353. :RunChef
  354. %PHPEXE% %~dp0piecrust.phar %*
  355. EOD;
  356. }