Allow automatically get latest gRPC source (#909)

This commit is contained in:
crazywhalecc 2025-12-11 15:51:32 +08:00
parent 88d135a4e5
commit fefcbf4029
3 changed files with 54 additions and 5 deletions

View File

@ -399,7 +399,7 @@
"binary": "hosted",
"source": {
"type": "git",
"rev": "v1.75.x",
"regex": "v(?<version>1.\\d+).x",
"url": "https://github.com/grpc/grpc.git"
}
},

View File

@ -6,6 +6,8 @@ namespace StaticPHP\Artifact\Downloader\Type;
use StaticPHP\Artifact\ArtifactDownloader;
use StaticPHP\Artifact\Downloader\DownloadResult;
use StaticPHP\Exception\DownloaderException;
use StaticPHP\Util\FileSystem;
/** git */
class Git implements DownloadTypeInterface
@ -15,8 +17,55 @@ class Git implements DownloadTypeInterface
$path = DOWNLOAD_PATH . "/{$name}";
logger()->debug("Cloning git repository for {$name} from {$config['url']}");
$shallow = !$downloader->getOption('no-shallow-clone', false);
default_shell()->executeGitClone($config['url'], $config['rev'], $path, $shallow, $config['submodules'] ?? null);
$version = "dev-{$config['rev']}";
return DownloadResult::git($name, $config, extract: $config['extract'] ?? null, version: $version);
// direct branch clone
if (isset($config['rev'])) {
default_shell()->executeGitClone($config['url'], $config['rev'], $path, $shallow, $config['submodules'] ?? null);
$version = "dev-{$config['rev']}";
return DownloadResult::git($name, $config, extract: $config['extract'] ?? null, version: $version);
}
if (!isset($config['regex'])) {
throw new DownloaderException('Either "rev" or "regex" must be specified for git download type.');
}
// regex matches branch first, we need to fetch all refs in emptyfirst
$gitdir = sys_get_temp_dir() . '/' . $name;
FileSystem::resetDir($gitdir);
$shell = PHP_OS_FAMILY === 'Windows' ? cmd(false) : shell(false);
$result = $shell->cd($gitdir)
->exec(SPC_GIT_EXEC . ' init')
->exec(SPC_GIT_EXEC . ' remote add origin ' . escapeshellarg($config['url']))
->execWithResult(SPC_GIT_EXEC . ' ls-remote origin');
if ($result[0] !== 0) {
throw new DownloaderException("Failed to ls-remote from {$config['url']}");
}
$refs = $result[1];
$matched_version_branch = [];
$matched_count = 0;
$regex = '/^' . $config['regex'] . '$/';
foreach ($refs as $ref) {
$matches = null;
if (preg_match('/^[0-9a-f]{40}\s+refs\/heads\/(.+)$/', $ref, $matches)) {
++$matched_count;
$branch = $matches[1];
if (preg_match($regex, $branch, $vermatch) && isset($vermatch['version'])) {
$matched_version_branch[$vermatch['version']] = $vermatch[0];
}
}
}
// sort versions
uksort($matched_version_branch, function ($a, $b) {
return version_compare($b, $a);
});
if (!empty($matched_version_branch)) {
// use the highest version
$version = array_key_first($matched_version_branch);
$branch = $matched_version_branch[$version];
logger()->info("Matched version {$version} from branch {$branch} for {$name}");
default_shell()->executeGitClone($config['url'], $branch, $path, $shallow, $config['submodules'] ?? null);
return DownloadResult::git($name, $config, extract: $config['extract'] ?? null, version: $version);
}
throw new DownloaderException("No matching branch found for regex {$config['regex']} (checked {$matched_count} branches).");
}
}

View File

@ -79,7 +79,7 @@ class ConfigValidator
public const array ARTIFACT_TYPE_FIELDS = [ // [required_fields, optional_fields]
'filelist' => [['url', 'regex'], ['extract']],
'git' => [['url', 'rev'], ['extract', 'submodules']],
'git' => [['url'], ['extract', 'submodules', 'rev', 'regex']],
'ghtagtar' => [['repo'], ['extract', 'prefer-stable', 'match']],
'ghtar' => [['repo'], ['extract', 'prefer-stable', 'match']],
'ghrel' => [['repo', 'match'], ['extract', 'prefer-stable']],