mirror of
https://github.com/getgrav/grav.git
synced 2026-01-11 01:53:07 +01:00
210 lines
5.6 KiB
PHP
Executable File
210 lines
5.6 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use Grav\Common\Filesystem\Folder;
|
|
|
|
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
if (!\defined('GRAV_ROOT')) {
|
|
\define('GRAV_ROOT', realpath(__DIR__ . '/..') ?: getcwd());
|
|
}
|
|
|
|
if (!\extension_loaded('zip')) {
|
|
fwrite(STDERR, "The PHP zip extension is required.\n");
|
|
exit(1);
|
|
}
|
|
|
|
$options = getopt('', [
|
|
'version:',
|
|
'output::',
|
|
'port::',
|
|
'base-url::',
|
|
'serve',
|
|
]);
|
|
|
|
if (!isset($options['version'])) {
|
|
fwrite(
|
|
STDERR,
|
|
"Usage: php bin/build-test-update.php --version=1.7.999 [--output=tmp/test-gpm] [--port=8043] [--base-url=http://127.0.0.1:8043] [--serve]\n"
|
|
);
|
|
exit(1);
|
|
}
|
|
|
|
$version = trim((string) $options['version']);
|
|
if ($version === '') {
|
|
fwrite(STDERR, "A non-empty --version value is required.\n");
|
|
exit(1);
|
|
}
|
|
|
|
$root = GRAV_ROOT;
|
|
|
|
$output = $options['output'] ?? $root . '/tmp/test-gpm';
|
|
if (!str_starts_with($output, DIRECTORY_SEPARATOR)) {
|
|
$output = $root . '/' . ltrim($output, '/');
|
|
}
|
|
$output = rtrim($output, DIRECTORY_SEPARATOR);
|
|
|
|
$defaultPort = isset($options['port']) ? (int) $options['port'] : 8043;
|
|
$baseUrl = $options['base-url'] ?? sprintf('http://127.0.0.1:%d', $defaultPort);
|
|
$serve = array_key_exists('serve', $options);
|
|
|
|
Folder::create($output);
|
|
|
|
$downloadName = sprintf('grav-update-%s.zip', $version);
|
|
$zipPath = $output . '/' . $downloadName;
|
|
$jsonPath = $output . '/grav.json';
|
|
$zipPrefix = 'grav-update/';
|
|
|
|
$excludeDirs = [
|
|
'.build',
|
|
'.crush',
|
|
'.ddev',
|
|
'.git',
|
|
'.github',
|
|
'.gitlab',
|
|
'.circleci',
|
|
'.idea',
|
|
'.vscode',
|
|
'.pytest_cache',
|
|
'backup',
|
|
'cache',
|
|
'images',
|
|
'logs',
|
|
'node_modules',
|
|
'tests',
|
|
'tmp',
|
|
'user',
|
|
];
|
|
|
|
$excludeFiles = [
|
|
'.htaccess',
|
|
'.DS_Store',
|
|
'robots.txt',
|
|
];
|
|
|
|
$directory = new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS);
|
|
$filtered = new RecursiveCallbackFilterIterator(
|
|
$directory,
|
|
function (SplFileInfo $current) use ($root, $excludeDirs, $excludeFiles): bool {
|
|
$relative = ltrim(str_replace($root, '', $current->getPathname()), DIRECTORY_SEPARATOR);
|
|
$relative = str_replace('\\', '/', $relative);
|
|
|
|
if ($relative === '') {
|
|
return true;
|
|
}
|
|
|
|
if (str_contains($relative, '..')) {
|
|
return false;
|
|
}
|
|
|
|
foreach ($excludeDirs as $prefix) {
|
|
$prefix = trim($prefix, '/');
|
|
if ($prefix === '') {
|
|
continue;
|
|
}
|
|
|
|
if ($relative === $prefix || str_starts_with($relative, $prefix . '/')) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (in_array($current->getFilename(), $excludeFiles, true)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
);
|
|
|
|
$zip = new ZipArchive();
|
|
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
|
throw new RuntimeException(sprintf('Unable to open archive at %s', $zipPath));
|
|
}
|
|
|
|
$zip->addEmptyDir($zipPrefix);
|
|
|
|
$iterator = new RecursiveIteratorIterator($filtered, RecursiveIteratorIterator::SELF_FIRST);
|
|
/** @var SplFileInfo $fileInfo */
|
|
foreach ($iterator as $fileInfo) {
|
|
$fullPath = $fileInfo->getPathname();
|
|
$relative = ltrim(str_replace($root, '', $fullPath), DIRECTORY_SEPARATOR);
|
|
$relative = str_replace('\\', '/', $relative);
|
|
$targetPath = $zipPrefix . $relative;
|
|
|
|
if ($fileInfo->isDir()) {
|
|
$zip->addEmptyDir(rtrim($targetPath, '/') . '/');
|
|
continue;
|
|
}
|
|
|
|
if ($fileInfo->isLink()) {
|
|
$target = readlink($fullPath);
|
|
$zip->addFromString($targetPath, $target === false ? '' : $target);
|
|
$zip->setExternalAttributesName($targetPath, ZipArchive::OPSYS_UNIX, 0120000 << 16);
|
|
continue;
|
|
}
|
|
|
|
$zip->addFile($fullPath, $targetPath);
|
|
|
|
$perms = @fileperms($fullPath);
|
|
if ($perms !== false) {
|
|
$zip->setExternalAttributesName($targetPath, ZipArchive::OPSYS_UNIX, ($perms & 0xFFFF) << 16);
|
|
}
|
|
}
|
|
|
|
$zip->close();
|
|
|
|
$size = filesize($zipPath);
|
|
$sha256 = hash_file('sha256', $zipPath);
|
|
$timestamp = date('c');
|
|
$downloadUrl = rtrim($baseUrl, '/') . '/' . rawurlencode($downloadName);
|
|
|
|
$manifest = [
|
|
'version' => $version,
|
|
'date' => $timestamp,
|
|
'min_php' => '8.3.0',
|
|
'assets' => [
|
|
'grav-update' => [
|
|
'name' => $downloadName,
|
|
'slug' => 'grav-update',
|
|
'version' => $version,
|
|
'date' => $timestamp,
|
|
'testing' => false,
|
|
'description' => 'Local test update package generated for safe-upgrade validation.',
|
|
'download' => $downloadUrl,
|
|
'size' => $size,
|
|
'checksum' => 'sha256:' . $sha256,
|
|
'sha256' => $sha256,
|
|
'host' => parse_url($downloadUrl, PHP_URL_HOST),
|
|
],
|
|
],
|
|
'changelog' => [
|
|
$version => [
|
|
'date' => $timestamp,
|
|
'content' => "- Local test update package generated by build-test-update.\n",
|
|
],
|
|
],
|
|
];
|
|
|
|
file_put_contents($jsonPath, json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL);
|
|
|
|
$manifestUrl = rtrim($baseUrl, '/') . '/grav.json';
|
|
|
|
echo "Update package created at: {$zipPath}\n";
|
|
echo "Manifest written to: {$jsonPath}\n";
|
|
echo "Manifest URL: {$manifestUrl}\n";
|
|
echo "Download URL: {$downloadUrl}\n";
|
|
echo "Archive size: {$size} bytes\n";
|
|
echo "SHA256: {$sha256}\n";
|
|
|
|
if ($serve) {
|
|
$host = parse_url($baseUrl, PHP_URL_HOST) ?: '127.0.0.1';
|
|
$port = parse_url($baseUrl, PHP_URL_PORT) ?: $defaultPort;
|
|
$command = sprintf('php -S %s:%d -t %s', $host, $port, escapeshellarg($output));
|
|
echo "\nServing files using PHP built-in server. Press Ctrl+C to stop.\n";
|
|
echo $command . "\n\n";
|
|
passthru($command);
|
|
}
|