diff --git a/src/Composer/Satis/Command/BuildCommand.php b/src/Composer/Satis/Command/BuildCommand.php index cfe52c0d..45f0fabc 100644 --- a/src/Composer/Satis/Command/BuildCommand.php +++ b/src/Composer/Satis/Command/BuildCommand.php @@ -12,6 +12,7 @@ namespace Composer\Satis\Command; +use Composer\Package\Loader\ArrayLoader; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -50,6 +51,7 @@ protected function configure() ->setDefinition(array( new InputArgument('file', InputArgument::OPTIONAL, 'Json file to use', './satis.json'), new InputArgument('output-dir', InputArgument::OPTIONAL, 'Location where to output built files', null), + new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be built, if not provided all packages are.', null), new InputOption('no-html-output', null, InputOption::VALUE_NONE, 'Turn off HTML view'), new InputOption('skip-errors', null, InputOption::VALUE_NONE, 'Skip Download or Archive errors'), )) @@ -101,6 +103,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { $verbose = $input->getOption('verbose'); $configFile = $input->getArgument('file'); + $packagesFilter = $input->getArgument('packages'); $skipErrors = (bool)$input->getOption('skip-errors'); if (preg_match('{^https?://}i', $configFile)) { @@ -141,7 +144,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $composer = $this->getApplication()->getComposer(true, $config); - $packages = $this->selectPackages($composer, $output, $verbose, $requireAll, $requireDependencies, $requireDevDependencies, $minimumStability, $skipErrors); + $packages = $this->selectPackages($composer, $output, $verbose, $requireAll, $requireDependencies, $requireDevDependencies, $minimumStability, $skipErrors, $packagesFilter); if ($htmlView = !$input->getOption('no-html-output')) { $htmlView = !isset($config['output-html']) || $config['output-html']; @@ -152,6 +155,15 @@ protected function execute(InputInterface $input, OutputInterface $output) } $filenamePrefix = $outputDir.'/include/all'; + $filename = $outputDir.'/packages.json'; + if(!empty($packagesFilter)) { + // in case of an active package filter we need to load the dumped packages.json and merge the + // updated packages in + $oldPackages = $this->loadDumpedPackages($filename, $packagesFilter); + $packages += $oldPackages; + ksort($packages); + } + $packageFile = $this->dumpPackageIncludeJson($packages, $output, $filenamePrefix); $packageFileHash = hash_file('sha1', $packageFile); @@ -159,7 +171,6 @@ protected function execute(InputInterface $input, OutputInterface $output) 'include/all$'.$packageFileHash.'.json' => array( 'sha1'=>$packageFileHash ), ); - $filename = $outputDir.'/packages.json'; $this->dumpPackagesJson($includes, $output, $filename); if ($htmlView) { @@ -176,7 +187,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - private function selectPackages(Composer $composer, OutputInterface $output, $verbose, $requireAll, $requireDependencies, $requireDevDependencies, $minimumStability, $skipErrors) + private function selectPackages(Composer $composer, OutputInterface $output, $verbose, $requireAll, $requireDependencies, $requireDevDependencies, $minimumStability, $skipErrors, array $packagesFilter = array()) { $selected = array(); @@ -198,6 +209,7 @@ private function selectPackages(Composer $composer, OutputInterface $output, $ve if ($requireAll) { $links = array(); + $filterForPackages = count($packagesFilter) > 0; foreach ($repos as $repo) { // collect links for composer repos with providers @@ -206,8 +218,18 @@ private function selectPackages(Composer $composer, OutputInterface $output, $ve $links[] = new Link('__root__', $name, new MultiConstraint(array()), 'requires', '*'); } } else { - // process other repos directly - foreach ($repo->getPackages() as $package) { + $packages = array(); + if($filterForPackages) { + // apply package filter if defined + foreach ($packagesFilter as $filter) { + $packages += $repo->findPackages($filter); + } + } else { + // process other repos directly + $packages = $repo->getPackages(); + } + + foreach ($packages as $package) { // skip aliases if ($package instanceof AliasPackage) { continue; @@ -425,6 +447,45 @@ private function dumpWeb(array $packages, OutputInterface $output, PackageInterf file_put_contents($directory.'/index.html', $content); } + private function loadDumpedPackages($filename, array $packagesFilter = array()) + { + $packages = array(); + $repoJson = new JsonFile($filename); + $dirName = dirname($filename); + + if ($repoJson->exists()) { + $loader = new ArrayLoader(); + $jsonIncludes = $repoJson->read(); + $jsonIncludes = isset($jsonIncludes['includes']) && is_array($jsonIncludes['includes']) + ? $jsonIncludes['includes'] + : array(); + + foreach ($jsonIncludes as $includeFile => $includeConfig) { + $includeJson = new JsonFile($dirName . '/' . $includeFile); + $jsonPackages = $includeJson->read(); + $jsonPackages = isset($jsonPackages['packages']) && is_array($jsonPackages['packages']) + ? $jsonPackages['packages'] + : array(); + + foreach ($jsonPackages as $jsonPackage) { + if (is_array($jsonPackage)) { + foreach ($jsonPackage as $jsonVersion) { + if (is_array($jsonVersion)) { + if(isset($jsonVersion['name']) && in_array($jsonVersion['name'], $packagesFilter)) { + continue; + } + $package = $loader->load($jsonVersion); + $packages[$package->getUniqueName()] = $package; + } + } + } + } + } + } + + return $packages; + } + private function getMappedPackageList(array $packages) { $groupedPackages = $this->groupPackagesByName($packages);