diff --git a/lib/build/mkdocs/script/vendor-licensing.php b/lib/build/mkdocs/script/vendor-licensing.php index 16944c63..250d820f 100755 --- a/lib/build/mkdocs/script/vendor-licensing.php +++ b/lib/build/mkdocs/script/vendor-licensing.php @@ -2,47 +2,114 @@ ] + * usage: script/vendor-licensing.php [--dev] [--] [] * * --dev include require-dev packages * path to directory with the composer.json to use + * + * obtain license information from composer packages + * and turn them into a markdown report for the + * pipelines HTML documentation + * + * markdown is written to stdout by default */ -$config['dev'] = false; -$config['composer_dir'] = __DIR__ . '/../../../..'; +function _start() +{ + // --dev : include require-dev packages + $config['dev'] = false; + // : directory having the composer.json + $config['composer_dir'] = ''; + $config['composer_filename'] = 'composer.json'; -if (isset($argv[1]) && '--dev' === $argv[1]) { - $config['dev'] = true; - array_splice($argv, 1, 1); -} + $argv = $_SERVER['argv']; -if (isset($argv[1]) && '' !== $argv[1]) { - $config['composer_dir'] = $argv[1]; -} + if (isset($argv[1]) && '--dev' === $argv[1]) { + $config['dev'] = true; + array_splice($argv, 1, 1); + } + + if (isset($argv[1]) && '--' === $argv[1]) { + array_splice($argv, 1, 1); + } + + if (isset($argv[1])) { + $buffer = realpath(trim($argv[1])); + is_string($buffer) && is_dir($buffer) + or trigger_error(sprintf('not a directory: %s', trim($argv[1])), E_USER_ERROR); + $config['composer_dir'] = $buffer; + unset($buffer); + array_splice($argv, 1, 1); + } + + isset($argv[1]) + and trigger_error(sprintf("unknown option, argument or parameter: '%s'", $argv[1]), E_USER_ERROR); + + $srcDir = realpath($config['composer_dir']); + is_string($srcDir) && is_dir($srcDir) + or trigger_error(sprintf('composer-dir not a directory: %s', $config['composer_dir']), E_USER_ERROR); + + $composerFilePath = $srcDir . '/' . $config['composer_filename']; + $project = json_decode((string)@file_get_contents($composerFilePath), true); + is_array($project) + or trigger_error(sprintf("not a composer.json: '%s'", $composerFilePath), E_USER_ERROR); -$composerFile = $config['composer_dir'] . '/composer.json'; -$project = json_decode((string)@file_get_contents($composerFile), true); -if (!is_array($project)) { - fprintf(STDERR, "fatal: not a composer.json: '%s'\n", $composerFile); - exit(1); + $project += array('require' => array(), 'require-dev' => array()); + + $require = $project['require']; + $config['dev'] && $require += $project['require-dev']; + $pkgs = packages($require, dirname($composerFilePath) . '/vendor'); + + tpl_render_pkgs($pkgs); + + // done + return 0; } -$project += array('require' => array(), 'require-dev' => array()); -$require = $project['require']; -$config['dev'] && $require += $project['require-dev']; -$pkgs = packages($require, dirname($composerFile) . '/vendor'); +register_shutdown_function(function ($_start) { + + $start = $_SERVER['REQUEST_TIME']; + if (!is_float($start)) { + $start = isset($_SERVER['REQUEST_TIME_FLOAT']) && is_float($_SERVER['REQUEST_TIME_FLOAT']) + ? $_SERVER['REQUEST_TIME_FLOAT'] + : $_start; + } + $_SERVER['REQUEST_TIME'] = (int)$_SERVER['REQUEST_TIME_FLOAT'] = $_start; + + $argv = $_SERVER['argv']; + if (!is_array($argv)) { + $argv = array(); + } + $argv = array_filter($argv, 'is_string'); + $_SERVER['argv'] = $argv; + + set_error_handler(function ($type, $message, $file, $line) { + if ($type === E_USER_ERROR) { + throw new ErrorException($message, 0, $type, $file, $line); + } + return false; + }); + + $error = null; + try { + $result = _start(); + } catch (Exception $error) { + vfprintf(STDERR, "fatal: %s\n", array_slice(explode("\n", $error->getMessage()), 0, 1)); + } -tpl_render_pkgs($pkgs); + $time = microtime(true) - $_start; + $php = vsprintf('%d.%d.%d', sscanf(PHP_VERSION, '%d.%d.%d')); + fprintf(STDERR, "%s: took %.5fs (php %s)\n", $argv[0], $time, $php); -// done + if (false === empty($result)) { + exit(2); + } + exit($error ? 1 : 0); +}, microtime(true)); /** * render packages as markdown @@ -60,7 +127,7 @@ function tpl_render_pkgs(array $pkgs) ``` - + ``` #### SPDX @@ -128,7 +195,7 @@ function packages(array $require, $vendorFolder) if (!is_dir($dir)) { // filter non-project packages, e.g. php and extensions continue; } - $composer = find_file_recursive($dir, 'composer.json'); + $composer = find_file_down($dir, 'composer.json'); if (null === $composer) { throw new UnexpectedValueException(sprintf('Unable to find composer.json in %s', $pkg)); } @@ -151,7 +218,7 @@ function packages(array $require, $vendorFolder) * * @return string|null file found or null in case not found */ -function find_file_recursive($folder, $file) +function find_file_down($folder, $file) { $folders = array($folder); while ($folder = array_pop($folders)) { @@ -169,24 +236,62 @@ function find_file_recursive($folder, $file) } /** - * find license file in a folder - * * @param string $folder + * @param string|string[] ...$file * - * @return string path to license file + * @return null|string */ -function find_license_file($folder) +function find_file($folder, $file) { - $files = array( - 'COPYING', - 'LICENSE', - ); + $files = flatten(array_slice(func_get_args(), 1)); + if (empty($files)) { + + return null; + } foreach ($files as $file) { if (is_file($folder . '/' . $file)) { + return $folder . '/' . $file; } } + return null; +} + +/** + * @param array $args + * + * @return array + */ +function flatten(array $args) +{ + $flattened = array(); + + foreach ($args as $arg) { + $values = is_array($arg) ? flatten($arg) : array($arg); + foreach ($values as $value) { + $flattened[] = $value; + } + } + + return $flattened; +} + +/** + * find license file in a folder + * + * @param string $folder + * + * @return string path to license file + */ +function find_license_file($folder, array $files = array('COPYING', 'LICENSE')) +{ + $license = find_file($folder, $files); + if (null !== $license) { + + return $license; + } + throw new RuntimeException(sprintf('Unable to find license file in "%s"', $folder)); }