Skip to content

Commit

Permalink
Made default project template selection automatic based on core versi…
Browse files Browse the repository at this point in the history
…on. (#105)
  • Loading branch information
TravisCarden authored Aug 31, 2020
1 parent 93df119 commit ec5113d
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/Console/Command/Fixture/FixtureInitCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ protected function configure(): void {
->addOption('profile', NULL, InputOption::VALUE_REQUIRED, 'The Drupal installation profile to use, e.g., "minimal". ("orca" is a pseudo-profile based on "minimal", with the Toolbar module enabled and Seven as the admin theme)', FixtureCreator::DEFAULT_PROFILE)

// Uncommon options.
->addOption('project-template', NULL, InputOption::VALUE_REQUIRED, 'The Composer project template used to create the fixture', FixtureCreator::DEFAULT_PROJECT_TEMPLATE)
->addOption('project-template', NULL, InputOption::VALUE_REQUIRED, 'The Composer project template used to create the fixture')
->addOption('ignore-patch-failure', NULL, InputOption::VALUE_NONE, 'Do not exit on failure to apply Composer patches. (Useful for debugging failures)')
->addOption('no-sqlite', NULL, InputOption::VALUE_NONE, 'Use the default database settings instead of SQLite')
->addOption('no-site-install', NULL, InputOption::VALUE_NONE, 'Do not install Drupal. Supersedes the "--profile" option')
Expand Down
10 changes: 5 additions & 5 deletions src/Drupal/DrupalCoreVersionFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public function getPretty(DrupalCoreVersion $version): string {
/**
* Finds the Drupal core version matching the given criteria.
*
* @param string|null $target_package_version
* The target package version.
* @param string|null $target_core_version
* The target core version.
* @param string $minimum_stability
* The minimum stability. Available options (in order of stability) are
* dev, alpha, beta, RC, and stable.
Expand All @@ -94,11 +94,11 @@ public function getPretty(DrupalCoreVersion $version): string {
* @return string
* The version string.
*/
public function find(string $target_package_version = NULL, string $minimum_stability = 'stable', string $preferred_stability = 'stable'): string {
public function find(string $target_core_version = NULL, string $minimum_stability = 'stable', string $preferred_stability = 'stable'): string {
$best_candidate = $this->getVersionSelector($minimum_stability)
->findBestCandidate('drupal/core', $target_package_version, NULL, $preferred_stability);
->findBestCandidate('drupal/core', $target_core_version, NULL, $preferred_stability);
if (!$best_candidate) {
throw new RuntimeException(sprintf('No Drupal core version satisfies the given constraints: version=%s, minimum stability=%s', $target_package_version, $minimum_stability));
throw new RuntimeException(sprintf('No Drupal core version satisfies the given constraints: version=%s, minimum stability=%s', $target_core_version, $minimum_stability));
}
return $best_candidate->getPrettyVersion();
}
Expand Down
28 changes: 2 additions & 26 deletions src/Fixture/FixtureCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use Composer\Semver\Comparator;
use Composer\Semver\VersionParser;
use Symfony\Component\Console\Style\SymfonyStyle;
use UnexpectedValueException;

/**
* Creates a fixture.
Expand All @@ -31,8 +30,6 @@ class FixtureCreator {

public const DEFAULT_PROFILE = 'orca';

public const DEFAULT_PROJECT_TEMPLATE = 'acquia/blt-project';

/**
* The BLT package, if defined.
*
Expand Down Expand Up @@ -363,7 +360,7 @@ private function fixDefaultDependencies(): void {
* Returns TRUE if it should be required, or FALSE if not.
*/
private function shouldRequireDrupalConsole(): bool {
$version = $this->getResolvedDrupalCoreVersion();
$version = $this->options->getCoreResolved();
return Comparator::lessThan($version, '9');
}

Expand All @@ -377,31 +374,10 @@ private function shouldRequireDrupalConsole(): bool {
* Returns TRUE if it should be required, or FALSE if not.
*/
private function shouldRequireDrupalCoreDev(): bool {
$version = $this->getResolvedDrupalCoreVersion();
$version = $this->options->getCoreResolved();
return Comparator::greaterThanOrEqualTo($version, '8.8');
}

/**
* Gets the concrete version of Drupal core that will be installed.
*
* @return string
* The best match for the requested version of Drupal core, accounting for
* ranges.
*/
private function getResolvedDrupalCoreVersion(): string {
$core = $this->options->getCore();
try {
// Get the version if it's concrete as opposed to a range.
$version = $this->versionParser->normalize($core);
}
catch (UnexpectedValueException $e) {
// The requested Drupal core version is a range. Get the best match.
$stability = $this->options->isDev() ? 'dev' : 'stable';
$version = $this->coreVersionFinder->find($core, $stability, $stability);
}
return $version;
}

/**
* Gets the list of unwanted packages.
*
Expand Down
53 changes: 51 additions & 2 deletions src/Fixture/FixtureOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
use Acquia\Orca\Package\Package;
use Acquia\Orca\Package\PackageManager;
use Closure;
use Composer\Semver\Comparator;
use Composer\Semver\VersionParser;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\OptionsResolver;
use UnexpectedValueException;

/**
* Encapsulates fixture options.
Expand All @@ -25,6 +28,13 @@ class FixtureOptions {
*/
private $composer;

/**
* The resolved core version.
*
* @var string
*/
private $coreResolved = '';

/**
* The Drupal Core version finder.
*
Expand Down Expand Up @@ -279,13 +289,52 @@ public function getProfile(): ?string {
/**
* Gets the Composer project template package name.
*
* @return string|null
* @return string
* The package name.
*/
public function getProjectTemplate(): ?string {
public function getProjectTemplate(): string {
if ($this->options['project-template']) {
return $this->options['project-template'];
}
if (Comparator::lessThan($this->getCoreResolved(), '9')) {
$this->options['project-template'] = 'acquia/blt-project';
return $this->options['project-template'];
}
$this->options['project-template'] = 'acquia/drupal-recommended-project';
return $this->options['project-template'];
}

/**
* Gets the exact, resolved version of Drupal core.
*
* @return string
* The best match for the current version of Drupal core, accounting for
* ranges.
*/
public function getCoreResolved(): string {
if ($this->coreResolved) {
return $this->coreResolved;
}
$core = $this->getCore();
try {
// Get the version if it's exact as opposed to a range.
$parser = new VersionParser();
$version = $parser->normalize($core);
// Catch dev versions being treated as exact instead of ranges.
if (strpos($version, 'dev') !== FALSE) {
throw new UnexpectedValueException('Version is a dev version.');
}
}
catch (UnexpectedValueException $e) {
// The core version is a range. Get the best match.
$stability = $this->isDev() ? 'dev' : 'stable';
$version = $this->drupalCoreVersionFinder
->find($core, $stability, $stability);
}
$this->coreResolved = $version;
return $version;
}

/**
* Gets the SUT if set.
*
Expand Down
81 changes: 69 additions & 12 deletions tests/Fixture/FixtureOptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function testDefaults(): void {
self::assertFalse($options->symlinkAll(), 'Set/got default "symlink-all" option.');
self::assertEquals($core, $options->getCore(), 'Set/got default "core" option.');
self::assertNull($options->getProfile(), 'Set/got default "profile" option.');
self::assertNull($options->getProjectTemplate(), 'Set/got default "project-template" option.');
self::assertEquals('acquia/drupal-recommended-project', $options->getProjectTemplate(), 'Set/got default "project-template" option.');
self::assertNull($options->getSut(), 'Set/got default "sut" option.');
self::assertTrue($options->installSite(), 'Set/got default "no-site-install" option.');
self::assertTrue($options->useSqlite(), 'Set/got default "no-sqlite" option.');
Expand Down Expand Up @@ -266,8 +266,12 @@ public function testCoreConstantValid($version): void {
->willReturn($expected);

$options = $this->createFixtureOptions(['core' => $version]);
// Call once to test essential functionality.
$core = $options->getCore();
// Call again to test value caching.
$options->getCore();

self::assertEquals($expected, $options->getCore(), 'Accepted valid "core" constant option.');
self::assertEquals($expected, $core, 'Accepted valid "core" constant option.');
}

public function providerCoreConstantValid(): array {
Expand All @@ -279,6 +283,39 @@ public function providerCoreConstantValid(): array {
return $array;
}

/**
* @dataProvider providerCoreResolvedRange
*
* @covers ::getCoreResolved
* @covers ::resolve
*/
public function testCoreResolvedRange($core, $dev, $stability): void {
$this->drupalCoreVersionFinder
->find($core, $stability, $stability)
->shouldBeCalledOnce()
->willReturn('string');

$options = $this->createFixtureOptions([
'core' => $core,
'dev' => $dev,
]);
// Call once to test essential functionality.
$options->getCoreResolved();
// Call again to test value caching.
$options->getCoreResolved();
}

public function providerCoreResolvedRange(): array {
return [
['~8', FALSE, 'stable'],
['8.0.0@dev', FALSE, 'stable'],
['8.0.x-dev', FALSE, 'stable'],
['>8 <9', FALSE, 'stable'],
['~9', FALSE, 'stable'],
['~9', TRUE, 'dev'],
];
}

/**
* @covers ::findCoreVersion
* @covers ::getCore
Expand Down Expand Up @@ -347,24 +384,16 @@ public function providerProfileInvalid(): array {
}

/**
* @dataProvider providerProjectTemplateValid
*
* @covers ::isValidProjectTemplateValue
* @covers ::resolve
*/
public function testProjectTemplateValid($name): void {
public function testProjectTemplateValid(): void {
$name = 'test/example';
$options = $this->createFixtureOptions(['project-template' => $name]);

self::assertEquals($name, $options->getProjectTemplate(), 'Accepted valid "project-template" option.');
}

public function providerProjectTemplateValid(): array {
return [
[NULL],
['test/example'],
];
}

/**
* @covers ::isValidProjectTemplateValue
* @covers ::resolve
Expand All @@ -375,6 +404,34 @@ public function testProjectTemplateInvalid(): void {
$this->createFixtureOptions(['project-template' => 'invalid']);
}

/**
* @dataProvider providerProjectTemplateSelectionByCoreVersion
*
* @covers ::getCoreResolved
* @covers ::getProjectTemplate
* @covers ::resolve
*/
public function testProjectTemplateSelectionByCoreVersion($core, $expected): void {
$this->drupalCoreVersionFinder
->find($core, Argument::any(), Argument::any())
->willReturnArgument();

$options = $this->createFixtureOptions(['core' => $core]);

self::assertEquals($expected, $options->getProjectTemplate(), 'Selected correct project template for core version.');
}

public function providerProjectTemplateSelectionByCoreVersion(): array {
return [
['8.0.0@dev', 'acquia/blt-project'],
['8.0.x-dev', 'acquia/blt-project'],
['8.0.0', 'acquia/blt-project'],
['8.0.x-dev', 'acquia/blt-project'],
['9.0.0', 'acquia/drupal-recommended-project'],
['9.0.0@dev', 'acquia/drupal-recommended-project'],
];
}

/**
* @covers ::getSut
* @covers ::hasSut
Expand Down

0 comments on commit ec5113d

Please sign in to comment.