Add support for custom source check-update callbacks in artifacts

This commit is contained in:
crazywhalecc
2026-02-28 14:35:48 +08:00
parent 0a07f6b27c
commit 28f4a5c523
4 changed files with 107 additions and 11 deletions

View File

@@ -27,6 +27,9 @@ class Artifact
/** @var null|callable Bind custom source fetcher callback */
protected mixed $custom_source_callback = null;
/** @var null|callable Bind custom source check-update callback */
protected mixed $custom_source_check_update_callback = null;
/** @var array<string, callable> Bind custom binary fetcher callbacks */
protected mixed $custom_binary_callbacks = [];
@@ -408,6 +411,19 @@ class Artifact
return $this->custom_source_callback ?? null;
}
/**
* Set custom source check-update callback.
*/
public function setCustomSourceCheckUpdateCallback(callable $callback): void
{
$this->custom_source_check_update_callback = $callback;
}
public function getCustomSourceCheckUpdateCallback(): ?callable
{
return $this->custom_source_check_update_callback ?? null;
}
public function getCustomBinaryCallback(): ?callable
{
$current_platform = SystemTarget::getCurrentPlatformString();

View File

@@ -332,17 +332,14 @@ class ArtifactDownloader
throw new WrongUsageException("Artifact '{$artifact_name}' not found, please check the name.");
}
if ($bare) {
$config = $artifact->getDownloadConfig('source');
if (!is_array($config)) {
throw new WrongUsageException("Artifact '{$artifact_name}' has no source config for bare update check.");
[$first, $second] = $prefer_source
? [fn () => $this->probeSourceCheckUpdate($artifact, $artifact_name), fn () => $this->probeBinaryCheckUpdate($artifact, $artifact_name)]
: [fn () => $this->probeBinaryCheckUpdate($artifact, $artifact_name), fn () => $this->probeSourceCheckUpdate($artifact, $artifact_name)];
$result = $first() ?? $second();
if ($result !== null) {
return $result;
}
$cls = $this->downloaders[$config['type']] ?? null;
if (!is_a($cls, CheckUpdateInterface::class, true)) {
throw new WrongUsageException("Artifact '{$artifact_name}' downloader does not support update checking.");
}
/** @var CheckUpdateInterface $downloader */
$downloader = new $cls();
return $downloader->checkUpdate($artifact_name, $config, null, $this);
throw new WrongUsageException("Artifact '{$artifact_name}' downloader does not support update checking.");
}
$cache = ApplicationContext::get(ArtifactCache::class);
if ($prefer_source) {
@@ -358,7 +355,15 @@ class ArtifactDownloader
/** @var CheckUpdateInterface $downloader */
$downloader = new $cls();
return $downloader->checkUpdate($artifact_name, $info['config'], $info['version'], $this);
} // custom binary: delegate to registered check-update callback
}
// custom source: delegate to registered check-update callback
if (($info['lock_type'] ?? null) === 'source' && ($callback = $artifact->getCustomSourceCheckUpdateCallback()) !== null) {
return ApplicationContext::invoke($callback, [
ArtifactDownloader::class => $this,
'old_version' => $info['version'],
]);
}
// custom binary: delegate to registered check-update callback
if (($callback = $artifact->getCustomBinaryCheckUpdateCallback()) !== null) {
return ApplicationContext::invoke($callback, [
ArtifactDownloader::class => $this,
@@ -383,6 +388,50 @@ class ArtifactDownloader
return $this->options[$name] ?? $default;
}
private function probeSourceCheckUpdate(Artifact $artifact, string $artifact_name): ?CheckUpdateResult
{
if (($callback = $artifact->getCustomSourceCheckUpdateCallback()) !== null) {
return ApplicationContext::invoke($callback, [
ArtifactDownloader::class => $this,
'old_version' => null,
]);
}
$config = $artifact->getDownloadConfig('source');
if (!is_array($config)) {
return null;
}
$cls = $this->downloaders[$config['type']] ?? null;
if (!is_a($cls, CheckUpdateInterface::class, true)) {
return null;
}
/** @var CheckUpdateInterface $dl */
$dl = new $cls();
return $dl->checkUpdate($artifact_name, $config, null, $this);
}
private function probeBinaryCheckUpdate(Artifact $artifact, string $artifact_name): ?CheckUpdateResult
{
// custom binary callback takes precedence over config-based binary
if (($callback = $artifact->getCustomBinaryCheckUpdateCallback()) !== null) {
return ApplicationContext::invoke($callback, [
ArtifactDownloader::class => $this,
'old_version' => null,
]);
}
$binary_config = $artifact->getDownloadConfig('binary');
$platform_config = is_array($binary_config) ? ($binary_config[SystemTarget::getCurrentPlatformString()] ?? null) : null;
if (!is_array($platform_config)) {
return null;
}
$cls = $this->downloaders[$platform_config['type']] ?? null;
if (!is_a($cls, CheckUpdateInterface::class, true)) {
return null;
}
/** @var CheckUpdateInterface $dl */
$dl = new $cls();
return $dl->checkUpdate($artifact_name, $platform_config, null, $this);
}
private function downloadWithType(Artifact $artifact, int $current, int $total, bool $parallel = false, bool $interactive = true): int
{
$queue = $this->generateQueue($artifact);