setDescription('Extract downloaded artifacts to their target locations');
$this->addArgument('artifacts', InputArgument::OPTIONAL, 'Specific artifacts to extract, comma separated, e.g "php-src,openssl,curl"');
$this->addOption('for-extensions', 'e', InputOption::VALUE_REQUIRED, 'Extract artifacts for extensions, e.g "openssl,mbstring"');
$this->addOption('for-libs', 'l', InputOption::VALUE_REQUIRED, 'Extract artifacts for libraries, e.g "libcares,openssl"');
$this->addOption('for-packages', null, InputOption::VALUE_REQUIRED, 'Extract artifacts for packages, e.g "php,libssl,libcurl"');
$this->addOption('without-suggests', null, null, 'Do not include suggested packages when using --for-extensions');
$this->addOption('force-source', null, null, 'Force extract source even if binary is available');
}
public function handle(): int
{
$cache = ApplicationContext::get(ArtifactCache::class);
$extractor = new ArtifactExtractor($cache);
$force_source = (bool) $this->getOption('force-source');
$artifacts = [];
// Direct artifact names
if ($artifact_arg = $this->getArgument('artifacts')) {
$artifact_names = parse_comma_list($artifact_arg);
foreach ($artifact_names as $name) {
$artifact = ArtifactLoader::getArtifactInstance($name);
if ($artifact === null) {
$this->output->writeln("Artifact '{$name}' not found.");
return static::FAILURE;
}
$artifacts[$name] = $artifact;
}
}
// Resolve packages and get their artifacts
$packages = [];
if ($exts = $this->getOption('for-extensions')) {
$packages = array_map(fn ($x) => "ext-{$x}", parse_extension_list($exts));
// Include php package when using for-extensions
array_unshift($packages, 'php');
}
if ($libs = $this->getOption('for-libs')) {
$packages = array_merge($packages, parse_comma_list($libs));
}
if ($pkgs = $this->getOption('for-packages')) {
$packages = array_merge($packages, parse_comma_list($pkgs));
}
if (!empty($packages)) {
$resolved = DependencyResolver::resolve($packages, [], !$this->getOption('without-suggests'));
foreach ($resolved as $pkg_name) {
$pkg = PackageLoader::getPackage($pkg_name);
if ($artifact = $pkg->getArtifact()) {
$artifacts[$artifact->getName()] = $artifact;
}
}
}
if (empty($artifacts)) {
$this->output->writeln('No artifacts specified. Use artifact names or --for-extensions/--for-libs/--for-packages options.');
$this->output->writeln('');
$this->output->writeln('Examples:');
$this->output->writeln(' spc extract php-src,openssl');
$this->output->writeln(' spc extract --for-extensions=openssl,mbstring');
$this->output->writeln(' spc extract --for-libs=libcurl,libssl');
return static::SUCCESS;
}
// make php-src always extracted first
uksort($artifacts, fn ($a, $b) => $a === 'php-src' ? -1 : ($b === 'php-src' ? 1 : 0));
try {
InteractiveTerm::notice('Extracting ' . count($artifacts) . ' artifacts: ' . implode(',', array_map(fn ($x) => ConsoleColor::yellow($x->getName()), $artifacts)) . '...');
InteractiveTerm::indicateProgress('Extracting artifacts');
foreach ($artifacts as $artifact) {
InteractiveTerm::setMessage('Extracting artifact: ' . ConsoleColor::green($artifact->getName()));
$extractor->extract($artifact, $force_source);
}
InteractiveTerm::finish('Extracted all artifacts successfully.');
} catch (\Exception $e) {
InteractiveTerm::finish('Extraction failed!', false);
throw $e;
}
return static::SUCCESS;
}
}