mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-09 01:45:36 +08:00
Add PECL download type and support for PECL artifacts
This commit is contained in:
@@ -163,7 +163,7 @@ class ArtifactCache
|
||||
throw new SPCInternalException("Invalid lock type '{$lock_type}' for artifact {$artifact_name}");
|
||||
}
|
||||
// save cache to file
|
||||
file_put_contents($this->cache_file, json_encode($this->cache, JSON_PRETTY_PRINT));
|
||||
file_put_contents($this->cache_file, json_encode($this->cache, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +281,7 @@ class ArtifactCache
|
||||
*/
|
||||
public function save(): void
|
||||
{
|
||||
file_put_contents($this->cache_file, json_encode($this->cache, JSON_PRETTY_PRINT));
|
||||
file_put_contents($this->cache_file, json_encode($this->cache, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
private function isObjectDownloaded(?array $object, bool $compare_hash = false): bool
|
||||
|
||||
@@ -22,7 +22,7 @@ class Git implements DownloadTypeInterface, CheckUpdateInterface
|
||||
if (isset($config['rev'])) {
|
||||
default_shell()->executeGitClone($config['url'], $config['rev'], $path, $shallow, $config['submodules'] ?? null);
|
||||
$shell = PHP_OS_FAMILY === 'Windows' ? cmd(false) : shell(false);
|
||||
$hash_result = $shell->execWithResult(SPC_GIT_EXEC . ' -C ' . escapeshellarg($path) . ' rev-parse HEAD');
|
||||
$hash_result = $shell->execWithResult(SPC_GIT_EXEC . ' -C ' . escapeshellarg($path) . ' rev-parse --short HEAD');
|
||||
$hash = ($hash_result[0] === 0 && !empty($hash_result[1])) ? trim($hash_result[1][0]) : '';
|
||||
$version = $hash !== '' ? "dev-{$config['rev']}+{$hash}" : "dev-{$config['rev']}";
|
||||
return DownloadResult::git($name, $config, extract: $config['extract'] ?? null, version: $version, downloader: static::class);
|
||||
@@ -80,7 +80,7 @@ class Git implements DownloadTypeInterface, CheckUpdateInterface
|
||||
if ($result[0] !== 0 || empty($result[1])) {
|
||||
throw new DownloaderException("Failed to ls-remote from {$config['url']}");
|
||||
}
|
||||
$new_hash = substr($result[1][0], 0, 40);
|
||||
$new_hash = substr($result[1][0], 0, 7);
|
||||
$new_version = "dev-{$config['rev']}+{$new_hash}";
|
||||
// Extract stored hash from "dev-{rev}+{hash}", null if bare mode or old format without hash
|
||||
$old_hash = ($old_version !== null && str_contains($old_version, '+')) ? substr(strrchr($old_version, '+'), 1) : null;
|
||||
|
||||
79
src/StaticPHP/Artifact/Downloader/Type/PECL.php
Normal file
79
src/StaticPHP/Artifact/Downloader/Type/PECL.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace StaticPHP\Artifact\Downloader\Type;
|
||||
|
||||
use StaticPHP\Artifact\ArtifactDownloader;
|
||||
use StaticPHP\Artifact\Downloader\DownloadResult;
|
||||
use StaticPHP\Exception\DownloaderException;
|
||||
|
||||
/* pecl */
|
||||
class PECL implements DownloadTypeInterface, CheckUpdateInterface
|
||||
{
|
||||
private const string PECL_BASE_URL = 'https://pecl.php.net';
|
||||
|
||||
/** REST API: returns XML with <r><v>VERSION</v><s>STATE</s></r> per release */
|
||||
private const string PECL_REST_URL = 'https://pecl.php.net/rest/r/%s/allreleases.xml';
|
||||
|
||||
public function checkUpdate(string $name, array $config, ?string $old_version, ArtifactDownloader $downloader): CheckUpdateResult
|
||||
{
|
||||
[, $version] = $this->fetchPECLInfo($name, $config, $downloader);
|
||||
return new CheckUpdateResult(
|
||||
old: $old_version,
|
||||
new: $version,
|
||||
needUpdate: $old_version === null || version_compare($version, $old_version, '>'),
|
||||
);
|
||||
}
|
||||
|
||||
public function download(string $name, array $config, ArtifactDownloader $downloader): DownloadResult
|
||||
{
|
||||
[$filename, $version] = $this->fetchPECLInfo($name, $config, $downloader);
|
||||
$url = self::PECL_BASE_URL . '/get/' . $filename;
|
||||
$path = DOWNLOAD_PATH . DIRECTORY_SEPARATOR . $filename;
|
||||
logger()->debug("Downloading {$name} from URL: {$url}");
|
||||
default_shell()->executeCurlDownload($url, $path, retries: $downloader->getRetry());
|
||||
$extract = $config['extract'] ?? ('php-src/ext/' . $this->getExtractName($name));
|
||||
return DownloadResult::archive($filename, $config, $extract, version: $version, downloader: static::class);
|
||||
}
|
||||
|
||||
protected function fetchPECLInfo(string $name, array $config, ArtifactDownloader $downloader): array
|
||||
{
|
||||
$peclName = strtolower($config['name'] ?? $this->getExtractName($name));
|
||||
$url = sprintf(self::PECL_REST_URL, $peclName);
|
||||
logger()->debug("Fetching PECL release list for {$name} from REST API");
|
||||
$xml = default_shell()->executeCurl($url, retries: $downloader->getRetry());
|
||||
if ($xml === false) {
|
||||
throw new DownloaderException("Failed to fetch PECL release list for {$name}");
|
||||
}
|
||||
// Match <r><v>VERSION</v><s>STATE</s></r>
|
||||
preg_match_all('/<r><v>(?P<version>[^<]+)<\/v><s>(?P<state>[^<]+)<\/s><\/r>/', $xml, $matches);
|
||||
if (empty($matches['version'])) {
|
||||
throw new DownloaderException("Failed to parse PECL release list for {$name}");
|
||||
}
|
||||
$versions = [];
|
||||
logger()->debug('Matched ' . count($matches['version']) . " releases for {$name} from PECL");
|
||||
foreach ($matches['version'] as $i => $version) {
|
||||
if ($matches['state'][$i] !== 'stable') {
|
||||
continue;
|
||||
}
|
||||
$versions[$version] = $peclName . '-' . $version . '.tgz';
|
||||
}
|
||||
if (empty($versions)) {
|
||||
throw new DownloaderException("No stable releases found for {$name} on PECL");
|
||||
}
|
||||
uksort($versions, 'version_compare');
|
||||
$filename = end($versions);
|
||||
$version = array_key_last($versions);
|
||||
return [$filename, $version, $versions];
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the lowercase PECL package / extract name from the artifact name.
|
||||
* e.g. "ext-apcu" -> "apcu", "ext-ast" -> "ast"
|
||||
*/
|
||||
private function getExtractName(string $name): string
|
||||
{
|
||||
return strtolower(preg_replace('/^ext-/i', '', $name));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user