diff --git a/.travis.yml b/.travis.yml
index 9af339e7b..6425f9eb5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -90,6 +90,8 @@ script:
- drupal yaml:update:value project.yml project.local.hostname '127.0.0.1:8888'
# BLT added new dependencies for us, so we must update.
- composer update
+ # Execute all updates with fake "dev" => "dev" version specs. This must be done manually since BLT was not installed prior to this.
+ - blt-console blt:update dev dev $(pwd) --yes
# Create a .travis.yml, just to make sure it works. It won't be executed.
- blt ci:travis:init
- blt ci:pipelines:init
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 000000000..e69de29bb
diff --git a/bin/blt-console b/bin/blt-console
index 592e0101e..56ba7e647 100755
--- a/bin/blt-console
+++ b/bin/blt-console
@@ -3,6 +3,7 @@
use Acquia\Blt\Console\Command\ComposerMungeCommand;
use Acquia\Blt\Console\Command\YamlMungeCommand;
+use Acquia\Blt\Console\Command\UpdateCommand;
use Symfony\Bridge\Twig\Command\LintCommand;
use Symfony\Component\Console\Application;
@@ -26,4 +27,6 @@ $application = new Application();
$application->add(new ComposerMungeCommand());
$application->add(new YamlMungeCommand());
$application->add(new \Acquia\Blt\Console\Command\TwigLintCommand);
+$application->add(new UpdateCommand());
+
$application->run();
diff --git a/composer.json b/composer.json
index d0155f5ff..07ef23205 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,9 @@
"squizlabs/php_codesniffer": "^2.7",
"symfony/yaml": "^2.8.11",
"symfony/console": "^2.8.11",
- "symfony/twig-bridge": "^2.8.11"
+ "symfony/twig-bridge": "^2.8.11",
+ "doctrine/common": "^2.5",
+ "vierbergenlars/php-semver": "^3.0"
},
"autoload": {
"psr-4": {
diff --git a/composer.lock b/composer.lock
index 2a61c9232..fac6972b6 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "5a569247ba859639075a439aded0c6bd",
- "content-hash": "421ea293c853ac6e7c05681341757e84",
+ "hash": "cccdab26f0d5b46cf505a27ae59514a6",
+ "content-hash": "e036a66c5f77742dc664e908fb5ffde0",
"packages": [
{
"name": "alchemy/zippy",
@@ -350,6 +350,76 @@
],
"time": "2015-08-31 12:32:49"
},
+ {
+ "name": "doctrine/cache",
+ "version": "v1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/cache.git",
+ "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3",
+ "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~5.5|~7.0"
+ },
+ "conflict": {
+ "doctrine/common": ">2.2,<2.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8|~5.0",
+ "predis/predis": "~1.0",
+ "satooshi/php-coveralls": "~0.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Caching library offering an object-oriented API for many cache backends",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "cache",
+ "caching"
+ ],
+ "time": "2016-10-29 11:16:17"
+ },
{
"name": "doctrine/collections",
"version": "v1.3.0",
@@ -416,6 +486,146 @@
],
"time": "2015-04-14 22:21:58"
},
+ {
+ "name": "doctrine/common",
+ "version": "v2.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/common.git",
+ "reference": "a579557bc689580c19fee4e27487a67fe60defc0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/common/zipball/a579557bc689580c19fee4e27487a67fe60defc0",
+ "reference": "a579557bc689580c19fee4e27487a67fe60defc0",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/annotations": "1.*",
+ "doctrine/cache": "1.*",
+ "doctrine/collections": "1.*",
+ "doctrine/inflector": "1.*",
+ "doctrine/lexer": "1.*",
+ "php": "~5.5|~7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8|~5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\": "lib/Doctrine/Common"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Common Library for Doctrine projects",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "annotations",
+ "collections",
+ "eventmanager",
+ "persistence",
+ "spl"
+ ],
+ "time": "2015-12-25 13:18:31"
+ },
+ {
+ "name": "doctrine/inflector",
+ "version": "v1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "90b2128806bfde671b6952ab8bea493942c1fdae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
+ "reference": "90b2128806bfde671b6952ab8bea493942c1fdae",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Inflector\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Common String Manipulations with regard to casing and singular/plural rules.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "inflection",
+ "pluralize",
+ "singularize",
+ "string"
+ ],
+ "time": "2015-11-06 14:35:42"
+ },
{
"name": "doctrine/instantiator",
"version": "1.0.5",
@@ -650,16 +860,16 @@
},
{
"name": "gabordemooij/redbean",
- "version": "v4.3.2",
+ "version": "v4.3.3",
"source": {
"type": "git",
"url": "https://github.com/gabordemooij/redbean.git",
- "reference": "72368f15cedfa7990c7fb228e47d2f00c7f49d4f"
+ "reference": "1c7ec69850e9f7966ff7feb87b01d8f43a9753d3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/gabordemooij/redbean/zipball/72368f15cedfa7990c7fb228e47d2f00c7f49d4f",
- "reference": "72368f15cedfa7990c7fb228e47d2f00c7f49d4f",
+ "url": "https://api.github.com/repos/gabordemooij/redbean/zipball/1c7ec69850e9f7966ff7feb87b01d8f43a9753d3",
+ "reference": "1c7ec69850e9f7966ff7feb87b01d8f43a9753d3",
"shasum": ""
},
"require": {
@@ -687,7 +897,7 @@
"keywords": [
"orm"
],
- "time": "2016-05-01 10:27:43"
+ "time": "2016-10-03 21:25:17"
},
{
"name": "guzzlehttp/guzzle",
@@ -904,16 +1114,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.5.4",
+ "version": "1.5.5",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f"
+ "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
- "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108",
+ "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108",
"shasum": ""
},
"require": {
@@ -942,7 +1152,7 @@
"object",
"object graph"
],
- "time": "2016-09-16 13:37:59"
+ "time": "2016-10-31 17:19:45"
},
{
"name": "padraic/humbug_get_contents",
@@ -1448,16 +1658,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "4.0.1",
+ "version": "4.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3"
+ "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3",
- "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
+ "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
"shasum": ""
},
"require": {
@@ -1507,7 +1717,7 @@
"testing",
"xunit"
],
- "time": "2016-07-26 14:39:29"
+ "time": "2016-11-01 05:06:24"
},
{
"name": "phpunit/php-file-iterator",
@@ -1692,16 +1902,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "5.6.1",
+ "version": "5.6.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7"
+ "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60c32c5b5e79c2248001efa2560f831da11cc2d7",
- "reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c",
+ "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c",
"shasum": ""
},
"require": {
@@ -1770,7 +1980,7 @@
"testing",
"xunit"
],
- "time": "2016-10-07 13:03:26"
+ "time": "2016-11-14 06:39:40"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -2305,16 +2515,16 @@
},
{
"name": "sebastian/recursion-context",
- "version": "1.0.2",
+ "version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
+ "reference": "938df7a6478e72795e5f8266cff24d06e3136f2e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
- "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/938df7a6478e72795e5f8266cff24d06e3136f2e",
+ "reference": "938df7a6478e72795e5f8266cff24d06e3136f2e",
"shasum": ""
},
"require": {
@@ -2354,7 +2564,7 @@
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
- "time": "2015-11-11 19:50:13"
+ "time": "2016-11-15 06:55:36"
},
{
"name": "sebastian/resource-operations",
@@ -2566,7 +2776,7 @@
},
{
"name": "symfony/config",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
@@ -2619,16 +2829,16 @@
},
{
"name": "symfony/console",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "d7a5a88178f94dcc29531ea4028ea614e35452d4"
+ "reference": "7350016c8abcab897046f1aead2b766b84d3eff8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/d7a5a88178f94dcc29531ea4028ea614e35452d4",
- "reference": "d7a5a88178f94dcc29531ea4028ea614e35452d4",
+ "url": "https://api.github.com/repos/symfony/console/zipball/7350016c8abcab897046f1aead2b766b84d3eff8",
+ "reference": "7350016c8abcab897046f1aead2b766b84d3eff8",
"shasum": ""
},
"require": {
@@ -2676,11 +2886,11 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2016-09-28 00:10:16"
+ "time": "2016-10-06 01:43:09"
},
{
"name": "symfony/css-selector",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -2733,7 +2943,7 @@
},
{
"name": "symfony/debug",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
@@ -2790,16 +3000,16 @@
},
{
"name": "symfony/dependency-injection",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75"
+ "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ee9ec9ac2b046462d341e9de7c4346142d335e75",
- "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3d61c765daa1a5832f1d7c767f48886b8d8ea64c",
+ "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c",
"shasum": ""
},
"require": {
@@ -2849,20 +3059,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2016-09-24 09:47:20"
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/dom-crawler",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "aac03b7ea2a7adff10a3599d614e79e6101230ab"
+ "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/aac03b7ea2a7adff10a3599d614e79e6101230ab",
- "reference": "aac03b7ea2a7adff10a3599d614e79e6101230ab",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4",
+ "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4",
"shasum": ""
},
"require": {
@@ -2905,20 +3115,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
- "time": "2016-07-30 07:20:35"
+ "time": "2016-10-18 15:35:45"
},
{
"name": "symfony/event-dispatcher",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8"
+ "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8",
- "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
+ "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
"shasum": ""
},
"require": {
@@ -2965,20 +3175,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2016-07-28 16:56:28"
+ "time": "2016-10-13 01:43:15"
},
{
"name": "symfony/filesystem",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf"
+ "reference": "a3784111af9f95f102b6411548376e1ae7c93898"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/44b499521defddf2eae17a18c811bbdae4f98bdf",
- "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/a3784111af9f95f102b6411548376e1ae7c93898",
+ "reference": "a3784111af9f95f102b6411548376e1ae7c93898",
"shasum": ""
},
"require": {
@@ -3014,11 +3224,11 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2016-09-06 10:55:00"
+ "time": "2016-10-18 04:28:30"
},
{
"name": "symfony/finder",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@@ -3067,16 +3277,16 @@
},
{
"name": "symfony/http-foundation",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "91f87d27e9fe99435278c337375b0dce292fe0e2"
+ "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/91f87d27e9fe99435278c337375b0dce292fe0e2",
- "reference": "91f87d27e9fe99435278c337375b0dce292fe0e2",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a6e6c34d337f3c74c39b29c5f54d33023de8897c",
+ "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c",
"shasum": ""
},
"require": {
@@ -3118,20 +3328,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
- "time": "2016-09-21 19:04:07"
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "dff51f72b0706335131b00a7f49606168c582594"
+ "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
- "reference": "dff51f72b0706335131b00a7f49606168c582594",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4",
+ "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4",
"shasum": ""
},
"require": {
@@ -3143,7 +3353,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2-dev"
+ "dev-master": "1.3-dev"
}
},
"autoload": {
@@ -3177,20 +3387,20 @@
"portable",
"shim"
],
- "time": "2016-05-18 14:26:46"
+ "time": "2016-11-14 01:06:16"
},
{
"name": "symfony/polyfill-php54",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php54.git",
- "reference": "34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1"
+ "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1",
- "reference": "34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1",
+ "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/90e085822963fdcc9d1c5b73deb3d2e5783b16a0",
+ "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0",
"shasum": ""
},
"require": {
@@ -3199,7 +3409,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2-dev"
+ "dev-master": "1.3-dev"
}
},
"autoload": {
@@ -3235,20 +3445,20 @@
"portable",
"shim"
],
- "time": "2016-05-18 14:26:46"
+ "time": "2016-11-14 01:06:16"
},
{
"name": "symfony/polyfill-php55",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php55.git",
- "reference": "bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d"
+ "reference": "03e3f0350bca2220e3623a0e340eef194405fc67"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d",
- "reference": "bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d",
+ "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/03e3f0350bca2220e3623a0e340eef194405fc67",
+ "reference": "03e3f0350bca2220e3623a0e340eef194405fc67",
"shasum": ""
},
"require": {
@@ -3258,7 +3468,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2-dev"
+ "dev-master": "1.3-dev"
}
},
"autoload": {
@@ -3291,11 +3501,11 @@
"portable",
"shim"
],
- "time": "2016-05-18 14:26:46"
+ "time": "2016-11-14 01:06:16"
},
{
"name": "symfony/process",
- "version": "v3.1.5",
+ "version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
@@ -3344,16 +3554,16 @@
},
{
"name": "symfony/translation",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "bf0ff95faa9b6c0708efc1986255e3608d0ed3c7"
+ "reference": "cca6ff892355876534b01a927f789bac9601c935"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/bf0ff95faa9b6c0708efc1986255e3608d0ed3c7",
- "reference": "bf0ff95faa9b6c0708efc1986255e3608d0ed3c7",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/cca6ff892355876534b01a927f789bac9601c935",
+ "reference": "cca6ff892355876534b01a927f789bac9601c935",
"shasum": ""
},
"require": {
@@ -3404,25 +3614,25 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
- "time": "2016-09-06 10:55:00"
+ "time": "2016-10-18 04:28:30"
},
{
"name": "symfony/twig-bridge",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bridge.git",
- "reference": "5586685d161c411ab33a9ea72d3b25a337337942"
+ "reference": "b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5586685d161c411ab33a9ea72d3b25a337337942",
- "reference": "5586685d161c411ab33a9ea72d3b25a337337942",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf",
+ "reference": "b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
- "twig/twig": "~1.26|~2.0"
+ "twig/twig": "~1.27|~2.0"
},
"require-dev": {
"symfony/asset": "~2.7|~3.0.0",
@@ -3485,20 +3695,20 @@
],
"description": "Symfony Twig Bridge",
"homepage": "https://symfony.com",
- "time": "2016-10-03 15:49:46"
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/yaml",
- "version": "v2.8.12",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c"
+ "reference": "396784cd06b91f3db576f248f2402d547a077787"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/e7540734bad981fe59f8ef14b6fc194ae9df8d9c",
- "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/396784cd06b91f3db576f248f2402d547a077787",
+ "reference": "396784cd06b91f3db576f248f2402d547a077787",
"shasum": ""
},
"require": {
@@ -3534,20 +3744,20 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2016-09-02 01:57:56"
+ "time": "2016-10-21 20:59:10"
},
{
"name": "twig/twig",
- "version": "v1.26.1",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d"
+ "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/a09d8ee17ac1cfea29ed60c83960ad685c6a898d",
- "reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
+ "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
"shasum": ""
},
"require": {
@@ -3560,7 +3770,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.26-dev"
+ "dev-master": "1.27-dev"
}
},
"autoload": {
@@ -3595,7 +3805,59 @@
"keywords": [
"templating"
],
- "time": "2016-10-05 18:57:41"
+ "time": "2016-10-25 19:17:17"
+ },
+ {
+ "name": "vierbergenlars/php-semver",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vierbergenlars/php-semver.git",
+ "reference": "516bb3061577e60e9420cbecc479362d3ad8c7f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vierbergenlars/php-semver/zipball/516bb3061577e60e9420cbecc479362d3ad8c7f1",
+ "reference": "516bb3061577e60e9420cbecc479362d3ad8c7f1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "simpletest/simpletest": "1.1.*"
+ },
+ "bin": [
+ "bin/semver",
+ "bin/update-versions"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "vierbergenlars\\SemVer\\": "src/",
+ "vierbergenlars\\LibJs\\": "src/"
+ },
+ "classmap": [
+ "src/vierbergenlars/SemVer/internal.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Vierbergen",
+ "email": "vierbergenlars@gmail.com"
+ }
+ ],
+ "description": "The Semantic Versioner for PHP",
+ "keywords": [
+ "semantic",
+ "semver",
+ "versioning"
+ ],
+ "time": "2015-05-02 19:28:54"
},
{
"name": "webmozart/assert",
diff --git a/phing/tasks/blt.xml b/phing/tasks/blt.xml
index 1f1b770dc..5b4fbfdfc 100644
--- a/phing/tasks/blt.xml
+++ b/phing/tasks/blt.xml
@@ -48,6 +48,12 @@
To remove deprecated BLT files, run "blt cleanup".
+
+
+
+
+
+
Merging BLT's composer.json template with your project's composer.json.
diff --git a/src/Annotations/Update.php b/src/Annotations/Update.php
new file mode 100644
index 000000000..e610856fc
--- /dev/null
+++ b/src/Annotations/Update.php
@@ -0,0 +1,19 @@
+ "onPrePackageEvent",
+ PackageEvents::PRE_PACKAGE_UPDATE => "onPrePackageEvent",
PackageEvents::POST_PACKAGE_INSTALL => "onPostPackageEvent",
PackageEvents::POST_PACKAGE_UPDATE => "onPostPackageEvent",
ScriptEvents::POST_UPDATE_CMD => 'onPostCmdEvent'
);
}
+ /**
+ * Marks initial blt version before install or update command.
+ *
+ * @param \Composer\Installer\PackageEvent $event
+ */
+ public function onPrePackageEvent(\Composer\Installer\PackageEvent $event){
+ $package = $this->getBltPackage($event->getOperation());
+ if ($package) {
+ $this->blt_prior_version = $package->getVersion();
+ // We write this to disk because the blt_prior_version property does not persist.
+ file_put_contents($this->getVendorPath() . '/blt_prior_version.txt', $this->blt_prior_version);
+ }
+ }
/**
* Marks blt to be processed after an install or update command.
*
@@ -88,18 +107,20 @@ public function onPostPackageEvent(\Composer\Installer\PackageEvent $event){
}
/**
- * Post install command event to execute the blt update.
+ * Execute blt update after update command has been executed, if applicable.
*
* @param \Composer\Script\Event $event
*/
public function onPostCmdEvent(\Composer\Script\Event $event) {
// Only install the template files if acquia/blt was installed.
if (isset($this->bltPackage)) {
- $this->executeBltUpdate();
+ $version = $this->bltPackage->getVersion();
+ $this->executeBltUpdate($version);
}
}
/**
+ * Gets the acquia/blt package, if it is the package that is being operated on.
* @param $operation
* @return mixed
*/
@@ -116,18 +137,54 @@ protected function getBltPackage($operation) {
return NULL;
}
- protected function executeBltUpdate() {
+ /**
+ * Executes `blt update` and `blt-console blt:update` commands.
+ * @param $version
+ */
+ protected function executeBltUpdate($version) {
$options = $this->getOptions();
if ($options['blt']['update']) {
- $this->io->write('Updating BLT templated files');
+ $this->io->write('Updating BLT templated files...');
+
+ // Rsyncs, updates composer.json, project.yml.
$this->executeCommand('blt update');
+
+ if (file_exists($this->getVendorPath() . '/blt_prior_version.txt')) {
+ $this->blt_prior_version = file_get_contents($this->getVendorPath() . '/blt_prior_version.txt');
+ unlink($this->getVendorPath() . '/blt_prior_version.txt');
+ }
+
+ // Execute update hooks for this specific version delta.
+ if (isset($this->blt_prior_version)) {
+ $this->io->write("Executing scripted updates for BLT version delta {$this->blt_prior_version} -> $version ...");
+ // $this->executeCommand("blt blt:update-delta -Dblt.prior_version={$this->blt_prior_version} -Dblt.version=$version");
+ // @todo Allow prompt here.
+ $this->executeCommand("blt-console blt:update {$this->blt_prior_version} $version {$this->getRepoRoot()} --yes");
+ }
+ else {
+ $this->io->write("Could not detect prior BLT version. Skipping scripted updates.");
+ }
+
$this->io->write('This may have modified your composer.json and require a subsequent `composer update`');
+
+ // @todo check if require or require-dev changed. If so, run `composer update`.
+ // @todo if require and require-dev did not change, but something else in composer.json changed, execute `composer update --lock`.
}
else {
$this->io->write('Skipping update of BLT templated files');
}
}
+ /**
+ * Returns the repo root's filepath, assumed to be one dir above vendor dir.
+ *
+ * @return string
+ * The file path of the repository root.
+ */
+ public function getRepoRoot() {
+ return dirname($this->getVendorPath());
+ }
+
/**
* Get the path to the 'vendor' directory.
*
@@ -138,6 +195,7 @@ public function getVendorPath() {
$filesystem = new Filesystem();
$filesystem->ensureDirectoryExists($config->get('vendor-dir'));
$vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
+
return $vendorPath;
}
diff --git a/src/Console/Command/UpdateCommand.php b/src/Console/Command/UpdateCommand.php
new file mode 100644
index 000000000..1c8036b47
--- /dev/null
+++ b/src/Console/Command/UpdateCommand.php
@@ -0,0 +1,77 @@
+setName('blt:update')
+ ->setDescription('Performs BLT updates for specific version delta.')
+ ->addArgument(
+ 'starting_version',
+ InputArgument::REQUIRED,
+ 'The starting version'
+ )
+ ->addArgument(
+ 'ending_version',
+ InputArgument::REQUIRED,
+ 'The ending version.'
+ )
+ ->addArgument(
+ 'repo_root',
+ InputArgument::REQUIRED,
+ 'The root directory of the repository that utilizes BLT.'
+ )
+ ->addOption(
+ 'yes',
+ 'y',
+ InputOption::VALUE_NONE,
+ 'Answers yes to all question prompts'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $starting_version = $input->getArgument('starting_version');
+ $ending_version = $input->getArgument('ending_version');
+ $repo_root = $input->getArgument('repo_root');
+
+ $updater = new Updater();
+ $updater->setRepoRoot($repo_root);
+ $updates = $updater->getUpdates($starting_version, $ending_version);
+ if ($updates) {
+ $output->writeln("The following BLT updates are outstanding:");
+ $updater->printUpdates($updates);
+
+ if (!$input->getOption('yes')) {
+ $question = new ConfirmationQuestion(
+ 'Would you like to perform the listed updates? ',
+ false
+ );
+
+ $continue = $this->getHelper('question')->ask($input, $output, $question);
+ if (!$continue) {
+ return 1;
+ }
+ }
+
+ $updater->executeUpdates($updates);
+ }
+ else {
+ $output->writeln("There are no scripted updates avaiable between BLT versions $starting_version and $ending_version.");
+ }
+ }
+}
diff --git a/src/Update/Updater.php b/src/Update/Updater.php
new file mode 100644
index 000000000..3e37fc6e8
--- /dev/null
+++ b/src/Update/Updater.php
@@ -0,0 +1,227 @@
+repoRoot.
+ *
+ * @return string
+ * The filepath of the repository root directory.
+ */
+ public function getRepoRoot() {
+ return $this->repoRoot;
+ }
+
+ /**
+ * The filepath of the repository root directory.
+ *
+ * This directory is expected to contain the composer.json that defines
+ * acquia/blt as a dependency.
+ *
+ * @param string $repoRoot
+ * The filepath of the repository root directory.
+ */
+ public function setRepoRoot($repoRoot) {
+ if (!$this->fs->exists($repoRoot)) {
+ throw new FileNotFoundException();
+ }
+
+ $this->repoRoot = $repoRoot;
+ }
+
+ /**
+ * Updater constructor.
+ *
+ * @param string $update_class
+ * The name of the class containing the update methods to be executed.
+ */
+ public function __construct($update_class = 'Acquia\Blt\Update\Updates')
+ {
+ $this->output = new ConsoleOutput();
+ $this->output->setFormatter(new OutputFormatter(true));
+ AnnotationRegistry::registerFile(__DIR__ . '/../Annotations/Update.php');
+ $this->annotationsReader = new IndexedReader(new AnnotationReader());
+ $this->updateClassName = $update_class;
+ $this->fs = new Filesystem();
+ }
+
+ /**
+ * Executes an array of updates.
+ *
+ * @param $updates \Acquia\Blt\Annotations\Update[]
+ */
+ public function executeUpdates($updates) {
+ /** @var Updates $updates_object */
+ $updates_object = new $this->updateClassName();
+ $updates_object->setUpdater($this);
+ /**
+ * @var string $method_name
+ * @var Update $update
+ */
+ foreach ($updates as $method_name => $update) {
+ $this->output->writeln("Executing Updater->$method_name: {$update->description}");
+ call_user_func([$updates_object, $method_name]);
+ }
+ }
+
+ /**
+ * Prints a human-readable list of update methods to the screen.
+ *
+ * @param $updates \Acquia\Blt\Annotations\Update[]
+ */
+ public function printUpdates($updates) {
+ /**
+ * @var string $method_name
+ * @var Update $update
+ */
+ foreach ($updates as $method_name => $update) {
+ $this->output->writeln("{$update->version}: {$update->description}");
+ }
+ }
+
+ /**
+ * Gets all applicable updates for a given version delta.
+ *
+ * @param string $starting_version
+ * The starting version. E.g., 8.5.0.
+ *
+ * @param string $ending_version
+ * The ending version. E.g., 8.5.1.
+ *
+ * @return array
+ * An array of applicable update methods, keyed by method name. Each row
+ * contains the metadata from the Update annotation.
+ */
+ public function getUpdates($starting_version, $ending_version) {
+ $updates = [];
+ $update_methods = $this->getAllUpdateMethods();
+ $include_all_updates = FALSE;
+
+ if (strpos($starting_version, 'dev') !== FALSE
+ || strpos($ending_version, 'dev') !== FALSE ) {
+ $this->output->writeln("You are (or were) using a development branch of BLT. Assuming that you require all scripted updates.");
+ $include_all_updates = TRUE;
+ }
+
+ /**
+ * @var string $method_name
+ * @var Update $metadata
+ */
+ foreach ($update_methods as $method_name => $metadata) {
+ $version = $metadata->version;
+
+ if ($include_all_updates
+ || (version::gt($version, $starting_version) && version::lte($version, $ending_version))) {
+ $updates[$method_name] = $metadata;
+ }
+ }
+
+ return $updates;
+ }
+
+ /**
+ * Gather an array of all available update methods.
+ *
+ * This will only return methods using the Update annotation.
+ *
+ * @see drupal_get_schema_versions()
+ */
+ protected function getAllUpdateMethods() {
+ $update_methods = [];
+ $methods = get_class_methods($this->updateClassName);
+ foreach ($methods as $method_name) {
+ $reflectionMethod = new \ReflectionMethod($this->updateClassName, $method_name);
+ $annotations = $this->annotationsReader->getMethodAnnotation($reflectionMethod, 'Acquia\Blt\Annotations\Update');
+ if ($annotations) {
+ $update_methods[$method_name] = $annotations;
+ }
+ }
+
+ return $update_methods;
+ }
+
+ /**
+ * @param string $command
+ * @param string $cwd
+ * @param bool $display_output
+ * Optional. Whether to print command output to screen. Changes return
+ * value.
+ * @param bool $mustRun
+ *
+ * @return bool|string
+ * If $display_output is true, method will return TRUE for success, FALSE
+ * for failure. If $display_output false, method will return command output.
+ */
+ public static function executeCommand($command, $cwd = null, $display_output = true, $mustRun = true)
+ {
+ $timeout = 10800;
+ $env = [
+ 'COMPOSER_PROCESS_TIMEOUT' => $timeout
+ ] + $_ENV;
+ $process = new Process($command, $cwd, $env, null, $timeout);
+ $method = $mustRun ? 'mustRun' : 'run';
+ if ($display_output) {
+ $process->$method(function ($type, $buffer) {
+ print $buffer;
+ });
+ return $process->isSuccessful();
+ } else {
+ $process->$method();
+ return $process->getOutput();
+ }
+ }
+
+ /**
+ * Removes a patch from repo's root composer.json file.
+ *
+ * @param string $package
+ * The composer package name. E.g., 'drupal/features'.
+ *
+ * @param string $url
+ * The URL of the patch.
+ *
+ * @return bool
+ * TRUE if patch was removed, otherwise FALSE.
+ */
+ public function removePatch($package, $url) {
+ $composer_json_filepath = $this->repoRoot . '/composer.json';
+ $composer_json = json_decode(file_get_contents($composer_json_filepath), TRUE);
+ if (!empty($composer_json['extra']['patches'][$package])) {
+ foreach ($composer_json['extra']['patches'][$package] as $key => $patch_url) {
+ if ($patch_url == $url) {
+ unset($composer_json['extra']['patches'][$package][$key]);
+ // If that was the only patch for this module, unset the parent too.
+ if (empty($composer_json['extra']['patches'][$package])) {
+ unset($composer_json['extra']['patches'][$package]);
+ }
+ file_put_contents($composer_json_filepath, json_encode($composer_json, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
+
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ }
+}
diff --git a/src/Update/Updates.php b/src/Update/Updates.php
new file mode 100644
index 000000000..6c03e558b
--- /dev/null
+++ b/src/Update/Updates.php
@@ -0,0 +1,28 @@
+updater = $updater;
+ }
+
+ /**
+ * @Update(
+ * version = "8.5.1",
+ * description = "Removes deprecated features patch."
+ * )
+ */
+ public function update_851() {
+ $this->updater->removePatch("drupal/features", "https://www.drupal.org/files/issues/features-2808303-2.patch");
+ }
+}
diff --git a/template/project.yml b/template/project.yml
index 75ef3aed7..62bff58cc 100644
--- a/template/project.yml
+++ b/template/project.yml
@@ -70,8 +70,7 @@ target-hooks:
# Define any custom Phing files that you'd like to import. E.g., ${repo.root}/blt/phing/build.xml
import: ~
-# An array of modules to be enabled or uninstalled automatically in dev vs prod contexts.
-# All local:* targets assume the "dev" context, whereas "deploy:*" targets assume a prod context.
+# An array of modules to be enabled or uninstalled automatically in local, ci, and deploy contexts.
modules:
ci:
enable: []