Move all interactive input to construct

This commit is contained in:
crazywhalecc
2026-03-09 11:04:18 +08:00
parent 1f768ffc64
commit 77e129881a
11 changed files with 96 additions and 61 deletions

View File

@@ -443,7 +443,27 @@ trait unix
$package->runStage([$this, 'makeForUnix']); $package->runStage([$this, 'makeForUnix']);
$package->runStage([$this, 'unixBuildSharedExt']); $package->runStage([$this, 'unixBuildSharedExt']);
$package->runStage([$this, 'smokeTestForUnix']); }
#[Stage('postInstall')]
public function postInstall(TargetPackage $package, PackageInstaller $installer): void
{
if ($package->getName() === 'frankenphp') {
$package->runStage([$this, 'smokeTestFrankenphpForUnix']);
return;
}
if ($package->getName() !== 'php') {
return;
}
if (SystemTarget::isUnix()) {
if ($installer->interactive) {
InteractiveTerm::indicateProgress('Running PHP smoke tests');
}
$package->runStage([$this, 'smokeTestForUnix']);
if ($installer->interactive) {
InteractiveTerm::finish('PHP smoke tests passed');
}
}
} }
/** /**

View File

@@ -106,7 +106,7 @@ class ArtifactDownloader
* no-shallow-clone?: bool * no-shallow-clone?: bool
* } $options Downloader options * } $options Downloader options
*/ */
public function __construct(protected array $options = []) public function __construct(protected array $options = [], public readonly bool $interactive = true)
{ {
// Allow setting concurrency via options // Allow setting concurrency via options
$this->parallel = max(1, (int) ($options['parallel'] ?? 1)); $this->parallel = max(1, (int) ($options['parallel'] ?? 1));
@@ -273,12 +273,10 @@ class ArtifactDownloader
/** /**
* Download all artifacts, with optional parallel processing. * Download all artifacts, with optional parallel processing.
*
* @param bool $interactive Enable interactive mode with Ctrl+C handling
*/ */
public function download(bool $interactive = true): void public function download(): void
{ {
if ($interactive) { if ($this->interactive) {
Shell::passthruCallback(function () { Shell::passthruCallback(function () {
InteractiveTerm::advance(); InteractiveTerm::advance();
}); });
@@ -311,7 +309,7 @@ class ArtifactDownloader
$count = count($this->artifacts); $count = count($this->artifacts);
$artifacts_str = implode(',', array_map(fn ($x) => '' . ConsoleColor::yellow($x->getName()), $this->artifacts)); $artifacts_str = implode(',', array_map(fn ($x) => '' . ConsoleColor::yellow($x->getName()), $this->artifacts));
// mute the first line if not interactive // mute the first line if not interactive
if ($interactive) { if ($this->interactive) {
InteractiveTerm::notice("Downloading {$count} artifacts: {$artifacts_str} ..."); InteractiveTerm::notice("Downloading {$count} artifacts: {$artifacts_str} ...");
} }
try { try {
@@ -329,19 +327,19 @@ class ArtifactDownloader
$skipped = []; $skipped = [];
foreach ($this->artifacts as $artifact) { foreach ($this->artifacts as $artifact) {
++$current; ++$current;
if ($this->downloadWithType($artifact, $current, $count, interactive: $interactive) === SPC_DOWNLOAD_STATUS_SKIPPED) { if ($this->downloadWithType($artifact, $current, $count) === SPC_DOWNLOAD_STATUS_SKIPPED) {
$skipped[] = $artifact->getName(); $skipped[] = $artifact->getName();
continue; continue;
} }
$this->_before_files = FileSystem::scanDirFiles(DOWNLOAD_PATH, false, true, true) ?: []; $this->_before_files = FileSystem::scanDirFiles(DOWNLOAD_PATH, false, true, true) ?: [];
} }
if ($interactive) { if ($this->interactive) {
$skip_msg = !empty($skipped) ? ' (Skipped ' . count($skipped) . ' artifacts for being already downloaded)' : ''; $skip_msg = !empty($skipped) ? ' (Skipped ' . count($skipped) . ' artifacts for being already downloaded)' : '';
InteractiveTerm::success("Downloaded all {$count} artifacts.{$skip_msg}\n", true); InteractiveTerm::success("Downloaded all {$count} artifacts.{$skip_msg}\n", true);
} }
} }
} finally { } finally {
if ($interactive) { if ($this->interactive) {
Shell::passthruCallback(null); Shell::passthruCallback(null);
keyboard_interrupt_unregister(); keyboard_interrupt_unregister();
} }
@@ -537,7 +535,7 @@ class ArtifactDownloader
return $dl->checkUpdate($artifact_name, $platform_config, null, $this); return $dl->checkUpdate($artifact_name, $platform_config, null, $this);
} }
private function downloadWithType(Artifact $artifact, int $current, int $total, bool $parallel = false, bool $interactive = true): int private function downloadWithType(Artifact $artifact, int $current, int $total, bool $parallel = false): int
{ {
$queue = $this->generateQueue($artifact); $queue = $this->generateQueue($artifact);
// already downloaded // already downloaded
@@ -558,7 +556,7 @@ class ArtifactDownloader
}; };
$try_h = $try ? 'Try downloading' : 'Downloading'; $try_h = $try ? 'Try downloading' : 'Downloading';
logger()->info("{$try_h} artifact '{$artifact->getName()}' {$item['display']} ..."); logger()->info("{$try_h} artifact '{$artifact->getName()}' {$item['display']} ...");
if ($parallel === false && $interactive) { if ($parallel === false && $this->interactive) {
InteractiveTerm::indicateProgress("[{$current}/{$total}] Downloading artifact " . ConsoleColor::green($artifact->getName()) . " {$item['display']} from {$type_display_name} ..."); InteractiveTerm::indicateProgress("[{$current}/{$total}] Downloading artifact " . ConsoleColor::green($artifact->getName()) . " {$item['display']} from {$type_display_name} ...");
} }
// is valid download type // is valid download type
@@ -597,13 +595,13 @@ class ArtifactDownloader
} }
// process lock // process lock
ApplicationContext::get(ArtifactCache::class)->lock($artifact, $item['lock'], $lock, SystemTarget::getCurrentPlatformString()); ApplicationContext::get(ArtifactCache::class)->lock($artifact, $item['lock'], $lock, SystemTarget::getCurrentPlatformString());
if ($parallel === false && $interactive) { if ($parallel === false && $this->interactive) {
$ver = $lock->hasVersion() ? (' (' . ConsoleColor::yellow($lock->version) . ')') : ''; $ver = $lock->hasVersion() ? (' (' . ConsoleColor::yellow($lock->version) . ')') : '';
InteractiveTerm::finish('Downloaded ' . ($verified ? 'and verified ' : '') . 'artifact ' . ConsoleColor::green($artifact->getName()) . $ver . " {$item['display']} ."); InteractiveTerm::finish('Downloaded ' . ($verified ? 'and verified ' : '') . 'artifact ' . ConsoleColor::green($artifact->getName()) . $ver . " {$item['display']} .");
} }
return SPC_DOWNLOAD_STATUS_SUCCESS; return SPC_DOWNLOAD_STATUS_SUCCESS;
} catch (DownloaderException|ExecutionException $e) { } catch (DownloaderException|ExecutionException $e) {
if ($parallel === false && $interactive) { if ($parallel === false && $this->interactive) {
InteractiveTerm::finish("Download artifact {$artifact->getName()} {$item['display']} failed !", false); InteractiveTerm::finish("Download artifact {$artifact->getName()} {$item['display']} failed !", false);
InteractiveTerm::error("Failed message: {$e->getMessage()}", true); InteractiveTerm::error("Failed message: {$e->getMessage()}", true);
} }

View File

@@ -34,9 +34,9 @@ class InstallPackageCommand extends BaseCommand
public function handle(): int public function handle(): int
{ {
ApplicationContext::set('elephant', true); ApplicationContext::set('elephant', true);
$installer = new PackageInstaller([...$this->input->getOptions(), 'dl-prefer-binary' => true]); $installer = new PackageInstaller([...$this->input->getOptions(), 'dl-prefer-binary' => true], false);
$installer->addInstallPackage($this->input->getArgument('package')); $installer->addInstallPackage($this->input->getArgument('package'));
$installer->run(true, true); $installer->run(true);
return static::SUCCESS; return static::SUCCESS;
} }
} }

