Add doctor cache check and version management to ensure environment validation

This commit is contained in:
crazywhalecc
2026-02-28 10:32:50 +08:00
parent 7623b9e673
commit c218aef947
8 changed files with 94 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\SPCException;
use StaticPHP\Registry\DoctorLoader;
use StaticPHP\Runtime\Shell\Shell;
use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Util\InteractiveTerm;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Logger\ConsoleColor;
@@ -25,6 +26,29 @@ readonly class Doctor
logger()->debug("Loaded doctor check items:\n\t" . implode("\n\t", $names));
}
/**
* Returns true if doctor was previously passed with the current SPC version.
*/
public static function isHealthy(): bool
{
$lock = self::getLockPath();
return file_exists($lock) && trim((string) @file_get_contents($lock)) === \StaticPHP\ConsoleApplication::VERSION;
}
/**
* Write current SPC version to the lock file, marking doctor as passed.
*/
public static function markPassed(): void
{
$primary = self::getLockPath();
if (!is_dir(dirname($primary))) {
@mkdir(dirname($primary), 0755, true);
}
if (@file_put_contents($primary, \StaticPHP\ConsoleApplication::VERSION) === false) {
@file_put_contents((getcwd() ?: '.') . DIRECTORY_SEPARATOR . '.spc-doctor.lock', \StaticPHP\ConsoleApplication::VERSION);
}
}
/**
* Check all valid check items.
* @return bool true if all checks passed, false otherwise
@@ -119,6 +143,30 @@ readonly class Doctor
return false;
}
private static function getLockPath(): string
{
if (SystemTarget::getTargetOS() === 'Windows') {
$trial_ls = [
getenv('LOCALAPPDATA') ?: ((getenv('USERPROFILE') ?: 'C:\Users\Default') . '\AppData\Local') . '\.spc-doctor.lock',
sys_get_temp_dir() . '\.spc-doctor.lock',
WORKING_DIR . '\.spc-doctor.lock',
];
} else {
$trial_ls = [
getenv('XDG_CACHE_HOME') ?: ((getenv('HOME') ?: '/tmp') . '/.cache') . '/.spc-doctor.lock',
sys_get_temp_dir() . '/.spc-doctor.lock',
WORKING_DIR . '/.spc-doctor.lock',
];
}
foreach ($trial_ls as $path) {
if (is_writable(dirname($path))) {
return $path;
}
}
// fallback to current directory
return WORKING_DIR . DIRECTORY_SEPARATOR . '.spc-doctor.lock';
}
private function emitFix(string $fix_item, array $fix_item_params = []): bool
{
keyboard_interrupt_register(function () {