morph 0.1.1.3 → 0.2.0.0
raw patch · 5 files changed
+39/−118 lines, 5 filesdep −aesondep −yamlPVP ok
version bump matches the API change (PVP)
Dependencies removed: aeson, yaml
API changes (from Hackage documentation)
- Morph.Config: instance Data.Aeson.Types.FromJSON.FromJSON Morph.Config.Config
- Morph.Config: readConfigOrDie :: Options -> IO Config
- Morph.Config: withConnection :: Config -> (Connection -> IO a) -> IO a
- Morph.Options: [optsConfigFile] :: Options -> Maybe FilePath
- Morph.Options: [optsJSONConfig] :: Options -> Bool
- Morph.Options: [optsKeysPath] :: Options -> [Text]
+ Morph.Options: [optsConnectionString] :: Options -> Maybe ByteString
+ Morph.Options: withConnection :: Options -> (Connection -> IO a) -> IO a
- Morph.Options: Options :: Maybe FilePath -> [Text] -> FilePath -> Bool -> Bool -> Options
+ Morph.Options: Options :: Maybe ByteString -> FilePath -> Bool -> Options
Files
- LICENSE +1/−1
- Main.hs +2/−4
- morph.cabal +4/−7
- src/Morph/Config.hs +0/−89
- src/Morph/Options.hs +32/−17
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2016, Thomas Feron+Copyright (c) 2016-2021, Thomas Feron All rights reserved.
Main.hs view
@@ -1,10 +1,8 @@-import Morph.Config import Morph.Migrator import Morph.Options main :: IO () main = do- opts <- getOptions- config <- readConfigOrDie opts- withConnection config $ \conn -> do+ opts <- getOptions+ withConnection opts $ \conn -> do migrate (optsTransaction opts) conn (optsMigrationsDirectory opts)
morph.cabal view
@@ -1,5 +1,5 @@ name: morph-version: 0.1.1.3+version: 0.2.0.0 synopsis: A simple database migrator for PostgreSQL description: Morph is a tool to migrate your PostgreSQL databases safely which supports rollbacks.@@ -13,8 +13,8 @@ source-repository head type: git- location: http://github.com/thoferon/morph- tag: 0.1.1.3+ location: http://github.com/tomferon/morph+ tag: 0.2.0.0 library hs-source-dirs: src@@ -23,14 +23,11 @@ default-extensions: OverloadedStrings - exposed-modules: Morph.Config- Morph.Migrator+ exposed-modules: Morph.Migrator Morph.Options build-depends: base >=4.8 && <5 , optparse-applicative- , aeson- , yaml , postgresql-simple , bytestring , text
− src/Morph/Config.hs
@@ -1,89 +0,0 @@-module Morph.Config- ( readConfigOrDie- , withConnection- ) where--import Control.Exception--import Data.Maybe-import qualified Data.Aeson as J-import qualified Data.Aeson.Types as J hiding (Options)-import qualified Data.Bifunctor as B-import qualified Data.Yaml as Y-import qualified Data.ByteString.Lazy.Char8 as BSL-import qualified Data.Text as T--import System.Exit-import System.IO--import Database.PostgreSQL.Simple--import Morph.Options--data Config = Config- { configUsername :: String- , configPassword :: String- , configHostname :: String- , configPort :: Integer- , configName :: String- }--instance J.FromJSON Config where- parseJSON = J.withObject "Config" $ \obj -> Config- <$> obj J..: "username"- <*> obj J..: "password"- <*> obj J..: "hostname"- <*> obj J..: "port"- <*> obj J..: "name"--parseJSONConfig :: [T.Text] -> J.Value -> J.Parser Config-parseJSONConfig [] = J.parseJSON-parseJSONConfig (key : keys) = J.withObject "Parent object" $ \obj -> do- val <- obj J..: key- parseJSONConfig keys val--parseYAMLConfig :: [T.Text] -> Y.Value -> Y.Parser Config-parseYAMLConfig [] val = Y.parseJSON val-parseYAMLConfig (key : keys) (Y.Object obj) = do- val <- obj Y..: key- parseYAMLConfig keys val-parseYAMLConfig _ _ = fail "Object expected"--readConfigOrDie :: Options -> IO Config-readConfigOrDie opts = do- contents <- BSL.readFile $- fromMaybe (if optsJSONConfig opts then "config.json" else "config.yml")- (optsConfigFile opts)-- let eConfig- | optsJSONConfig opts = do- val <- J.eitherDecode contents- J.parseEither (parseJSONConfig (optsKeysPath opts)) val- | otherwise = do- val <- B.first show . Y.decodeEither' . BSL.toStrict $ contents- Y.parseEither (parseYAMLConfig (optsKeysPath opts)) val-- case eConfig of- Right config -> return config- Left err -> do- hPutStrLn stderr $ "Can't read the config file: " ++ err- exitFailure--createConn :: Config -> IO Connection-createConn config = connect ConnectInfo- { connectHost = configHostname config- , connectUser = configUsername config- , connectPassword = configPassword config- , connectDatabase = configName config- , connectPort = fromInteger $ configPort config- }--destroyConn :: Connection -> IO ()-destroyConn = close--withConnection :: Config -> (Connection -> IO a) -> IO a-withConnection config f = do- conn <- createConn config- res <- catch (f conn) $ \e -> destroyConn conn >> throw (e :: SomeException)- destroyConn conn- return res
src/Morph/Options.hs view
@@ -1,40 +1,55 @@ module Morph.Options ( Options(..) , getOptions+ , withConnection ) where +import Control.Exception (bracket)+import System.Environment (getEnv)+ import Data.Monoid-import qualified Data.Text as T+import qualified Data.ByteString.Char8 as BS +import Database.PostgreSQL.Simple+ import Options.Applicative data Options = Options- { optsConfigFile :: Maybe FilePath- , optsKeysPath :: [T.Text]+ { optsConnectionString :: Maybe BS.ByteString , optsMigrationsDirectory :: FilePath- , optsJSONConfig :: Bool , optsTransaction :: Bool } optionsParser :: Parser Options optionsParser = Options <$> option (Just <$> str)- (short 'c' <> long "config" <> metavar "PATH"- <> value Nothing <> help "Path to the config file.")- <*> option ((T.splitOn "." . T.pack) <$> str)- (short 'p' <> long "path" <> metavar "KEY1[.KEY2[...]]"- <> value [] <> help "The keys to traverse in the JSON to find\- \ the database connection info.")- <*> strOption (short 'd' <> long "dir" <> metavar "PATH"- <> showDefault <> value "migrations"- <> help "Path to the directory containing migrations.")- <*> flag False True (short 'j' <> long "json"- <> help "Read config file as JSON.")- <*> flag True False (long "no-transaction"- <> help "Do not run migrations in a SQL transaction. ")+ (short 'c' <> long "connection"+ <> metavar "DATABASE_CONNECTION_STRING"+ <> help "Libpq connection string. Read from environment variable otherwise."+ <> value Nothing)+ <*> strOption+ (short 'd' <> long "dir" <> metavar "PATH"+ <> showDefault <> value "migrations"+ <> help "Path to the directory containing migrations.")+ <*> flag True False+ (long "no-transaction"+ <> help "Do not run migrations in a SQL transaction.") getOptions :: IO Options getOptions = execParser $ info (helper <*> optionsParser) $ fullDesc <> progDesc "Migrator for PostgreSQL databases with support for rollbacks" <> footer "This program is licensed under the BSD-3 license."++createConn :: Options -> IO Connection+createConn opts = do+ connString <- case optsConnectionString opts of+ Nothing -> BS.pack <$> getEnv "DATABASE_CONNECTION_STRING"+ Just cs -> pure cs+ connectPostgreSQL connString++destroyConn :: Connection -> IO ()+destroyConn = close++withConnection :: Options -> (Connection -> IO a) -> IO a+withConnection options f = bracket (createConn options) destroyConn f