packages feed

database-migrate 0.0.1 → 0.0.2

raw patch · 6 files changed

+230/−20 lines, 6 filesdep +cmdargsdep +database-migratenew-component:exe:migratePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: cmdargs, database-migrate

API changes (from Hackage documentation)

- Database.Migrate.Core: type MigrationId = Text
+ Database.Migrate.Core: MigrationId :: Text -> MigrationId
+ Database.Migrate.Core: data MigrationId
+ Database.Migrate.Core: extract :: MigrationId -> Text
+ Database.Migrate.Core: instance Eq Migration
+ Database.Migrate.Core: instance Eq MigrationId
+ Database.Migrate.Core: instance Ord Migration
+ Database.Migrate.Core: instance Ord MigrationId
+ Database.Migrate.Core: instance Show Migration
+ Database.Migrate.Core: instance Show MigrationId
+ Database.Migrate.Main: defaultMain :: IO ()
+ Database.Migrate.Main: instance Eq Arguments
+ Database.Migrate.Main: instance Show Arguments
+ Database.Migrate.PostgreSQL: instance FromField MigrationId
+ Database.Migrate.PostgreSQL: instance ToField MigrationId
+ Database.Migrate.PostgreSQL: migratePostgres :: Connection -> FilePath -> (String -> IO ()) -> IO () -> IO ()
+ Paths_database_migrate: getBinDir, getLibexecDir, getDataDir, getLibDir :: IO FilePath
+ Paths_database_migrate: getDataFileName :: FilePath -> IO FilePath
+ Paths_database_migrate: version :: Version

Files

