@@ -23,6 +23,11 @@ import Formatting ( (%), sformat, stext )
23
23
import Shelly
24
24
25
25
26
+ -- types
27
+
28
+ type Migration = (FilePath , FilePath )
29
+
30
+
26
31
-- psql
27
32
28
33
psqlCommand :: Text -> Text -> Sh Text
@@ -77,10 +82,13 @@ checkSchema schema url = do
77
82
r <- psqlCommand (countSchema schema) url
78
83
return $ strip r == " 0"
79
84
80
- filterMigrations :: [FilePath ] -> Text -> Text -> Text -> Sh [FilePath ]
85
+ filterMigrations :: [Migration ] -> Text -> Text -> Text -> Sh [Migration ]
81
86
filterMigrations migrations table schema url = do
82
- r <- psqlCommand (selectMigrations migrations table schema) url
83
- return $ migrations \\ map fromText (lines r)
87
+ r <- psqlCommand (selectMigrations (map snd migrations) table schema) url
88
+ return $ removes ((==) . snd ) migrations (map fromText (lines r)) where
89
+ removes p = foldr remove where
90
+ remove x = foldr f [] where
91
+ f a b = if p a x then b else a : b
84
92
85
93
86
94
-- migrations
@@ -90,24 +98,37 @@ ls_f dir = do
90
98
items <- ls dir
91
99
filterM test_f items
92
100
93
- findMigrations :: FilePath -> Sh [FilePath ]
94
- findMigrations dir = do
101
+ lsMigrations :: FilePath -> Sh [Migration ]
102
+ lsMigrations dir = do
95
103
migrations <- ls_f dir
96
- forM migrations $ relativeTo dir
104
+ migrations' <- forM migrations $ relativeTo dir
105
+ return $ sortBy (comparing snd ) $ zip (repeat dir) migrations'
97
106
98
- migrate :: [FilePath ] -> Text -> Text -> Text -> Sh ()
107
+ findMigrations :: FilePath -> Sh [Migration ]
108
+ findMigrations dir = do
109
+ dirs <- findWhen test_d dir
110
+ migrations <- forM (dir : dirs) lsMigrations
111
+ return $ sortBy (comparing snd ) $ concat migrations
112
+
113
+ searchMigrations :: Bool -> FilePath -> Sh [Migration ]
114
+ searchMigrations recur =
115
+ if recur then findMigrations else lsMigrations
116
+
117
+ migrate :: [Migration ] -> Text -> Text -> Text -> Sh ()
99
118
migrate migrations table schema url =
100
- withTmpDir $ \ dir ->
101
- forM_ migrations $ \ migration -> do
119
+ forM_ migrations $ uncurry $ \ dir migration ->
120
+ chdir dir $ do
102
121
echo $ out migration
103
122
contents <- readfile migration
104
- appendfile (dir </> migration) " \\ set ON_ERROR_STOP true\n\n "
105
- appendfile (dir </> migration) contents
106
- appendfile (dir </> migration) $ insertMigration migration table schema
107
- psqlFile (dir </> migration) url where
108
- out migration =
109
- sformat ( " M " % stext % " -> " % stext )
110
- (toTextIgnore migration) table
123
+ withTmpDir $ \ dir' ->
124
+ chdir dir' $ do
125
+ appendfile migration " \\ set ON_ERROR_STOP true\n\n "
126
+ appendfile migration contents
127
+ appendfile migration $ insertMigration migration table schema
128
+ psqlFile migration url where
129
+ out migration =
130
+ sformat ( " M " % stext % " -> " % stext )
131
+ (toTextIgnore migration) table
111
132
112
133
113
134
-- API
@@ -120,8 +141,7 @@ add migration file dir = do
120
141
mv file (dir </> migration) where
121
142
out =
122
143
sformat ( " A " % stext % " -> " % stext )
123
- (toTextIgnore file)
124
- (toTextIgnore (dir </> migration))
144
+ (toTextIgnore file) (toTextIgnore (dir </> migration))
125
145
126
146
-- | Apply bootstrap migrations to a database. Checks if a database
127
147
-- has been previously bootstrapped, and applies all bootstrap
@@ -130,24 +150,23 @@ add migration file dir = do
130
150
-- their application.
131
151
bootstrap :: FilePath -> Text -> Text -> Text -> Sh ()
132
152
bootstrap dir table schema url = do
133
- migrations <- findMigrations dir
134
- chdir dir $ do
135
- check <- checkSchema schema url
136
- when check $ do
137
- echo " Bootstrapping... "
138
- migrate migrations table schema url
139
- migrations' <- filterMigrations migrations table schema url
140
- unless ( null migrations') $ do
141
- echo " Bootstrap migrating... "
142
- migrate migrations' table schema url
153
+ migrations <- lsMigrations dir
154
+ check <- checkSchema schema url
155
+ when check $ do
156
+ echo " Bootstrapping... "
157
+ migrate migrations table schema url
158
+ migrations' <- filterMigrations migrations table schema url
159
+ unless ( null migrations') $ do
160
+ echo " Bootstrap migrating... "
161
+ migrate migrations' table schema url
162
+
143
163
144
164
-- | Apply migrations to a database. Applies all migrations that have
145
165
-- not been applied yet and records their application.
146
- converge :: FilePath -> Text -> Text -> Text -> Sh ()
147
- converge dir table schema url = do
148
- migrations <- findMigrations dir
149
- chdir dir $ do
150
- migrations' <- filterMigrations migrations table schema url
151
- unless (null migrations') $ do
152
- echo " Migrating..."
153
- migrate migrations' table schema url
166
+ converge :: Bool -> FilePath -> Text -> Text -> Text -> Sh ()
167
+ converge recur dir table schema url = do
168
+ migrations <- searchMigrations recur dir
169
+ migrations' <- filterMigrations migrations table schema url
170
+ unless (null migrations') $ do
171
+ echo " Migrating..."
172
+ migrate migrations' table schema url
0 commit comments