diff --git a/RoboFile.php b/RoboFile.php index 58a4ca984..ab595c8e9 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -252,44 +252,85 @@ public function publish() */ public function pharBuild() { - // Make sure to remove dev files before finding the files to pack into - // the phar. This must therefore be done outside the collection, - // as the files to pack are found when the collection is built. - $this->taskComposerInstall() - ->noDev() - ->printed(false) - ->run(); + $uncommitted = exec('git diff-index --name-only HEAD --'); + if (!empty($uncommitted)) { + $this->yell('Uncommitted changes present. Only committed files will be included in the phar.'); + } + // Create a collection builder to hold the temporary + // directory until the pack phar task runs. $collection = $this->collectionBuilder(); - // revert back phar dependencies on completion - $collection->completion($this + $workDir = $collection->tmpDir(); + $roboBuildDir = "$workDir/robo"; + $sourceRepo = 'file://' . __DIR__ . '/.git'; + + // Before we run `composer install`, we will remove the dev + // dependencies thatwe use in the unit tests. Any dev dependency + // that is in the 'suggested' section is used by a core task; + // we will include all of those in the phar. + $devProjectsToRemove = $this->devDependenciesToRemoveFromPhar(); + + // We need to create our work dir and run `composer install` + // before we prepare the pack phar task, so create a separate + // collection builder to do this step in. + $preparationResult = $this->collectionBuilder() + ->taskGitStack() + ->cloneRepo($sourceRepo, $roboBuildDir) + ->taskFilesystemStack() + ->remove("$workDir/robo/composer.lock") + ->taskComposerRemove() + ->dir($roboBuildDir) + ->dev() + ->noUpdate() + ->args($devProjectsToRemove) ->taskComposerInstall() - ->printed(false) - ); + ->dir($roboBuildDir) + ->printed(false) + ->run(); + + // Exit if the preparation step failed + if (!$preparationResult->wasSuccessful()) { + return $preparationResult; + } - $packer = $collection->taskPackPhar('robo.phar'); + // Decide which files we're going to pack $files = Finder::create()->ignoreVCS(true) ->files() ->name('*.php') ->name('*.exe') // for 1symfony/console/Resources/bin/hiddeninput.exe + ->name('GeneratedWrapper.tmpl') ->path('src') ->path('vendor') - ->exclude('symfony/config/Tests') - ->exclude('symfony/console/Tests') - ->exclude('symfony/event-dispatcher/Tests') - ->exclude('symfony/filesystem/Tests') - ->exclude('symfony/finder/Tests') - ->exclude('symfony/process/Tests') - ->exclude('henrikbjorn/lurker/tests') - ->in(__DIR__); - foreach ($files as $file) { - $packer->addFile($file->getRelativePathname(), $file->getRealPath()); - } - $packer->addFile('robo', 'robo') - ->executable('robo'); + ->notPath('docs') + ->notPath('/vendor\/.*\/[Tt]est/') + ->in($roboBuildDir); + + // Build the phar + return $collection + ->taskPackPhar('robo.phar') + ->addFiles($files) + ->addFile('robo', 'robo') + ->executable('robo') + ->taskFilesystemStack() + ->chmod('robo.phar', 0777) + ->run(); + } - return $collection->run(); + /** + * The phar:build command removes the project requirements from the + * 'require-dev' section that are not in the 'suggest' section. + * + * @return array + */ + protected function devDependenciesToRemoveFromPhar() + { + $composerInfo = (array) json_decode(file_get_contents(__DIR__ . '/composer.json')); + + $devDependencies = array_keys((array)$composerInfo['require-dev']); + $suggestedProjects = array_keys((array)$composerInfo['suggest']); + + return array_diff($devDependencies, $suggestedProjects); } /** diff --git a/src/Task/Composer/Remove.php b/src/Task/Composer/Remove.php new file mode 100644 index 000000000..4daadf574 --- /dev/null +++ b/src/Task/Composer/Remove.php @@ -0,0 +1,54 @@ +taskComposerValidate()->run(); + * ?> + * ``` + */ +class Remove extends Base +{ + protected $action = 'remove'; + + public function dev() + { + $this->option('--dev'); + return $this; + } + + public function noProgress() + { + $this->option('--no-progress'); + return $this; + } + + public function noUpdate() + { + $this->option('--no-update'); + return $this; + } + + public function updateNoDev() + { + $this->option('--update-no-dev'); + return $this; + } + + public function noUpdateWithDependencies() + { + $this->option('--no-update-with-dependencies'); + return $this; + } + + public function run() + { + $command = $this->getCommand(); + $this->printTaskInfo('Removing packages: {command}', ['command' => $command]); + return $this->executeCommand($command); + } +} diff --git a/src/Task/Composer/loadTasks.php b/src/Task/Composer/loadTasks.php index 58f12e7c5..2bd11819c 100644 --- a/src/Task/Composer/loadTasks.php +++ b/src/Task/Composer/loadTasks.php @@ -16,6 +16,7 @@ public static function getComposerServices() 'taskComposerUpdate' => Update::class, 'taskComposerDumpAutoload' => DumpAutoload::class, 'taskComposerValidate' => Validate::class, + 'taskComposerRemove' => Remove::class, ] ); } @@ -55,4 +56,13 @@ protected function taskComposerValidate($pathToComposer = null) { return $this->task(__FUNCTION__, $pathToComposer); } + + /** + * @param null $pathToComposer + * @return Remove + */ + protected function taskComposerRemove($pathToComposer = null) + { + return $this->task(__FUNCTION__, $pathToComposer); + } } diff --git a/src/Task/Development/PackPhar.php b/src/Task/Development/PackPhar.php index 926e7fa5a..1f47d3d5b 100644 --- a/src/Task/Development/PackPhar.php +++ b/src/Task/Development/PackPhar.php @@ -145,6 +145,13 @@ public function addFile($path, $file) return $this; } + public function addFiles($files) + { + foreach ($files as $file) { + $this->addFile($file->getRelativePathname(), $file->getRealPath()); + } + } + public function executable($file) { $source = file_get_contents($file);