From cf781bd40964f39acb07feea92fa58692eda10d7 Mon Sep 17 00:00:00 2001 From: maxhelias Date: Wed, 29 Jul 2020 11:02:11 +0200 Subject: [PATCH] Add a dedicated file deletion for unconfigure recipes --- src/Configurator.php | 6 +- src/Configurator/AbstractConfigurator.php | 5 +- .../CopyFromPackageConfigurator.php | 2 +- .../CopyFromRecipeConfigurator.php | 30 +----- src/FilesManager.php | 102 ++++++++++++++++++ src/Flex.php | 6 +- src/Options.php | 43 +------- .../Configurator/BundlesConfiguratorTest.php | 2 + .../ContainerConfiguratorTest.php | 6 ++ ...pyDirectoryFromPackageConfiguratorTest.php | 3 +- .../CopyFromPackageConfiguratorTest.php | 3 +- .../CopyFromRecipeConfiguratorTest.php | 3 +- .../DockerComposeConfiguratorTest.php | 1 + .../DockerfileConfiguratorTest.php | 1 + tests/Configurator/EnvConfiguratorTest.php | 3 + .../GitignoreConfiguratorTest.php | 2 + .../Configurator/MakefileConfiguratorTest.php | 2 + 17 files changed, 141 insertions(+), 79 deletions(-) create mode 100644 src/FilesManager.php diff --git a/src/Configurator.php b/src/Configurator.php index 80a83b1ab..0e59df495 100644 --- a/src/Configurator.php +++ b/src/Configurator.php @@ -22,14 +22,16 @@ class Configurator { private $composer; private $io; + private $filesManager; private $options; private $configurators; private $cache; - public function __construct(Composer $composer, IOInterface $io, Options $options) + public function __construct(Composer $composer, IOInterface $io, FilesManager $filesManager, Options $options) { $this->composer = $composer; $this->io = $io; + $this->filesManager = $filesManager; $this->options = $options; // ordered list of configurators $this->configurators = [ @@ -78,6 +80,6 @@ private function get($key): AbstractConfigurator $class = $this->configurators[$key]; - return $this->cache[$key] = new $class($this->composer, $this->io, $this->options); + return $this->cache[$key] = new $class($this->composer, $this->io, $this->filesManager, $this->options); } } diff --git a/src/Configurator/AbstractConfigurator.php b/src/Configurator/AbstractConfigurator.php index ec05dacf0..73d321213 100644 --- a/src/Configurator/AbstractConfigurator.php +++ b/src/Configurator/AbstractConfigurator.php @@ -13,6 +13,7 @@ use Composer\Composer; use Composer\IO\IOInterface; +use Symfony\Flex\FilesManager; use Symfony\Flex\Lock; use Symfony\Flex\Options; use Symfony\Flex\Path; @@ -25,13 +26,15 @@ abstract class AbstractConfigurator { protected $composer; protected $io; + protected $filesManager; protected $options; protected $path; - public function __construct(Composer $composer, IOInterface $io, Options $options) + public function __construct(Composer $composer, IOInterface $io, FilesManager $filesManager, Options $options) { $this->composer = $composer; $this->io = $io; + $this->filesManager = $filesManager; $this->options = $options; $this->path = new Path($options->get('root-dir')); } diff --git a/src/Configurator/CopyFromPackageConfigurator.php b/src/Configurator/CopyFromPackageConfigurator.php index 75af761a7..9d52214f2 100644 --- a/src/Configurator/CopyFromPackageConfigurator.php +++ b/src/Configurator/CopyFromPackageConfigurator.php @@ -94,7 +94,7 @@ private function copyDir(string $source, string $target, array $options) public function copyFile(string $source, string $target, array $options) { $overwrite = $options['force'] ?? false; - if (!$this->options->shouldWriteFile($target, $overwrite)) { + if (!$this->filesManager->shouldWriteFile($target, $overwrite)) { return; } diff --git a/src/Configurator/CopyFromRecipeConfigurator.php b/src/Configurator/CopyFromRecipeConfigurator.php index 9bc708496..196310a05 100644 --- a/src/Configurator/CopyFromRecipeConfigurator.php +++ b/src/Configurator/CopyFromRecipeConfigurator.php @@ -30,33 +30,7 @@ public function configure(Recipe $recipe, $config, Lock $lock, array $options = public function unconfigure(Recipe $recipe, $config, Lock $lock) { $this->write('Removing files from recipe'); - $this->removeFiles($config, $this->getRemovableFilesFromRecipeAndLock($recipe, $lock), $this->options->get('root-dir')); - } - - private function getRemovableFilesFromRecipeAndLock(Recipe $recipe, Lock $lock): array - { - $lockedFiles = array_unique( - array_reduce( - array_column($lock->all(), 'files'), - function (array $carry, array $package) { - return array_merge($carry, $package); - }, - [] - ) - ); - - $removableFiles = $recipe->getFiles(); - - $lockedFiles = array_map('realpath', $lockedFiles); - - // Compare file paths by their real path to abstract OS differences - foreach (array_keys($removableFiles) as $file) { - if (\in_array(realpath($file), $lockedFiles)) { - unset($removableFiles[$file]); - } - } - - return $removableFiles; + $this->removeFiles($config, $this->filesManager->getRemovableFilesFromRecipeAndLock($recipe), $this->options->get('root-dir')); } private function copyFiles(array $manifest, array $files, array $options): array @@ -98,7 +72,7 @@ private function copyFile(string $to, string $contents, bool $executable, array $basePath = $options['root-dir'] ?? '.'; $copiedFile = str_replace($basePath.\DIRECTORY_SEPARATOR, '', $to); - if (!$this->options->shouldWriteFile($to, $overwrite)) { + if (!$this->filesManager->shouldWriteFile($to, $overwrite)) { return $copiedFile; } diff --git a/src/FilesManager.php b/src/FilesManager.php new file mode 100644 index 000000000..9d92caabe --- /dev/null +++ b/src/FilesManager.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Flex; + +use Composer\IO\IOInterface; +use Composer\Util\ProcessExecutor; + +/** + * @author Maxime Hélias + */ +class FilesManager +{ + private $io; + protected $path; + + private $writtenFiles = []; + private $files; + + public function __construct(IOInterface $io, Lock $lock, string $rootDir) + { + $this->io = $io; + + $this->path = new Path($rootDir); + $this->files = array_count_values( + array_map( + function (string $file) { + return realpath($file) ?: ''; + }, array_reduce( + array_column($lock->all(), 'files'), + function (array $carry, array $package) { + return array_merge($carry, $package); + }, + [] + ) + ) + ); + } + + public function shouldWriteFile(string $file, bool $overwrite): bool + { + if (isset($this->writtenFiles[$file])) { + return false; + } + $this->writtenFiles[$file] = true; + + if (!file_exists($file)) { + return true; + } + + if (!$overwrite) { + return false; + } + + if (!filesize($file)) { + return true; + } + + exec('git status --short --ignored --untracked-files=all -- '.ProcessExecutor::escape($file).' 2>&1', $output, $status); + + if (0 !== $status) { + return (bool) $this->io && $this->io->askConfirmation(sprintf('Cannot determine the state of the "%s" file, overwrite anyway? [y/N] ', $file), false); + } + + if (empty($output[0]) || preg_match('/^[ AMDRCU][ D][ \t]/', $output[0])) { + return true; + } + + $name = basename($file); + $name = \strlen($output[0]) - \strlen($name) === strrpos($output[0], $name) ? substr($output[0], 3) : $name; + + return (bool) $this->io && $this->io->askConfirmation(sprintf('File "%s" has uncommitted changes, overwrite? [y/N] ', $name), false); + } + + public function getRemovableFilesFromRecipeAndLock(Recipe $recipe): array + { + $removableFiles = $recipe->getFiles(); + // Compare file paths by their real path to abstract OS differences + foreach (array_keys($removableFiles) as $file) { + $file = realpath($file); + if (!isset($this->files[$file])) { + continue; + } + + --$this->files[$file]; + + if ($this->files[$file] <= 0) { + unset($removableFiles[$file]); + } + } + + return $removableFiles; + } +} diff --git a/src/Flex.php b/src/Flex.php index 88171311a..c3e87c76b 100644 --- a/src/Flex.php +++ b/src/Flex.php @@ -70,6 +70,7 @@ class Flex implements PluginInterface, EventSubscriberInterface private $config; private $options; + private $filesManager; private $configurator; private $downloader; private $installer; @@ -159,8 +160,9 @@ class_exists(__NAMESPACE__.str_replace('/', '\\', substr($file, \strlen(__DIR__) $composer->setRepositoryManager($manager); } - $this->configurator = new Configurator($composer, $io, $this->options); $this->lock = new Lock(getenv('SYMFONY_LOCKFILE') ?: str_replace('composer.json', 'symfony.lock', Factory::getComposerFile())); + $this->filesManager = new FilesManager($io, $this->lock, $this->options->get('root-dir')); + $this->configurator = new Configurator($composer, $io, $this->filesManager, $this->options); $disable = true; foreach (array_merge($composer->getPackage()->getRequires() ?? [], $composer->getPackage()->getDevRequires() ?? []) as $link) { @@ -877,7 +879,7 @@ private function initOptions(): Options 'root-dir' => $extra['symfony']['root-dir'] ?? '.', ], $extra); - return new Options($options, $this->io); + return new Options($options); } private function getFlexId() diff --git a/src/Options.php b/src/Options.php index 0a5bbc0c4..502bd45e9 100644 --- a/src/Options.php +++ b/src/Options.php @@ -11,22 +11,16 @@ namespace Symfony\Flex; -use Composer\IO\IOInterface; -use Composer\Util\ProcessExecutor; - /** * @author Fabien Potencier */ class Options { private $options; - private $writtenFiles = []; - private $io; - public function __construct(array $options = [], IOInterface $io = null) + public function __construct(array $options = []) { $this->options = $options; - $this->io = $io; } public function get(string $name) @@ -46,41 +40,6 @@ public function expandTargetDir(string $target): string }, $target); } - public function shouldWriteFile(string $file, bool $overwrite): bool - { - if (isset($this->writtenFiles[$file])) { - return false; - } - $this->writtenFiles[$file] = true; - - if (!file_exists($file)) { - return true; - } - - if (!$overwrite) { - return false; - } - - if (!filesize($file)) { - return true; - } - - exec('git status --short --ignored --untracked-files=all -- '.ProcessExecutor::escape($file).' 2>&1', $output, $status); - - if (0 !== $status) { - return (bool) $this->io && $this->io->askConfirmation(sprintf('Cannot determine the state of the "%s" file, overwrite anyway? [y/N] ', $file), false); - } - - if (empty($output[0]) || preg_match('/^[ AMDRCU][ D][ \t]/', $output[0])) { - return true; - } - - $name = basename($file); - $name = \strlen($output[0]) - \strlen($name) === strrpos($output[0], $name) ? substr($output[0], 3) : $name; - - return (bool) $this->io && $this->io->askConfirmation(sprintf('File "%s" has uncommitted changes, overwrite? [y/N] ', $name), false); - } - public function toArray(): array { return $this->options; diff --git a/tests/Configurator/BundlesConfiguratorTest.php b/tests/Configurator/BundlesConfiguratorTest.php index e7f99a39c..50134a089 100644 --- a/tests/Configurator/BundlesConfiguratorTest.php +++ b/tests/Configurator/BundlesConfiguratorTest.php @@ -26,6 +26,7 @@ public function testConfigure() $configurator = new BundlesConfigurator( $this->getMockBuilder('Composer\Composer')->getMock(), $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); @@ -64,6 +65,7 @@ public function testConfigureWhenBundlesAlreayExists() $configurator = new BundlesConfigurator( $this->getMockBuilder('Composer\Composer')->getMock(), $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); diff --git a/tests/Configurator/ContainerConfiguratorTest.php b/tests/Configurator/ContainerConfiguratorTest.php index 57c18d0d8..4fd7a529e 100644 --- a/tests/Configurator/ContainerConfiguratorTest.php +++ b/tests/Configurator/ContainerConfiguratorTest.php @@ -39,6 +39,7 @@ public function testConfigure() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['locale' => 'en'], $lock); @@ -78,6 +79,7 @@ public function testConfigureWithoutParametersKey() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['locale' => 'en'], $lock); @@ -118,6 +120,7 @@ public function testConfigureWithoutDuplicated() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['locale' => 'en'], $lock); @@ -162,6 +165,7 @@ public function testConfigureWithComplexContent() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['locale' => 'en', 'foobar' => 'baz'], $lock); @@ -212,6 +216,7 @@ public function testConfigureWithComplexContent2() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['locale' => 'en', 'foobar' => 'baz', 'array' => ['key1' => 'value', 'key2' => "Escape ' one quote"], 'key1' => 'Keep It'], $lock); @@ -262,6 +267,7 @@ public function testConfigureWithEnvVariable() $configurator = new ContainerConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['env(APP_ENV)' => ''], $lock); diff --git a/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php b/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php index 694b8709e..5d6b37652 100644 --- a/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php +++ b/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php @@ -17,6 +17,7 @@ use Composer\Package\PackageInterface; use PHPUnit\Framework\TestCase; use Symfony\Flex\Configurator\CopyFromPackageConfigurator; +use Symfony\Flex\FilesManager; use Symfony\Flex\Lock; use Symfony\Flex\Options; use Symfony\Flex\Recipe; @@ -106,7 +107,7 @@ protected function tearDown(): void private function createConfigurator(): CopyFromPackageConfigurator { - return new CopyFromPackageConfigurator($this->composer, $this->io, new Options(['root-dir' => FLEX_TEST_DIR])); + return new CopyFromPackageConfigurator($this->composer, $this->io, new FilesManager($this->io, $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(), FLEX_TEST_DIR), new Options(['root-dir' => FLEX_TEST_DIR])); } private function cleanUpTargetFiles() diff --git a/tests/Configurator/CopyFromPackageConfiguratorTest.php b/tests/Configurator/CopyFromPackageConfiguratorTest.php index d5fdccc38..1e4c5c400 100644 --- a/tests/Configurator/CopyFromPackageConfiguratorTest.php +++ b/tests/Configurator/CopyFromPackageConfiguratorTest.php @@ -18,6 +18,7 @@ use LogicException; use PHPUnit\Framework\TestCase; use Symfony\Flex\Configurator\CopyFromPackageConfigurator; +use Symfony\Flex\FilesManager; use Symfony\Flex\Lock; use Symfony\Flex\Options; use Symfony\Flex\Recipe; @@ -166,7 +167,7 @@ protected function tearDown(): void private function createConfigurator(): CopyFromPackageConfigurator { - return new CopyFromPackageConfigurator($this->composer, $this->io, new Options(['root-dir' => FLEX_TEST_DIR], $this->io)); + return new CopyFromPackageConfigurator($this->composer, $this->io, new FilesManager($this->io, $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(), FLEX_TEST_DIR), new Options(['root-dir' => FLEX_TEST_DIR], $this->io)); } private function cleanUpTargetFiles() diff --git a/tests/Configurator/CopyFromRecipeConfiguratorTest.php b/tests/Configurator/CopyFromRecipeConfiguratorTest.php index 6c811ed19..fba3dd993 100644 --- a/tests/Configurator/CopyFromRecipeConfiguratorTest.php +++ b/tests/Configurator/CopyFromRecipeConfiguratorTest.php @@ -15,6 +15,7 @@ use Composer\IO\IOInterface; use PHPUnit\Framework\TestCase; use Symfony\Flex\Configurator\CopyFromRecipeConfigurator; +use Symfony\Flex\FilesManager; use Symfony\Flex\Lock; use Symfony\Flex\Options; use Symfony\Flex\Recipe; @@ -167,7 +168,7 @@ protected function tearDown(): void private function createConfigurator(): CopyFromRecipeConfigurator { - return new CopyFromRecipeConfigurator($this->getMockBuilder(Composer::class)->getMock(), $this->io, new Options(['root-dir' => FLEX_TEST_DIR], $this->io)); + return new CopyFromRecipeConfigurator($this->getMockBuilder(Composer::class)->getMock(), $this->io, new FilesManager($this->io, $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(), FLEX_TEST_DIR), new Options(['root-dir' => FLEX_TEST_DIR], $this->io)); } private function cleanUpTargetFiles() diff --git a/tests/Configurator/DockerComposeConfiguratorTest.php b/tests/Configurator/DockerComposeConfiguratorTest.php index 965d9b719..644b1dec1 100644 --- a/tests/Configurator/DockerComposeConfiguratorTest.php +++ b/tests/Configurator/DockerComposeConfiguratorTest.php @@ -122,6 +122,7 @@ protected function setUp(): void $this->configurator = new DockerComposeConfigurator( $composer, $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); } diff --git a/tests/Configurator/DockerfileConfiguratorTest.php b/tests/Configurator/DockerfileConfiguratorTest.php index c344470b6..a627e7520 100644 --- a/tests/Configurator/DockerfileConfiguratorTest.php +++ b/tests/Configurator/DockerfileConfiguratorTest.php @@ -116,6 +116,7 @@ public function testConfigure() $configurator = new DockerfileConfigurator( $composer, $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) ); $configurator->configure($recipe, ['RUN docker-php-ext-install pdo_mysql'], $lock); diff --git a/tests/Configurator/EnvConfiguratorTest.php b/tests/Configurator/EnvConfiguratorTest.php index bc6fd7943..d80bc30f3 100644 --- a/tests/Configurator/EnvConfiguratorTest.php +++ b/tests/Configurator/EnvConfiguratorTest.php @@ -26,6 +26,7 @@ public function testConfigure() $configurator = new EnvConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['root-dir' => FLEX_TEST_DIR]) ); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); @@ -155,6 +156,7 @@ public function testConfigureGeneratedSecret() $configurator = new EnvConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['root-dir' => FLEX_TEST_DIR]) ); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); @@ -202,6 +204,7 @@ public function testConfigureForce() $configurator = new EnvConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['root-dir' => FLEX_TEST_DIR]) ); diff --git a/tests/Configurator/GitignoreConfiguratorTest.php b/tests/Configurator/GitignoreConfiguratorTest.php index dc0e90477..17cbcd509 100644 --- a/tests/Configurator/GitignoreConfiguratorTest.php +++ b/tests/Configurator/GitignoreConfiguratorTest.php @@ -26,6 +26,7 @@ public function testConfigure() $configurator = new GitignoreConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['public-dir' => 'public', 'root-dir' => FLEX_TEST_DIR]) ); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); @@ -86,6 +87,7 @@ public function testConfigureForce() $configurator = new GitignoreConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['public-dir' => 'public', 'root-dir' => FLEX_TEST_DIR]) ); diff --git a/tests/Configurator/MakefileConfiguratorTest.php b/tests/Configurator/MakefileConfiguratorTest.php index a00c5cb23..e5b9897ad 100644 --- a/tests/Configurator/MakefileConfiguratorTest.php +++ b/tests/Configurator/MakefileConfiguratorTest.php @@ -26,6 +26,7 @@ public function testConfigure() $configurator = new MakefileConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['root-dir' => FLEX_TEST_DIR]) ); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); @@ -88,6 +89,7 @@ public function testConfigureForce() $configurator = new MakefileConfigurator( $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), + $this->getMockBuilder('Symfony\Flex\FilesManager')->disableOriginalConstructor()->getMock(), new Options(['root-dir' => FLEX_TEST_DIR]) );