diff --git a/.appveyor/composer.bat b/.appveyor/composer.bat new file mode 100644 index 000000000..5e3ac8511 --- /dev/null +++ b/.appveyor/composer.bat @@ -0,0 +1 @@ +@php "%~dp0composer.phar" %* \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..18ea90640 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,50 @@ +build: false +clone_folder: c:\projects\maker-bundle + +cache: + - composer.phar + - .phpunit -> phpunit + +init: + - SET PATH=c:\php;%PATH% + +install: + - mkdir c:\php && cd c:\php + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip + - 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul + - cd ext + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.8-7.1-ts-vc14-x86.zip + - 7z x php_apcu-5.1.8-7.1-ts-vc14-x86.zip -y >nul + - cd .. + - copy /Y php.ini-development php.ini-min + - echo memory_limit=-1 >> php.ini-min + - echo serialize_precision=14 >> php.ini-min + - echo max_execution_time=1200 >> php.ini-min + - echo date.timezone="America/Los_Angeles" >> php.ini-min + - echo extension_dir=ext >> php.ini-min + - copy /Y php.ini-min php.ini-max + - echo zend_extension=php_opcache.dll >> php.ini-max + - echo opcache.enable_cli=1 >> php.ini-max + - echo extension=php_openssl.dll >> php.ini-max + - echo extension=php_apcu.dll >> php.ini-max + - echo apc.enable_cli=1 >> php.ini-max + - echo extension=php_intl.dll >> php.ini-max + - echo extension=php_mbstring.dll >> php.ini-max + - echo extension=php_fileinfo.dll >> php.ini-max + - echo extension=php_pdo_sqlite.dll >> php.ini-max + - echo extension=php_curl.dll >> php.ini-max + - copy /Y php.ini-max php.ini + + - cd c:\php + - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.6.3/composer.phar) + - php composer.phar self-update + # copy instead of using echo because appveyor does not allow "%s" characters + - copy /Y c:\projects\maker-bundle\.appveyor\composer.bat composer.bat + + - cd c:\projects\maker-bundle + - php -dmemory_limit=-1 c:\php\composer.phar install --no-progress --no-suggest --ansi + - composer dump-autoload + - ./vendor/bin/simple-phpunit install + +test_script: + - ./vendor/bin/simple-phpunit diff --git a/src/FileManager.php b/src/FileManager.php index d53244d40..e924cc32a 100644 --- a/src/FileManager.php +++ b/src/FileManager.php @@ -33,7 +33,7 @@ class FileManager public function __construct(Filesystem $fs, string $rootDirectory) { $this->fs = $fs; - $this->rootDirectory = rtrim($this->realpath($rootDirectory).'/'); + $this->rootDirectory = rtrim($this->realpath($this->normalizeSlashes($rootDirectory)), '/'); } public function setIO(SymfonyStyle $io) @@ -61,8 +61,19 @@ public function fileExists($path): bool return file_exists($this->absolutizePath($path)); } + /** + * Attempts to make the path relative to the root directory. + * + * @param string $absolutePath + * + * @return string + * + * @throws \Exception + */ public function relativizePath($absolutePath): string { + $absolutePath = $this->normalizeSlashes($absolutePath); + // see if the path is even in the root if (false === strpos($absolutePath, $this->rootDirectory)) { return $absolutePath; @@ -78,6 +89,15 @@ public function relativizePath($absolutePath): string return is_dir($absolutePath) ? rtrim($relativePath, '/').'/' : $relativePath; } + /** + * Returns the relative path to where a new class should live. + * + * @param string $className + * + * @return null|string + * + * @throws \Exception + */ public function getPathForFutureClass(string $className) { // lookup is obviously modeled off of Composer's autoload logic @@ -138,12 +158,17 @@ private function getClassLoader(): ClassLoader return self::$classLoader; } - private function absolutizePath($path): string + public function absolutizePath($path): string { if (0 === strpos($path, '/')) { return $path; } + // support windows drive paths: C:\ + if (1 === strpos($path, ':\\')) { + return $path; + } + return sprintf('%s/%s', $this->rootDirectory, $path); } @@ -159,6 +184,7 @@ private function realPath($absolutePath): string $finalParts = []; $currentIndex = -1; + $absolutePath = $this->normalizeSlashes($absolutePath); foreach (explode('/', $absolutePath) as $pathPart) { if ('..' === $pathPart) { // we need to remove the previous entry @@ -184,4 +210,9 @@ private function realPath($absolutePath): string return $finalPath; } + + private function normalizeSlashes(string $path) + { + return str_replace('\\', '/', $path); + } } diff --git a/src/Test/MakerTestCase.php b/src/Test/MakerTestCase.php index 338d057e4..4dd13b016 100644 --- a/src/Test/MakerTestCase.php +++ b/src/Test/MakerTestCase.php @@ -34,8 +34,8 @@ class MakerTestCase extends TestCase public static function setupPaths() { self::$currentRootDir = __DIR__.'/../../tests/tmp/current_project'; - self::$flexProjectPath = __DIR__.'/../../tests/tmp/template_project'; self::$fixturesCachePath = __DIR__.'/../../tests/tmp/cache'; + self::$flexProjectPath = self::$fixturesCachePath.'/flex_project'; } protected function executeMakerCommand(MakerTestDetails $testDetails) @@ -133,7 +133,7 @@ protected function executeMakerCommand(MakerTestDetails $testDetails) // execute the tests that were moved into the project! $process = $this->createProcess( // using OUR simple-phpunit for speed (to avoid downloading more deps) - '../../../vendor/bin/simple-phpunit', + __DIR__.'/../../vendor/bin/simple-phpunit', self::$currentRootDir ); $process->run(); @@ -155,7 +155,11 @@ protected function assertContainsCount(string $needle, string $haystack, int $co private function buildFlexProject() { - $process = $this->createProcess('composer create-project symfony/skeleton template_project', dirname(self::$flexProjectPath)); + $targetFlexDir = dirname(self::$flexProjectPath); + if (!file_exists($targetFlexDir)) { + self::$fs->mkdir($targetFlexDir); + } + $process = $this->createProcess('composer create-project symfony/skeleton flex_project', $targetFlexDir); $this->runProcess($process); // processes any changes needed to the Flex project @@ -168,7 +172,7 @@ private function buildFlexProject() [ 'filename' => 'composer.json', 'find' => '"App\\\Tests\\\": "tests/"', - 'replace' => sprintf('"App\\\Tests\\\": "tests/",'."\n".' "Symfony\\\Bundle\\\MakerBundle\\\": "%s/src/"', __DIR__.'../../../'), + 'replace' => sprintf('"App\\\Tests\\\": "tests/",'."\n".' "Symfony\\\Bundle\\\MakerBundle\\\": "%s/src/"', str_replace('\\', '\\\\', __DIR__.'../../..')), ], ]; $this->processReplacements($replacements, self::$flexProjectPath); diff --git a/tests/DependencyBuilderTest.php b/tests/DependencyBuilderTest.php index 3b02882b0..572a5cf04 100644 --- a/tests/DependencyBuilderTest.php +++ b/tests/DependencyBuilderTest.php @@ -55,6 +55,8 @@ public function testGetMissingPackagesMessage(array $missingPackages, array $mis $depBuilder->addClassDependency('Foo', $missingPackage, true, true); } + // normalize line breaks on Windows for comparison + $expectedMessage = str_replace("\r\n", "\n", $expectedMessage); $this->assertSame($expectedMessage, $depBuilder->getMissingPackagesMessage('make:something')); } diff --git a/tests/FileManagerTest.php b/tests/FileManagerTest.php index 07528370c..f2d60a0db 100644 --- a/tests/FileManagerTest.php +++ b/tests/FileManagerTest.php @@ -45,6 +45,12 @@ public function getRelativizePathTests() '/home/project/foo/bar/../../src/Baz.php', 'src/Baz.php', ]; + + yield 'windows_path' => [ + 'D:\path\to\project', + 'D:\path\to\project\vendor\composer/../../src/Controller/TestController.php', + 'src/Controller/TestController.php', + ]; } public function testGetPathForFutureClass() @@ -96,4 +102,34 @@ public function getPathForFutureClassTests() 'Psr0\Package\Admin\Bar' => 'lib/other/Psr0/Package/Admin/Bar.php' ]; } + + /** + * @dataProvider getAbsolutePathTests + */ + public function testAbsolutizePath(string $rootDir, string $path, string $expectedPath) + { + $fileManager = new FileManager(new Filesystem(), $rootDir); + $this->assertSame($expectedPath, $fileManager->absolutizePath($path)); + } + + public function getAbsolutePathTests() + { + yield 'normal_path_change' => [ + '/home/project/', + 'foo/bar', + '/home/project/foo/bar', + ]; + + yield 'already_absolute_path' => [ + '/home/project/', + '/foo/bar', + '/foo/bar', + ]; + + yield 'windows_already_absolute_path' => [ + 'D:\path\to\project', + 'D:\foo\bar', + 'D:\foo\bar', + ]; + } } diff --git a/tests/Maker/FunctionalTest.php b/tests/Maker/FunctionalTest.php index 5aba62ebf..6e77b0c84 100644 --- a/tests/Maker/FunctionalTest.php +++ b/tests/Maker/FunctionalTest.php @@ -154,7 +154,7 @@ public function getCommandTests() 'mysql://db_user:db_password@127.0.0.1:3306/db_name', 'sqlite:///%kernel.project_dir%/var/app.db' ) - ->addPostMakeCommand('./bin/console doctrine:schema:create --env=test') + ->addPostMakeCommand('php bin/console doctrine:schema:create --env=test') ]; yield 'fixtures' => [MakerTestDetails::createTest( @@ -293,7 +293,7 @@ public function getCommandTests() ) ->addExtraDependencies('doctrine/orm') // sync the database, so no changes are needed - ->addPreMakeCommand('./bin/console doctrine:schema:create --env=test') + ->addPreMakeCommand('php bin/console doctrine:schema:create --env=test') ->assert(function(string $output, string $directory) { $this->assertNotContains('Success', $output);