<NME> MigrationDirectoryHelper.php
<BEF> <?php

declare(strict_types=1);

namespace Doctrine\Migrations\Tools\Console\Helper;

use Doctrine\Migrations\Configuration\Configuration;
use InvalidArgumentException;
use const DIRECTORY_SEPARATOR;
use function date;
use function file_exists;
use function getcwd;
use function mkdir;
use function rtrim;
use function sprintf;

/**
 * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.
 * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.
 *
 * @internal
 */
class MigrationDirectoryHelper
{
    /**
     * @throws DirectoryDoesNotExist
     */
    public function getMigrationDirectory(Configuration $configuration, string $dir): string
        $this->configuration = $configuration;
    }

    /** @throws InvalidArgumentException */
    public function getMigrationDirectory() : string
    {
        $dir = $this->configuration->getMigrationsDirectory();
        }
        $dir = rtrim($dir, '/');

        if (! file_exists($dir)) {
            throw new InvalidArgumentException(sprintf('Migrations directory "%s" does not exist.', $dir));
        }

        if ($this->configuration->areMigrationsOrganizedByYear()) {
        return $dir;
    }

    private function appendDir(string $dir): string
    {
        return DIRECTORY_SEPARATOR . $dir;
    }

    private function createDirIfNotExists(string $dir): void
    {
        if (file_exists($dir)) {
            return;
        }

        mkdir($dir, 0755, true);
    }
}

<MSG> Throw only specialized package-only exceptions

<DFF> @@ -5,14 +5,13 @@ declare(strict_types=1);
 namespace Doctrine\Migrations\Tools\Console\Helper;
 
 use Doctrine\Migrations\Configuration\Configuration;
-use InvalidArgumentException;
+use Doctrine\Migrations\Tools\Console\Exception\DirectoryDoesNotExist;
 use const DIRECTORY_SEPARATOR;
 use function date;
 use function file_exists;
 use function getcwd;
 use function mkdir;
 use function rtrim;
