Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #57: Distinguish files depending on dev environment. #58

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ of your root `composer.json`.
"includes": [
"sites/default/example.settings.my.php"
],
"includes-dev": [
"my_settings_file_for_development.php"
],
"initial": {
"sites/default/default.services.yml": "sites/default/services.yml",
"sites/default/default.settings.php": "sites/default/settings.php"
Expand All @@ -58,25 +61,29 @@ default.

Default includes are provided by the plugin:
```
.csslintrc
.editorconfig
.eslintignore
.eslintrc (Drupal <= 8.2.x)
.eslintrc.json (Drupal >= 8.3.x)
.gitattributes
.ht.router.php (Drupal >= 8.5.x)
.htaccess
index.php
robots.txt
sites/default/default.settings.php
sites/default/default.services.yml
sites/development.services.yml
sites/example.settings.local.php
sites/example.sites.php
update.php
web.config
```

Default includes dev are provided by the plugin:
```
.csslintrc
.editorconfig
.eslintignore
.eslintrc (Drupal <= 8.2.x)
.eslintrc.json (Drupal >= 8.3.x)
.gitattributes
.ht.router.php (Drupal >= 8.5.x)
sites/development.services.yml
```

When setting `omit-defaults` to `true`, neither the default excludes nor the
default includes will be provided; in this instance, only those files explicitly
listed in the `excludes` and `includes` options will be considered. If
Expand All @@ -87,6 +94,9 @@ The `initial` hash lists files that should be copied over only if they do not
exist in the destination. The key specifies the path to the source file, and
the value indicates the path to the destination file.

The `includes-dev` hash lists files that should be copied over only if they do not
exist in the destination and if the dev packages are installed.

## Limitation

When using Composer to install or update the Drupal development branch, the
Expand Down
8 changes: 6 additions & 2 deletions src/DrupalScaffoldCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Composer\Command\BaseCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
Expand All @@ -20,15 +21,18 @@ protected function configure() {
parent::configure();
$this
->setName('drupal:scaffold')
->setDescription('Update the Drupal scaffold files.');
->setDescription('Update the Drupal scaffold files.')
->setDefinition(array(
new InputOption('no-dev', NULL, InputOption::VALUE_NONE, 'Disables download of include-dev files.'),
));
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$handler = new Handler($this->getComposer(), $this->getIO());
$handler->downloadScaffold();
$handler->downloadScaffold(!$input->getOption('no-dev'));
// Generate the autoload.php file after generating the scaffold files.
$handler->generateAutoload();
}
Expand Down
59 changes: 46 additions & 13 deletions src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,30 @@ public function onPostCmdEvent(Event $event) {
// Only install the scaffolding if drupal/core was installed,
// AND there are no scaffolding files present.
if (isset($this->drupalCorePackage)) {
$this->downloadScaffold();
$this->downloadScaffold($event->isDevMode());
// Generate the autoload.php file after generating the scaffold files.
$this->generateAutoload();
}
}

/**
* Downloads drupal scaffold files for the current process.
*
* @param bool $dev
* TRUE if dev packages are installed. FALSE otherwise.
*/
public function downloadScaffold() {
public function downloadScaffold($dev = TRUE) {
$drupalCorePackage = $this->getDrupalCorePackage();
$webroot = realpath($this->getWebRoot());

// Collect options, excludes and settings files.
// Collect options, excludes, dev and settings files.
$options = $this->getOptions();
$files = array_diff($this->getIncludes(), $this->getExcludes());
$includes = $this->getIncludes();
// Check dev files if necessary.
if ($dev) {
$includes = array_merge($includes, $this->getIncludesDev());
}
$files = array_diff($includes, $this->getExcludes());

// Call any pre-scaffold scripts that may be defined.
$dispatcher = new EventDispatcher($this->composer, $this->io);
Expand Down Expand Up @@ -304,6 +312,15 @@ protected function getIncludes() {
return $this->getNamedOptionList('includes', 'getIncludesDefault');
}

/**
* Retrieve list of additional dev files from optional "extra" configuration.
*
* @return array
*/
protected function getIncludesDev() {
return $this->getNamedOptionList('includes-dev', 'getIncludesDevDefault');
}

/**
* Retrieve list of initial files from optional "extra" configuration.
*
Expand Down Expand Up @@ -342,6 +359,7 @@ protected function getOptions() {
'omit-defaults' => FALSE,
'excludes' => [],
'includes' => [],
'includes-dev' => [],
'initial' => [],
'source' => 'https://cgit.drupalcode.org/drupal/plain/{path}?h={version}',
// Github: https://raw.githubusercontent.com/drupal/drupal/{version}/{path}
Expand All @@ -360,32 +378,47 @@ protected function getExcludesDefault() {
* Holds default settings files list.
*/
protected function getIncludesDefault() {
$version = $this->getDrupalCoreVersion($this->getDrupalCorePackage());
list($major, $minor) = explode('.', $version, 3);
$version = "$major.$minor";

/**
* Files from 8.3.x
*
* @see https://cgit.drupalcode.org/drupal/tree/?h=8.3.x
*/
$common = [
'.csslintrc',
'.editorconfig',
'.eslintignore',
'.gitattributes',
'.htaccess',
'index.php',
'robots.txt',
'sites/default/default.settings.php',
'sites/default/default.services.yml',
'sites/development.services.yml',
'sites/example.settings.local.php',
'sites/example.sites.php',
'update.php',
'web.config',
];

return $common;
}

/**
* Holds default dev files list.
*/
protected function getIncludesDevDefault() {
$version = $this->getDrupalCoreVersion($this->getDrupalCorePackage());
list($major, $minor) = explode('.', $version, 3);
$version = "$major.$minor";

/**
* Files from 8.3.x
*
* @see http://cgit.drupalcode.org/drupal/tree/?h=8.3.x
*/
$common = [
'.csslintrc',
'.editorconfig',
'.eslintignore',
'.gitattributes',
'sites/development.services.yml',
];

// Version specific variations.
if (Semver::satisfies($version, '<8.3')) {
$common[] = '.eslintrc';
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function postCmd(Event $event) {
public static function scaffold(Event $event) {
@trigger_error('\DrupalComposer\DrupalScaffold\Plugin::scaffold is deprecated since version 2.5.0 and will be removed in 3.0. Use "composer drupal:scaffold" instead.', E_USER_DEPRECATED);
$handler = new Handler($event->getComposer(), $event->getIO());
$handler->downloadScaffold();
$handler->downloadScaffold($event->isDevMode());
// Generate the autoload.php file after generating the scaffold files.
$handler->generateAutoload();
}
Expand Down
141 changes: 141 additions & 0 deletions tests/BaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace DrupalComposer\DrupalScaffold\Tests;

use Composer\Util\Filesystem;
use PHPUnit\Framework\TestCase;

/**
* Base test Class for drupal-scaffold features.
*/
abstract class BaseTest extends TestCase {

/**
* @var \Composer\Util\Filesystem
*/
protected $fs;

/**
* @var string
*/
protected $tmpDir;

/**
* @var string
*/
protected $rootDir;

/**
* @var string
*/
protected $tmpReleaseTag;

/**
* SetUp test
*/
public function setUp() {
$this->rootDir = realpath(realpath(__DIR__ . '/..'));

// Prepare temp directory.
$this->fs = new Filesystem();
$this->tmpDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'drupal-scaffold';
$this->ensureDirectoryExistsAndClear($this->tmpDir);

$this->writeTestReleaseTag();
$this->writeComposerJSON();

chdir($this->tmpDir);
}

/**
* tearDown
*
* @return void
*/
public function tearDown() {
$this->fs->removeDirectory($this->tmpDir);
$this->git(sprintf('tag -d "%s"', $this->tmpReleaseTag));
}

/**
* Writes the default composer json to the temp direcoty.
*/
protected function writeComposerJSON() {
$json = json_encode($this->composerJSONDefaults(), JSON_PRETTY_PRINT);
// Write composer.json.
file_put_contents($this->tmpDir . '/composer.json', $json);
}

/**
* Writes a tag for the current commit, so we can reference it directly in the
* composer.json.
*/
protected function writeTestReleaseTag() {
// Tag the current state.
$this->tmpReleaseTag = '999.0.' . time();
$this->git(sprintf('tag -a "%s" -m "%s"', $this->tmpReleaseTag, 'Tag for testing this exact commit'));
}

/**
* Provides the default composer.json data.
*
* @return array
*/
protected function composerJSONDefaults() {
return array(
'repositories' => array(
array(
'type' => 'vcs',
'url' => $this->rootDir,
),
),
'require' => array(
'drupal-composer/drupal-scaffold' => $this->tmpReleaseTag,
'composer/installers' => '^1.0.20',
'drupal/core' => '8.0.0',
),
'minimum-stability' => 'dev',
);
}

/**
* Wrapper for the composer command.
*
* @param string $command
* Composer command name, arguments and/or options
*/
protected function composer($command) {
chdir($this->tmpDir);
passthru(escapeshellcmd($this->rootDir . '/vendor/bin/composer ' . $command), $exit_code);
if ($exit_code !== 0) {
throw new \Exception('Composer returned a non-zero exit code');
}
}

/**
* Wrapper for git command in the root directory.
*
* @param $command
* Git command name, arguments and/or options.
*/
protected function git($command) {
chdir($this->rootDir);
passthru(escapeshellcmd('git ' . $command), $exit_code);
if ($exit_code !== 0) {
throw new \Exception('Git returned a non-zero exit code');
}
}

/**
* Makes sure the given directory exists and has no content.
*
* @param string $directory
*/
protected function ensureDirectoryExistsAndClear($directory) {
if (is_dir($directory)) {
$this->fs->removeDirectory($directory);
}
mkdir($directory, 0777, TRUE);
}

}
42 changes: 42 additions & 0 deletions tests/HandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/**
* @file
* Contains \DrupalComposer\DrupalScaffold\Tests\HandlerTest.
*/

namespace DrupalComposer\DrupalScaffold\Tests;

/**
* Tests composer plugin functionality.
*/
class HandlerTest extends BaseTest {

/**
* Tests that files for dev environments are downloaded only in dev mode.
*/
public function testDevFiles() {
$exampleScaffoldFile = $this->tmpDir . DIRECTORY_SEPARATOR . 'index.php';
$developmentScaffoldFile = $this->tmpDir . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . 'development.services.yml';
$this->assertFileNotExists($exampleScaffoldFile, 'Scaffold file should not exist.');
$this->assertFileNotExists($developmentScaffoldFile, 'Development scaffold file should not exist.');
$this->composer('install --no-dev');
$this->assertFileExists($exampleScaffoldFile, 'Scaffold file should exist.');
$this->assertFileNotExists($developmentScaffoldFile, 'Development scaffold file should not exist.');
$this->composer('drupal:scaffold');
$this->assertFileExists($exampleScaffoldFile, 'Scaffold file should exist.');
$this->assertFileExists($developmentScaffoldFile, 'Development scaffold file should exist.');
}

/**
* Add prefer-stable true to speed up tests.
*
* @return array
*/
protected function composerJSONDefaults() {
$composerJsonDefault = parent::composerJSONDefaults();
$composerJsonDefault['prefer-stable'] = TRUE;
return $composerJsonDefault;
}

}
Loading