@@ -25,15 +25,12 @@ module Cardano.Db.Migration (
25
25
) where
26
26
27
27
import Cardano.Prelude (textShow )
28
- import Control.Exception (Exception , SomeException , handle )
28
+ import Control.Exception (Exception )
29
29
import Control.Monad.Extra
30
30
import Control.Monad.IO.Class (MonadIO , liftIO )
31
31
import Control.Monad.Logger (NoLoggingT )
32
- import Control.Monad.Trans.Resource (runResourceT )
33
32
import qualified Data.ByteString.Char8 as BS
34
33
import Data.Char (isDigit )
35
- import Data.Conduit.Binary (sinkHandle )
36
- import Data.Conduit.Process (sourceCmdWithConsumer )
37
34
import Data.Either (partitionEithers )
38
35
import Data.List ((\\) )
39
36
import qualified Data.List as List
@@ -53,7 +50,6 @@ import System.FilePath (takeExtension, takeFileName, (</>))
53
50
import System.IO (
54
51
Handle ,
55
52
IOMode (AppendMode ),
56
- hFlush ,
57
53
hPrint ,
58
54
hPutStrLn ,
59
55
stdout ,
@@ -63,13 +59,14 @@ import Text.Read (readMaybe)
63
59
64
60
import Cardano.BM.Trace (Trace )
65
61
import Cardano.Crypto.Hash (Blake2b_256 , ByteString , Hash , hashToStringAsHex , hashWith )
66
- import Cardano.Db.Migration.Haskell
67
62
import Cardano.Db.Migration.Version
68
63
import Cardano.Db.PGConfig
69
64
import Cardano.Db.Run
70
65
import Cardano.Db.Schema.Variants (TxOutVariantType (.. ))
71
66
import qualified Cardano.Db.Statement.Function.Core as DB
72
67
import qualified Cardano.Db.Types as DB
68
+ import System.Process (readProcessWithExitCode )
69
+ import Cardano.Db.Progress (withProgress , updateProgress )
73
70
74
71
newtype MigrationDir
75
72
= MigrationDir FilePath
@@ -104,19 +101,32 @@ runMigrations pgconfig quiet migrationDir mLogfiledir mToRun txOutVariantType =
104
101
(_, [] ) ->
105
102
error $ " Empty schema dir " ++ show migrationDir
106
103
(Nothing , scripts) -> do
107
- -- Remove the pattern match that separates first script
108
104
putStrLn " Running:"
109
- (scripts', ranAll) <- filterMigrations scripts -- Filter ALL scripts including first
110
- forM_ scripts' $ applyMigration' Nothing stdout
105
+ (scripts', ranAll) <- filterMigrations scripts
106
+
107
+ -- Replace just this forM_ with progress bar
108
+ withProgress (length scripts') " Database migrations" $ \ progressRef -> do
109
+ forM_ (zip [1 :: Integer .. ] scripts' ) $ \ (i, script) -> do
110
+ updateProgress progressRef (fromIntegral i) $
111
+ " Migration " <> Text. pack (show i) <> " /" <> Text. pack (show (length scripts'))
112
+ applyMigration' Nothing stdout script
113
+
111
114
putStrLn " Success!"
112
115
pure ranAll
116
+
113
117
(Just logfiledir, scripts) -> do
114
- -- Remove the pattern match here too
115
118
logFilename <- genLogFilename logfiledir
116
119
withFile logFilename AppendMode $ \ logHandle -> do
117
120
unless quiet $ putStrLn " Running:"
118
- (scripts', ranAll) <- filterMigrations scripts -- Filter ALL scripts including first
119
- forM_ scripts' $ applyMigration' (Just logFilename) logHandle
121
+ (scripts', ranAll) <- filterMigrations scripts
122
+
123
+ -- Replace just this forM_ with progress bar
124
+ withProgress (length scripts') " Database migrations" $ \ progressRef -> do
125
+ forM_ (zip [1 :: Integer .. ] scripts' ) $ \ (i, script) -> do
126
+ updateProgress progressRef (fromIntegral i) $
127
+ " Migration " <> Text. pack (show i) <> " /" <> Text. pack (show (length scripts'))
128
+ applyMigration' (Just logFilename) logHandle script
129
+
120
130
unless quiet $ putStrLn " Success!"
121
131
pure ranAll
122
132
pure (ranAll, map (takeFileName . snd ) (filter isUnofficialMigration allScripts))
@@ -169,37 +179,32 @@ validateMigrations migrationDir knownMigrations = do
169
179
stage3or4 = flip elem [3 , 4 ] . readStageFromFilename . Text. unpack . mvFilepath
170
180
171
181
applyMigration :: MigrationDir -> Bool -> PGConfig -> Maybe FilePath -> Handle -> (MigrationVersion , FilePath ) -> IO ()
172
- applyMigration (MigrationDir location) quiet pgconfig mLogFilename logHandle (version, script) = do
173
- -- This assumes that the credentials for 'psql' are already sorted out.
174
- -- One way to achive this is via a 'PGPASSFILE' environment variable
175
- -- as per the PostgreSQL documentation.
176
- let command =
177
- List. unwords
178
- [ " psql"
179
- , Text. unpack (pgcDbname pgconfig)
180
- , " --no-password"
181
- , " --quiet"
182
- , " --username=" <> Text. unpack (pgcUser pgconfig)
183
- , " --host=" <> Text. unpack (pgcHost pgconfig)
184
- , " --port=" <> Text. unpack (pgcPort pgconfig)
185
- , " --no-psqlrc" -- Ignore the ~/.psqlrc file.
186
- , " --single-transaction" -- Run the file as a transaction.
187
- , " --set ON_ERROR_STOP=on" -- Exit with non-zero on error.
188
- , " --file='" ++ location </> script ++ " '"
189
- , " 2>&1" -- Pipe stderr to stdout.
190
- ]
182
+ applyMigration (MigrationDir location) quiet pgconfig mLogFilename logHandle (_, script) = do
191
183
hPutStrLn logHandle $ " Running : " ++ script
192
184
unless quiet $ putStr (" " ++ script ++ " ... " )
193
- hFlush stdout
194
- exitCode <-
195
- fst
196
- <$> handle
197
- (errorExit :: SomeException -> IO a )
198
- (runResourceT $ sourceCmdWithConsumer command (sinkHandle logHandle))
185
+ -- hFlush stdout
186
+
187
+ let psqlArgs = [ Text. unpack (pgcDbname pgconfig)
188
+ , " --no-password"
189
+ , " --quiet"
190
+ , " --username=" <> Text. unpack (pgcUser pgconfig)
191
+ , " --host=" <> Text. unpack (pgcHost pgconfig)
192
+ , " --port=" <> Text. unpack (pgcPort pgconfig)
193
+ , " --no-psqlrc"
194
+ , " --single-transaction"
195
+ , " --set" , " ON_ERROR_STOP=on"
196
+ , " --file=" ++ location </> script
197
+ ]
198
+
199
+ hPutStrLn logHandle $ " DEBUG: About to execute psql with args: " ++ show psqlArgs
200
+ (exitCode, stdt, stderr) <- readProcessWithExitCode " psql" psqlArgs " "
201
+ hPutStrLn logHandle $ " DEBUG: Command completed with exit code: " ++ show exitCode
202
+ hPutStrLn logHandle $ " Command output: " ++ stdt
203
+ unless (null stderr) $ hPutStrLn logHandle $ " Command stderr: " ++ stderr
204
+
199
205
case exitCode of
200
206
ExitSuccess -> do
201
207
unless quiet $ putStrLn " ok"
202
- runHaskellMigration (PGPassCached pgconfig) logHandle version
203
208
ExitFailure _ -> errorExit exitCode
204
209
where
205
210
errorExit :: Show e => e -> IO a
@@ -212,8 +217,6 @@ applyMigration (MigrationDir location) quiet pgconfig mLogFilename logHandle (ve
212
217
exitFailure
213
218
214
219
-- | Create a database migration.
215
- -- TODO: Cmdv - This functionality will need to be reimplemented without Persistent.
216
- -- For now, this serves as a placeholder.
217
220
createMigration :: PGPassSource -> MigrationDir -> TxOutVariantType -> IO (Maybe FilePath )
218
221
createMigration _source (MigrationDir _migdir) _txOutVariantType = do
219
222
-- This would need to be completely rewritten to generate migrations manually
0 commit comments