Skip to content

Commit 7d3e1f8

Browse files
committed
work around gnu mirrors constantly being down
1 parent 2824de2 commit 7d3e1f8

9 files changed

Lines changed: 71 additions & 4 deletions

File tree

config/artifact/ncurses.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ ncurses:
66
type: filelist
77
url: 'https://ftpmirror.gnu.org/gnu/ncurses/'
88
regex: '/href="(?<file>ncurses-(?<version>[^"]+)\.tar\.gz)"/'
9+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/ncurses/ncurses-spc-mirror.tar.gz'

config/pkg/lib/gettext.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ gettext:
55
type: filelist
66
url: 'https://ftpmirror.gnu.org/gnu/gettext/'
77
regex: '/href="(?<file>gettext-(?<version>[^"]+)\.tar\.xz)"/'
8+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/gettext/gettext-spc-mirror.tar.xz'
89
metadata:
910
license-files: [gettext-runtime/intl/COPYING.LIB]
1011
license: LGPL-2.1-or-later

config/pkg/lib/idn2.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ idn2:
55
type: filelist
66
url: 'https://ftpmirror.gnu.org/gnu/libidn/'
77
regex: '/href="(?<file>libidn2-(?<version>[^"]+)\.tar\.gz)"/'
8+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/libidn2/libidn2-spc-mirror.tar.gz'
89
metadata:
910
license-files: [COPYING.LESSERv3]
1011
license: LGPL-3.0-or-later

config/pkg/lib/libiconv.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ libiconv:
55
type: filelist
66
url: 'https://ftpmirror.gnu.org/gnu/libiconv/'
77
regex: '/href="(?<file>libiconv-(?<version>[^"]+)\.tar\.gz)"/'
8+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/libiconv/libiconv-spc-mirror.tar.gz'
89
metadata:
910
license-files: [COPYING.LIB]
1011
license: LGPL-2.0-or-later

config/pkg/lib/libunistring.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ libunistring:
55
type: filelist
66
url: 'https://ftpmirror.gnu.org/gnu/libunistring/'
77
regex: '/href="(?<file>libunistring-(?<version>[^"]+)\.tar\.gz)"/'
8+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/libunistring/libunistring-spc-mirror.tar.gz'
89
metadata:
910
license-files: [COPYING.LIB]
1011
license: LGPL-3.0-or-later

config/pkg/lib/readline.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ readline:
55
type: filelist
66
url: 'https://ftpmirror.gnu.org/gnu/readline/'
77
regex: '/href="(?<file>readline-(?<version>[^"]+)\.tar\.gz)"/'
8+
source-mirror: 'https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/readline/readline-spc-mirror.tar.gz'
89
metadata:
910
license-files: [COPYING]
1011
license: GPL-3.0-or-later

