Add build function check for current OS and update validation logic

This commit is contained in:
crazywhalecc 2025-12-10 13:38:25 +08:00
parent 66d3af518b
commit 458af6ac78
5 changed files with 57 additions and 9 deletions

View File

@ -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",

View File

@ -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
*/

View File

@ -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.
*/

View File

@ -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}].");
}
}

View File

@ -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 = '<?php
namespace Test\Package;
use StaticPHP\Attribute\Package\Library;
#[Library("test-lib")]
class TestPackage1 {
$classContent = '<?php
namespace Test\Package;
use StaticPHP\Attribute\Package\Library;
#[Library("test-lib")]
class TestPackage1 {
}';
file_put_contents($psr4Dir . '/TestPackage1.php', $classContent);