View File

@@ -16,6 +16,7 @@ class ConfigValidator
public const array PACKAGE_FIELD_TYPES = [ public const array PACKAGE_FIELD_TYPES = [
// package fields // package fields
'type' => ConfigType::STRING, 'type' => ConfigType::STRING,
'description' => ConfigType::STRING,
'depends' => ConfigType::LIST_ARRAY, // @ 'depends' => ConfigType::LIST_ARRAY, // @
'suggests' => ConfigType::LIST_ARRAY, // @ 'suggests' => ConfigType::LIST_ARRAY, // @
'artifact' => [self::class, 'validateArtifactField'], // STRING or OBJECT 'artifact' => [self::class, 'validateArtifactField'], // STRING or OBJECT
@@ -43,6 +44,7 @@ class ConfigValidator
public const array PACKAGE_FIELDS = [ public const array PACKAGE_FIELDS = [
'type' => true, 'type' => true,
'description' => false,
'depends' => false, // @ 'depends' => false, // @
'suggests' => false, // @ 'suggests' => false, // @
'artifact' => false, 'artifact' => false,

View File

@@ -18,7 +18,7 @@ use function Laravel\Prompts\confirm;
readonly class Doctor readonly class Doctor
{ {
public function __construct(private ?OutputInterface $output = null, private int $auto_fix = FIX_POLICY_PROMPT) public function __construct(private ?OutputInterface $output = null, private int $auto_fix = FIX_POLICY_PROMPT, public readonly bool $interactive = true)
{ {
// debug shows all loaded doctor items // debug shows all loaded doctor items
$items = DoctorLoader::getDoctorItems(); $items = DoctorLoader::getDoctorItems();
@@ -53,13 +53,13 @@ readonly class Doctor
* Check all valid check items. * Check all valid check items.
* @return bool true if all checks passed, false otherwise * @return bool true if all checks passed, false otherwise
*/ */
public function checkAll(bool $interactive = true): bool public function checkAll(): bool
{ {
if ($interactive) { if ($this->interactive) {
InteractiveTerm::notice('Starting doctor checks ...'); InteractiveTerm::notice('Starting doctor checks ...');
} }
foreach ($this->getValidCheckList() as $check) { foreach ($this->getValidCheckList() as $check) {
if (!$this->checkItem($check, $interactive)) { if (!$this->checkItem($check)) {
return false; return false;
} }
} }
@@ -72,7 +72,7 @@ readonly class Doctor
* @param CheckItem|string $check The check item to be checked * @param CheckItem|string $check The check item to be checked
* @return bool True if the check passed or was fixed, false otherwise * @return bool True if the check passed or was fixed, false otherwise
*/ */
public function checkItem(CheckItem|string $check, bool $interactive = true): bool public function checkItem(CheckItem|string $check): bool
{ {
if (is_string($check)) { if (is_string($check)) {
$found = null; $found = null;
@@ -88,7 +88,7 @@ readonly class Doctor
} }
$check = $found; $check = $found;
} }
$prepend = $interactive ? ' - ' : ''; $prepend = $this->interactive ? ' - ' : '';
$this->output?->write("{$prepend}Checking <comment>{$check->item_name}</comment> ... "); $this->output?->write("{$prepend}Checking <comment>{$check->item_name}</comment> ... ");
// call check // call check

View File

@@ -59,8 +59,8 @@ class LinuxMuslCheck
#[FixItem('fix-musl-wrapper')] #[FixItem('fix-musl-wrapper')]
public function fixMusl(): bool public function fixMusl(): bool
{ {
$downloader = new ArtifactDownloader(); $downloader = new ArtifactDownloader(interactive: false);
$downloader->add('musl-wrapper')->download(false); $downloader->add('musl-wrapper')->download();
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class)); $extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
$extractor->extract('musl-wrapper'); $extractor->extract('musl-wrapper');
@@ -96,9 +96,9 @@ class LinuxMuslCheck
Shell::passthruCallback(function () { Shell::passthruCallback(function () {
InteractiveTerm::advance(); InteractiveTerm::advance();
}); });
$downloader = new ArtifactDownloader(); $downloader = new ArtifactDownloader(interactive: false);
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class)); $extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
$downloader->add('musl-toolchain')->download(false); $downloader->add('musl-toolchain')->download();
$extractor->extract('musl-toolchain'); $extractor->extract('musl-toolchain');
$pkg_root = PKG_ROOT_PATH . '/musl-toolchain'; $pkg_root = PKG_ROOT_PATH . '/musl-toolchain';
f_passthru("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl"); f_passthru("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");

View File

@@ -45,9 +45,9 @@ class PkgConfigCheck
public function fix(): bool public function fix(): bool
{ {
ApplicationContext::set('elephant', true); ApplicationContext::set('elephant', true);
$installer = new PackageInstaller(['dl-binary-only' => true]); $installer = new PackageInstaller(['dl-binary-only' => true], interactive: false);
$installer->addInstallPackage('pkg-config'); $installer->addInstallPackage('pkg-config');
$installer->run(false, true); $installer->run(true);
return true; return true;
} }
} }

View File

@@ -30,9 +30,9 @@ class Re2cVersionCheck
#[FixItem('build-re2c')] #[FixItem('build-re2c')]
public function buildRe2c(): bool public function buildRe2c(): bool
{ {
$installer = new PackageInstaller(); $installer = new PackageInstaller(interactive: false);
$installer->addInstallPackage('re2c'); $installer->addInstallPackage('re2c');
$installer->run(false); $installer->run(true);
return true; return true;
} }
} }

View File

@@ -107,7 +107,7 @@ class WindowsToolCheck
{ {
$installer = new PackageInstaller(); $installer = new PackageInstaller();
$installer->addInstallPackage('strawberry-perl'); $installer->addInstallPackage('strawberry-perl');
$installer->run(false); $installer->run(true);
GlobalEnvManager::addPathIfNotExists(PKG_ROOT_PATH . '\strawberry-perl'); GlobalEnvManager::addPathIfNotExists(PKG_ROOT_PATH . '\strawberry-perl');
return true; return true;
} }
@@ -116,27 +116,27 @@ class WindowsToolCheck
public function installSDK(): bool public function installSDK(): bool
{ {
FileSystem::removeDir(getenv('PHP_SDK_PATH')); FileSystem::removeDir(getenv('PHP_SDK_PATH'));
$installer = new PackageInstaller(); $installer = new PackageInstaller(interactive: false);
$installer->addInstallPackage('php-sdk-binary-tools'); $installer->addInstallPackage('php-sdk-binary-tools');
$installer->run(false); $installer->run(true);
return true; return true;
} }
#[FixItem('install-nasm')] #[FixItem('install-nasm')]
public function installNasm(): bool public function installNasm(): bool
{ {
$installer = new PackageInstaller(); $installer = new PackageInstaller(interactive: false);
$installer->addInstallPackage('nasm'); $installer->addInstallPackage('nasm');
$installer->run(false); $installer->run(true);
return true; return true;
} }
#[FixItem('install-vswhere')] #[FixItem('install-vswhere')]
public function installVSWhere(): bool public function installVSWhere(): bool
{ {
$installer = new PackageInstaller(); $installer = new PackageInstaller(interactive: false);
$installer->addInstallPackage('vswhere'); $installer->addInstallPackage('vswhere');
$installer->run(false); $installer->run(true);
return true; return true;
} }
} }

View File

@@ -34,9 +34,9 @@ class ZigCheck
#[FixItem('install-zig')] #[FixItem('install-zig')]
public function installZig(): bool public function installZig(): bool
{ {
$installer = new PackageInstaller(); $installer = new PackageInstaller(interactive: false);
$installer->addInstallPackage('zig'); $installer->addInstallPackage('zig');
$installer->run(false); $installer->run(true);
return $installer->isPackageInstalled('zig'); return $installer->isPackageInstalled('zig');
} }
} }

