diff --git a/src/Exception/InvalidConfigException.php b/src/Exception/InvalidConfigException.php
new file mode 100644
index 000000000..49874cc0e
--- /dev/null
+++ b/src/Exception/InvalidConfigException.php
@@ -0,0 +1,8 @@
+fs->remove($link);
}
diff --git a/src/Local/LocalBuild.php b/src/Local/LocalBuild.php
index 1718dd42e..7e90461d7 100644
--- a/src/Local/LocalBuild.php
+++ b/src/Local/LocalBuild.php
@@ -1,6 +1,7 @@
parse(file_get_contents($appRoot . '/.platform.app.yaml'));
+ try {
+ $parser = new Parser();
+ $config = (array) $parser->parse(file_get_contents($appRoot . '/.platform.app.yaml'));
+ }
+ catch (ParseException $e) {
+ throw new InvalidConfigException(
+ "Parse error in file '$appRoot/.platform.app.yaml'. \n" . $e->getMessage()
+ );
+ }
+ }
+
+ return $this->normalizeConfig($config);
+ }
+
+ /**
+ * Normalize an application's configuration.
+ *
+ * @param array $config
+ *
+ * @return array
+ */
+ public function normalizeConfig(array $config)
+ {
+ if (isset($config['toolstack'])) {
+ $this->deprecationWarning('2015.7');
+ if (!strpos($config['toolstack'], ':')) {
+ throw new InvalidConfigException("Invalid value for 'toolstack'");
+ }
+ list($config['type'], $config['build']['flavor']) = explode(':', $config['toolstack'], 2);
}
return $config;
}
+ /**
+ * Show a warning about deprecated configuration.
+ *
+ * @param string $version
+ * @param string $file
+ */
+ public function deprecationWarning($version, $file = '.platform.app.yaml')
+ {
+ $this->output->writeln("The format of your $file configuration file is deprecated.");
+ $this->output->writeln(sprintf("See how to upgrade at: https://docs.platform.sh/reference/upgrade/#changes-in-%s", $version));
+ $this->output->writeln("");
+ }
+
/**
* Get the toolstack for a particular application.
*
@@ -180,9 +222,22 @@ public function getAppConfig($appRoot)
public function getToolstack($appRoot, array $appConfig = array())
{
$toolstackChoice = false;
- if (isset($appConfig['toolstack'])) {
- $toolstackChoice = $appConfig['toolstack'];
+
+ // For now, we reconstruct a toolstack string based on the 'type' and
+ // 'build.flavor' config keys.
+ if (isset($appConfig['type'])) {
+ $toolstackChoice = sprintf(
+ '%s:%s',
+ $appConfig['type'],
+ !empty($appConfig['build']['flavor']) ? $appConfig['build']['flavor'] : 'default'
+ );
+
+ // Alias php:default to php:composer.
+ if ($toolstackChoice === 'php:default') {
+ $toolstackChoice = 'php:composer';
+ }
}
+
foreach (self::getToolstacks() as $toolstack) {
$key = $toolstack->getKey();
if ((!$toolstackChoice && $toolstack->detect($appRoot))
@@ -319,8 +374,15 @@ protected function buildApp($appRoot, $sourceDir, $destination, array $appConfig
$this->fsHelper->extractArchive($archive, $buildDir);
} else {
$message = "Building application $appIdentifier";
- if ($key = $toolstack->getKey()) {
- $message .= " using the toolstack $key";
+ $info = array();
+ if (isset($appConfig['type'])) {
+ $info[] = 'runtime type: ' . $appConfig['type'];
+ }
+ if (!empty($treeId)) {
+ $info[] = "tree: " . substr($treeId, 0, 7);
+ }
+ if (!empty($info)) {
+ $message .= ' (' . implode(', ', $info) . ')';
}
$this->output->writeln($message);
diff --git a/src/Local/Toolstack/Composer.php b/src/Local/Toolstack/Composer.php
index 4540bc64e..8667b25db 100644
--- a/src/Local/Toolstack/Composer.php
+++ b/src/Local/Toolstack/Composer.php
@@ -4,6 +4,10 @@
class Composer extends ToolstackBase
{
+ public function getKey()
+ {
+ return 'php:composer';
+ }
public function detect($appRoot)
{
diff --git a/src/Local/Toolstack/ToolstackBase.php b/src/Local/Toolstack/ToolstackBase.php
index 3b55fe5ab..ea7eed0ce 100644
--- a/src/Local/Toolstack/ToolstackBase.php
+++ b/src/Local/Toolstack/ToolstackBase.php
@@ -107,6 +107,9 @@ protected function processSpecialDestinations()
if (!$matched) {
continue;
}
+ if ($relDestination === '{webroot}' && $this->buildInPlace) {
+ continue;
+ }
// On Platform these replacements would be a bit different.
$absDestination = str_replace(array('{webroot}', '{approot}'), array($this->getWebRoot(), $this->buildDir), $relDestination);
@@ -117,17 +120,21 @@ protected function processSpecialDestinations()
if (in_array($relSource, $this->ignoredFiles)) {
continue;
}
+ $destination = $absDestination;
+ // Do not overwrite directories with files.
+ if (!is_dir($source) && is_dir($destination)) {
+ $destination = $destination . '/' . basename($source);
+ }
+ // Ignore if source and destination are the same.
+ if ($destination === $source) {
+ continue;
+ }
if ($this->copy) {
$this->output->writeln("Copying $relSource to $relDestination");
}
else {
$this->output->writeln("Symlinking $relSource to $relDestination");
}
- $destination = $absDestination;
- // Do not overwrite directories with files.
- if (!is_dir($source) && is_dir($destination)) {
- $destination = $destination . '/' . basename($source);
- }
// Delete existing files, emitting a warning.
if (file_exists($destination)) {
$this->output->writeln(
diff --git a/tests/Local/Toolstack/ComposerTest.php b/tests/Local/Toolstack/ComposerTest.php
index 2e8d4e96f..e740edd8d 100644
--- a/tests/Local/Toolstack/ComposerTest.php
+++ b/tests/Local/Toolstack/ComposerTest.php
@@ -26,4 +26,12 @@ public function testBuildFakeSymfony()
{
$this->assertBuildSucceeds('tests/data/apps/fake-symfony');
}
+
+ /**
+ * Test the deprecated config file format still works.
+ */
+ public function testBuildDeprecatedConfig()
+ {
+ $this->assertBuildSucceeds('tests/data/apps/deprecated-config');
+ }
}
diff --git a/tests/data/apps/deprecated-config/.platform.app.yaml b/tests/data/apps/deprecated-config/.platform.app.yaml
new file mode 100644
index 000000000..6f0986971
--- /dev/null
+++ b/tests/data/apps/deprecated-config/.platform.app.yaml
@@ -0,0 +1,2 @@
+name: deprecated-config
+toolstack: php:symfony
diff --git a/tests/data/apps/drupal/project-yaml/.platform.app.yaml b/tests/data/apps/drupal/project-yaml/.platform.app.yaml
index 5838d4806..bbf5203ff 100644
--- a/tests/data/apps/drupal/project-yaml/.platform.app.yaml
+++ b/tests/data/apps/drupal/project-yaml/.platform.app.yaml
@@ -1 +1,3 @@
-toolstack: "php:drupal"
+type: php
+build:
+ flavor: drupal
diff --git a/tests/data/apps/drupal/project/.platform.app.yaml b/tests/data/apps/drupal/project/.platform.app.yaml
index e70640625..c2eb729b8 100644
--- a/tests/data/apps/drupal/project/.platform.app.yaml
+++ b/tests/data/apps/drupal/project/.platform.app.yaml
@@ -1,4 +1,6 @@
-toolstack: "php:drupal"
+type: php
+build:
+ flavor: drupal
# Test build hook
hooks:
diff --git a/tests/data/apps/fake-symfony/.platform.app.yaml b/tests/data/apps/fake-symfony/.platform.app.yaml
index 862c680a4..cfa869d6a 100644
--- a/tests/data/apps/fake-symfony/.platform.app.yaml
+++ b/tests/data/apps/fake-symfony/.platform.app.yaml
@@ -2,4 +2,6 @@
# composer.json file.
name: fake-symfony
-toolstack: "php:symfony"
+type: php
+build:
+ flavor: symfony
diff --git a/tests/data/repositories/multiple/drupal/.platform.app.yaml b/tests/data/repositories/multiple/drupal/.platform.app.yaml
index d9aab9aaa..07d0f82cf 100644
--- a/tests/data/repositories/multiple/drupal/.platform.app.yaml
+++ b/tests/data/repositories/multiple/drupal/.platform.app.yaml
@@ -1,3 +1,4 @@
name: drupal
-
-toolstack: "php:drupal"
+type: php
+build:
+ flavor: drupal