PageRenderTime 60ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/build.php

https://github.com/dskanth/XMLReaderIterator
PHP | 408 lines | 275 code | 68 blank | 65 comment | 47 complexity | 238d5ffb7a7634a6b5ddc7f7c7a5c360 MD5 | raw file
Possible License(s): AGPL-3.0
  1. #!/usr/bin/env php
  2. <?php
  3. /**
  4. * This file is part of the XMLReaderIterator package.
  5. *
  6. * Copyright (C) 2012, 2013 hakre <http://hakre.wordpress.com>
  7. *
  8. * build script
  9. */
  10. $errors = 0;
  11. $warnings = 0;
  12. $buildDir = __DIR__ . '/build';
  13. $concatenateDir = $buildDir . '/include';
  14. $concatenateFile = $concatenateDir . '/xmlreader-iterators.php';
  15. $autoLoadFile = __DIR__ . '/autoload.php';
  16. ### test if autoload.php contains all classes ###
  17. build_test_autoload_file($errors, $autoLoadFile);
  18. ### test if tests run clean ###
  19. build_test_tests($errors);
  20. if ($errors) {
  21. printf("ERROR: Build (Tests only) had %d errors, quitting.\n", $errors);
  22. return;
  23. }
  24. ### clean ###
  25. build_make_clean($errors, $buildDir, $concatenateDir);
  26. ### create concatenateFile ###
  27. build_create_concatenate_file($errors, $concatenateFile, $autoLoadFile);
  28. copy_file_to_dir('README.md', $concatenateDir);
  29. ### conditional build target into gist ###
  30. $gistDir = __DIR__ . '/../' . basename(__dir__) . '-Gist-5147685';
  31. if (is_dir($gistDir)) {
  32. copy_dir_to_dir($concatenateDir, $gistDir);
  33. }
  34. if ($errors) {
  35. printf("ERROR: Build had %d errors.\n");
  36. }
  37. /**
  38. * @param $errors
  39. */
  40. function build_test_tests(&$errors)
  41. {
  42. echo "INFO: Running phpunit testuite before building:\n";
  43. $phpunit = 'phpunit';
  44. $command = "$phpunit --version";
  45. $lastline = exec($command, $output, $exitCode);
  46. list($versionLine) = $output;
  47. if (!preg_match('~^PHPUnit \d\.\d\.\d+ by Sebastian Bergmann\.$~', $versionLine)) {
  48. echo "ERROR: Unable to invoke PHPUnit.\n";
  49. $errors++;
  50. return;
  51. }
  52. $command = "$phpunit --stop-on-failure tests";
  53. $result = system($command, $exitCode);
  54. if ($result === false) {
  55. echo "ERROR: Unable to invoke PHPUnit tests.\n";
  56. $errors++;
  57. return;
  58. }
  59. if ($exitCode !== 0) {
  60. echo "ERROR: PHPUnit did return exit code $exitCode which is not 0.\n";
  61. $errors++;
  62. return;
  63. }
  64. echo "INFO: phpunit testuite did pass.\n";
  65. return;
  66. }
  67. /**
  68. * @param $errors
  69. * @param $autoLoadFile
  70. */
  71. function build_test_autoload_file(&$errors, $autoLoadFile)
  72. {
  73. require_once($autoLoadFile);
  74. foreach (glob('src/*.php') as $file) {
  75. $class = basename($file, '.php');
  76. if (!class_exists($class) && !interface_exists($class)) {
  77. echo "ERROR: ", $class, " does not exists.\n";
  78. $errors++;
  79. }
  80. }
  81. }
  82. /**
  83. * @param $errors
  84. * @param $concatenateFile
  85. * @param $autoLoadFile
  86. *
  87. * @internal param $buildDir
  88. * @internal param $concatenateFileHandle
  89. */
  90. function build_create_concatenate_file(&$errors, $concatenateFile, $autoLoadFile)
  91. {
  92. if (!is_dir(dirname($concatenateFile))) {
  93. echo "ERROR: target dir '", dirname($concatenateFile), "' missing.\n";
  94. $errors++;
  95. return;
  96. } else {
  97. $concatenateFileHandle = fopen($concatenateFile, 'c+');
  98. if (!$concatenateFileHandle) {
  99. echo "ERROR: concatenateFile '$concatenateFile' can not be created.\n";
  100. $errors++;
  101. return;
  102. }
  103. }
  104. ### write concatenateFile based on autoload.php ###
  105. $pattern = '~^require .*\'/([^.]*\.php)\';$~';
  106. $lines = preg_grep($pattern, file($autoLoadFile));
  107. if (!$lines) {
  108. echo "ERROR: Problem parsing file.\n";
  109. }
  110. $count = 0;
  111. foreach ($lines as $line) {
  112. $result = preg_match($pattern, $line, $matches);
  113. if (!$result) {
  114. echo "ERROR: Problem parsing file.\n";
  115. continue;
  116. }
  117. $file = sprintf('src/%s', $matches[1]);
  118. $handle = fopen($file, 'r');
  119. if (!$handle) {
  120. echo "ERROR: Can not open file '$file' for reading.\n";
  121. continue;
  122. }
  123. if (!isset($concatenateFileHandle)) {
  124. fclose($handle);
  125. continue;
  126. }
  127. if ($count !== 0 && false === fseek_first_empty_line($handle)) { // first file is complete copy
  128. echo "ERROR: Problem reading file until first empty line.\n";
  129. continue;
  130. }
  131. stream_copy_to_stream($handle, $concatenateFileHandle);
  132. fclose($handle);
  133. $count++;
  134. }
  135. printf("INFO: concatenated %d files into %s.\n", $count, cwdname($concatenateFile));
  136. ### change the part of line ###
  137. do {
  138. $buffer = stream_get_contents($concatenateFileHandle, 512, 0);
  139. $search = ' * This file is part of the XMLReaderIterator package.';
  140. $replace = ' * XMLReaderIterator <http://git.io/xmlreaderiterator>';
  141. $length = strlen($search);
  142. if ($length !== strlen($replace)) {
  143. echo "ERROR: Search and replace must have the same length.\n";
  144. $errors++;
  145. break;
  146. }
  147. $pos = strpos($buffer, $search);
  148. if (!$pos) {
  149. echo "ERROR: Unable to find search string in first 512 bytes.\n";
  150. $errors++;
  151. break;
  152. }
  153. $buffer = substr_replace($buffer, $replace, $pos, $length);
  154. $bytesWritten = stream_put_contents($concatenateFileHandle, $buffer, 0, $pos + $length);
  155. if (false === $bytesWritten) {
  156. echo "ERROR: Failed to put first 512 bytes into stream.\n";
  157. $errors++;
  158. break;
  159. }
  160. } while (false);
  161. fclose($concatenateFileHandle);
  162. }
  163. /**
  164. * @param $errors
  165. * @param $buildDir
  166. * @param $concatenateDir
  167. */
  168. function build_make_clean(&$errors, $buildDir, $concatenateDir)
  169. {
  170. if (is_dir($buildDir)) {
  171. deltree($buildDir);
  172. }
  173. if (is_dir($buildDir)) {
  174. printf("ERROR: cannot clean buildDir %s .\n", cwdname($buildDir));
  175. $errors++;
  176. } else {
  177. mkdir($buildDir);
  178. mkdir($concatenateDir);
  179. }
  180. }
  181. /**
  182. * @param $handle
  183. *
  184. * @return bool
  185. */
  186. function fseek_first_empty_line($handle)
  187. {
  188. $lastLine = 0;
  189. while (false !== $line = fgets($handle)) {
  190. if ('' === rtrim($line, "\r\n")) {
  191. break;
  192. }
  193. $lastLine += strlen($line);
  194. }
  195. if ($line === false) {
  196. return false;
  197. }
  198. return !fseek($handle, $lastLine);
  199. }
  200. /**
  201. * shorten pathname realtive to cwd
  202. *
  203. * @param $path
  204. *
  205. * @return string
  206. */
  207. function cwdname($path)
  208. {
  209. static $base;
  210. $base || $base = realpath('.');
  211. $result = realpath($path);
  212. if (substr($result, 0, strlen($base)) === $base) {
  213. $result = '.' . substr($result, strlen($base));
  214. } else {
  215. echo "INFO: File '$path' not relative to cwd. Please verify.\n";
  216. }
  217. return strtr($result, '\\', '/');
  218. }
  219. /**
  220. * copy files from one directory into another.
  221. *
  222. * @param string $sourceDir
  223. * @param string $targetDir
  224. */
  225. function copy_dir_to_dir($sourceDir, $targetDir)
  226. {
  227. foreach (new DirectoryIterator($sourceDir) as $file) {
  228. if (!$file->isFile()) {
  229. continue;
  230. }
  231. copy_file_to_dir($file->getPathname(), $targetDir);
  232. }
  233. }
  234. /**
  235. * copy file into directory
  236. *
  237. * @param string $file
  238. * @param string $targetDir
  239. *
  240. * @return bool
  241. */
  242. function copy_file_to_dir($file, $targetDir)
  243. {
  244. $target = rtrim($targetDir, '/\\') . '/' . basename($file);
  245. if (realpath($file) === realpath($target)) {
  246. echo "INFO: source and target in copy_to_dir() are the same.\n";
  247. return true; // already copied
  248. }
  249. $result = copy($file, $target);
  250. if ($result) {
  251. printf("INFO: copied %s to %s.\n", cwdname($file), cwdname($target));
  252. }
  253. return $result;
  254. }
  255. /**
  256. * deltree() - delete a directory incl. subdirectories and files therein.
  257. *
  258. * implemented as a stack so that no recursion is necessar and
  259. * traversal is fast.
  260. *
  261. * @param $path
  262. */
  263. function deltree($path)
  264. {
  265. if (!is_dir($path) || is_link($path)) {
  266. echo "ERROR: given path rejected by deltree.\n";
  267. return;
  268. }
  269. $stack = array($path);
  270. $rmdirStack = array();
  271. while ($stack) {
  272. $path = array_pop($stack);
  273. $it = new DirectoryIterator($path);
  274. foreach ($it as $file) {
  275. /* @var $file DirectoryIterator */
  276. if ($file->isDot()) {
  277. continue;
  278. }
  279. $localPath = $path . '/' . $file->getBasename();
  280. if ($file->isDir()) {
  281. $stack[] = $localPath;
  282. } elseif ($file->isLink() || $file->isFile()) {
  283. $result = unlink($localPath);
  284. if (!$result) {
  285. echo "ERROR: Failed to delete file '$localPath'. Expecting more problems.\n";
  286. }
  287. } else {
  288. printf(
  289. "ERROR: Unknown processing for %s [%s] (%s) isDot: %d\n",
  290. $file,
  291. get_class($file),
  292. $localPath,
  293. $file->isDir()
  294. );
  295. }
  296. }
  297. unset($file, $it);
  298. array_unshift($rmdirStack, $path);
  299. }
  300. clearstatcache(true);
  301. foreach ($rmdirStack as $path) {
  302. chmod($path, 0777);
  303. clearstatcache(true, $path);
  304. $result = @rmdir($path);
  305. if (!$result) {
  306. echo "ERROR: Failed to delete directory '$path'. Skipping rest.\n";
  307. break;
  308. }
  309. }
  310. }
  311. /**
  312. * @param resource $handle destination stream
  313. * @param string $data data to write
  314. * @param int $offset offset in destination stream if specified
  315. * @param int $maxlength specify bytes to write if specified
  316. *
  317. * @return bool|int
  318. * @internal param string $string string to write
  319. */
  320. function stream_put_contents($handle, $data, $offset = null, $maxlength = null)
  321. {
  322. if (!is_resource($handle) or 'stream' !== get_resource_type($handle)) {
  323. trigger_error('Destination is not a stream resource type.');
  324. return false;
  325. }
  326. $length = strlen($data);
  327. if (null !== $maxlength) {
  328. $length = max(0, (int) $maxlength);
  329. }
  330. if (null !== $offset) {
  331. if (-1 === fseek($handle, $offset)) {
  332. trigger_error('Unable to seek.');
  333. return false;
  334. }
  335. }
  336. return fwrite($handle, $data, $length);
  337. }