diff --git a/box.json.dist b/box.json.dist index 453105b4..fa3b3489 100644 --- a/box.json.dist +++ b/box.json.dist @@ -2,6 +2,7 @@ "alias": "pie.phar", "output": "pie.phar", "git": "pie_version", + "stub": "phar-stub.php", "force-autodiscovery": true, "directories": [ "resources" diff --git a/phar-stub.php b/phar-stub.php new file mode 100644 index 00000000..79c9db6a --- /dev/null +++ b/phar-stub.php @@ -0,0 +1,19 @@ +#!/usr/bin/env php + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 79ea4916..dde554b7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -300,18 +300,6 @@ parameters: count: 4 path: src/Platform/TargetPhp/PhpBinaryPath.php - - - message: '#^Call to function array_key_exists\(\) with 2 and array\{non\-falsy\-string, string, non\-falsy\-string\} will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Platform/TargetPlatform.php - - - - message: '#^Strict comparison using \!\=\= between non\-falsy\-string and '''' will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: src/Platform/TargetPlatform.php - - message: '#^Dead catch \- Php\\Pie\\SelfManage\\Verify\\GithubCliNotAvailable is never thrown in the try block\.$#' identifier: catch.neverThrown diff --git a/src/Platform/TargetPhp/PhpBinaryPath.php b/src/Platform/TargetPhp/PhpBinaryPath.php index 1b2769fb..5a6c67ec 100644 --- a/src/Platform/TargetPhp/PhpBinaryPath.php +++ b/src/Platform/TargetPhp/PhpBinaryPath.php @@ -385,6 +385,20 @@ public function minorVersion(): int public function machineType(): Architecture { + /** + * On Windows, this will be x32 or x64; should not be used on other platforms + * + * Based on xdebug.org wizard, copyright Derick Rethans, used under MIT licence + * + * @link https://github.com/xdebug/xdebug.org/blob/aff649f2c3ca303ad471e6ed9dd29c0db16d3e22/src/XdebugVersion.php#L186-L190 + */ + if ( + $this->operatingSystem() === OperatingSystem::Windows + && preg_match('/Architecture([ =>\t]*)(x[0-9]*)/', $this->phpinfo(), $m) + ) { + return Architecture::parseArchitecture($m[2]); + } + $phpMachineType = self::cleanWarningAndDeprecationsFromOutput(Process::run([ $this->phpBinaryPath, '-r', @@ -392,7 +406,14 @@ public function machineType(): Architecture ])); Assert::stringNotEmpty($phpMachineType, 'Could not determine PHP machine type'); - return Architecture::parseArchitecture($phpMachineType); + $unameArchitecture = Architecture::parseArchitecture($phpMachineType); + + // If we're not on ARM, a more reliable way of determining 32-bit/64-bit is to use PHP_INT_SIZE + if ($unameArchitecture !== Architecture::arm64) { + return $this->phpIntSize() === 4 ? Architecture::x86 : Architecture::x86_64; + } + + return $unameArchitecture; } public function phpIntSize(): int diff --git a/src/Platform/TargetPlatform.php b/src/Platform/TargetPlatform.php index 5d351aae..e6eb7cae 100644 --- a/src/Platform/TargetPlatform.php +++ b/src/Platform/TargetPlatform.php @@ -8,7 +8,6 @@ use Php\Pie\Platform\TargetPhp\PhpBinaryPath; use Php\Pie\Platform\TargetPhp\PhpizePath; -use function array_key_exists; use function explode; use function function_exists; use function posix_getuid; @@ -52,31 +51,10 @@ public static function isRunningAsRoot(): bool public static function fromPhpBinaryPath(PhpBinaryPath $phpBinaryPath, int|null $makeParallelJobs, PhpizePath|null $phpizePath): self { - $os = $phpBinaryPath->operatingSystem(); - $osFamily = $phpBinaryPath->operatingSystemFamily(); - - $phpinfo = $phpBinaryPath->phpinfo(); - - $architecture = $phpBinaryPath->machineType(); - - // If we're not on ARM, a more reliable way of determining 32-bit/64-bit is to use PHP_INT_SIZE - if ($architecture !== Architecture::arm64) { - $architecture = $phpBinaryPath->phpIntSize() === 4 ? Architecture::x86 : Architecture::x86_64; - } - - /** - * Based on xdebug.org wizard, copyright Derick Rethans, used under MIT licence - * - * @link https://github.com/xdebug/xdebug.org/blob/aff649f2c3ca303ad471e6ed9dd29c0db16d3e22/src/XdebugVersion.php#L186-L190 - */ - if ( - preg_match('/Architecture([ =>\t]*)(x[0-9]*)/', $phpinfo, $m) - && array_key_exists(2, $m) - && $m[2] !== '' - ) { - $architecture = Architecture::parseArchitecture($m[2]); - } - + $os = $phpBinaryPath->operatingSystem(); + $osFamily = $phpBinaryPath->operatingSystemFamily(); + $phpinfo = $phpBinaryPath->phpinfo(); + $architecture = $phpBinaryPath->machineType(); $windowsCompiler = null; $threadSafety = ThreadSafetyMode::ThreadSafe; diff --git a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php index 4bd9a668..64151b07 100644 --- a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php +++ b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php @@ -30,22 +30,25 @@ use function array_map; use function array_unique; use function assert; +use function chmod; use function count; use function defined; use function dirname; use function file_exists; +use function file_put_contents; use function get_loaded_extensions; use function ini_get; use function is_dir; use function is_executable; use function mkdir; -use function php_uname; use function phpversion; use function sprintf; use function strtolower; use function sys_get_temp_dir; +use function tempnam; use function trim; use function uniqid; +use function unlink; use const DIRECTORY_SEPARATOR; use const PHP_INT_SIZE; @@ -241,15 +244,46 @@ public function testMajorMinorVersion(): void ); } - public function testMachineType(): void + /** @return list */ + public static function machineTypeProvider(): array { - $myUnameMachineType = php_uname('m'); - assert($myUnameMachineType !== ''); - self::assertSame( - Architecture::parseArchitecture($myUnameMachineType), - PhpBinaryPath::fromCurrentProcess() - ->machineType(), - ); + return [ + // x86 (32-bit) + [OperatingSystem::Windows, 'Architecture => x32', '', 4, Architecture::x86], + [OperatingSystem::NonWindows, 'Architecture => x86', 'x86', 4, Architecture::x86], + [OperatingSystem::NonWindows, '', 'x86', 4, Architecture::x86], + + // x86_64 (64-bit) + [OperatingSystem::Windows, 'Architecture => x64', 'AMD64', 8, Architecture::x86_64], + [OperatingSystem::Windows, 'Architecture => x64', '', 8, Architecture::x86_64], + [OperatingSystem::NonWindows, 'Architecture => x86_64', 'x86_64', 8, Architecture::x86_64], + [OperatingSystem::NonWindows, '', 'x86_64', 8, Architecture::x86_64], + + // arm64 + [OperatingSystem::NonWindows, 'Architecture => arm64', 'arm64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, '', 'arm64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, 'Architecture => aarch64', 'aarch64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, '', 'aarch64', 8, Architecture::arm64], + ]; + } + + #[RequiresOperatingSystemFamily('Linux')] + #[DataProvider('machineTypeProvider')] + public function testMachineType(OperatingSystem $os, string $phpinfo, string $uname, int $phpIntSize, Architecture $expectedArchitecture): void + { + $tmpSh = tempnam(sys_get_temp_dir(), uniqid('pie_machine_type_test')); + file_put_contents($tmpSh, "#!/usr/bin/env bash\necho \"" . $uname . "\";\n"); + chmod($tmpSh, 0777); + + $phpBinary = $this->createPartialMock(PhpBinaryPath::class, ['operatingSystem', 'phpinfo', 'phpIntSize']); + (new ReflectionMethod($phpBinary, '__construct'))->invoke($phpBinary, $tmpSh, null); + + $phpBinary->method('operatingSystem')->willReturn($os); + $phpBinary->method('phpinfo')->willReturn($phpinfo); + $phpBinary->method('phpIntSize')->willReturn($phpIntSize); + + self::assertEquals($expectedArchitecture, $phpBinary->machineType()); + unlink($tmpSh); } public function testPhpIntSize(): void diff --git a/test/unit/Platform/TargetPlatformTest.php b/test/unit/Platform/TargetPlatformTest.php index 87499da7..b9274b70 100644 --- a/test/unit/Platform/TargetPlatformTest.php +++ b/test/unit/Platform/TargetPlatformTest.php @@ -29,7 +29,7 @@ public function testWindowsPlatformFromPhpInfo(): void ->willReturn(OperatingSystemFamily::Windows); $phpBinaryPath->expects(self::any()) ->method('machineType') - ->willReturn(Architecture::x86); + ->willReturn(Architecture::x86_64); $phpBinaryPath->expects(self::any()) ->method('phpinfo') ->willReturn(<<<'TEXT' diff --git a/test/unit/SelfManage/Update/ReleaseIsNewerTest.php b/test/unit/SelfManage/Update/ReleaseIsNewerTest.php index ca44fea8..a1e06f8e 100644 --- a/test/unit/SelfManage/Update/ReleaseIsNewerTest.php +++ b/test/unit/SelfManage/Update/ReleaseIsNewerTest.php @@ -15,7 +15,7 @@ final class ReleaseIsNewerTest extends TestCase { /** @return array */ - public function provider(): array + public static function provider(): array { return [ 'stable-oldstable-to-newstable' => [Channel::Stable, '1.0.0', '1.0.1', true],