View File

@@ -46,7 +46,7 @@ class PackageInstaller
/** @var null|BuildRootTracker buildroot file tracker for debugging purpose */ /** @var null|BuildRootTracker buildroot file tracker for debugging purpose */
protected ?BuildRootTracker $tracker = null; protected ?BuildRootTracker $tracker = null;
public function __construct(protected array $options = []) public function __construct(protected array $options = [], public readonly bool $interactive = true)
{ {
ApplicationContext::set(PackageInstaller::class, $this); ApplicationContext::set(PackageInstaller::class, $this);
$builder = new PackageBuilder($options); $builder = new PackageBuilder($options);
@@ -143,7 +143,7 @@ class PackageInstaller
/** /**
* Run the package installation process. * Run the package installation process.
*/ */
public function run(bool $interactive = true, bool $disable_delay_msg = false): void public function run(bool $disable_delay_msg = false): void
{ {
// apply build toolchain envs // apply build toolchain envs
GlobalEnvManager::afterInit(); GlobalEnvManager::afterInit();
@@ -153,7 +153,7 @@ class PackageInstaller
$this->resolvePackages(); $this->resolvePackages();
} }
if ($interactive && !$disable_delay_msg) { if ($this->interactive && !$disable_delay_msg) {
// show install or build options in terminal with beautiful output // show install or build options in terminal with beautiful output
$this->printInstallerInfo(); $this->printInstallerInfo();
@@ -167,14 +167,17 @@ class PackageInstaller
// check download // check download
if ($this->download) { if ($this->download) {
$downloaderOptions = DownloaderOptions::extractFromConsoleOptions($this->options, 'dl'); $downloaderOptions = DownloaderOptions::extractFromConsoleOptions($this->options, 'dl');
$downloader = new ArtifactDownloader([...$downloaderOptions, 'source-only' => implode(',', array_map(fn ($x) => $x->getName(), $this->build_packages))]); $downloader = new ArtifactDownloader(
$downloader->addArtifacts($this->getArtifacts())->download($interactive); [...$downloaderOptions, 'source-only' => implode(',', array_map(fn ($x) => $x->getName(), $this->build_packages))],
$this->interactive
);
$downloader->addArtifacts($this->getArtifacts())->download();
} else { } else {
logger()->notice('Skipping download (--no-download option enabled)'); logger()->notice('Skipping download (--no-download option enabled)');
} }
// extract sources // extract sources
$this->extractSourceArtifacts(interactive: $interactive); $this->extractSourceArtifacts();
// validate packages // validate packages
foreach ($this->packages as $package) { foreach ($this->packages as $package) {
@@ -183,7 +186,7 @@ class PackageInstaller
} }
// build/install packages // build/install packages
if ($interactive) { if ($this->interactive) {
InteractiveTerm::notice('Building/Installing packages ...'); InteractiveTerm::notice('Building/Installing packages ...');
keyboard_interrupt_register(function () { keyboard_interrupt_register(function () {
InteractiveTerm::finish('Build/Install process interrupted by user!', false); InteractiveTerm::finish('Build/Install process interrupted by user!', false);
@@ -198,7 +201,7 @@ class PackageInstaller
$has_source = $package->hasSource(); $has_source = $package->hasSource();
if (!$is_to_build && $should_use_binary) { if (!$is_to_build && $should_use_binary) {
// install binary // install binary
if ($interactive) { if ($this->interactive) {
InteractiveTerm::indicateProgress('Installing package: ' . ConsoleColor::yellow($package->getName())); InteractiveTerm::indicateProgress('Installing package: ' . ConsoleColor::yellow($package->getName()));
} }
try { try {
@@ -210,17 +213,17 @@ class PackageInstaller
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Stop tracking on error // Stop tracking on error
$this->tracker?->stopTracking(); $this->tracker?->stopTracking();
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Installing binary package failed: ' . ConsoleColor::red($package->getName()), false); InteractiveTerm::finish('Installing binary package failed: ' . ConsoleColor::red($package->getName()), false);
echo PHP_EOL; echo PHP_EOL;
} }
throw $e; throw $e;
} }
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Installed binary package: ' . ConsoleColor::green($package->getName()) . ($status === SPC_STATUS_ALREADY_INSTALLED ? ' (already installed, skipped)' : '')); InteractiveTerm::finish('Installed binary package: ' . ConsoleColor::green($package->getName()) . ($status === SPC_STATUS_ALREADY_INSTALLED ? ' (already installed, skipped)' : ''));
} }
} elseif ($is_to_build && $has_build_stage || $has_source && $has_build_stage) { } elseif ($is_to_build && $has_build_stage || $has_source && $has_build_stage) {
if ($interactive) { if ($this->interactive) {
InteractiveTerm::indicateProgress('Building package: ' . ConsoleColor::yellow($package->getName())); InteractiveTerm::indicateProgress('Building package: ' . ConsoleColor::yellow($package->getName()));
} }
try { try {
@@ -243,22 +246,20 @@ class PackageInstaller
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Stop tracking on error // Stop tracking on error
$this->tracker?->stopTracking(); $this->tracker?->stopTracking();
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Building package failed: ' . ConsoleColor::red($package->getName()), false); InteractiveTerm::finish('Building package failed: ' . ConsoleColor::red($package->getName()), false);
echo PHP_EOL; echo PHP_EOL;
} }
throw $e; throw $e;
} }
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Built package: ' . ConsoleColor::green($package->getName()) . ($status === SPC_STATUS_ALREADY_BUILT ? ' (already built, skipped)' : '')); InteractiveTerm::finish('Built package: ' . ConsoleColor::green($package->getName()) . ($status === SPC_STATUS_ALREADY_BUILT ? ' (already built, skipped)' : ''));
} }
} }
} }
$this->dumpLicenseFiles($this->packages); // perform after-install actions and emit post-install events
if ($interactive) { $this->emitPostInstallEvents();
InteractiveTerm::success('Exported package licenses', true);
}
} }
public function isBuildPackage(Package|string $package): bool public function isBuildPackage(Package|string $package): bool
@@ -311,6 +312,17 @@ class PackageInstaller
return false; return false;
} }
public function emitPostInstallEvents(): void
{
foreach ($this->packages as $package) {
if ($package->hasStage('postInstall')) {
$package->runStage('postInstall');
}
}
$this->dumpLicenseFiles($this->packages);
}
/** /**
* Returns the download status of all artifacts for the resolved packages. * Returns the download status of all artifacts for the resolved packages.
* *
@@ -368,7 +380,7 @@ class PackageInstaller
/** /**
* Extract all artifacts for resolved packages. * Extract all artifacts for resolved packages.
*/ */
public function extractSourceArtifacts(bool $interactive = true): void public function extractSourceArtifacts(): void
{ {
FileSystem::createDir(SOURCE_PATH); FileSystem::createDir(SOURCE_PATH);
$packages = array_values($this->packages); $packages = array_values($this->packages);
@@ -403,7 +415,7 @@ class PackageInstaller
} }
// Extract each artifact // Extract each artifact
if ($interactive) { if ($this->interactive) {
InteractiveTerm::notice('Extracting source for ' . count($artifacts) . ' artifacts: ' . implode(',', array_map(fn ($x) => ConsoleColor::yellow($x->getName()), $artifacts)) . ' ...'); InteractiveTerm::notice('Extracting source for ' . count($artifacts) . ' artifacts: ' . implode(',', array_map(fn ($x) => ConsoleColor::yellow($x->getName()), $artifacts)) . ' ...');
InteractiveTerm::indicateProgress('Extracting artifacts'); InteractiveTerm::indicateProgress('Extracting artifacts');
} }
@@ -411,7 +423,7 @@ class PackageInstaller
try { try {
V2CompatLayer::beforeExtsExtractHook(); V2CompatLayer::beforeExtsExtractHook();
foreach ($artifacts as $artifact) { foreach ($artifacts as $artifact) {
if ($interactive) { if ($this->interactive) {
InteractiveTerm::setMessage('Extracting source: ' . ConsoleColor::green($artifact->getName())); InteractiveTerm::setMessage('Extracting source: ' . ConsoleColor::green($artifact->getName()));
} }
if (($pkg = array_search($artifact->getName(), $pkg_artifact_map, true)) !== false) { if (($pkg = array_search($artifact->getName(), $pkg_artifact_map, true)) !== false) {
@@ -423,12 +435,12 @@ class PackageInstaller
} }
} }
V2CompatLayer::afterExtsExtractHook(); V2CompatLayer::afterExtsExtractHook();
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Extracted all sources successfully.'); InteractiveTerm::finish('Extracted all sources successfully.');
echo PHP_EOL; echo PHP_EOL;
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
if ($interactive) { if ($this->interactive) {
InteractiveTerm::finish('Artifact extraction failed!', false); InteractiveTerm::finish('Artifact extraction failed!', false);
echo PHP_EOL; echo PHP_EOL;
} }
@@ -525,6 +537,9 @@ class PackageInstaller
} }
} }
$dumper->dump(BUILD_ROOT_PATH . '/license'); $dumper->dump(BUILD_ROOT_PATH . '/license');
if ($this->interactive) {
InteractiveTerm::success('Exported package licenses', true);
}
} }
/** /**