src/StaticPHP/Artifact/Downloader/Type/FileList.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ protected function fetchFileList(string $name, array $config, ArtifactDownloader
4040
{
4141
logger()->debug("Fetching file list from {$config['url']}");
4242
$page = default_shell()->executeCurl($config['url'], retries: $downloader->getRetry());
43-
preg_match_all($config['regex'], $page ?: '', $matches);
44-
if (!$matches) {
43+
if ($page === false || !preg_match_all($config['regex'], $page, $matches)) {
4544
throw new DownloaderException("Failed to get {$name} file list from {$config['url']}");
4645
}
4746
$versions = [];
@@ -55,6 +54,9 @@ protected function fetchFileList(string $name, array $config, ArtifactDownloader
5554
}
5655
$versions[$version] = $matches['file'][$i];
5756
}
57+
if ($versions === []) {
58+
throw new DownloaderException("No stable {$name} release found in file list from {$config['url']}");
59+
}
5860
uksort($versions, 'version_compare');
5961
$filename = end($versions);
6062
$version = array_key_last($versions);

src/StaticPHP/Runtime/Shell/DefaultShell.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function executeCurl(string $url, string $method = 'GET', array $headers
4141
$header_arg = implode(' ', array_map(fn ($v) => '"-H' . $v . '"', $headers));
4242
$retry_arg = $retries > 0 ? "--retry {$retries}" : '';
4343
$compressed_arg = $compressed ? '--compressed' : '';
44-
$cmd = SPC_CURL_EXEC . " -sfSL --max-time 3600 {$retry_arg} {$compressed_arg} {$method_arg} {$header_arg} {$url_arg}";
44+
$cmd = SPC_CURL_EXEC . " -sfSL --connect-timeout 15 --speed-limit 1 --speed-time 30 --max-time 3600 {$retry_arg} {$compressed_arg} {$method_arg} {$header_arg} {$url_arg}";
4545

4646
$this->logCommandInfo($cmd);
4747
logger()->debug("[CURL EXECUTE] {$cmd}");
@@ -75,7 +75,7 @@ public function executeCurlDownload(string $url, string $path, array $headers =
7575
$header_arg = implode(' ', array_map(fn ($v) => '"-H' . $v . '"', $headers));
7676
$retry_arg = $retries > 0 ? "--retry {$retries}" : '';
7777
$check = $this->console_putput ? '#' : 's';
78-
$cmd = clean_spaces(SPC_CURL_EXEC . " -{$check}fSL --max-time 3600 {$retry_arg} {$header_arg} -o {$path_arg} {$url_arg}");
78+
$cmd = clean_spaces(SPC_CURL_EXEC . " -{$check}fSL --connect-timeout 15 --speed-limit 1 --speed-time 30 --max-time 3600 {$retry_arg} {$header_arg} -o {$path_arg} {$url_arg}");
7979
$this->logCommandInfo($cmd);
8080
logger()->debug('[CURL DOWNLOAD] ' . $cmd);
8181
$this->passthru($cmd, $this->console_putput, capture_output: false, throw_on_error: true);

tests/StaticPHP/Artifact/ArtifactDownloaderTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66

77
use PHPUnit\Framework\TestCase;
88
use StaticPHP\Artifact\Artifact;
9+
use StaticPHP\Artifact\ArtifactCache;
910
use StaticPHP\Artifact\ArtifactDownloader;
11+
use StaticPHP\Artifact\Downloader\DownloadResult;
1012
use StaticPHP\Config\ArtifactConfig;
13+
use StaticPHP\DI\ApplicationContext;
14+
use StaticPHP\Exception\DownloaderException;
1115
use StaticPHP\Exception\WrongUsageException;
1216
use StaticPHP\Registry\ArtifactLoader;
1317

@@ -337,6 +341,61 @@ public function testSetParallelAcceptsNormalValue(): void
337341
$this->assertSame($downloader, $result);
338342
}
339343

344+
/**
345+
* @dataProvider failedFileListProvider
346+
*/
347+
public function testFailedFileListFallsBackToSourceMirror(?string $page, bool $no_alt): void
348+
{
349+
$listing = tempnam(sys_get_temp_dir(), 'spc-filelist-');
350+
$this->assertNotFalse($listing);
351+
if ($page === null) {
352+
// A missing file URL makes curl fail without depending on the network.
353+
unlink($listing);
354+
} else {
355+
file_put_contents($listing, $page);
356+
}
357+
$artifact = new Artifact('fallback-test', [
358+
'source' => [
359+
'type' => 'filelist',
360+
'url' => 'file://' . $listing,
361+
'regex' => '/href="(?<file>libiconv-(?<version>[^"]+)\.tar\.gz)"/',
362+
],
363+
'source-mirror' => ['type' => 'local', 'dirname' => __DIR__],
364+
]);
365+
$original_cache = ApplicationContext::get(ArtifactCache::class);
366+
$cache = $this->createMock(ArtifactCache::class);
367+
$cache->expects($no_alt ? $this->never() : $this->once())
368+
->method('lock')
369+
->with($artifact, 'source', $this->callback(fn (DownloadResult $result) => $result->dirname === __DIR__));
370+
ApplicationContext::set(ArtifactCache::class, $cache);
371+
try {
372+
if ($no_alt) {
373+
$this->expectException(DownloaderException::class);
374+
$this->expectExceptionMessage("Download artifact 'fallback-test' failed");
375+
}
376+
(new ArtifactDownloader(['source-only' => true, 'no-alt' => $no_alt], false))
377+
->add($artifact)
378+
->download();
379+
} finally {
380+
ApplicationContext::set(ArtifactCache::class, $original_cache);
381+
if (file_exists($listing)) {
382+
unlink($listing);
383+
}
384+
}
385+
}
386+
387+
public static function failedFileListProvider(): iterable
388+
{
389+
foreach ([false, true] as $no_alt) {
390+
$suffix = $no_alt ? ' without mirrors' : ' with mirrors';
391+
yield 'request failure' . $suffix => [null, $no_alt];
392+
yield 'empty listing' . $suffix => ['', $no_alt];
393+
yield 'no matching releases' . $suffix => ['<html>Mirror unavailable</html>', $no_alt];
394+
yield 'prereleases only' . $suffix => ['<a href="libiconv-1.20-rc1.tar.gz">release candidate</a>', $no_alt];
395+
yield 'archive download failure' . $suffix => ['<a href="libiconv-1.19.tar.gz">release</a>', $no_alt];
396+
}
397+
}
398+
340399
// ==================== Helpers ====================
341400

342401
private function injectArtifactConfig(string $name, array $config): void

0 commit comments

Comments
 (0)