Do some code quality check and fix #126

This commit is contained in:
crazywhalecc
2023-08-20 19:51:45 +08:00
committed by Jerry Ma
parent 9c57ed6439
commit c8fa767576
104 changed files with 1040 additions and 785 deletions

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\store;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
/**
@@ -83,7 +82,6 @@ class Config
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public static function getExt(string $name, ?string $key = null, mixed $default = null)
@@ -126,6 +124,9 @@ class Config
return self::$ext;
}
/**
* @throws FileSystemException
*/
public static function getSources(): array
{
if (self::$source === null) {

View File

@@ -13,7 +13,7 @@ class CurlHook
* @param string $url 修改的链接
* @param array $headers 修改的 headers
*/
public static function setupGithubToken(string &$method, string &$url, array &$headers): void
public static function setupGithubToken(string $method, string $url, array &$headers): void
{
if (!getenv('GITHUB_TOKEN')) {
return;

View File

@@ -4,23 +4,22 @@ declare(strict_types=1);
namespace SPC\store;
use JetBrains\PhpStorm\ArrayShape;
use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\source\CustomSourceBase;
/**
* 资源下载器
* Source Downloader.
*/
class Downloader
{
/**
* 获取 BitBucket 仓库的最新 Tag
* Get latest version from BitBucket tag
*
* @param string $name 资源名称
* @param array $source 资源的元信息,包含字段 repo
* @return array<int, string> 返回下载 url 链接和文件名
* @param string $name source name
* @param array $source source meta info: [repo]
* @return array<int, string> [url, filename]
* @throws DownloaderException
*/
public static function getLatestBitbucketTag(string $name, array $source): array
@@ -49,10 +48,13 @@ class Downloader
}
/**
* 获取 GitHub 最新的打包地址和文件名
* Get latest version from GitHub tarball
*
* @param string $name source name
* @param array $source source meta info: [repo]
* @param string $type type of tarball, default is 'releases'
* @return array<int, string> [url, filename]
*
* @param string $name 包名称
* @param array $source 源信息
* @throws DownloaderException
*/
public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array
@@ -82,10 +84,11 @@ class Downloader
}
/**
* 获取 GitHub 最新的 Release 下载信息
* Get latest version from GitHub release (uploaded archive)
*
* @param string $name 资源名
* @param array $source 资源的元信息,包含字段 repomatch
* @param string $name source name
* @param array $source source meta info: [repo, match]
* @return array<int, string> [url, filename]
* @throws DownloaderException
*/
public static function getLatestGithubRelease(string $name, array $source): array
@@ -111,10 +114,11 @@ class Downloader
}
/**
* 获取文件列表的资源链接和名称
* Get latest version from file list (regex based crawler)
*
* @param string $name 资源名称
* @param array $source 资源元信息,包含 urlregex
* @param string $name source name
* @param array $source source meta info: [url, regex]
* @return array<int, string> [url, filename]
* @throws DownloaderException
*/
public static function getFromFileList(string $name, array $source): array
@@ -149,6 +153,8 @@ class Downloader
}
/**
* Just download file using system curl command, and lock it
*
* @throws DownloaderException
* @throws RuntimeException
* @throws FileSystemException
@@ -168,6 +174,11 @@ class Downloader
self::lockSource($name, ['source_type' => 'archive', 'filename' => $filename, 'move_path' => $move_path]);
}
/**
* Try to lock source.
*
* @throws FileSystemException
*/
public static function lockSource(string $name, array $data): void
{
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
@@ -180,40 +191,11 @@ class Downloader
}
/**
* 通过链接下载资源到本地并解压
* Download git source, and lock it.
*
* @param string $name 资源名称
* @param string $url 下载链接
* @param string $filename 下载到下载目录的目标文件名称,例如 xz.tar.gz
* @param null|string $path 如果指定了此参数,则会移动该资源目录到目标目录
* @throws FileSystemException
* @throws RuntimeException
* @throws DownloaderException
*/
public static function downloadUrl(string $name, string $url, string $filename, ?string $path = null): void
{
if (!file_exists(DOWNLOAD_PATH . "/{$filename}")) {
logger()->debug("downloading {$url}");
self::curlDown(url: $url, path: DOWNLOAD_PATH . "/{$filename}");
} else {
logger()->notice("{$filename} already exists");
}
FileSystem::extractSource($name, DOWNLOAD_PATH . "/{$filename}");
if ($path) {
$path = FileSystem::convertPath(SOURCE_PATH . "/{$path}");
$src_path = FileSystem::convertPath(SOURCE_PATH . "/{$name}");
switch (PHP_OS_FAMILY) {
case 'Windows':
f_passthru('move "' . $src_path . '" "' . $path . '"');
break;
case 'Linux':
case 'Darwin':
f_passthru('mv "' . $src_path . '" "' . $path . '"');
break;
}
}
}
public static function downloadGit(string $name, string $url, string $branch, ?string $move_path = null): void
{
$download_path = DOWNLOAD_PATH . "/{$name}";
@@ -257,10 +239,10 @@ class Downloader
}
/**
* 拉取资源
* Download source by name and meta.
*
* @param string $name 资源名称
* @param null|array $source 资源参数,包含 typepathrevurlfilenameregexlicense
* @param string $name source name
* @param null|array $source source meta info: [type, path, rev, url, filename, regex, license]
* @throws DownloaderException
* @throws FileSystemException
* @throws RuntimeException
@@ -291,35 +273,35 @@ class Downloader
try {
switch ($source['type']) {
case 'bitbuckettag': // BitBucket Tag 拉取
case 'bitbuckettag': // BitBucket Tag
[$url, $filename] = self::getLatestBitbucketTag($name, $source);
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'ghtar': // GitHub 的 TarBall 拉取
case 'ghtar': // GitHub Release (tar)
[$url, $filename] = self::getLatestGithubTarball($name, $source);
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'ghtagtar': // 根据 GitHub Tag 拉取相应版本的 Tar
case 'ghtagtar': // GitHub Tag (tar)
[$url, $filename] = self::getLatestGithubTarball($name, $source, 'tags');
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'ghrel': // 通过 GitHub Release 来拉取
case 'ghrel': // GitHub Release (uploaded)
[$url, $filename] = self::getLatestGithubRelease($name, $source);
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'filelist': // 通过网站提供的 filelist 使用正则提取后拉取
case 'filelist': // Basic File List (regex based crawler)
[$url, $filename] = self::getFromFileList($name, $source);
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'url': // 通过直链拉取
case 'url': // Direct download URL
$url = $source['url'];
$filename = $source['filename'] ?? basename($source['url']);
self::downloadFile($name, $url, $filename, $source['path'] ?? null);
break;
case 'git': // 通过拉回 Git 仓库的形式拉取
case 'git': // Git repo
self::downloadGit($name, $source['url'], $source['rev'], $source['path'] ?? null);
break;
case 'custom': // 自定义,可能是通过复杂 API 形式获取的文件,需要手写 crawler
case 'custom': // Custom download method, like API-based download or other
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\\store\\source');
foreach ($classes as $class) {
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
@@ -332,7 +314,8 @@ class Downloader
throw new DownloaderException('unknown source type: ' . $source['type']);
}
} catch (RuntimeException $e) {
// 因为某些时候通过命令行下载的文件在失败后不会删除,这里检测到文件存在需要手动删一下
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
// Here we need to manually delete the file if it is detected to exist.
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
logger()->warning('Deleting download file: ' . $filename);
unlink(DOWNLOAD_PATH . '/' . $filename);
@@ -342,27 +325,7 @@ class Downloader
}
/**
* 获取 PHP x.y 的具体版本号,例如通过 8.1 来获取 8.1.10
*
* @throws DownloaderException
*/
#[ArrayShape(['type' => 'string', 'path' => 'string', 'rev' => 'string', 'url' => 'string'])]
public static function getLatestPHPInfo(string $major_version): array
{
// 查找最新的小版本号
$info = json_decode(self::curlExec(url: "https://www.php.net/releases/index.php?json&version={$major_version}"), true);
$version = $info['version'];
// 从官网直接下载
return [
'type' => 'url',
'url' => "https://www.php.net/distributions/php-{$version}.tar.gz",
// 'url' => "https://mirrors.zhamao.xin/php/php-{$version}.tar.gz",
];
}
/**
* 使用 curl 命令拉取元信息
* Use curl command to get http response
*
* @throws DownloaderException
*/
@@ -408,7 +371,7 @@ class Downloader
}
/**
* 使用 curl 命令下载文件
* Use curl to download sources from url
*
* @throws DownloaderException
* @throws RuntimeException

View File

@@ -55,23 +55,25 @@ class FileSystem
/**
* @throws FileSystemException
*/
public static function replaceFile(string $filename, int $replace_type = REPLACE_FILE_STR, mixed $callback_or_search = null, mixed $to_replace = null): bool|int
public static function replaceFileStr(string $filename, mixed $search = null, mixed $replace = null): bool|int
{
logger()->debug('Replacing file with type[' . $replace_type . ']: ' . $filename);
$file = self::readFile($filename);
switch ($replace_type) {
case REPLACE_FILE_STR:
default:
$file = str_replace($callback_or_search, $to_replace, $file);
break;
case REPLACE_FILE_PREG:
$file = preg_replace($callback_or_search, $to_replace, $file);
break;
case REPLACE_FILE_USER:
$file = $callback_or_search($file);
break;
}
return file_put_contents($filename, $file);
return self::replaceFile($filename, REPLACE_FILE_STR, $search, $replace);
}
/**
* @throws FileSystemException
*/
public static function replaceFileRegex(string $filename, mixed $search = null, mixed $replace = null): bool|int
{
return self::replaceFile($filename, REPLACE_FILE_PREG, $search, $replace);
}
/**
* @throws FileSystemException
*/
public static function replaceFileUser(string $filename, mixed $callback = null): bool|int
{
return self::replaceFile($filename, REPLACE_FILE_USER, $callback);
}
/**
@@ -117,6 +119,9 @@ class FileSystem
return null;
}
/**
* @throws RuntimeException
*/
public static function copyDir(string $from, string $to): void
{
$dst_path = FileSystem::convertPath($to);
@@ -384,6 +389,9 @@ class FileSystem
return rmdir($dir);
}
/**
* @throws FileSystemException
*/
public static function createDir(string $path): void
{
if (!is_dir($path) && !f_mkdir($path, 0755, true) && !is_dir($path)) {
@@ -391,7 +399,11 @@ class FileSystem
}
}
public static function writeFile(string $path, $content, ...$args): bool|string|int
/**
* @param mixed ...$args Arguments passed to file_put_contents
* @throws FileSystemException
*/
public static function writeFile(string $path, mixed $content, ...$args): bool|string|int
{
$dir = pathinfo($path, PATHINFO_DIRNAME);
if (!is_dir($dir) && !mkdir($dir, 0755, true)) {
@@ -413,7 +425,7 @@ class FileSystem
self::createDir($dir_name);
}
public static function addSourceExtractHook(string $name, callable $callback)
public static function addSourceExtractHook(string $name, callable $callback): void
{
self::$_extract_hook[$name][] = $callback;
}
@@ -425,14 +437,35 @@ class FileSystem
*/
public static function isRelativePath(string $path): bool
{
// 适配 Windows 的多盘符目录形式
if (DIRECTORY_SEPARATOR === '\\') {
return !(strlen($path) > 2 && ctype_alpha($path[0]) && $path[1] === ':');
}
return strlen($path) > 0 && $path[0] !== '/';
}
private static function emitSourceExtractHook(string $name)
/**
* @throws FileSystemException
*/
private static function replaceFile(string $filename, int $replace_type = REPLACE_FILE_STR, mixed $callback_or_search = null, mixed $to_replace = null): bool|int
{
logger()->debug('Replacing file with type[' . $replace_type . ']: ' . $filename);
$file = self::readFile($filename);
switch ($replace_type) {
case REPLACE_FILE_STR:
default:
$file = str_replace($callback_or_search, $to_replace, $file);
break;
case REPLACE_FILE_PREG:
$file = preg_replace($callback_or_search, $to_replace, $file);
break;
case REPLACE_FILE_USER:
$file = $callback_or_search($file);
break;
}
return file_put_contents($filename, $file);
}
private static function emitSourceExtractHook(string $name): void
{
foreach ((self::$_extract_hook[$name] ?? []) as $hook) {
if ($hook() === true) {

View File

@@ -4,10 +4,17 @@ declare(strict_types=1);
namespace SPC\store;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class SourceExtractor
{
/**
* @throws WrongUsageException
* @throws FileSystemException
* @throws RuntimeException
*/
public static function initSource(?array $sources = null, ?array $libs = null, ?array $exts = null): void
{
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {

View File

@@ -11,7 +11,7 @@ use SPC\exception\RuntimeException;
class SourcePatcher
{
public static function init()
public static function init(): void
{
// FileSystem::addSourceExtractHook('swow', [SourcePatcher::class, 'patchSwow']);
FileSystem::addSourceExtractHook('micro', [SourcePatcher::class, 'patchMicro']);
@@ -46,9 +46,13 @@ class SourcePatcher
}
}
// patch capstone
FileSystem::replaceFile(SOURCE_PATH . '/php-src/configure', REPLACE_FILE_PREG, '/have_capstone="yes"/', 'have_capstone="no"');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"');
}
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public static function patchMicro(?array $list = null, bool $reverse = false): bool
{
if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) {
@@ -66,7 +70,7 @@ class SourcePatcher
if ($major_ver === '74') {
return false;
}
$check = !defined('DEBUG_MODE') ? ' -q' : '';
// $check = !defined('DEBUG_MODE') ? ' -q' : '';
// f_passthru('cd ' . SOURCE_PATH . '/php-src && git checkout' . $check . ' HEAD');
$default = [
@@ -113,15 +117,13 @@ class SourcePatcher
return true;
}
/**
* @throws FileSystemException
*/
public static function patchOpenssl11Darwin(): bool
{
if (PHP_OS_FAMILY === 'Darwin' && !file_exists(SOURCE_PATH . '/openssl/VERSION.dat') && file_exists(SOURCE_PATH . '/openssl/test/v3ext.c')) {
FileSystem::replaceFile(
SOURCE_PATH . '/openssl/test/v3ext.c',
REPLACE_FILE_STR,
'#include <stdio.h>',
'#include <stdio.h>' . PHP_EOL . '#include <string.h>'
);
FileSystem::replaceFileStr(SOURCE_PATH . '/openssl/test/v3ext.c', '#include <stdio.h>', '#include <stdio.h>' . PHP_EOL . '#include <string.h>');
return true;
}
return false;
@@ -134,10 +136,10 @@ class SourcePatcher
{
// Try to fix debian environment build lack HAVE_STRLCAT problem
if ($builder instanceof LinuxBuilder) {
FileSystem::replaceFile(SOURCE_PATH . '/php-src/main/php_config.h', REPLACE_FILE_PREG, '/^#define HAVE_STRLCPY 1$/m', '');
FileSystem::replaceFile(SOURCE_PATH . '/php-src/main/php_config.h', REPLACE_FILE_PREG, '/^#define HAVE_STRLCAT 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCPY 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCAT 1$/m', '');
}
FileSystem::replaceFile(SOURCE_PATH . '/php-src/main/php_config.h', REPLACE_FILE_PREG, '/^#define HAVE_OPENPTY 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_OPENPTY 1$/m', '');
// call extension patch before make
foreach ($builder->getExts() as $ext) {
@@ -158,7 +160,7 @@ class SourcePatcher
$micro_c_bak = SOURCE_PATH . '/php-src/sapi/micro/php_micro.c.bak';
// Try to reverse backup file
$find_pattern = 'const char HARDCODED_INI[] =';
$find_str = 'const char HARDCODED_INI[] =';
$patch_str = '';
foreach ($ini as $key => $value) {
$patch_str .= "\"{$key}={$value}\\n\"\n";
@@ -178,8 +180,8 @@ class SourcePatcher
}
// Patch it
FileSystem::replaceFile($cli_c, REPLACE_FILE_STR, $find_pattern, $patch_str);
FileSystem::replaceFile($micro_c, REPLACE_FILE_STR, $find_pattern, $patch_str);
FileSystem::replaceFileStr($cli_c, $find_str, $patch_str);
FileSystem::replaceFileStr($micro_c, $find_str, $patch_str);
return true;
}

View File

@@ -6,6 +6,7 @@ namespace SPC\store\source;
use JetBrains\PhpStorm\ArrayShape;
use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\Downloader;
@@ -16,8 +17,9 @@ class PhpSource extends CustomSourceBase
/**
* @throws DownloaderException
* @throws RuntimeException
* @throws FileSystemException
*/
public function fetch()
public function fetch(): void
{
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.1';
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major));

View File

@@ -4,20 +4,31 @@ declare(strict_types=1);
namespace SPC\store\source;
use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\Downloader;
class PostgreSQLSource extends CustomSourceBase
{
public const NAME = 'postgresql';
public function fetch()
/**
* @throws DownloaderException
* @throws RuntimeException
* @throws FileSystemException
*/
public function fetch(): void
{
Downloader::downloadSource('postgresql', self::getLatestInfo());
}
/**
* @throws DownloaderException
*/
public function getLatestInfo(): array
{
[$url, $filename, $version] = Downloader::getFromFileList('postgresql', [
[, $filename, $version] = Downloader::getFromFileList('postgresql', [
'url' => 'https://www.postgresql.org/ftp/source/',
'regex' => '/href="(?<file>v(?<version>[^"]+)\/)"/',
]);