@@ -7,7 +7,8 @@ use crate::runner::Type;
7
7
use crate :: { error:: Kind , Error , Migration } ;
8
8
9
9
// Verifies applied and to be applied migrations returning Error if:
10
- // - `abort_divergent` is true and there are applied migrations with a different name and checksum but same version as a migration to be applied.
10
+ // - `abort_divergent` is true and there are applied migrations with a different name and checksum
11
+ // but same version as a migration to be applied.
11
12
// - `abort_missing` is true and there are applied migrations that are missing on the file system
12
13
// - there are repeated migrations with the same version to be applied
13
14
pub ( crate ) fn verify_migrations (
@@ -18,83 +19,80 @@ pub(crate) fn verify_migrations(
18
19
) -> Result < Vec < Migration > , Error > {
19
20
migrations. sort ( ) ;
20
21
21
- for app in applied. iter ( ) {
22
+ for app in & applied {
22
23
// iterate applied migrations on database and assert all migrations
23
24
// applied on database exist on the file system and have the same checksum
24
- match migrations. iter ( ) . find ( |m| m. version ( ) == app. version ( ) ) {
25
- None => {
26
- if abort_missing {
27
- return Err ( Error :: new ( Kind :: MissingVersion ( app. clone ( ) ) , None ) ) ;
28
- } else {
29
- log:: error!( target: "refinery_core::traits::missing" , "migration {} is missing from the filesystem" , app) ;
30
- }
31
- }
32
- Some ( migration) => {
33
- if migration != app {
34
- if abort_divergent {
35
- return Err ( Error :: new (
36
- Kind :: DivergentVersion ( app. clone ( ) , migration. clone ( ) ) ,
37
- None ,
38
- ) ) ;
39
- } else {
40
- log:: error!(
41
- target: "refinery_core::traits::divergent" ,
42
- "applied migration {} is different than filesystem one {}" ,
43
- app,
44
- migration
45
- ) ;
46
- }
47
- }
25
+ if let Err ( _) = migrations. binary_search_by ( |m| m. version ( ) . cmp ( & app. version ( ) ) ) {
26
+ if abort_missing {
27
+ return Err ( Error :: new ( Kind :: MissingVersion ( app. clone ( ) ) , None ) ) ;
28
+ } else {
29
+ log:: warn!( target: "refinery_core::traits::missing" , "migration {} is missing from the filesystem" , app) ;
48
30
}
49
31
}
50
32
}
51
33
52
- let current: i32 = match applied. last ( ) {
53
- Some ( last) => {
54
- log:: info!( "current version: {}" , last. version( ) ) ;
55
- last. version ( ) as i32
56
- }
57
- None => {
58
- log:: info!( "schema history table is empty, going to apply all migrations" ) ;
59
- // use -1 as versions might start with 0
60
- -1
61
- }
34
+ let stale = |migration : & Migration | {
35
+ applied
36
+ . last ( )
37
+ . map ( |latest| latest. version ( ) >= migration. version ( ) )
38
+ . unwrap_or ( false )
62
39
} ;
63
40
64
41
let mut to_be_applied = Vec :: new ( ) ;
65
- // iterate all migration files found on file system and assert that there are not migrations missing:
66
- // migrations which its version is inferior to the current version on the database, yet were not applied.
67
- // select to be applied all migrations with version greater than current
68
- for migration in migrations. into_iter ( ) {
69
- if ! applied
42
+ // iterate all migration files found on file system and assert that there are not migrations
43
+ // missing: migrations which its version is inferior to the current version on the database, yet
44
+ // were not applied. select to be applied all migrations with version greater than current
45
+ for migration in migrations {
46
+ if let Some ( app ) = applied
70
47
. iter ( )
71
- . any ( |app| app. version ( ) == migration. version ( ) )
48
+ . find ( |app| app. version ( ) == migration. version ( ) )
72
49
{
73
- if to_be_applied. contains ( & migration) {
74
- return Err ( Error :: new ( Kind :: RepeatedVersion ( migration) , None ) ) ;
75
- } else if migration. prefix ( ) == & Type :: Versioned
76
- && current >= migration. version ( ) as i32
77
- {
78
- if abort_missing {
79
- return Err ( Error :: new ( Kind :: MissingVersion ( migration) , None ) ) ;
80
- } else {
81
- log:: error!( target: "refinery_core::traits::missing" , "found migration on file system {} not applied" , migration) ;
82
- }
83
- } else {
84
- to_be_applied. push ( migration) ;
50
+ if * app == migration {
51
+ continue ;
52
+ }
53
+
54
+ if abort_divergent {
55
+ return Err ( Error :: new (
56
+ Kind :: DivergentVersion ( app. clone ( ) , migration. clone ( ) ) ,
57
+ None ,
58
+ ) ) ;
59
+ }
60
+
61
+ log:: warn!(
62
+ target: "refinery_core::traits::divergent" ,
63
+ "applied migration {app} is different than filesystem one {migration} => skipping {migration}" ,
64
+ ) ;
65
+ continue ;
66
+ }
67
+
68
+ if to_be_applied. contains ( & migration) {
69
+ return Err ( Error :: new ( Kind :: RepeatedVersion ( migration) , None ) ) ;
70
+ }
71
+
72
+ if migration. prefix ( ) == & Type :: Versioned && stale ( & migration) {
73
+ if abort_missing {
74
+ return Err ( Error :: new ( Kind :: MissingVersion ( migration) , None ) ) ;
85
75
}
76
+
77
+ log:: error!( target: "refinery_core::traits::missing" , "found strictly versioned, not applied migration on file system => skipping: {migration}" ) ;
78
+ continue ;
86
79
}
80
+
81
+ to_be_applied. push ( migration) ;
87
82
}
83
+
88
84
// with these two iterations we both assert that all migrations found on the database
89
85
// exist on the file system and have the same checksum, and all migrations found
90
- // on the file system are either on the database, or greater than the current, and therefore going to be applied
86
+ // on the file system are either on the database, or greater than the current, and therefore going
87
+ // to be applied
91
88
Ok ( to_be_applied)
92
89
}
93
90
94
91
pub ( crate ) fn insert_migration_query ( migration : & Migration , migration_table_name : & str ) -> String {
95
92
format ! (
96
93
"INSERT INTO {} (version, name, applied_on, checksum) VALUES ({}, '{}', '{}', '{}')" ,
97
- // safe to call unwrap as we just converted it to applied, and we are sure it can be formatted according to RFC 33339
94
+ // safe to call unwrap as we just converted it to applied, and we are sure it can be formatted
95
+ // according to RFC 33339
98
96
migration_table_name,
99
97
migration. version( ) ,
100
98
migration. name( ) ,
0 commit comments