@@ -43,6 +43,7 @@ public function configure(): void
4343 $ this ->addOption ('ignore-cache-sources ' , null , InputOption::VALUE_OPTIONAL , 'Ignore some source caches, comma separated, e.g "php-src,curl,openssl" ' , false );
4444 $ this ->addOption ('retry ' , 'R ' , InputOption::VALUE_REQUIRED , 'Set retry time when downloading failed (default: 0) ' , '0 ' );
4545 $ this ->addOption ('prefer-pre-built ' , 'P ' , null , 'Download pre-built libraries when available ' );
46+ $ this ->addOption ('no-alt ' , null , null , 'Do not download alternative sources ' );
4647 }
4748
4849 /**
@@ -95,22 +96,7 @@ public function handle(): int
9596 {
9697 try {
9798 if ($ this ->getOption ('clean ' )) {
98- logger ()->warning ('You are doing some operations that not recoverable: removing directories below ' );
99- logger ()->warning (SOURCE_PATH );
100- logger ()->warning (DOWNLOAD_PATH );
101- logger ()->warning (BUILD_ROOT_PATH );
102- logger ()->alert ('I will remove these dir after 5 seconds ! ' );
103- sleep (5 );
104- if (PHP_OS_FAMILY === 'Windows ' ) {
105- f_passthru ('rmdir /s /q ' . SOURCE_PATH );
106- f_passthru ('rmdir /s /q ' . DOWNLOAD_PATH );
107- f_passthru ('rmdir /s /q ' . BUILD_ROOT_PATH );
108- } else {
109- f_passthru ('rm -rf ' . SOURCE_PATH . '/* ' );
110- f_passthru ('rm -rf ' . DOWNLOAD_PATH . '/* ' );
111- f_passthru ('rm -rf ' . BUILD_ROOT_PATH . '/* ' );
112- }
113- return static ::FAILURE ;
99+ return $ this ->_clean ();
114100 }
115101
116102 // --from-zip
@@ -249,7 +235,24 @@ public function handle(): int
249235 logger ()->warning ("Pre-built content not found for {$ source }, fallback to source download " );
250236 }
251237 logger ()->info ("[ {$ ni }/ {$ cnt }] Downloading source {$ source }" );
252- Downloader::downloadSource ($ source , $ config , $ force_all || in_array ($ source , $ force_list ));
238+ try {
239+ Downloader::downloadSource ($ source , $ config , $ force_all || in_array ($ source , $ force_list ));
240+ } /* @noinspection PhpRedundantCatchClauseInspection */ catch (DownloaderException |RuntimeException $ e ) {
241+ // if `--no-alt` option is set, we will not download alternative sources
242+ if ($ this ->getOption ('no-alt ' )) {
243+ throw $ e ;
244+ }
245+ // if download failed, we will try to download alternative sources
246+ logger ()->warning ("Download failed: {$ e ->getMessage ()}" );
247+ logger ()->notice ("Trying to download alternative sources for {$ source }" );
248+ $ alt_sources = Config::getSource ($ source )['alt ' ] ?? null ;
249+ if ($ alt_sources === null ) {
250+ $ alt_config = array_merge ($ config , $ this ->getDefaultAlternativeSource ($ source ));
251+ } else {
252+ $ alt_config = array_merge ($ config , $ alt_sources );
253+ }
254+ Downloader::downloadSource ($ source , $ alt_config , $ force_all || in_array ($ source , $ force_list ));
255+ }
253256 }
254257 }
255258 $ time = round (microtime (true ) - START_TIME , 3 );
@@ -368,4 +371,50 @@ private function findPreBuilt(array $assets, string $filename): ?string
368371 }
369372 return null ;
370373 }
374+
375+ /**
376+ * @throws RuntimeException
377+ */
378+ private function _clean (): int
379+ {
380+ logger ()->warning ('You are doing some operations that not recoverable: removing directories below ' );
381+ logger ()->warning (SOURCE_PATH );
382+ logger ()->warning (DOWNLOAD_PATH );
383+ logger ()->warning (BUILD_ROOT_PATH );
384+ logger ()->alert ('I will remove these dir after 5 seconds ! ' );
385+ sleep (5 );
386+ if (PHP_OS_FAMILY === 'Windows ' ) {
387+ f_passthru ('rmdir /s /q ' . SOURCE_PATH );
388+ f_passthru ('rmdir /s /q ' . DOWNLOAD_PATH );
389+ f_passthru ('rmdir /s /q ' . BUILD_ROOT_PATH );
390+ } else {
391+ f_passthru ('rm -rf ' . SOURCE_PATH . '/* ' );
392+ f_passthru ('rm -rf ' . DOWNLOAD_PATH . '/* ' );
393+ f_passthru ('rm -rf ' . BUILD_ROOT_PATH . '/* ' );
394+ }
395+ return static ::FAILURE ;
396+ }
397+
398+ private function getDefaultAlternativeSource (string $ source_name ): array
399+ {
400+ return [
401+ 'type ' => 'custom ' ,
402+ 'func ' => function (bool $ force , array $ source , int $ download_as ) use ($ source_name ) {
403+ logger ()->debug ("Fetching alternative source for {$ source_name }" );
404+ // get from dl.static-php.dev
405+ $ url = "https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/ {$ source_name }/?format=json " ;
406+ $ json = json_decode (Downloader::curlExec (url: $ url , retries: intval (getenv ('SPC_DOWNLOAD_RETRIES ' ) ?: 0 )), true );
407+ if (!is_array ($ json )) {
408+ throw new RuntimeException ('failed http fetch ' );
409+ }
410+ $ item = $ json [0 ] ?? null ;
411+ if ($ item === null ) {
412+ throw new RuntimeException ('failed to parse json ' );
413+ }
414+ $ full_url = 'https://dl.static-php.dev ' . $ item ['full_path ' ];
415+ $ filename = basename ($ item ['full_path ' ]);
416+ Downloader::downloadFile ($ source_name , $ full_url , $ filename , $ source ['path ' ] ?? null , $ download_as );
417+ },
418+ ];
419+ }
371420}
0 commit comments