From ba241ce3cc9957fbfac1206e5e14a4f6b031f59a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 28 Jun 2019 18:36:51 +0200 Subject: [PATCH 01/13] deprecate the framework.templating option --- UPGRADE-4.3.md | 1 + UPGRADE-5.0.md | 2 +- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkBundle/DependencyInjection/Configuration.php | 1 + .../Tests/DependencyInjection/ConfigurationTest.php | 3 +++ .../Tests/DependencyInjection/FrameworkExtensionTest.php | 4 ++++ 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index 7a6abcca81..5b581405ce 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -71,6 +71,7 @@ Form FrameworkBundle --------------- + * Deprecated the `framework.templating` option, use Twig instead. * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will be mandatory in 5.0. * Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead. diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index e16fb86c79..f8e2c70d25 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -169,8 +169,8 @@ Form FrameworkBundle --------------- + * Remved the `framework.templating` option, use Twig instead. * The project dir argument of the constructor of `AssetsInstallCommand` is required. - * Removed support for `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn` is either the service ID when using controllers as services or the FQCN of the controller. diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 8c877f562d..d8c07db3fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.3.0 ----- + * Deprecated the `framework.templating` option, use Twig instead. * Added `WebTestAssertionsTrait` (included by default in `WebTestCase`) * Renamed `Client` to `KernelBrowser` * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ea64157fde..e7233cd49e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -605,6 +605,7 @@ class Configuration implements ConfigurationInterface ->arrayNode('templating') ->info('templating configuration') ->canBeEnabled() + ->setDeprecated('The "%path%.%node%" configuration is deprecated since Symfony 4.3. Use the "twig" service directly instead.') ->beforeNormalization() ->ifTrue(function ($v) { return false === $v || \is_array($v) && false === $v['enabled']; }) ->then(function () { return ['enabled' => false, 'engines' => false]; }) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 3980036006..4a5001e106 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -35,6 +35,9 @@ class ConfigurationTest extends TestCase ); } + /** + * @group legacy + */ public function testDoNoDuplicateDefaultFormResources() { $input = ['templating' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index fab27d4897..01cd04a743 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -602,6 +602,9 @@ abstract class FrameworkExtensionTest extends TestCase $this->assertEquals('global_hinclude_template', $container->getParameter('fragment.renderer.hinclude.global_template'), '->registerTemplatingConfiguration() registers the global hinclude.js template'); } + /** + * @group legacy + */ public function testTemplatingCanBeDisabled() { $container = $this->createContainerFromFile('templating_disabled'); @@ -867,6 +870,7 @@ abstract class FrameworkExtensionTest extends TestCase } /** + * @group legacy * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException */ public function testTemplatingRequiresAtLeastOneEngine() From 28882f52cbe8fc086d6ed32beff6290ee997793c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 29 Jun 2019 18:43:59 +0200 Subject: [PATCH 02/13] Annotated correct return type for getInEdges()/getOutEdges(). --- .../Compiler/ServiceReferenceGraphNode.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php index 6abd6c86af..50140b5fff 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php @@ -81,7 +81,7 @@ class ServiceReferenceGraphNode /** * Returns the in edges. * - * @return array The in ServiceReferenceGraphEdge array + * @return ServiceReferenceGraphEdge[] */ public function getInEdges() { @@ -91,7 +91,7 @@ class ServiceReferenceGraphNode /** * Returns the out edges. * - * @return array The out ServiceReferenceGraphEdge array + * @return ServiceReferenceGraphEdge[] */ public function getOutEdges() { From c986c86d1c015f611f1683e5db35135abecbef98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 1 Jul 2019 09:18:49 +0200 Subject: [PATCH 03/13] =?UTF-8?q?[Lock]=C2=A0Stores=20must=20implement=20`?= =?UTF-8?q?putOffExpiration`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Symfony/Component/Lock/Store/ZookeeperStore.php | 2 +- src/Symfony/Component/Lock/StoreInterface.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/Lock/Store/ZookeeperStore.php b/src/Symfony/Component/Lock/Store/ZookeeperStore.php index 4f8b4ee374..0302899921 100644 --- a/src/Symfony/Component/Lock/Store/ZookeeperStore.php +++ b/src/Symfony/Component/Lock/Store/ZookeeperStore.php @@ -91,7 +91,7 @@ class ZookeeperStore implements StoreInterface */ public function putOffExpiration(Key $key, $ttl) { - throw new NotSupportedException(); + // do nothing, zookeeper locks forever. } /** diff --git a/src/Symfony/Component/Lock/StoreInterface.php b/src/Symfony/Component/Lock/StoreInterface.php index 519c3e4731..e5a1dfa588 100644 --- a/src/Symfony/Component/Lock/StoreInterface.php +++ b/src/Symfony/Component/Lock/StoreInterface.php @@ -49,7 +49,6 @@ interface StoreInterface * @param float $ttl amount of seconds to keep the lock in the store * * @throws LockConflictedException - * @throws NotSupportedException */ public function putOffExpiration(Key $key, $ttl); From 8544a35e52a4a1acdfc134a9fb68c31fa3a677ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pluchino?= Date: Mon, 1 Jul 2019 10:51:14 +0200 Subject: [PATCH 04/13] Remove @internal annotations for the serilize methods --- src/Symfony/Component/Mime/Message.php | 6 ------ src/Symfony/Component/Mime/RawMessage.php | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/Symfony/Component/Mime/Message.php b/src/Symfony/Component/Mime/Message.php index db6e13fae6..4d6af1c94d 100644 --- a/src/Symfony/Component/Mime/Message.php +++ b/src/Symfony/Component/Mime/Message.php @@ -130,17 +130,11 @@ class Message extends RawMessage return bin2hex(random_bytes(16)).strstr($email, '@'); } - /** - * @internal - */ public function __serialize(): array { return [$this->headers, $this->body]; } - /** - * @internal - */ public function __unserialize(array $data): void { [$this->headers, $this->body] = $data; diff --git a/src/Symfony/Component/Mime/RawMessage.php b/src/Symfony/Component/Mime/RawMessage.php index 16b090c954..40a2795e23 100644 --- a/src/Symfony/Component/Mime/RawMessage.php +++ b/src/Symfony/Component/Mime/RawMessage.php @@ -69,17 +69,11 @@ class RawMessage implements \Serializable $this->__unserialize(unserialize($serialized)); } - /** - * @internal - */ public function __serialize(): array { return [$this->message]; } - /** - * @internal - */ public function __unserialize(array $data): void { [$this->message] = $data; From 58651409b47e86ece0473f22b08b9e63c067c8eb Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 1 Jul 2019 14:42:30 +0200 Subject: [PATCH 05/13] Removed unused field. --- .../Compiler/AnalyzeServiceReferencesPass.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 2dafb53789..87bb14780d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -34,7 +34,6 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe private $onlyConstructorArguments; private $hasProxyDumper; private $lazy; - private $expressionLanguage; private $byConstructor; private $definitions; private $aliases; From c6e18374a25518384ae094c8871cb5196a719890 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 1 Jul 2019 10:32:47 -0400 Subject: [PATCH 06/13] Fixing validation for messenger transports retry_strategy service key --- .../DependencyInjection/Configuration.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ea64157fde..e7034b411e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1195,9 +1195,14 @@ class Configuration implements ConfigurationInterface ->end() ->arrayNode('retry_strategy') ->addDefaultsIfNotSet() - ->validate() - ->ifTrue(function ($v) { return null !== $v['service'] && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay'])); }) - ->thenInvalid('"service" cannot be used along with the other retry_strategy options.') + ->beforeNormalization() + ->always(function ($v) { + if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) { + throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.'); + } + + return $v; + }) ->end() ->children() ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end() From fa6ae8ce5073f8ccdcffcc8d719e01caa470d4b3 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 2 Jul 2019 17:10:36 +0200 Subject: [PATCH 07/13] [FrmaeworkBundle] More simplifications in the DI configuration --- .../FrameworkBundle/DependencyInjection/Configuration.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ea64157fde..443332f2ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -339,10 +339,7 @@ class Configuration implements ConfigurationInterface ->defaultNull() ->end() ->arrayNode('initial_marking') - ->beforeNormalization() - ->ifTrue(function ($v) { return !\is_array($v); }) - ->then(function ($v) { return [$v]; }) - ->end() + ->beforeNormalization()->castToArray()->end() ->defaultValue([]) ->prototype('scalar')->end() ->end() From f19f28a41d62acf89f11ad077550ebb38767aad6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 3 Jul 2019 09:52:02 +0200 Subject: [PATCH 08/13] only decorate when an event dispatcher was passed --- src/Symfony/Component/Workflow/Workflow.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index e3df8cb0d0..76e53eda51 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -43,7 +43,7 @@ class Workflow implements WorkflowInterface { $this->definition = $definition; $this->markingStore = $markingStore ?: new MultipleStateMarkingStore(); - $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); + $this->dispatcher = null !== $dispatcher ? LegacyEventDispatcherProxy::decorate($dispatcher) : null; $this->name = $name; } From bedae5dde9ee9430e4ac077d905159e1968f272d Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 3 Jul 2019 11:22:31 +0200 Subject: [PATCH 09/13] Fix authentication for redis transport --- .../Tests/Transport/RedisExt/ConnectionTest.php | 10 ++++++++++ .../Messenger/Transport/RedisExt/Connection.php | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php index 177f6b9038..0d80e920c3 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php @@ -79,6 +79,16 @@ class ConnectionTest extends TestCase $this->assertNotNull($connection->get()); } + public function testAuth() + { + $redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock(); + + $redis->expects($this->exactly(1))->method('auth') + ->with('password'); + + Connection::fromDsn('redis://password@localhost/queue', [], $redis); + } + public function testFirstGetPendingMessagesThenNewMessages() { $redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock(); diff --git a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php index 18b6091e9c..8524c1fe03 100644 --- a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php @@ -51,6 +51,11 @@ class Connection $this->connection = $redis ?: new \Redis(); $this->connection->connect($connectionCredentials['host'] ?? '127.0.0.1', $connectionCredentials['port'] ?? 6379); $this->connection->setOption(\Redis::OPT_SERIALIZER, $redisOptions['serializer'] ?? \Redis::SERIALIZER_PHP); + + if (isset($connectionCredentials['auth'])) { + $this->connection->auth($connectionCredentials['auth']); + } + $this->stream = $configuration['stream'] ?? self::DEFAULT_OPTIONS['stream']; $this->group = $configuration['group'] ?? self::DEFAULT_OPTIONS['group']; $this->consumer = $configuration['consumer'] ?? self::DEFAULT_OPTIONS['consumer']; @@ -72,6 +77,7 @@ class Connection $connectionCredentials = [ 'host' => $parsedUrl['host'] ?? '127.0.0.1', 'port' => $parsedUrl['port'] ?? 6379, + 'auth' => $parsedUrl['pass'] ?? $parsedUrl['user'] ?? null, ]; if (isset($parsedUrl['query'])) { From b5c6a349ab38d8526bb6747b66a8c8da7bb4349a Mon Sep 17 00:00:00 2001 From: smoench Date: Wed, 3 Jul 2019 13:34:39 +0200 Subject: [PATCH 10/13] [Filesystem] added missing deprecations to UPGRADE-4.3.md --- UPGRADE-4.3.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index 20b970c15a..40d50e583f 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -57,6 +57,12 @@ EventDispatcher * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated * The `Event` class has been deprecated, use `Symfony\Contracts\EventDispatcher\Event` instead +Filesystem +---------- + + * Support for passing arrays to `Filesystem::dumpFile()` is deprecated. + * Support for passing arrays to `Filesystem::appendToFile()` is deprecated. + Form ---- From 5909e6f336320ed661459395225f735472b790a1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 3 Jul 2019 14:31:50 +0200 Subject: [PATCH 11/13] fixed typo --- UPGRADE-5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index f8e2c70d25..6e7bb0a736 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -169,7 +169,7 @@ Form FrameworkBundle --------------- - * Remved the `framework.templating` option, use Twig instead. + * Removed the `framework.templating` option, use Twig instead. * The project dir argument of the constructor of `AssetsInstallCommand` is required. * Removed support for `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn` is either the service ID when using controllers as services or the FQCN of the controller. From 5f4ab23991ee5d70746366d2384d8e33215d3482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 3 Jul 2019 14:56:57 +0200 Subject: [PATCH 12/13] [Messenger] Added more test for MessageBus --- .../Messenger/Tests/MessageBusTest.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php index bcddcffd8a..c8644623b7 100644 --- a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php +++ b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\MiddlewareInterface; +use Symfony\Component\Messenger\Middleware\StackInterface; use Symfony\Component\Messenger\Stamp\BusNameStamp; use Symfony\Component\Messenger\Stamp\DelayStamp; use Symfony\Component\Messenger\Stamp\ReceivedStamp; @@ -148,4 +149,44 @@ class MessageBusTest extends TestCase $finalEnvelope = (new MessageBus())->dispatch(new Envelope(new \stdClass()), [new DelayStamp(5), new BusNameStamp('bar')]); $this->assertCount(2, $finalEnvelope->all()); } + + public function provideConstructorDataStucture() + { + yield 'iterator' => [new \ArrayObject([ + new SimpleMiddleware(), + new SimpleMiddleware(), + ])]; + + yield 'array' => [[ + new SimpleMiddleware(), + new SimpleMiddleware(), + ]]; + + yield 'generator' => [(function (): \Generator { + yield new SimpleMiddleware(); + yield new SimpleMiddleware(); + })()]; + } + + /** @dataProvider provideConstructorDataStucture */ + public function testConstructDataStructure($dataStructure) + { + $bus = new MessageBus($dataStructure); + $envelope = new Envelope(new DummyMessage('Hello')); + $newEnvelope = $bus->dispatch($envelope); + $this->assertSame($envelope->getMessage(), $newEnvelope->getMessage()); + + // Test rewindable capacity + $envelope = new Envelope(new DummyMessage('Hello')); + $newEnvelope = $bus->dispatch($envelope); + $this->assertSame($envelope->getMessage(), $newEnvelope->getMessage()); + } +} + +class SimpleMiddleware implements MiddlewareInterface +{ + public function handle(Envelope $envelope, StackInterface $stack): Envelope + { + return $envelope; + } } From 1f8927a9a64dc80124389fe482ba9ccc40ed8689 Mon Sep 17 00:00:00 2001 From: misterx <216417+misterx@users.noreply.github.com> Date: Wed, 26 Jun 2019 14:51:54 +0300 Subject: [PATCH 13/13] Fixes windows error --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index c0f4b782b6..3f5d14574d 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -95,7 +95,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ $prevRoot = getenv('COMPOSER_ROOT_VERSION'); putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS - $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true))); + $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p)); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); if ($exit) { exit($exit);