Add custom package downloader and extractor

This commit is contained in:
crazywhalecc 2025-06-18 20:55:24 +08:00
parent 8e2dffc3b5
commit f709f3bb18
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
4 changed files with 61 additions and 4 deletions

View File

@ -9,6 +9,7 @@ use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\pkg\CustomPackage;
use SPC\store\source\CustomSourceBase;
/**
@ -385,10 +386,13 @@ class Downloader
]);
break;
case 'custom': // Custom download method, like API-based download or other
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\store\source');
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg');
foreach ($classes as $class) {
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
(new $class())->fetch($force);
if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
$cls = new $class();
if (in_array($name, $cls->getSupportName())) {
(new $class())->fetch($name, $force, $pkg);
}
break;
}
}
@ -708,7 +712,6 @@ class Downloader
}
}
// If lock file exists for current arch and glibc target, skip downloading
if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && isset($lock[$lock_name = self::getPreBuiltLockName($name)])) {
// lock name with env
if (
@ -719,6 +722,17 @@ class Downloader
return true;
}
}
// If lock file exists, skip downloading for source mode
if (!$force && $download_as === SPC_DOWNLOAD_PACKAGE && isset($lock[$name])) {
if (
$lock[$name]['source_type'] === SPC_SOURCE_ARCHIVE && file_exists(DOWNLOAD_PATH . '/' . $lock[$name]['filename']) ||
$lock[$name]['source_type'] === SPC_SOURCE_GIT && is_dir(DOWNLOAD_PATH . '/' . $lock[$name]['dirname'])
) {
logger()->notice("Package [{$name}] already downloaded: " . ($lock[$name]['filename'] ?? $lock[$name]['dirname']));
return true;
}
}
return false;
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\store;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
use SPC\store\pkg\CustomPackage;
class PackageManager
{
@ -32,6 +33,20 @@ class PackageManager
// Download package
Downloader::downloadPackage($pkg_name, $config, $force);
if (Config::getPkg($pkg_name)['type'] === 'custom') {
// Custom extract function
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg');
foreach ($classes as $class) {
if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
$cls = new $class();
if (in_array($pkg_name, $cls->getSupportName())) {
(new $class())->extract($pkg_name);
break;
}
}
}
return;
}
// After download, read lock file name
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true);
$source_type = $lock[$pkg_name]['source_type'];

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\store\pkg;
abstract class CustomPackage
{
abstract public function getSupportName(): array;
abstract public function fetch(string $name, bool $force = false, ?array $config = null): void;
public function extract(string $name): void
{
throw new \RuntimeException("Extract method not implemented for package: {$name}");
}
}

View File

@ -102,6 +102,17 @@ function osfamily2dir(): string
};
}
function osfamily2shortname(): string
{
return match (PHP_OS_FAMILY) {
'Windows', 'WINNT', 'Cygwin' => 'win',
'Darwin' => 'macos',
'Linux' => 'linux',
'BSD' => 'bsd',
default => throw new WrongUsageException('Not support os: ' . PHP_OS_FAMILY),
};
}
function shell(?bool $debug = null): UnixShell
{
/* @noinspection PhpUnhandledExceptionInspection */