-use function sprintf;
 
 /**
  * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.
@@ -29,7 +28,9 @@ class MigrationDirectoryHelper
         $this->configuration = $configuration;
     }
 
-    /** @throws InvalidArgumentException */
+    /**
+     * @throws DirectoryDoesNotExist
+     */
     public function getMigrationDirectory() : string
     {
         $dir = $this->configuration->getMigrationsDirectory();
@@ -37,7 +38,7 @@ class MigrationDirectoryHelper
         $dir = rtrim($dir, '/');
 
         if (! file_exists($dir)) {
-            throw new InvalidArgumentException(sprintf('Migrations directory "%s" does not exist.', $dir));
+            throw DirectoryDoesNotExist::new($dir);
         }
 
         if ($this->configuration->areMigrationsOrganizedByYear()) {

{'commit': 'diff --git a/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php b/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php\nindex b69ad270..b4b63928 100644\n--- a/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php\n+++ b/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php\n@@ -5,10 +5,9 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Configuration;\n \n use Doctrine\\Migrations\\Configuration\\Exception\\FileAlreadyLoaded;\n+use Doctrine\\Migrations\\Configuration\\Exception\\FileNotFound;\n use Doctrine\\Migrations\\Configuration\\Exception\\InvalidConfigurationKey;\n use Doctrine\\Migrations\\Configuration\\Exception\\UnknownConfigurationValue;\n-use Doctrine\\Migrations\\Exception\\MigrationException;\n-use InvalidArgumentException;\n use function dirname;\n use function file_exists;\n use function getcwd;\n@@ -58,7 +57,9 @@ abstract class AbstractFileConfiguration extends Configuration\n     /** @var bool */\n     private $loaded = false;\n \n-    /** @throws MigrationException */\n+    /**\n+     * @throws FileNotFound\n+     */\n     public function load(string $file) : void\n     {\n         if ($this->loaded) {\n@@ -74,7 +75,7 @@ abstract class AbstractFileConfiguration extends Configuration\n         $this->file = $file;\n \n         if (! file_exists($file)) {\n-            throw new InvalidArgumentException(\'Given config file does not exist\');\n+            throw FileNotFound::new();\n         }\n \n         $this->doLoad($file);\ndiff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php\nindex c46618f6..261aed86 100644\n--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php\n+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php\n@@ -7,7 +7,7 @@ namespace Doctrine\\Migrations\\Configuration\\Connection\\Loader;\n use Doctrine\\DBAL\\Connection;\n use Doctrine\\DBAL\\DriverManager;\n use Doctrine\\Migrations\\Configuration\\Connection\\ConnectionLoaderInterface;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Configuration\\Connection\\Loader\\Exception\\InvalidConfiguration;\n use function file_exists;\n use function is_array;\n \n@@ -31,7 +31,7 @@ class ArrayConnectionConfigurationLoader implements ConnectionLoaderInterface\n      * Read the input and return a Configuration, returns null if the config\n      * is not supported.\n      *\n-     * @throws InvalidArgumentException\n+     * @throws InvalidConfiguration\n      */\n     public function chosen() : ?Connection\n     {\n@@ -46,9 +46,7 @@ class ArrayConnectionConfigurationLoader implements ConnectionLoaderInterface\n         $params = include $this->filename;\n \n         if (! is_array($params)) {\n-            throw new InvalidArgumentException(\n-                \'The connection file has to return an array with database configuration parameters.\'\n-            );\n+            throw InvalidConfiguration::invalidArrayConfiguration();\n         }\n \n         return DriverManager::getConnection($params);\ndiff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php\nnew file mode 100644\nindex 00000000..3b14f939\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Configuration\\Connection\\Loader\\Exception;\n+\n+use InvalidArgumentException;\n+\n+final class InvalidConfiguration extends InvalidArgumentException implements LoaderException\n+{\n+    public static function invalidArrayConfiguration() : self\n+    {\n+        return new self(\'The connection file has to return an array with database configuration parameters.\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/LoaderException.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/LoaderException.php\nnew file mode 100644\nindex 00000000..d2543481\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/LoaderException.php\n@@ -0,0 +1,11 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Configuration\\Connection\\Loader\\Exception;\n+\n+use Doctrine\\Migrations\\Exception\\MigrationException;\n+\n+interface LoaderException extends MigrationException\n+{\n+}\ndiff --git a/lib/Doctrine/Migrations/Configuration/Exception/FileNotFound.php b/lib/Doctrine/Migrations/Configuration/Exception/FileNotFound.php\nnew file mode 100644\nindex 00000000..1577f105\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Configuration/Exception/FileNotFound.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Configuration\\Exception;\n+\n+use InvalidArgumentException;\n+\n+final class FileNotFound extends InvalidArgumentException implements ConfigurationException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'Given config file does not exist\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Exception/NoTablesFound.php b/lib/Doctrine/Migrations/Exception/NoTablesFound.php\nnew file mode 100644\nindex 00000000..0a46a579\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Exception/NoTablesFound.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Exception;\n+\n+use RuntimeException;\n+\n+final class NoTablesFound extends RuntimeException implements MigrationException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'Your database schema does not contain any tables.\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Exception/RollupFailed.php b/lib/Doctrine/Migrations/Exception/RollupFailed.php\nnew file mode 100644\nindex 00000000..470dbb05\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Exception/RollupFailed.php\n@@ -0,0 +1,20 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Exception;\n+\n+use RuntimeException;\n+\n+final class RollupFailed extends RuntimeException implements MigrationException\n+{\n+    public static function noMigrationsFound() : self\n+    {\n+        return new self(\'No migrations found.\');\n+    }\n+\n+    public static function tooManyMigrations() : self\n+    {\n+        return new self(\'Too many migrations.\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Finder/Exception/FinderException.php b/lib/Doctrine/Migrations/Finder/Exception/FinderException.php\nnew file mode 100644\nindex 00000000..15da8051\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Finder/Exception/FinderException.php\n@@ -0,0 +1,9 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Finder\\Exception;\n+\n+interface FinderException\n+{\n+}\ndiff --git a/lib/Doctrine/Migrations/Finder/Exception/InvalidDirectory.php b/lib/Doctrine/Migrations/Finder/Exception/InvalidDirectory.php\nnew file mode 100644\nindex 00000000..510a8647\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Finder/Exception/InvalidDirectory.php\n@@ -0,0 +1,16 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Finder\\Exception;\n+\n+use InvalidArgumentException;\n+use function sprintf;\n+\n+final class InvalidDirectory extends InvalidArgumentException implements FinderException\n+{\n+    public static function new(string $directory) : self\n+    {\n+        return new self(sprintf(\'Cannot load migrations from "%s" because it is not a valid directory\', $directory));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Finder/Exception/NameIsReserved.php b/lib/Doctrine/Migrations/Finder/Exception/NameIsReserved.php\nnew file mode 100644\nindex 00000000..4d11cfb8\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Finder/Exception/NameIsReserved.php\n@@ -0,0 +1,22 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Finder\\Exception;\n+\n+use InvalidArgumentException;\n+use const PHP_EOL;\n+use function sprintf;\n+\n+final class NameIsReserved extends InvalidArgumentException implements FinderException\n+{\n+    public static function new(string $version) : self\n+    {\n+        return new self(sprintf(\n+            \'Cannot load a migrations with the name "%s" because it is a reserved number by Doctrine Migrations.\'\n+            . PHP_EOL\n+            . "It\'s used to revert all migrations including the first one.",\n+            $version\n+        ));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Finder/Finder.php b/lib/Doctrine/Migrations/Finder/Finder.php\nindex 3fb2b0c9..ef4c03b0 100644\n--- a/lib/Doctrine/Migrations/Finder/Finder.php\n+++ b/lib/Doctrine/Migrations/Finder/Finder.php\n@@ -4,16 +4,15 @@ declare(strict_types=1);\n \n namespace Doctrine\\Migrations\\Finder;\n \n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Finder\\Exception\\InvalidDirectory;\n+use Doctrine\\Migrations\\Finder\\Exception\\NameIsReserved;\n use ReflectionClass;\n-use const PHP_EOL;\n use const SORT_STRING;\n use function get_declared_classes;\n use function in_array;\n use function is_dir;\n use function ksort;\n use function realpath;\n-use function sprintf;\n use function strlen;\n use function strncmp;\n use function substr;\n@@ -28,15 +27,15 @@ abstract class Finder implements MigrationFinder\n         require_once $path;\n     }\n \n+    /**\n+     * @throws InvalidDirectory\n+     */\n     protected function getRealPath(string $directory) : string\n     {\n         $dir = realpath($directory);\n \n         if ($dir === false || ! is_dir($dir)) {\n-            throw new InvalidArgumentException(sprintf(\n-                \'Cannot load migrations from "%s" because it is not a valid directory\',\n-                $directory\n-            ));\n+            throw InvalidDirectory::new($directory);\n         }\n \n         return $dir;\n@@ -46,6 +45,8 @@ abstract class Finder implements MigrationFinder\n      * @param string[] $files\n      *\n      * @return string[]\n+     *\n+     * @throws NameIsReserved\n      */\n     protected function loadMigrations(array $files, ?string $namespace) : array\n     {\n@@ -61,11 +62,7 @@ abstract class Finder implements MigrationFinder\n             $version = substr($class->getShortName(), 7);\n \n             if ($version === \'0\') {\n-                throw new InvalidArgumentException(sprintf(\n-                    \'Cannot load a migrations with the name "%s" because it is a reserved number by doctrine migrations\' . PHP_EOL .\n-                    \'It\\\'s used to revert all migrations including the first one.\',\n-                    $version\n-                ));\n+                throw NameIsReserved::new($version);\n             }\n \n             $versions[$version] = $class->getName();\ndiff --git a/lib/Doctrine/Migrations/Generator/DiffGenerator.php b/lib/Doctrine/Migrations/Generator/DiffGenerator.php\nindex 8174ea5f..bf6aef2d 100644\n--- a/lib/Doctrine/Migrations/Generator/DiffGenerator.php\n+++ b/lib/Doctrine/Migrations/Generator/DiffGenerator.php\n@@ -8,8 +8,8 @@ use Doctrine\\DBAL\\Configuration as DBALConfiguration;\n use Doctrine\\DBAL\\Platforms\\AbstractPlatform;\n use Doctrine\\DBAL\\Schema\\AbstractSchemaManager;\n use Doctrine\\DBAL\\Schema\\Schema;\n+use Doctrine\\Migrations\\Generator\\Exception\\NoChangesDetected;\n use Doctrine\\Migrations\\Provider\\SchemaProviderInterface;\n-use RuntimeException;\n use function preg_match;\n use function strpos;\n use function substr;\n@@ -56,6 +56,9 @@ class DiffGenerator\n         $this->migrationSqlGenerator = $migrationSqlGenerator;\n     }\n \n+    /**\n+     * @throws NoChangesDetected\n+     */\n     public function generate(\n         string $versionNumber,\n         ?string $filterExpression,\n@@ -83,7 +86,7 @@ class DiffGenerator\n         );\n \n         if ($up === \'\' && $down === \'\') {\n-            throw new RuntimeException(\'No changes detected in your mapping information.\');\n+            throw NoChangesDetected::new();\n         }\n \n         return $this->migrationGenerator->generateMigration(\ndiff --git a/lib/Doctrine/Migrations/Generator/Exception/GeneratorException.php b/lib/Doctrine/Migrations/Generator/Exception/GeneratorException.php\nnew file mode 100644\nindex 00000000..5e90fbc8\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Generator/Exception/GeneratorException.php\n@@ -0,0 +1,11 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Generator\\Exception;\n+\n+use Doctrine\\Migrations\\Exception\\MigrationException;\n+\n+interface GeneratorException extends MigrationException\n+{\n+}\ndiff --git a/lib/Doctrine/Migrations/Generator/Exception/InvalidTemplateSpecified.php b/lib/Doctrine/Migrations/Generator/Exception/InvalidTemplateSpecified.php\nnew file mode 100644\nindex 00000000..1ad53a6c\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Generator/Exception/InvalidTemplateSpecified.php\n@@ -0,0 +1,26 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Generator\\Exception;\n+\n+use InvalidArgumentException;\n+use function sprintf;\n+\n+final class InvalidTemplateSpecified extends InvalidArgumentException implements GeneratorException\n+{\n+    public static function notFoundOrNotReadable(string $path) : self\n+    {\n+        return new self(sprintf(\'The specified template "%s" cannot be found or is not readable.\', $path));\n+    }\n+\n+    public static function notReadable(string $path) : self\n+    {\n+        return new self(sprintf(\'The specified template "%s" could not be read.\', $path));\n+    }\n+\n+    public static function empty(string $path) : self\n+    {\n+        return new self(sprintf(\'The specified template "%s" is empty.\', $path));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Generator/Exception/NoChangesDetected.php b/lib/Doctrine/Migrations/Generator/Exception/NoChangesDetected.php\nnew file mode 100644\nindex 00000000..7b550bd4\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Generator/Exception/NoChangesDetected.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Generator\\Exception;\n+\n+use RuntimeException;\n+\n+final class NoChangesDetected extends RuntimeException implements GeneratorException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'No changes detected in your mapping information.\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Generator/Generator.php b/lib/Doctrine/Migrations/Generator/Generator.php\nindex 08e21a6d..86b73086 100644\n--- a/lib/Doctrine/Migrations/Generator/Generator.php\n+++ b/lib/Doctrine/Migrations/Generator/Generator.php\n@@ -5,8 +5,8 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Generator;\n \n use Doctrine\\Migrations\\Configuration\\Configuration;\n+use Doctrine\\Migrations\\Generator\\Exception\\InvalidTemplateSpecified;\n use Doctrine\\Migrations\\Tools\\Console\\Helper\\MigrationDirectoryHelper;\n-use InvalidArgumentException;\n use function explode;\n use function file_get_contents;\n use function file_put_contents;\n@@ -14,7 +14,6 @@ use function implode;\n use function is_file;\n use function is_readable;\n use function preg_replace;\n-use function sprintf;\n use function str_replace;\n use function trim;\n \n@@ -115,6 +114,9 @@ TEMPLATE;\n         return $this->template;\n     }\n \n+    /**\n+     * @throws InvalidTemplateSpecified\n+     */\n     private function loadCustomTemplate() : ?string\n     {\n         $customTemplate = $this->configuration->getCustomTemplate();\n@@ -124,32 +126,17 @@ TEMPLATE;\n         }\n \n         if (! is_file($customTemplate) || ! is_readable($customTemplate)) {\n-            throw new InvalidArgumentException(\n-                sprintf(\n-                    \'The specified template "%s" cannot be found or is not readable.\',\n-                    $customTemplate\n-                )\n-            );\n+            throw InvalidTemplateSpecified::notFoundOrNotReadable($customTemplate);\n         }\n \n         $content = file_get_contents($customTemplate);\n \n         if ($content === false) {\n-            throw new InvalidArgumentException(\n-                sprintf(\n-                    \'The specified template "%s" could not be read.\',\n-                    $customTemplate\n-                )\n-            );\n+            throw InvalidTemplateSpecified::notReadable($customTemplate);\n         }\n \n         if (trim($content) === \'\') {\n-            throw new InvalidArgumentException(\n-                sprintf(\n-                    \'The specified template "%s" is empty.\',\n-                    $customTemplate\n-                )\n-            );\n+            throw InvalidTemplateSpecified::empty($customTemplate);\n         }\n \n         return $content;\ndiff --git a/lib/Doctrine/Migrations/Provider/Exception/NoMappingFound.php b/lib/Doctrine/Migrations/Provider/Exception/NoMappingFound.php\nnew file mode 100644\nindex 00000000..eded25a0\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Provider/Exception/NoMappingFound.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Provider\\Exception;\n+\n+use UnexpectedValueException;\n+\n+final class NoMappingFound extends UnexpectedValueException implements ProviderException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'No mapping information to process\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Provider/Exception/ProviderException.php b/lib/Doctrine/Migrations/Provider/Exception/ProviderException.php\nnew file mode 100644\nindex 00000000..00b53781\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Provider/Exception/ProviderException.php\n@@ -0,0 +1,11 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Provider\\Exception;\n+\n+use Doctrine\\Migrations\\Exception\\MigrationException;\n+\n+interface ProviderException extends MigrationException\n+{\n+}\ndiff --git a/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php b/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php\nindex 3f22dd56..1becea14 100644\n--- a/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php\n+++ b/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php\n@@ -5,9 +5,9 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Provider;\n \n use Doctrine\\DBAL\\Schema\\Schema;\n+use Doctrine\\Migrations\\Provider\\Exception\\NoMappingFound;\n use Doctrine\\ORM\\EntityManagerInterface;\n use Doctrine\\ORM\\Tools\\SchemaTool;\n-use UnexpectedValueException;\n use function count;\n \n /**\n@@ -27,12 +27,15 @@ final class OrmSchemaProvider implements SchemaProviderInterface\n         $this->entityManager = $em;\n     }\n \n+    /**\n+     * @throws NoMappingFound\n+     */\n     public function createSchema() : Schema\n     {\n         $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata();\n \n         if (count($metadata) === 0) {\n-            throw new UnexpectedValueException(\'No mapping information to process\');\n+            throw NoMappingFound::new();\n         }\n \n         $tool = new SchemaTool($this->entityManager);\ndiff --git a/lib/Doctrine/Migrations/Rollup.php b/lib/Doctrine/Migrations/Rollup.php\nindex 495d12da..d2b9c3a1 100644\n--- a/lib/Doctrine/Migrations/Rollup.php\n+++ b/lib/Doctrine/Migrations/Rollup.php\n@@ -6,8 +6,8 @@ namespace Doctrine\\Migrations;\n \n use Doctrine\\DBAL\\Connection;\n use Doctrine\\Migrations\\Configuration\\Configuration;\n+use Doctrine\\Migrations\\Exception\\RollupFailed;\n use Doctrine\\Migrations\\Version\\Version;\n-use RuntimeException;\n use function count;\n use function current;\n use function sprintf;\n@@ -41,16 +41,19 @@ class Rollup\n         $this->migrationRepository = $migrationRepository;\n     }\n \n+    /**\n+     * @throws RollupFailed\n+     */\n     public function rollup() : Version\n     {\n         $versions = $this->migrationRepository->getVersions();\n \n         if (count($versions) === 0) {\n-            throw new RuntimeException(\'No migrations found.\');\n+            throw RollupFailed::noMigrationsFound();\n         }\n \n         if (count($versions) > 1) {\n-            throw new RuntimeException(\'Too many migrations.\');\n+            throw RollupFailed::tooManyMigrations();\n         }\n \n         $sql = sprintf(\ndiff --git a/lib/Doctrine/Migrations/SchemaDumper.php b/lib/Doctrine/Migrations/SchemaDumper.php\nindex 21df4f02..ae92bbd4 100644\n--- a/lib/Doctrine/Migrations/SchemaDumper.php\n+++ b/lib/Doctrine/Migrations/SchemaDumper.php\n@@ -6,9 +6,9 @@ namespace Doctrine\\Migrations;\n \n use Doctrine\\DBAL\\Platforms\\AbstractPlatform;\n use Doctrine\\DBAL\\Schema\\AbstractSchemaManager;\n+use Doctrine\\Migrations\\Exception\\NoTablesFound;\n use Doctrine\\Migrations\\Generator\\Generator;\n use Doctrine\\Migrations\\Generator\\SqlGenerator;\n-use RuntimeException;\n use function count;\n use function implode;\n \n@@ -46,6 +46,9 @@ class SchemaDumper\n         $this->migrationSqlGenerator = $migrationSqlGenerator;\n     }\n \n+    /**\n+     * @throws NoTablesFound\n+     */\n     public function dump(\n         string $versionNumber,\n         bool $formatted = false,\n@@ -85,7 +88,7 @@ class SchemaDumper\n         }\n \n         if (count($up) === 0) {\n-            throw new RuntimeException(\'Your database schema does not contain any tables.\');\n+            throw NoTablesFound::new();\n         }\n \n         $up   = implode("\\n", $up);\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php\nindex ffe460aa..82265719 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php\n@@ -7,7 +7,7 @@ namespace Doctrine\\Migrations\\Tools\\Console\\Command;\n use Doctrine\\Migrations\\Generator\\DiffGenerator;\n use Doctrine\\Migrations\\Provider\\OrmSchemaProvider;\n use Doctrine\\Migrations\\Provider\\SchemaProviderInterface;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\InvalidOptionUsage;\n use Symfony\\Component\\Console\\Input\\InputInterface;\n use Symfony\\Component\\Console\\Input\\InputOption;\n use Symfony\\Component\\Console\\Output\\OutputInterface;\n@@ -76,6 +76,9 @@ EOT\n         ;\n     }\n \n+    /**\n+     * @throws InvalidOptionUsage\n+     */\n     public function execute(\n         InputInterface $input,\n         OutputInterface $output\n@@ -86,7 +89,7 @@ EOT\n \n         if ($formatted) {\n             if (! class_exists(\'SqlFormatter\')) {\n-                throw new InvalidArgumentException(\n+                throw InvalidOptionUsage::new(\n                     \'The "--formatted" option can only be used if the sql formatter is installed. Please run "composer require jdorn/sql-formatter".\'\n                 );\n             }\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php\nindex c287ce62..afc45c09 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php\n@@ -4,7 +4,7 @@ declare(strict_types=1);\n \n namespace Doctrine\\Migrations\\Tools\\Console\\Command;\n \n-use RuntimeException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\SchemaDumpRequiresNoMigrations;\n use Symfony\\Component\\Console\\Input\\InputInterface;\n use Symfony\\Component\\Console\\Input\\InputOption;\n use Symfony\\Component\\Console\\Output\\OutputInterface;\n@@ -57,6 +57,9 @@ EOT\n         ;\n     }\n \n+    /**\n+     * @throws SchemaDumpRequiresNoMigrations\n+     */\n     public function execute(\n         InputInterface $input,\n         OutputInterface $output\n@@ -68,7 +71,7 @@ EOT\n         $versions     = $this->migrationRepository->getVersions();\n \n         if (count($versions) > 0) {\n-            throw new RuntimeException(\'Delete your old historical migrations before dumping your schema.\');\n+            throw SchemaDumpRequiresNoMigrations::new();\n         }\n \n         $versionNumber = $this->configuration->generateVersionNumber();\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php\nindex 81064249..8aa88b98 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php\n@@ -5,7 +5,9 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Tools\\Console\\Command;\n \n use Doctrine\\Migrations\\Exception\\UnknownMigrationVersion;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\InvalidOptionUsage;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\VersionAlreadyExists;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\VersionDoesNotExist;\n use Symfony\\Component\\Console\\Input\\InputArgument;\n use Symfony\\Component\\Console\\Input\\InputInterface;\n use Symfony\\Component\\Console\\Input\\InputOption;\n@@ -90,12 +92,13 @@ EOT\n         parent::configure();\n     }\n \n+    /**\n+     * @throws InvalidOptionUsage\n+     */\n     public function execute(InputInterface $input, OutputInterface $output) : ?int\n     {\n         if ($input->getOption(\'add\') === false && $input->getOption(\'delete\') === false) {\n-            throw new InvalidArgumentException(\n-                \'You must specify whether you want to --add or --delete the specified version.\'\n-            );\n+            throw InvalidOptionUsage::new(\'You must specify whether you want to --add or --delete the specified version.\');\n         }\n \n         $this->markMigrated = (bool) $input->getOption(\'add\');\n@@ -118,8 +121,7 @@ EOT\n     }\n \n     /**\n-     * @throws InvalidArgumentException\n-     * @throws UnknownMigrationVersion\n+     * @throws InvalidOptionUsage\n      */\n     private function markVersions(InputInterface $input, OutputInterface $output) : void\n     {\n@@ -129,13 +131,13 @@ EOT\n         $rangeToOption   = $input->getOption(\'range-to\');\n \n         if ($allOption === true && ($rangeFromOption !== null || $rangeToOption !== null)) {\n-            throw new InvalidArgumentException(\n+            throw InvalidOptionUsage::new(\n                 \'Options --all and --range-to/--range-from both used. You should use only one of them.\'\n             );\n         }\n \n         if ($rangeFromOption !== null ^ $rangeToOption !== null) {\n-            throw new InvalidArgumentException(\n+            throw InvalidOptionUsage::new(\n                 \'Options --range-to and --range-from should be used together.\'\n             );\n         }\n@@ -162,7 +164,8 @@ EOT\n     }\n \n     /**\n-     * @throws InvalidArgumentException\n+     * @throws VersionAlreadyExists\n+     * @throws VersionDoesNotExist\n      * @throws UnknownMigrationVersion\n      */\n     private function mark(OutputInterface $output, string $version, bool $all = false) : void\n@@ -177,9 +180,7 @@ EOT\n \n         if ($this->markMigrated && $this->migrationRepository->hasVersionMigrated($version)) {\n             if (! $all) {\n-                throw new InvalidArgumentException(\n-                    sprintf(\'The version "%s" already exists in the version table.\', $version)\n-                );\n+                throw VersionAlreadyExists::new($version);\n             }\n \n             $marked = true;\n@@ -187,9 +188,7 @@ EOT\n \n         if (! $this->markMigrated && ! $this->migrationRepository->hasVersionMigrated($version)) {\n             if (! $all) {\n-                throw new InvalidArgumentException(\n-                    sprintf(\'The version "%s" does not exist in the version table.\', $version)\n-                );\n+                throw VersionDoesNotExist::new($version);\n             }\n \n             $marked = true;\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php b/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php\nindex d4769a8d..92fbadf6 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php\n@@ -11,7 +11,7 @@ use Doctrine\\Migrations\\Configuration\\Connection\\Loader\\ArrayConnectionConfigura\n use Doctrine\\Migrations\\Configuration\\Connection\\Loader\\ConnectionConfigurationChainLoader;\n use Doctrine\\Migrations\\Configuration\\Connection\\Loader\\ConnectionConfigurationLoader;\n use Doctrine\\Migrations\\Configuration\\Connection\\Loader\\ConnectionHelperLoader;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\ConnectionNotSpecified;\n use Symfony\\Component\\Console\\Helper\\HelperSet;\n use Symfony\\Component\\Console\\Input\\InputInterface;\n \n@@ -39,9 +39,7 @@ class ConnectionLoader\n             return $connection;\n         }\n \n-        throw new InvalidArgumentException(\n-            \'You have to specify a --db-configuration file or pass a Database Connection as a dependency to the Migrations.\'\n-        );\n+        throw ConnectionNotSpecified::new();\n     }\n \n     protected function createConnectionConfigurationChainLoader(\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/ConnectionNotSpecified.php b/lib/Doctrine/Migrations/Tools/Console/Exception/ConnectionNotSpecified.php\nnew file mode 100644\nindex 00000000..098c841e\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/ConnectionNotSpecified.php\n@@ -0,0 +1,17 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use InvalidArgumentException;\n+\n+final class ConnectionNotSpecified extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\n+            \'You have to specify a --db-configuration file or pass a Database Connection as a dependency to the Migrations.\'\n+        );\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/ConsoleException.php b/lib/Doctrine/Migrations/Tools/Console/Exception/ConsoleException.php\nnew file mode 100644\nindex 00000000..9ee7a931\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/ConsoleException.php\n@@ -0,0 +1,11 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use Doctrine\\Migrations\\Exception\\MigrationException;\n+\n+interface ConsoleException extends MigrationException\n+{\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/DirectoryDoesNotExist.php b/lib/Doctrine/Migrations/Tools/Console/Exception/DirectoryDoesNotExist.php\nnew file mode 100644\nindex 00000000..5a1e9838\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/DirectoryDoesNotExist.php\n@@ -0,0 +1,16 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use InvalidArgumentException;\n+use function sprintf;\n+\n+final class DirectoryDoesNotExist extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new(string $directory) : self\n+    {\n+        return new self(sprintf(\'Migrations directory "%s" does not exist.\', $directory));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/FileTypeNotSupported.php b/lib/Doctrine/Migrations/Tools/Console/Exception/FileTypeNotSupported.php\nnew file mode 100644\nindex 00000000..cc74a039\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/FileTypeNotSupported.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use InvalidArgumentException;\n+\n+final class FileTypeNotSupported extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'Given config file type is not supported\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/InvalidOptionUsage.php b/lib/Doctrine/Migrations/Tools/Console/Exception/InvalidOptionUsage.php\nnew file mode 100644\nindex 00000000..f30bccbb\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/InvalidOptionUsage.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use InvalidArgumentException;\n+\n+final class InvalidOptionUsage extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new(string $explanation) : self\n+    {\n+        return new self($explanation);\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/SchemaDumpRequiresNoMigrations.php b/lib/Doctrine/Migrations/Tools/Console/Exception/SchemaDumpRequiresNoMigrations.php\nnew file mode 100644\nindex 00000000..28bea2a6\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/SchemaDumpRequiresNoMigrations.php\n@@ -0,0 +1,15 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use RuntimeException;\n+\n+final class SchemaDumpRequiresNoMigrations extends RuntimeException implements ConsoleException\n+{\n+    public static function new() : self\n+    {\n+        return new self(\'Delete your old historical migrations before dumping your schema.\');\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/VersionAlreadyExists.php b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionAlreadyExists.php\nnew file mode 100644\nindex 00000000..b1aa392c\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionAlreadyExists.php\n@@ -0,0 +1,17 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use Doctrine\\Migrations\\Version\\Version;\n+use InvalidArgumentException;\n+use function sprintf;\n+\n+final class VersionAlreadyExists extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new(Version $version) : self\n+    {\n+        return new self(sprintf(\'The version "%s" already exists in the version table.\', $version));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php\nnew file mode 100644\nindex 00000000..0a0782dc\n--- /dev/null\n+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php\n@@ -0,0 +1,17 @@\n+<?php\n+\n+declare(strict_types=1);\n+\n+namespace Doctrine\\Migrations\\Tools\\Console\\Exception;\n+\n+use Doctrine\\Migrations\\Version\\Version;\n+use InvalidArgumentException;\n+use function sprintf;\n+\n+final class VersionDoesNotExist extends InvalidArgumentException implements ConsoleException\n+{\n+    public static function new(Version $version) : self\n+    {\n+        return new self(sprintf(\'The version "%s" does not exist in the version table.\', $version));\n+    }\n+}\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php\nindex de030c4d..771a3b65 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php\n@@ -10,7 +10,7 @@ use Doctrine\\Migrations\\Configuration\\Configuration;\n use Doctrine\\Migrations\\Configuration\\JsonConfiguration;\n use Doctrine\\Migrations\\Configuration\\XmlConfiguration;\n use Doctrine\\Migrations\\Configuration\\YamlConfiguration;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\FileTypeNotSupported;\n use Symfony\\Component\\Console\\Helper\\Helper;\n use Symfony\\Component\\Console\\Input\\InputInterface;\n use function file_exists;\n@@ -81,7 +81,9 @@ class ConfigurationHelper extends Helper implements ConfigurationHelperInterface\n         return file_exists($config);\n     }\n \n-    /** @throws InvalidArgumentException */\n+    /**\n+     * @throws FileTypeNotSupported\n+     */\n     private function loadConfig(string $config) : Configuration\n     {\n         $map = [\n@@ -96,7 +98,7 @@ class ConfigurationHelper extends Helper implements ConfigurationHelperInterface\n \n         // check we can support this file type\n         if (! isset($map[$info[\'extension\']])) {\n-            throw new InvalidArgumentException(\'Given config file type is not supported\');\n+            throw FileTypeNotSupported::new();\n         }\n \n         $class         = $map[$info[\'extension\']];\ndiff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php\nindex ba18df94..3ca36957 100644\n--- a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php\n+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php\n@@ -5,14 +5,13 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Tools\\Console\\Helper;\n \n use Doctrine\\Migrations\\Configuration\\Configuration;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\DirectoryDoesNotExist;\n use const DIRECTORY_SEPARATOR;\n use function date;\n use function file_exists;\n use function getcwd;\n use function mkdir;\n use function rtrim;\n-use function sprintf;\n \n /**\n  * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.\n@@ -29,7 +28,9 @@ class MigrationDirectoryHelper\n         $this->configuration = $configuration;\n     }\n \n-    /** @throws InvalidArgumentException */\n+    /**\n+     * @throws DirectoryDoesNotExist\n+     */\n     public function getMigrationDirectory() : string\n     {\n         $dir = $this->configuration->getMigrationsDirectory();\n@@ -37,7 +38,7 @@ class MigrationDirectoryHelper\n         $dir = rtrim($dir, \'/\');\n \n         if (! file_exists($dir)) {\n-            throw new InvalidArgumentException(sprintf(\'Migrations directory "%s" does not exist.\', $dir));\n+            throw DirectoryDoesNotExist::new($dir);\n         }\n \n         if ($this->configuration->areMigrationsOrganizedByYear()) {\n', 'commit_subject': 'Throw only specialized package-only exceptions', 'repo_name': 'doctrine/migrations', 'committer': {'name': 'Michael Moravec', 'email': 'b1c1d8736f20db3fb6c1c66bb1455ed43909f0d8@majkl.me', 'time_sec': '1528226254', 'tz_offset': '120', 'date': {'seconds': '1528226254'}}, 'commit_tree': 'e15e1c22dae6385bf026cc79445db12da9d3c143', 'commit_message': 'Throw only specialized package-only exceptions\n', 'language_name': 'PHP', 'license': 'mit', 'hunks': '@@ -5,14 +5,13 @@ declare(strict_types=1);\n namespace Doctrine\\Migrations\\Tools\\Console\\Helper;\n \n use Doctrine\\Migrations\\Configuration\\Configuration;\n-use InvalidArgumentException;\n+use Doctrine\\Migrations\\Tools\\Console\\Exception\\DirectoryDoesNotExist;\n use const DIRECTORY_SEPARATOR;\n use function date;\n use function file_exists;\n use function getcwd;\n use function mkdir;\n use function rtrim;\n-use function sprintf;\n \n /**\n  * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.\n@@ -29,7 +28,9 @@ class MigrationDirectoryHelper\n         $this->configuration = $configuration;\n     }\n \n-    /** @throws InvalidArgumentException */\n+    /**\n+     * @throws DirectoryDoesNotExist\n+     */\n     public function getMigrationDirectory() : string\n     {\n         $dir = $this->configuration->getMigrationsDirectory();\n@@ -37,7 +38,7 @@ class MigrationDirectoryHelper\n         $dir = rtrim($dir, \'/\');\n \n         if (! file_exists($dir)) {\n-            throw new InvalidArgumentException(sprintf(\'Migrations directory "%s" does not exist.\', $dir));\n+            throw DirectoryDoesNotExist::new($dir);\n         }\n \n         if ($this->configuration->areMigrationsOrganizedByYear()) {\n', 'addition_count': 5, 'deletion_count': 4, 'src_file': 'a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php', 'tgt_file': 'b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php', 'file_extension': '.php', 'before_file': '<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Migrations\\Tools\\Console\\Helper;\n\nuse Doctrine\\Migrations\\Configuration\\Configuration;\nuse InvalidArgumentException;\nuse const DIRECTORY_SEPARATOR;\nuse function date;\nuse function file_exists;\nuse function getcwd;\nuse function mkdir;\nuse function rtrim;\nuse function sprintf;\n\n/**\n * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.\n * The MigrationDirectoryHelper class is responsible for returning the directory that migrations are stored in.\n *\n * @internal\n */\nclass MigrationDirectoryHelper\n{\n    /**\n     * @throws DirectoryDoesNotExist\n     */\n    public function getMigrationDirectory(Configuration $configuration, string $dir): string\n        $this->configuration = $configuration;\n    }\n\n    /** @throws InvalidArgumentException */\n    public function getMigrationDirectory() : string\n    {\n        $dir = $this->configuration->getMigrationsDirectory();\n        }\n        $dir = rtrim($dir, \'/\');\n\n        if (! file_exists($dir)) {\n            throw new InvalidArgumentException(sprintf(\'Migrations directory "%s" does not exist.\', $dir));\n        }\n\n        if ($this->configuration->areMigrationsOrganizedByYear()) {\n        return $dir;\n    }\n\n    private function appendDir(string $dir): string\n    {\n        return DIRECTORY_SEPARATOR . $dir;\n    }\n\n    private function createDirIfNotExists(string $dir): void\n    {\n        if (file_exists($dir)) {\n            return;\n        }\n\n        mkdir($dir, 0755, true);\n    }\n}\n', 'message': 'Throw only specialized package-only exceptions\n', 'author_name': 'Michael Moravec', 'lang': 'php'}