Skip to content

Commit

Permalink
touch composer vendor licensing report script
Browse files Browse the repository at this point in the history
- fix(report): prevent caret injection in code-fence
- fix(argv): error on unknown options or operands
- fix(argv): support "--" argument delimiter
- style: less hard encoded parameters
- feat(diag): report runtime information
  • Loading branch information
ktomk committed Oct 10, 2024
1 parent 2b0c615 commit 4b22aa7
Showing 1 changed file with 143 additions and 38 deletions.
181 changes: 143 additions & 38 deletions lib/build/mkdocs/script/vendor-licensing.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,114 @@
<?php

/*
* composer packages license information to markdown
* this file is part of pipelines
*
* obtain license information from composer packages
* and turn them into a markdown report for the
* pipelines HTML documentation
*
* markdown is written to stdout
* vendor-licensing - composer packages license information markdown report
*
* usage: script/vendor-licensing.php [--dev] [<composer-dir>]
* usage: script/vendor-licensing.php [--dev] [--] [<composer-dir>]
*
* --dev include require-dev packages
* <composer-dir> 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;
// <composer-dir> : 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
Expand All @@ -60,7 +127,7 @@ function tpl_render_pkgs(array $pkgs)


```
<?= rtrim(file_get_contents($lic_file)), "\n"; ?>
<?= strtr(rtrim(file_get_contents($lic_file)), '`', '#'), "\n"; ?>
```

#### SPDX
Expand Down Expand Up @@ -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));
}
Expand All @@ -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)) {
Expand All @@ -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));
}

0 comments on commit 4b22aa7

Please sign in to comment.