change build target meaning, separate ensure procedure

This commit is contained in:
Jerry 2023-02-01 16:28:30 +08:00
parent 74cbfb8b73
commit 755d66c658
2 changed files with 69 additions and 39 deletions

View File

@ -7,8 +7,9 @@ namespace ZM\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;
use ZM\Store\FileSystem;
use ZM\Store\PharHelper;
#[AsCommand(name: 'build', description: '将项目构建一个 Phar 包')]
#[AsCommand(name: 'build', description: '将炸毛框架项目构建一个 Phar 包')]
class BuildCommand extends Command
{
use NonPharLoadModeOnly;
@ -18,20 +19,29 @@ class BuildCommand extends Command
*/
protected function configure()
{
$this->setHelp('此功能将会把整个项目打包为 Phar' . PHP_EOL . '默认会启用压缩功能,通过去除文件中的注释和空格,以减小文件大小,但可能增加构建耗时');
$this->addOption('target', 'D', InputOption::VALUE_REQUIRED, '指定输出文件位置', 'zm.phar');
$this->setHelp('此功能将会把整个框架项目打包为 Phar' . PHP_EOL . '默认会启用压缩功能,通过去除文件中的注释和空格,以减小文件大小,但可能增加构建耗时');
$this->addOption('build-dir', 'D', InputOption::VALUE_REQUIRED, '指定输出文件夹(默认为 build/', WORKING_DIR . '/build');
$this->addOption('target', 'T', InputOption::VALUE_REQUIRED, '指定输出文件名称(默认为 zm.phar', 'zm.phar');
$this->addOption('no-compress', null, InputOption::VALUE_NONE, '是否不压缩文件,以减小构建耗时');
}
/**
* @throws \PharException
*/
protected function handle(): int
{
$this->ensurePharWritable();
// 确认可写 Phar
PharHelper::ensurePharWritable();
$target = $this->input->getOption('target');
if (FileSystem::isRelativePath($target)) {
$target = SOURCE_ROOT_DIR . '/' . $target;
$build_dir = $this->input->getOption('build-dir');
if (FileSystem::isRelativePath($build_dir)) {
$build_dir = WORKING_DIR . '/' . $build_dir;
}
$this->ensureTargetWritable($target);
$target = $build_dir . '/' . $target;
// 确认 Phar 文件可以写入
PharHelper::ensurePharFileWritable($target);
$this->comment("目标文件:{$target}");
if (file_exists($target)) {
@ -51,38 +61,6 @@ class BuildCommand extends Command
return self::SUCCESS;
}
private function ensurePharWritable(): void
{
if (ini_get('phar.readonly') === '1') {
if (!function_exists('pcntl_exec')) {
$this->error('Phar 处于只读模式,且 pcntl 扩展未加载,无法自动切换到读写模式。');
$this->error('请修改 php.ini 中的 phar.readonly 为 0或执行 php -d phar.readonly=0 ' . $_SERVER['PHP_SELF'] . ' build');
exit(1);
}
// Windows 下无法使用 pcntl_exec
if (DIRECTORY_SEPARATOR === '\\') {
$this->error('Phar 处于只读模式,且当前运行环境为 Windows无法自动切换到读写模式。');
$this->error('请修改 php.ini 中的 phar.readonly 为 0或执行 php -d phar.readonly=0 ' . $_SERVER['PHP_SELF'] . ' build');
exit(1);
}
$this->info('Phar 处于只读模式,正在尝试切换到读写模式...');
sleep(1);
$args = array_merge(['-d', 'phar.readonly=0'], $_SERVER['argv']);
if (pcntl_exec(PHP_BINARY, $args) === false) {
$this->error('切换到读写模式失败,请检查环境。');
exit(1);
}
}
}
private function ensureTargetWritable(string $target): void
{
if (file_exists($target) && !is_writable($target)) {
$this->error('目标文件不可写:' . $target);
exit(1);
}
}
private function build(string $target, string $entry): void
{
$phar = new \Phar($target, 0);

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace ZM\Store;
/**
* Phar 打包、解包一系列工具集
*/
class PharHelper
{
/**
* 确认环境是否允许写入 phar
*
* 调用该方法将确认能否写入 Phar如果不能但能通过 pcnlt_exec 自动切换为可写模式,则切换并继续执行后续流程。
* 否则将抛出 \PharException 异常。
*
* @throws \PharException
*/
public static function ensurePharWritable(): void
{
if (ini_get('phar.readonly') === '1') {
if (!function_exists('pcntl_exec')) {
throw new \PharException("Phar 处于只读模式,且 pcntl 扩展未加载,无法自动切换到读写模式。\n" . '请修改 php.ini 中的 phar.readonly 为 0或执行 php -d phar.readonly=0 ' . $_SERVER['PHP_SELF'] . ' build');
}
// Windows 下无法使用 pcntl_exec
if (DIRECTORY_SEPARATOR === '\\') {
throw new \PharException("Phar 处于只读模式,且当前运行环境为 Windows无法自动切换到读写模式。\n" . '请修改 php.ini 中的 phar.readonly 为 0或执行 php -d phar.readonly=0 ' . $_SERVER['PHP_SELF'] . ' build');
}
if (ob_logger_registered()) {
ob_logger()->info('Phar 处于只读模式,正在尝试切换到读写模式...');
}
sleep(1);
$args = array_merge(['-d', 'phar.readonly=0'], $_SERVER['argv']);
if (pcntl_exec(PHP_BINARY, $args) === false) {
throw new \PharException('切换到读写模式失败,请检查环境。');
}
}
}
/**
* 调用该方法将确认传入的 Phar 文件是否可写,如果不可写将抛出 \PharException 异常。
*
* @throws \PharException
*/
public static function ensurePharFileWritable(string $phar_path): void
{
if (file_exists($phar_path) && !is_writable($phar_path)) {
throw new \PharException('目标文件不可写:' . $phar_path);
}
}
}