Skip to content

Commit

Permalink
Fixes acquia#341 acquia#284: Automating alias installation and templa…
Browse files Browse the repository at this point in the history
…te updates.
  • Loading branch information
grasmash committed Sep 9, 2016
1 parent 51c42a0 commit 13aede8
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 6 deletions.
10 changes: 8 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "acquia/blt",
"description": "BLT",
"type": "composer-plugin",
"license": "GPL-2.0",
"require": {
"drupal/console": "~1",
Expand All @@ -11,14 +12,19 @@
"symfony/yaml": "~2.7",
"drupal/coder": "~8.2",
"symfony/console": "~2",
"symfony/twig-bridge": "~2"
"symfony/twig-bridge": "~2",
"php": ">=5.6",
"composer-plugin-api": "^1.0.0"
},
"autoload": {
"psr-4": {
"Acquia\\Blt\\": "src/",
"Acquia\\Blt\\Tests\\": "tests/phpunit/src/"
}
},
"extra": {
"class": "Acquia\\Blt\\Composer\\BltPlugin"
},
"bin": [
"bin/blt",
"bin/blt-console"
Expand All @@ -29,6 +35,6 @@
"minimum-stability": "beta",
"prefer-stable": true,
"scripts": {
"install-blt-alias": "./blt.sh install-alias"
"install-blt-alias": "yes | ./blt.sh install-alias"
}
}
8 changes: 5 additions & 3 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion phing/tasks/blt.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<exec dir="${repo.root}" command="rsync -a --no-g ${blt.root}/template/README.md ${repo.root}/ --ignore-existing" logoutput="true" checkreturn="true" level="info" passthru="true"/>
</target>

<target name="update" depends="init, blt:update-yml, configure">
<target name="update" depends="init, configure">
<!-- @todo Ignore some files, settings.php, project.yml, in update. Instead, change only specific values. -->
<exec dir="${repo.root}" command="${blt.root}/scripts/blt/update.sh" logoutput="true" checkreturn="true" level="info" passthru="true" />
<echo>Some of your customized files may have been modified.</echo>
Expand Down
174 changes: 174 additions & 0 deletions src/Composer/BltPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

/**
* @file
* Provides a way to patch Composer packages after installation.
*/

namespace Acquia\Blt\Composer;

use Composer\Composer;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginInterface;
use Composer\Installer\PackageEvents;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use Composer\Script\PackageEvent;
use Composer\Util\ProcessExecutor;
use Composer\Util\RemoteFilesystem;
use Symfony\Component\Process\Process;

class BltPlugin implements PluginInterface, EventSubscriberInterface {

/**
* @var Composer $composer
*/
protected $composer;
/**
* @var IOInterface $io
*/
protected $io;
/**
* @var EventDispatcher $eventDispatcher
*/
protected $eventDispatcher;
/**
* @var ProcessExecutor $executor
*/
protected $executor;

/**
* @var \Composer\Package\PackageInterface
*/
protected $bltPackage;

/**
* Apply plugin modifications to composer
*
* @param Composer $composer
* @param IOInterface $io
*/
public function activate(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
$this->eventDispatcher = $composer->getEventDispatcher();
$this->executor = new ProcessExecutor($this->io);
}

/**
* Returns an array of event names this subscriber wants to listen to.
*/
public static function getSubscribedEvents() {
return array(
PackageEvents::POST_PACKAGE_INSTALL => "onPostPackageEvent",
PackageEvents::POST_PACKAGE_UPDATE => "onPostPackageEvent",
ScriptEvents::POST_UPDATE_CMD => 'onPostCmdEvent',
ScriptEvents::POST_INSTALL_CMD => 'onPostCmdEvent',
);
}

/**
* Marks blt to be processed after an install or update command.
*
* @param \Composer\Installer\PackageEvent $event
*/
public function onPostPackageEvent(\Composer\Installer\PackageEvent $event){
$package = $this->getBltPackage($event->getOperation());
if ($package) {
// By explicitly setting the blt package, the onPostCmdEvent() will
// process the update automatically.
$this->bltPackage = $package;
}
}

/**
* Post install command event to execute the blt update.
*
* @param \Composer\Script\Event $event
*/
public function onPostCmdEvent(\Composer\Script\Event $event) {
// Only install the scaffolding if acquia/blt was installed,
if (isset($this->bltPackage)) {
$this->executeBltUpdate();
}
}

/**
* @param $operation
* @return mixed
*/
protected function getBltPackage($operation) {
if ($operation instanceof InstallOperation) {
$package = $operation->getPackage();
}
elseif ($operation instanceof UpdateOperation) {
$package = $operation->getTargetPackage();
}
if (isset($package) && $package instanceof PackageInterface && $package->getName() == 'acquia/blt') {
return $package;
}
return NULL;
}

protected function executeBltUpdate() {
// @todo cd into project root from getVendorPath?
$this->io->write('<info>Updating BLT templated files</info>');
$this->executeCommand('blt update');
$this->io->write('<info>BLT template files were updated</info>');
$this->io->write('<comment>This may have modified your composer.json and require a subsequent `composer update`</comment>');
}

/**
* Get the path to the 'vendor' directory.
*
* @return string
*/
public function getVendorPath() {
$config = $this->composer->getConfig();
$filesystem = new Filesystem();
$filesystem->ensureDirectoryExists($config->get('vendor-dir'));
$vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
return $vendorPath;
}

/**
* Executes a shell command with escaping.
*
* @param string $cmd
* @return bool
*/
protected function executeCommand($cmd) {
// Shell-escape all arguments except the command.
$args = func_get_args();
foreach ($args as $index => $arg) {
if ($index !== 0) {
$args[$index] = escapeshellarg($arg);
}
}
// And replace the arguments.
$command = call_user_func_array('sprintf', $args);
$output = '';
if ($this->io->isVerbose()) {
$this->io->write('<comment> > ' . $command . '</comment>');
$io = $this->io;
$output = function ($type, $buffer) use ($io) {
if ($type == Process::ERR) {
$io->write('<error>' . $buffer . '</error>');
}
else {
// @todo Figure out how to preserve color!
$io->write($buffer);
}
};
}
return ($this->executor->execute($command, $output) == 0);
}

}

0 comments on commit 13aede8

Please sign in to comment.