database-migrate.cabal view
@@ -1,5 +1,5 @@ Name:               database-migrate-Version:            0.0.1+Version:            0.0.2 License:            BSD3 License-File:       LICENSE Author:             Mark Hibberd <mark@hibberd.id.au>@@ -9,16 +9,16 @@ Category:           Database Homepage:           https://github.com/markhibberd/database-migrate Bug-reports:           https://github.com/markhibberd/database-migrate/issues-Cabal-Version:      >= 1.6+Cabal-Version:      >= 1.8 Build-Type:         Simple Description:   A database versioning and migration library.   .-  /Note/: that this library is under heavy development, currently+  /Note/: This library is under heavy development, currently   the PostgreSQL implementation is functional, but   expected to change. It is intended that a type safe-  migration api and command line tools be added to this-  library before it be considered stable.+  migration api, command line tools and MySql support be added+  before this library will be considered stable.  Source-Repository   head   Type:             git@@ -29,7 +29,7 @@  Library   Build-Depends:-                    base >= 3 && < 5+                    base                            >= 3          && < 5                     , text                          >= 0.11       && < 0.12                     , directory                     >= 1.0        && < 2.0                     , filepath                      >= 1.0        && < 2.0@@ -39,6 +39,7 @@                     , containers                    >= 0.4        && < 0.5                     , either                        >= 3.0.2      && < 4.0                     , transformers                  >= 0.2        && < 0.4+                    , cmdargs                       >= 0.9.3      && < 1.0.0    GHC-Options:                     -Wall -fno-warn-orphans@@ -48,6 +49,7 @@    Exposed-Modules:                     Database.Migrate+                    Database.Migrate.Main                     Database.Migrate.Core                     Database.Migrate.PostgreSQL @@ -56,3 +58,14 @@                     OverloadedStrings  +Executable          migrate+  Main-Is:          main.hs+  Hs-Source-Dirs:   src+  Ghc-Options:      -Wall -O2+  Build-Depends:+                    base                            >= 3          && < 5+                    , database-migrate+                    , cmdargs                       >= 0.9.3      && < 1.0.0+                    , directory                     >= 1.0        && < 2.0+                    , postgresql-simple             >= 0.1        && < 1.0+                    , text                          >= 0.11       && < 0.12
src/Database/Migrate.hs view
@@ -8,14 +8,17 @@ -- A library to assist with managing database versioning -- and migration. ----- Note: This library is under heavy development, currently---       the PostgreSQL implementation is functional, but---       expected to change. It is intended that a type safe---       migration api and command line tools be added to this---       library before it be considered stable.+--  /Note/: This library is under heavy development, currently+--  the PostgreSQL implementation is functional, but+--  expected to change. It is intended that a type safe+--  migration api, command line tools and MySql support be added+--  before this library will be considered stable.+-- module Database.Migrate (module X) where +import Database.Migrate.Main as X import Database.Migrate.Core as X -- import Database.Migrate.MySQL as X import Database.Migrate.PostgreSQL as X+ 
src/Database/Migrate/Core.hs view
@@ -1,4 +1,4 @@-{-#LANGUAGE OverloadedStrings #-}+{-#LANGUAGE OverloadedStrings, ScopedTypeVariables#-} module Database.Migrate.Core where  import Control.Monad@@ -7,13 +7,22 @@ import Control.Monad.Trans.Either  import qualified Data.Set as S+import Data.List (sort) import Data.Text hiding (foldr, filter, reverse, length)  import System.FilePath import System.Directory import System.IO -type MigrationId = Text+data MigrationId =+  MigrationId { extract :: Text } deriving (Eq, Show)++instance Ord MigrationId where+  compare a b =+   case (reads . unpack . extract $ a, reads . unpack . extract $ b) of+     ([(i :: Int, "")], [(j :: Int, "")]) -> compare i j+     _ -> compare (extract a) (extract b)+ type Ddl = Text  data Migration =@@ -23,8 +32,11 @@     , down :: Text     , upsource :: Maybe FilePath     , downsource :: Maybe FilePath-    }+    } deriving (Eq, Show) +instance Ord Migration where+  compare a b = compare (migration a) (migration b)+ data Context = Context {     succeeded :: [MigrationId]   , failed :: MigrationId@@ -51,18 +63,19 @@   lift (getMigrations c) >>= \installed -> runMigrations c up (pick migrations installed)  find :: FilePath -> EitherT String IO [Migration]-find b = liftIO (getDirectoryContents b) >>= \fs -> liftIO (migrationids b fs) >>=+find b = liftIO (getDirectoryContents b) >>= \fs -> liftM sort (liftIO (migrationids b fs) >>=   mapM (\p ->          do downexists <- liftIO $ doesFileExist (b </> p <.> "down.sql")             unless downexists (left $ "no down.sql for migration [" ++ p ++ "]")             u <- liftIO . readFile $ b </> p <.> "up.sql"             d <- liftIO . readFile $ b </> p <.> "down.sql"-            right (Migration (pack p) (pack u) (pack d) (Just $ b </> p <.> "up.sql") (Just $ b </> p <.> "down.sql")))+            right (Migration (MigrationId . pack $ p) (pack u) (pack d) (Just $ b </> p <.> "up.sql") (Just $ b </> p <.> "down.sql"))))  migrationids :: FilePath -> [FilePath] -> IO [String] migrationids b ps =   filterM (\p -> doesFileExist (b </> p)) ps >>= \files ->-    return (filter (\p -> takeExtensions p == ".up.sql" ) files) >>= \ups -> return (fmap dropExtensions ups)+    ((return . fmap dropExtensions)+      (filter (\p -> takeExtensions p == ".up.sql") files))  readFile' :: FilePath -> IO String readFile' p = withFile p ReadMode hGetContents
+ src/Database/Migrate/Main.hs view
@@ -0,0 +1,78 @@+module Database.Migrate.Main (defaultMain) where++import qualified Paths_database_migrate as Program (version)++import qualified Data.Text as T+import Data.Version (showVersion)++import Database.PostgreSQL.Simple++import System.Console.CmdArgs.Explicit+import System.Directory+import System.Exit++usage = [+    "usage: migrate [-v|--verbose] [-r|--dry-run] [-t|--test-run] [-a|--auto] [-s|--scripts DIR]"+  , "               [-h|--host HOSTNAME] [-p|--port PORTNUMBER] [-u|--user USER]"+  , "               [-P|--password PASSWORD] [-d|--db DATABASE] [-g|--postgres] [-m|--mysql] [VERSION]"+  , "       migrate -h|--help"+  , "       migrate -V|--version"+  ]++data Arguments = Arguments {+    printhelp :: Bool+  , printversion :: Bool+  , dry :: Bool+  , test :: Bool+  , auto :: Bool+  , postgres :: Bool+  , mysql :: Bool+  , version :: Maybe String+  , scripts :: String+  } deriving (Eq, Show)++defaultArguments cwd = Arguments {+    printhelp = False+  , printversion = False+  , dry = False+  , test = False+  , auto = False+  , postgres = False+  , mysql = False+  , version = Nothing+  , scripts = cwd+  }++migratemode cwd =+  mode "migrate" (defaultArguments cwd) "" (flagArg (\v a -> Right $ a { version = Just v }) "VERSION") [+      flagNone [ "h", "help" ]     (\a -> a { printhelp = True })    ""+    , flagNone [ "V", "version" ]  (\a -> a { printversion = True }) ""+    , flagNone [ "r", "dry-run" ]  (\a -> a { dry = True })          ""+    , flagNone [ "g", "postgres" ]  (\a -> a { postgres = True })    ""+    , flagNone [ "m", "mysql" ]  (\a -> a { postgres = True })    ""+    ]++defaultMain =+  getCurrentDirectory >>= \cwd -> processArgs (migratemode cwd) >>= run++run args+  | printhelp args      = mapM_ putStrLn usage+  | printversion args   = putStrLn $ "migrate " ++ showVersion Program.version+  | otherwise           = migrate args++bomb msg =+  putStrLn msg >> exitFailure++migrate args =+  case (postgres args, mysql args) of+    (False, False) -> bomb "Must specify exactly one of -p or -m for database selection, specified none."+    (True, True) -> bomb "Must specify exactly one of -p or -m for database selection, specified two."+    (True, _) -> runpostgres args+    (_, True) -> runmysql args++runmysql _  =+  bomb "Not implemented yet."++runpostgres args =+  undefined+
src/Database/Migrate/PostgreSQL.hs view
@@ -6,29 +6,55 @@ import Control.Monad.IO.Class import Control.Monad.Trans.Either -import Data.Text hiding (filter, reverse)+import Data.Text hiding (filter, reverse, find, null) import Data.String (IsString(..))  import Database.PostgreSQL.Simple+import Database.PostgreSQL.Simple.FromField+import Database.PostgreSQL.Simple.ToField import Database.Migrate.Core +instance FromField MigrationId where+  fromField f m = fmap MigrationId $ fromField f m++instance ToField MigrationId where+  toField (MigrationId m) = toField m+ instance MigrateDatabase IO Connection where   initialize c = void $ execute_ c "CREATE TABLE IF NOT EXISTS MIGRATION_INFO (MIGRATION VARCHAR(50) PRIMARY KEY)"   runMigrations = runall   getMigrations c = fmap (fmap fromOnly) (query_ c "SELECT MIGRATION FROM MIGRATION_INFO") ++migratePostgres :: Connection -> FilePath -> (String -> IO ()) -> IO () -> IO ()+migratePostgres c path logger bomb = do+   initialize c+   ems <- runEitherT $ find path+   case ems of+     Left e -> logger e >> bomb+     Right ms -> runEitherT (latest c ms) >>= \er ->+       case er of+         Left (Context s f m r) ->+           forM_ s (\mid -> logger ("migration:applied: " ++ (unpack . extract $ mid))) >>+           logger ("migration:failed:" ++ (unpack . extract $ f) ++ ":" ++ unpack m) >>+           logger ("migration:rolledback:" ++ show r) >>+           bomb+         Right mids -> if null mids+                         then logger "migration:up-to-date"+                         else forM_ mids $ \mid -> logger $ "migration:applied: " ++ (unpack . extract $ mid)+ record :: Connection -> MigrationId -> IO () record conn mid = void $ execute conn "INSERT INTO MIGRATION_INFO VALUES (?)" (Only mid)  runall :: Connection -> (Migration -> Ddl) -> [Migration] -> MigrationResultT IO [MigrationId] runall c f ms =   liftIO (begin c) >>-    (foldM (\rs m ->+    foldM (\rs m ->              EitherT $                do e <- runEitherT (saferun c f m)                   case e of                     Left emsg -> rollback c >> (return . Left $ Context (reverse rs) (migration m) emsg True)-                    Right r -> return . Right $ r:rs) [] ms) >>= \result -> liftIO (commit c) >> return (reverse result)+                    Right r -> return . Right $ r:rs) [] ms >>= \result -> liftIO (commit c) >> return (reverse result)  saferun :: Connection -> (Migration -> Ddl) -> Migration -> EitherT Text IO MigrationId saferun c f m = EitherT $ handle (\e -> return (Left (pack . show $ (e :: SomeException)))) (fmap Right $ run c f m)
+ src/main.hs view
@@ -0,0 +1,77 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+import qualified Paths_database_migrate as Program (version)++import qualified Data.Text as T+import Data.Version (showVersion)++import Database.PostgreSQL.Simple++import System.Console.CmdArgs.Explicit+import System.Directory+import System.Exit++usage = [+    "usage: migrate [-v|--verbose] [-d|--dry-run] [-t|--test-run] [-a|--auto] [-s|--scripts DIR]"+  , "               [-h|--host HOSTNAME] [-p|--port PORTNUMBER] [-u|--user USER] [-P|--password PASSWORD]"+  , "               "+  , "               [-g|--postgres] [-m|--mysql] [VERSION]"+  , "       migrate -h|--help"+  , "       migrate -V|--version"+  ]++data Arguments = Arguments {+    printhelp :: Bool+  , printversion :: Bool+  , dry :: Bool+  , test :: Bool+  , auto :: Bool+  , postgres :: Maybe String+  , mysql :: Maybe String+  , version :: Maybe String+  , scripts :: String+  } deriving (Eq, Show)++defaultArguments cwd = Arguments {+    printhelp = False+  , printversion = False+  , dry = False+  , test = False+  , auto = False+  , postgres = Nothing+  , mysql = Nothing+  , version = Nothing+  , scripts = cwd+  }++migratemode cwd =+  mode "migrate" (defaultArguments cwd) "" (flagArg (\v a -> Right $ a { version = Just v }) "VERSION") [+      flagNone [ "h", "help" ]     (\a -> a { printhelp = True })    "print help and exit"+    , flagNone [ "V", "version" ]  (\a -> a { printversion = True }) "print version and exit"+    , flagNone [ "d", "dry-run" ]  (\a -> a { dry = True })          "do not perform any updates"+    ]++main =+  getCurrentDirectory >>= \cwd -> processArgs (migratemode cwd) >>= run++run args+  | printhelp args      = mapM_ putStrLn usage+  | printversion args   = putStrLn $ "migrate " ++ showVersion Program.version+  | otherwise           = migrate args++bomb msg =+  putStrLn msg >> exitFailure++migrate args =+  case (postgres args, mysql args) of+    (Nothing, Nothing) -> bomb "Must specify at exactly one of -p or -m for database selection, specified none."+    (Just _, Just _) -> bomb "Must specify at exactly one of -p or -m for database selection, specified two."+    (Just p, _) -> runpostgres args p+    (_, Just m) -> runmysql args m++runmysql _ _ =+  bomb "Not implemented yet."++runpostgres args connstr =+  undefined++