PageRenderTime 29ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/builders/build-skel/build-skel.php

https://gitlab.com/src-run/usr-src-runner
PHP | 389 lines | 367 code | 21 blank | 1 comment | 12 complexity | 68750be24ba723ce1f54feef4692d321 MD5 | raw file
  1. #!/usr/bin/env php
  2. <?php
  3. function ask($what, $default = null, \Closure $validator = null)
  4. {
  5. while (true) {
  6. echo PHP_EOL . ' >> ' . $what;
  7. if ($default) {
  8. echo ' [ ' . $default . ' ] : ';
  9. } else {
  10. echo ' [ <none> ] : ';
  11. }
  12. $stdin = fopen ("php://stdin","r");
  13. $input = trim(fgets($stdin));
  14. if (!($validator instanceof \Closure)) {
  15. $validator = $default === null
  16. ?
  17. function($in) {
  18. if (strlen($in) === 0) {
  19. return false;
  20. }
  21. return $in;
  22. }
  23. :
  24. function($in, $default) {
  25. if (strlen($in) === 0) {
  26. return $default;
  27. }
  28. return $in;
  29. };
  30. }
  31. if (false !== ($return = $validator($input, $default))) {
  32. break;
  33. }
  34. outWarning('Your entry was invalid; please try again.', 'BAD INPUT');
  35. }
  36. return $return;
  37. }
  38. function outLines(array $lines, $prefix = null)
  39. {
  40. $prefix = ($prefix === null ? ' ' : $prefix) . ' ';
  41. foreach ($lines as $l) {
  42. if ($l === null) {
  43. echo PHP_EOL;
  44. continue;
  45. }
  46. echo ' ' . $prefix . $l . PHP_EOL;
  47. }
  48. echo PHP_EOL;
  49. }
  50. function outOpener($lines)
  51. {
  52. outLines(array_merge([null, ''], (array) $lines, ['', null]), '||');
  53. }
  54. function outWarning($lines, $title = 'WARNING')
  55. {
  56. outLines(array_merge([null, ''], (array) $title, [''], (array) $lines, ['', null]), '!!');
  57. }
  58. function outSection($lines, $title = 'SECTION')
  59. {
  60. outLines(array_merge([''], (array) $title, [''], (array) $lines, ['']), '##');
  61. }
  62. function outInfo($lines)
  63. {
  64. outLines(array_merge([''], (array) $lines, ['']), '--');
  65. }
  66. function getPackageInfoParts($pkg)
  67. {
  68. $parts = array_merge(['Scribe'], explode('-', $pkg));
  69. $parts = array_map(function($v) {
  70. return ucfirst(strtolower($v));
  71. }, $parts);
  72. $class = implode('', $parts);
  73. $ns = '';
  74. for ($i = 0; $i < count($parts); ++$i) {
  75. if ($i < 2) {
  76. $ns .= $parts[$i] . '\\';
  77. continue;
  78. }
  79. $ns .= $parts[$i];
  80. }
  81. $binParts = $parts;
  82. $cfgParts = $parts;
  83. array_shift($binParts);
  84. array_pop($binParts);
  85. array_pop($cfgParts);
  86. $bin = 'bin/' . strtolower(implode('-', $binParts));
  87. $cfg = strtolower(implode('_', $cfgParts));
  88. return [
  89. $ns,
  90. $class,
  91. $bin,
  92. $cfg,
  93. $parts[1],
  94. ];
  95. }
  96. function groupDesc($group, $attributes)
  97. {
  98. $groupAttributes = $attributes['groups'];
  99. if (array_key_exists($group, $groupAttributes)) {
  100. return $groupAttributes[$group]['description'];
  101. }
  102. return null;
  103. }
  104. function getAttributes($attributesFilePath)
  105. {
  106. outInfo('Reading in attributes: '.$attributesFilePath);
  107. return json_decode(file_get_contents($attributesFilePath), true);
  108. }
  109. function getPackageCfg($packageCfgFilePath, $packageCfg)
  110. {
  111. outInfo('Reading in package config: '.$packageCfgFilePath);
  112. $fileLines = explode(PHP_EOL, file_get_contents($packageCfgFilePath));
  113. foreach ($fileLines as $line) {
  114. $linePosition = strpos($line, ':');
  115. $lineVariable = trim(substr($line, 0, $linePosition));
  116. $lineValue = trim(substr($line, $linePosition + 1));
  117. $lineValue = preg_replace('{^"}', '', $lineValue);
  118. $lineValue = preg_replace('{"$}', '', $lineValue);
  119. if (array_key_exists($lineVariable, $packageCfg)) {
  120. $packageCfg[$lineVariable] = $lineValue;
  121. }
  122. }
  123. return $packageCfg;
  124. }
  125. function getFileInfoModeSpecific($file, $isBndlMode, $attributes)
  126. {
  127. if ($isBndlMode) {
  128. $fileInfo = $attributes['tpls']['bdl'][$file];
  129. } else {
  130. $fileInfo = $attributes['tpls']['lib'][$file];
  131. }
  132. if (!array_key_exists('from', $fileInfo) || !array_key_exists('dest', $fileInfo)) {
  133. outError('Invalid attributes config for '.$file);
  134. doExit();
  135. }
  136. if (!array_key_exists('mode', $fileInfo)) {
  137. $fileInfo['mode'] = 'link';
  138. }
  139. if (!($realPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . $fileInfo['from'])) || !file_exists($realPath)) {
  140. outError('Could not read template: %s', $fileInfo['from']);
  141. doExit();
  142. }
  143. return $fileInfo;
  144. }
  145. function assignReadMeFilePath($isBndlMode, $attributes, &$copyFiles, &$linkFiles)
  146. {
  147. $file = getFileInfoModeSpecific('readme', $isBndlMode, $attributes);
  148. $fileOp = [$file['dest'] => $file['from']];
  149. if ($file['mode'] === 'link') {
  150. $linkFiles = array_merge($linkFiles, (array) $fileOp);
  151. } else {
  152. $copyFiles = array_merge($copyFiles, (array) $fileOp);
  153. }
  154. }
  155. function assignPhpUnitFilePath($isBndlMode, $attributes, &$copyFiles, &$linkFiles)
  156. {
  157. $file = getFileInfoModeSpecific('phpunit', $isBndlMode, $attributes);
  158. $fileOp = [$file['dest'] => $file['from']];
  159. if ($file['mode'] === 'link') {
  160. $linkFiles = array_merge($linkFiles, (array) $fileOp);
  161. } else {
  162. $copyFiles = array_merge($copyFiles, (array) $fileOp);
  163. }
  164. }
  165. function assignOtherFilePaths($attributes, &$copyFiles, &$linkFiles)
  166. {
  167. $getFilesOfType = function($which) use ($attributes) {
  168. return $attributes['tpls'][$which];
  169. };
  170. $validateAndNormalizeFiles = function(array $files) {
  171. array_map(function ($from) {
  172. if (!($realPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . $from)) || !file_exists($realPath)) {
  173. outError('Could not read file template: %s', $from);
  174. doExit();
  175. }
  176. }, array_keys($files));
  177. return array_combine(array_values($files), array_keys($files));
  178. };
  179. $copyFiles = array_merge($copyFiles, $validateAndNormalizeFiles($getFilesOfType('copy')));
  180. $linkFiles = array_merge($linkFiles, $validateAndNormalizeFiles($getFilesOfType('link')));
  181. }
  182. function normalizeFilePaths(array $collections)
  183. {
  184. $normalized = [];
  185. foreach ($collections as $i => $c) {
  186. if (!isset($normalized[$i])) {
  187. $normalized[$i] = [];
  188. }
  189. foreach ($c as $j => $f) {
  190. $normalized[$i][getcwd() . DIRECTORY_SEPARATOR . $j] = realpath(__DIR__ . DIRECTORY_SEPARATOR . $f);
  191. }
  192. }
  193. return $normalized;
  194. }
  195. function getAllFilePaths($isBndlMode, $attributes)
  196. {
  197. $files = $copyFiles = $linkFiles = [];
  198. assignReadMeFilePath($isBndlMode, $attributes, $copyFiles, $linkFiles);
  199. assignPhpUnitFilePath($isBndlMode, $attributes, $copyFiles, $linkFiles);
  200. assignOtherFilePaths($attributes, $copyFiles, $linkFiles);
  201. list($copyFiles, $linkFiles) = normalizeFilePaths([$copyFiles, $linkFiles]);
  202. $files = array_merge(
  203. (array) $copyFiles,
  204. (array) $linkFiles
  205. );
  206. return [$files, $copyFiles, $linkFiles];
  207. }
  208. function getFileContentsReplaced($files, $replacements)
  209. {
  210. $fileContents = [];
  211. foreach ($files as $i => $f) {
  212. $c = file_get_contents($f);
  213. foreach ($replacements as $search => $replace) {
  214. $c = str_replace('%' . $search . '%', $replace, $c);
  215. }
  216. $fileContents[$i] = $c;
  217. }
  218. return $fileContents;
  219. }
  220. function getFileOperations($isBndlMode, $packageCfg, $attributes)
  221. {
  222. list($files, $copyFiles, $linkFiles) = getAllFilePaths($isBndlMode, $attributes);
  223. outSection([
  224. 'Enter the requested information about the package to allow for skeleton auto-generation.',
  225. 'If a default value is shown it can be used by not entering a new value.',
  226. ], 'Configuration');
  227. $r['package'] = ask('Package Name', $packageCfg['pkg_name']);
  228. $r['desc'] = ask('Short Desc', $packageCfg['pkg_desc'], function($in, $default) {
  229. if (strlen($in) === 0) {
  230. $in = $default;
  231. }
  232. return str_replace('\\n', PHP_EOL, $in);
  233. });
  234. $r['group'] = ask('Group Name', substr($r['package'], 0, strpos($r['package'], '-')));
  235. $r['group-desc'] = ask('Group Concentration', groupDesc($r['group'], $attributes));
  236. if ($isBndlMode) {
  237. $r['bundle'] = ask('Bundle Classname', getPackageInfoParts($r['package'])[1]);
  238. $r['ns'] = ask('Bundle Namespace', getPackageInfoParts($r['package'])[0]);
  239. $r['bin'] = ask('Console Bin Path', getPackageInfoParts($r['package'])[2]);
  240. $r['bin-rel'] = pathinfo($r['bin'], PATHINFO_BASENAME);
  241. $r['config-dump'] = ask('Config Root Tree Name', getPackageInfoParts($r['package'])[3]);
  242. }
  243. outLines([null, null]);
  244. $copyFileContents = getFileContentsReplaced($copyFiles, $r);
  245. return [$files, $linkFiles, $copyFiles, $copyFileContents];
  246. }
  247. function performLinkOperations($files)
  248. {
  249. outSection(['Writing out symbolic links.']);
  250. $cwd = getcwd() . DIRECTORY_SEPARATOR;
  251. foreach ($files as $dest => $from) {
  252. $fileDest = str_replace($cwd, '', $dest);
  253. $fileFrom = str_replace($cwd, '', $from);
  254. $cmdRemove = 'rm -fr ' . escapeshellarg($dest);
  255. $cmdSymlink = 'ln -s ' . escapeshellarg($fileFrom) . ' ' . escapeshellarg($fileDest);
  256. outInfo('Writing link: ' . $fileDest . ' -> ' . $fileFrom);
  257. exec($cmdRemove);
  258. exec($cmdSymlink);
  259. }
  260. }
  261. function performCopyOperations($files, $contents)
  262. {
  263. outSection(['Writing out new files.']);
  264. $cwd = getcwd() . DIRECTORY_SEPARATOR;
  265. foreach ($files as $dest => $from) {
  266. if (!array_key_exists($dest, $contents)) {
  267. continue;
  268. }
  269. $cmdRemove = 'rm -fr ' . escapeshellarg($dest);
  270. $fileDest = str_replace($cwd, '', $dest);
  271. outInfo('Writing new file: ' . $fileDest);
  272. exec($cmdRemove);
  273. file_put_contents($fileDest, $contents[$dest]);
  274. }
  275. }
  276. function main()
  277. {
  278. outOpener([
  279. 'Build Package Skeleton (v1.0.0)',
  280. '',
  281. 'Author : Rob Frawley 2nd <rmf@src.run>',
  282. 'License : MIT License',
  283. 'Copyright : (c) 2016 Rob Frawley 2nd',
  284. ]);
  285. $attributesFilePath = realpath(__DIR__ . DIRECTORY_SEPARATOR . '.build-skel-config' . DIRECTORY_SEPARATOR . 'attributes.json');
  286. $packageCfgFilePath = realpath(getcwd() . DIRECTORY_SEPARATOR . '.package.yml');
  287. $packageCfg = [ 'pkg_name' => null, 'pkg_desc' => null, 'pkg_bndl' => false];
  288. if (!file_exists($attributesFilePath)) {
  289. die('Unable to find attributes config file: attributes.json');
  290. } elseif (!file_exists($packageCfgFilePath)) {
  291. die('Unable to find package config file: .package.yml');
  292. }
  293. $attributes = getAttributes($attributesFilePath);
  294. $packageCfg = getPackageCfg($packageCfgFilePath, $packageCfg);
  295. $isBndlMode = (bool) ($packageCfg['pkg_bndl'] === "true");
  296. outInfo('Setting runtime mode: '.($isBndlMode ? 'BUNDLE' : 'LIBRARY'));
  297. list($files, $linkFiles, $copyFiles, $copyFileContents) = getFileOperations($isBndlMode, $packageCfg, $attributes);
  298. performLinkOperations($linkFiles);
  299. performCopyOperations($copyFiles, $copyFileContents);
  300. }
  301. main();