Refactor shell utilities: reorganize namespaces and introduce Shell base class

This commit is contained in:
crazywhalecc
2025-08-06 20:28:25 +08:00
committed by Jerry Ma
parent cc447a089a
commit e28580de00
10 changed files with 314 additions and 150 deletions

View File

@@ -0,0 +1,114 @@
<?php
declare(strict_types=1);
namespace SPC\util\shell;
use SPC\builder\freebsd\library\BSDLibraryBase;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\SPCInternalException;
use ZM\Logger\ConsoleColor;
/**
* Unix-like OS shell command executor.
*
* This class provides methods to execute shell commands in a Unix-like environment.
* It supports setting environment variables and changing the working directory.
*/
class UnixShell extends Shell
{
public function __construct(?bool $debug = null)
{
if (PHP_OS_FAMILY === 'Windows') {
throw new SPCInternalException('Windows cannot use UnixShell');
}
parent::__construct($debug);
}
public function exec(string $cmd): static
{
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd));
$original_command = $cmd;
$this->logCommandInfo($original_command);
$this->last_cmd = $cmd = $this->getExecString($cmd);
$this->passthru($cmd, $this->debug, $original_command);
return $this;
}
/**
* Init the environment variable that common build will be used.
*
* @param BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library Library class
*/
public function initializeEnv(BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library): UnixShell
{
$this->setEnv([
'CFLAGS' => $library->getLibExtraCFlags(),
'CXXFLAGS' => $library->getLibExtraCXXFlags(),
'LDFLAGS' => $library->getLibExtraLdFlags(),
'LIBS' => $library->getLibExtraLibs(),
]);
return $this;
}
public function execWithResult(string $cmd, bool $with_log = true): array
{
if ($with_log) {
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::blue('[EXEC] ') . ConsoleColor::green($cmd));
} else {
/* @phpstan-ignore-next-line */
logger()->debug(ConsoleColor::blue('[EXEC] ') . ConsoleColor::gray($cmd));
}
$cmd = $this->getExecString($cmd);
exec($cmd, $out, $code);
return [$code, $out];
}
/**
* Returns unix-style environment variable string.
*/
public function getEnvString(): string
{
$str = '';
foreach ($this->env as $k => $v) {
$str .= ' ' . $k . '="' . $v . '"';
}
return trim($str);
}
protected function logCommandInfo(string $cmd): void
{
// write executed command to log file using fwrite
$log_file = fopen(SPC_SHELL_LOG, 'a');
fwrite($log_file, "\n>>>>>>>>>>>>>>>>>>>>>>>>>> [" . date('Y-m-d H:i:s') . "]\n");
fwrite($log_file, "> Executing command: {$cmd}\n");
// get the backtrace to find the file and line number
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
if (isset($backtrace[1]['file'], $backtrace[1]['line'])) {
$file = $backtrace[1]['file'];
$line = $backtrace[1]['line'];
fwrite($log_file, "> Called from: {$file} at line {$line}\n");
}
fwrite($log_file, "> Environment variables: {$this->getEnvString()}\n");
if ($this->cd !== null) {
fwrite($log_file, "> Working dir: {$this->cd}\n");
}
fwrite($log_file, "\n");
}
private function getExecString(string $cmd): string
{
// logger()->debug('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']);
$env_str = $this->getEnvString();
if (!empty($env_str)) {
$cmd = "{$env_str} {$cmd}";
}
if ($this->cd !== null) {
$cmd = 'cd ' . escapeshellarg($this->cd) . ' && ' . $cmd;
}
return $cmd;
}
}