From 458af6ac783bb6dab4d4ab57c8a03e8800e4f1e7 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Wed, 10 Dec 2025 13:38:25 +0800 Subject: [PATCH] Add build function check for current OS and update validation logic --- captainhook.json | 2 +- src/Package/Target/php.php | 7 +++ src/StaticPHP/Package/Package.php | 8 ++++ src/StaticPHP/Registry/PackageLoader.php | 4 +- .../StaticPHP/Registry/PackageLoaderTest.php | 45 ++++++++++++++++--- 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/captainhook.json b/captainhook.json index 77be1d57..8af0df3e 100644 --- a/captainhook.json +++ b/captainhook.json @@ -11,7 +11,7 @@ "enabled": true, "actions": [ { - "action": "composer cs-fix -- --config=.php-cs-fixer.php --dry-run --diff {$STAGED_FILES|of-type:php}", + "action": ".\\vendor\\bin\\php-cs-fixer fix --config=.php-cs-fixer.php --dry-run --diff {$STAGED_FILES|of-type:php}", "conditions": [ { "exec": "\\CaptainHook\\App\\Hook\\Condition\\FileStaged\\OfType", diff --git a/src/Package/Target/php.php b/src/Package/Target/php.php index 03b50073..88e01858 100644 --- a/src/Package/Target/php.php +++ b/src/Package/Target/php.php @@ -15,6 +15,7 @@ use StaticPHP\Attribute\Package\Validate; use StaticPHP\Attribute\PatchDescription; use StaticPHP\Config\PackageConfig; use StaticPHP\DI\ApplicationContext; +use StaticPHP\Exception\EnvironmentException; use StaticPHP\Exception\SPCException; use StaticPHP\Exception\WrongUsageException; use StaticPHP\Package\Package; @@ -529,6 +530,12 @@ class php extends TargetPackage $package->runStage([$this, 'unixBuildSharedExt']); } + #[BuildFor('Windows')] + public function buildWin(TargetPackage $package): void + { + throw new EnvironmentException('Not implemented'); + } + /** * Patch phpize and php-config if needed */ diff --git a/src/StaticPHP/Package/Package.php b/src/StaticPHP/Package/Package.php index 6cad1fab..aa8ab6f0 100644 --- a/src/StaticPHP/Package/Package.php +++ b/src/StaticPHP/Package/Package.php @@ -127,6 +127,14 @@ abstract class Package return false; } + /** + * Check if the package has a build function for the current OS. + */ + public function hasBuildFunctionForCurrentOS(): bool + { + return isset($this->build_functions[PHP_OS_FAMILY]); + } + /** * Get the name of the package. */ diff --git a/src/StaticPHP/Registry/PackageLoader.php b/src/StaticPHP/Registry/PackageLoader.php index 0ef3fb8e..29ce0a96 100644 --- a/src/StaticPHP/Registry/PackageLoader.php +++ b/src/StaticPHP/Registry/PackageLoader.php @@ -306,7 +306,9 @@ class PackageLoader } } // check stage exists - if (!$pkg->hasStage($stage_name)) { + // Skip validation if the package has no build function for current OS + // (e.g., libedit has BeforeStage for 'build' but only BuildFor('Darwin'/'Linux')) + if (!$pkg->hasStage($stage_name) && $pkg->hasBuildFunctionForCurrentOS()) { throw new RegistryException("Package stage [{$stage_name}] is not registered in package [{$package_name}]."); } } diff --git a/tests/StaticPHP/Registry/PackageLoaderTest.php b/tests/StaticPHP/Registry/PackageLoaderTest.php index 7228b5ae..a40c79fa 100644 --- a/tests/StaticPHP/Registry/PackageLoaderTest.php +++ b/tests/StaticPHP/Registry/PackageLoaderTest.php @@ -377,6 +377,10 @@ class PackageLoaderTest extends TestCase $this->createTestPackageConfig('test-lib', 'library'); PackageLoader::initPackageInstances(); + // Add a build function for current OS so the stage validation is triggered + $package = PackageLoader::getPackage('test-lib'); + $package->addBuildFunction(PHP_OS_FAMILY, fn () => null); + // Manually add a before_stage for non-existent stage $reflection = new \ReflectionClass(PackageLoader::class); $property = $reflection->getProperty('before_stages'); @@ -417,6 +421,33 @@ class PackageLoaderTest extends TestCase PackageLoader::checkLoadedStageEvents(); } + public function testCheckLoadedStageEventsDoesNotThrowForNonCurrentOSPackage(): void + { + $this->createTestPackageConfig('test-lib', 'library'); + PackageLoader::initPackageInstances(); + + // Add a build function for a different OS (not current OS) + $package = PackageLoader::getPackage('test-lib'); + $otherOS = PHP_OS_FAMILY === 'Windows' ? 'Linux' : 'Windows'; + $package->addBuildFunction($otherOS, fn () => null); + + // Manually add a before_stage for 'build' stage + // This should NOT throw an exception because the package has no build function for current OS + $reflection = new \ReflectionClass(PackageLoader::class); + $property = $reflection->getProperty('before_stages'); + $property->setAccessible(true); + $property->setValue(null, [ + 'test-lib' => [ + 'build' => [[fn () => null, null]], + ], + ]); + + // This should not throw an exception + PackageLoader::checkLoadedStageEvents(); + + $this->assertTrue(true); // If we get here, the test passed + } + public function testGetBeforeStageCallbacksReturnsCallbacks(): void { PackageLoader::initPackageInstances(); @@ -502,13 +533,13 @@ class PackageLoaderTest extends TestCase mkdir($psr4Dir, 0755, true); // Create test class file - $classContent = '