packages feed

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 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