mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-03 06:45:39 +08:00
Add retry mechanism to Git clone and GitHub release fetching methods
This commit is contained in:
@@ -23,13 +23,13 @@ class go_win
|
||||
$pkgroot = PKG_ROOT_PATH;
|
||||
|
||||
// get version
|
||||
[$version] = explode("\n", default_shell()->executeCurl('https://go.dev/VERSION?m=text') ?: '');
|
||||
[$version] = explode("\n", default_shell()->executeCurl('https://go.dev/VERSION?m=text', retries: $downloader->getRetry()) ?: '');
|
||||
if ($version === '') {
|
||||
throw new DownloaderException('Failed to get latest Go version from https://go.dev/VERSION?m=text');
|
||||
}
|
||||
|
||||
// find SHA256 hash from download page
|
||||
$page = default_shell()->executeCurl('https://go.dev/dl/');
|
||||
$page = default_shell()->executeCurl('https://go.dev/dl/', retries: $downloader->getRetry());
|
||||
if ($page === '' || $page === false) {
|
||||
throw new DownloaderException('Failed to get Go download page from https://go.dev/dl/');
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ class go_xcaddy
|
||||
};
|
||||
|
||||
// get version and hash
|
||||
[$version] = explode("\n", default_shell()->executeCurl('https://go.dev/VERSION?m=text') ?: '');
|
||||
[$version] = explode("\n", default_shell()->executeCurl('https://go.dev/VERSION?m=text', retries: $downloader->getRetry()) ?: '');
|
||||
if ($version === '') {
|
||||
throw new DownloaderException('Failed to get latest Go version from https://go.dev/VERSION?m=text');
|
||||
}
|
||||
$page = default_shell()->executeCurl('https://go.dev/dl/');
|
||||
$page = default_shell()->executeCurl('https://go.dev/dl/', retries: $downloader->getRetry());
|
||||
if ($page === '' || $page === false) {
|
||||
throw new DownloaderException('Failed to get Go download page from https://go.dev/dl/');
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class Git implements DownloadTypeInterface, CheckUpdateInterface
|
||||
|
||||
// direct branch clone
|
||||
if (isset($config['rev'])) {
|
||||
default_shell()->executeGitClone($config['url'], $config['rev'], $path, $shallow, $config['submodules'] ?? null);
|
||||
default_shell()->executeGitClone($config['url'], $config['rev'], $path, $shallow, $config['submodules'] ?? null, $downloader->getRetry());
|
||||
$shell = PHP_OS_FAMILY === 'Windows' ? cmd(false) : shell(false);
|
||||
$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]) : '';
|
||||
@@ -66,7 +66,7 @@ class Git implements DownloadTypeInterface, CheckUpdateInterface
|
||||
$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);
|
||||
default_shell()->executeGitClone($config['url'], $branch, $path, $shallow, $config['submodules'] ?? null, $downloader->getRetry());
|
||||
return DownloadResult::git($name, $config, extract: $config['extract'] ?? null, version: $version, downloader: static::class);
|
||||
}
|
||||
throw new DownloaderException("No matching branch found for regex {$config['regex']} (checked {$matched_count} branches).");
|
||||
|
||||
@@ -21,13 +21,13 @@ class GitHubRelease implements DownloadTypeInterface, ValidatorInterface, CheckU
|
||||
|
||||
private ?string $version = null;
|
||||
|
||||
public function getGitHubReleases(string $name, string $repo, bool $prefer_stable = true, ?string $query = null): array
|
||||
public function getGitHubReleases(string $name, string $repo, bool $prefer_stable = true, ?string $query = null, int $retries = 0): array
|
||||
{
|
||||
logger()->debug("Fetching {$name} GitHub releases from {$repo}");
|
||||
$url = str_replace('{repo}', $repo, self::API_URL);
|
||||
$url .= ($query ?? '');
|
||||
$headers = $this->getGitHubTokenHeaders();
|
||||
$data2 = default_shell()->executeCurl($url, headers: $headers);
|
||||
$data2 = default_shell()->executeCurl($url, headers: $headers, retries: $retries);
|
||||
$data = json_decode($data2 ?: '', true);
|
||||
if (!is_array($data)) {
|
||||
throw new DownloaderException("Failed to get GitHub release API info for {$repo} from {$url}");
|
||||
@@ -46,13 +46,13 @@ class GitHubRelease implements DownloadTypeInterface, ValidatorInterface, CheckU
|
||||
* Get the latest GitHub release assets for a given repository.
|
||||
* match_asset is provided, only return the asset that matches the regex.
|
||||
*/
|
||||
public function getLatestGitHubRelease(string $name, string $repo, bool $prefer_stable, string $match_asset, ?string $query = null): array
|
||||
public function getLatestGitHubRelease(string $name, string $repo, bool $prefer_stable, string $match_asset, ?string $query = null, int $retries = 0): array
|
||||
{
|
||||
logger()->debug("Fetching {$name} GitHub release from {$repo}");
|
||||
$url = str_replace('{repo}', $repo, self::API_URL);
|
||||
$url .= ($query ?? '');
|
||||
$headers = $this->getGitHubTokenHeaders();
|
||||
$data2 = default_shell()->executeCurl($url, headers: $headers);
|
||||
$data2 = default_shell()->executeCurl($url, headers: $headers, retries: $retries);
|
||||
$data = json_decode($data2 ?: '', true);
|
||||
if (!is_array($data)) {
|
||||
throw new DownloaderException("Failed to get GitHub release API info for {$repo} from {$url}");
|
||||
@@ -84,7 +84,7 @@ class GitHubRelease implements DownloadTypeInterface, ValidatorInterface, CheckU
|
||||
if (!isset($config['match'])) {
|
||||
throw new DownloaderException("GitHubRelease downloader requires 'match' config for {$name}");
|
||||
}
|
||||
$rel = $this->getLatestGitHubRelease($name, $config['repo'], $config['prefer-stable'] ?? true, $config['match'], $config['query'] ?? null);
|
||||
$rel = $this->getLatestGitHubRelease($name, $config['repo'], $config['prefer-stable'] ?? true, $config['match'], $config['query'] ?? null, $downloader->getRetry());
|
||||
|
||||
// download file using curl
|
||||
$asset_url = str_replace(['{repo}', '{id}'], [$config['repo'], $rel['id']], self::ASSET_URL);
|
||||
@@ -124,7 +124,7 @@ class GitHubRelease implements DownloadTypeInterface, ValidatorInterface, CheckU
|
||||
if (!isset($config['match'])) {
|
||||
throw new DownloaderException("GitHubRelease downloader requires 'match' config for {$name}");
|
||||
}
|
||||
$this->getLatestGitHubRelease($name, $config['repo'], $config['prefer-stable'] ?? true, $config['match'], $config['query'] ?? null);
|
||||
$this->getLatestGitHubRelease($name, $config['repo'], $config['prefer-stable'] ?? true, $config['match'], $config['query'] ?? null, $downloader->getRetry());
|
||||
$new_version = $this->version ?? $old_version ?? '';
|
||||
return new CheckUpdateResult(
|
||||
old: $old_version,
|
||||
|
||||
@@ -22,11 +22,11 @@ class GitHubTarball implements DownloadTypeInterface, CheckUpdateInterface
|
||||
* Get the GitHub tarball URL for a given repository and release type.
|
||||
* If match_url is provided, only return the tarball that matches the regex.
|
||||
*/
|
||||
public function getGitHubTarballInfo(string $name, string $repo, string $rel_type, bool $prefer_stable = true, ?string $match_url = null, ?string $basename = null, ?string $query = null): array
|
||||
public function getGitHubTarballInfo(string $name, string $repo, string $rel_type, bool $prefer_stable = true, ?string $match_url = null, ?string $basename = null, ?string $query = null, int $retries = 0): array
|
||||
{
|
||||
if ($rel_type === 'releases' && $match_url === null && $query === null && $prefer_stable) {
|
||||
$api_url = str_replace(['{repo}', '{rel_type}'], [$repo, 'releases/latest'], self::API_URL);
|
||||
$data = default_shell()->executeCurl($api_url, headers: $this->getGitHubTokenHeaders());
|
||||
$data = default_shell()->executeCurl($api_url, headers: $this->getGitHubTokenHeaders(), retries: $retries);
|
||||
$data = json_decode($data ?: '', true);
|
||||
if (!is_array($data) || empty($data['tarball_url'])) {
|
||||
throw new DownloaderException("Failed to get GitHub latest release for {$repo} from {$api_url}");
|
||||
@@ -36,7 +36,7 @@ class GitHubTarball implements DownloadTypeInterface, CheckUpdateInterface
|
||||
} else {
|
||||
$api_url = str_replace(['{repo}', '{rel_type}'], [$repo, $rel_type], self::API_URL);
|
||||
$api_url .= ($query ?? '');
|
||||
$data = default_shell()->executeCurl($api_url, headers: $this->getGitHubTokenHeaders());
|
||||
$data = default_shell()->executeCurl($api_url, headers: $this->getGitHubTokenHeaders(), retries: $retries);
|
||||
$data = json_decode($data ?: '', true);
|
||||
if (!is_array($data)) {
|
||||
throw new DownloaderException("Failed to get GitHub tarball URL for {$repo} from {$api_url}");
|
||||
@@ -65,7 +65,7 @@ class GitHubTarball implements DownloadTypeInterface, CheckUpdateInterface
|
||||
}
|
||||
$this->version = $version ?? null;
|
||||
}
|
||||
$head = default_shell()->executeCurl($rel_url, 'HEAD', headers: $this->getGitHubTokenHeaders()) ?: '';
|
||||
$head = default_shell()->executeCurl($rel_url, 'HEAD', headers: $this->getGitHubTokenHeaders(), retries: $retries) ?: '';
|
||||
preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?<filename>.+\.tar\.gz)\1/im', $head, $matches);
|
||||
if ($matches) {
|
||||
$filename = $matches['filename'];
|
||||
@@ -84,9 +84,9 @@ class GitHubTarball implements DownloadTypeInterface, CheckUpdateInterface
|
||||
'ghtagtar' => 'tags',
|
||||
default => throw new DownloaderException("Invalid GitHubTarball type for {$name}"),
|
||||
};
|
||||
[$url, $filename] = $this->getGitHubTarballInfo($name, $config['repo'], $rel_type, $config['prefer-stable'] ?? true, $config['match'] ?? null, $name, $config['query'] ?? null);
|
||||
[$url, $filename] = $this->getGitHubTarballInfo($name, $config['repo'], $rel_type, $config['prefer-stable'] ?? true, $config['match'] ?? null, $name, $config['query'] ?? null, $downloader->getRetry());
|
||||
$path = DOWNLOAD_PATH . "/{$filename}";
|
||||
default_shell()->executeCurlDownload($url, $path, headers: $this->getGitHubTokenHeaders());
|
||||
default_shell()->executeCurlDownload($url, $path, headers: $this->getGitHubTokenHeaders(), retries: $downloader->getRetry());
|
||||
return DownloadResult::archive($filename, $config, $config['extract'] ?? null, version: $this->version, downloader: static::class);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ class GitHubTarball implements DownloadTypeInterface, CheckUpdateInterface
|
||||
'ghtagtar' => 'tags',
|
||||
default => throw new DownloaderException("Invalid GitHubTarball type for {$name}"),
|
||||
};
|
||||
$this->getGitHubTarballInfo($name, $config['repo'], $rel_type, $config['prefer-stable'] ?? true, $config['match'] ?? null, $name, $config['query'] ?? null);
|
||||
$this->getGitHubTarballInfo($name, $config['repo'], $rel_type, $config['prefer-stable'] ?? true, $config['match'] ?? null, $name, $config['query'] ?? null, $downloader->getRetry());
|
||||
$new_version = $this->version ?? $old_version ?? '';
|
||||
return new CheckUpdateResult(
|
||||
old: $old_version,
|
||||
|
||||
@@ -84,7 +84,7 @@ class DefaultShell extends Shell
|
||||
/**
|
||||
* Execute a Git clone command to clone a repository.
|
||||
*/
|
||||
public function executeGitClone(string $url, string $branch, string $path, bool $shallow = true, ?array $submodules = null): void
|
||||
public function executeGitClone(string $url, string $branch, string $path, bool $shallow = true, ?array $submodules = null, int $retries = 0): void
|
||||
{
|
||||
$path = FileSystem::convertPath($path);
|
||||
if (file_exists($path)) {
|
||||
@@ -99,7 +99,21 @@ class DefaultShell extends Shell
|
||||
$cmd = clean_spaces("{$git} clone -c http.lowSpeedLimit=1 -c http.lowSpeedTime=3600 --config core.autocrlf=false --branch {$branch_arg} {$shallow_arg} {$submodules_arg} {$url_arg} {$path_arg}");
|
||||
$this->logCommandInfo($cmd);
|
||||
logger()->debug("[GIT CLONE] {$cmd}");
|
||||
$this->passthru($cmd, $this->console_putput);
|
||||
try {
|
||||
$this->passthru($cmd, $this->console_putput);
|
||||
} catch (InterruptException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
if ($retries > 0) {
|
||||
logger()->warning("Git clone failed, retrying... ({$retries} retries left)");
|
||||
if (is_dir($path)) {
|
||||
FileSystem::removeDir($path);
|
||||
}
|
||||
$this->executeGitClone($url, $branch, $path, $shallow, $submodules, $retries - 1);
|
||||
return;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
if ($submodules !== null) {
|
||||
$depth_flag = $shallow ? '--depth 1' : '';
|
||||
foreach ($submodules as $submodule) {
|
||||
|
||||
Reference in New Issue
Block a user