1
- use crate :: opt:: ConnectOpts ;
1
+ use crate :: opt:: { AddMigrationOpts , ConnectOpts } ;
2
2
use anyhow:: { bail, Context } ;
3
- use chrono:: Utc ;
4
3
use console:: style;
5
4
use sqlx:: migrate:: { AppliedMigration , Migrate , MigrateError , MigrationType , Migrator } ;
6
5
use sqlx:: Connection ;
@@ -10,6 +9,7 @@ use std::fmt::Write;
10
9
use std:: fs:: { self , File } ;
11
10
use std:: path:: Path ;
12
11
use std:: time:: Duration ;
12
+ use crate :: config:: Config ;
13
13
14
14
fn create_file (
15
15
migration_source : & str ,
@@ -37,116 +37,46 @@ fn create_file(
37
37
Ok ( ( ) )
38
38
}
39
39
40
- enum MigrationOrdering {
41
- Timestamp ( String ) ,
42
- Sequential ( String ) ,
43
- }
44
-
45
- impl MigrationOrdering {
46
- fn timestamp ( ) -> MigrationOrdering {
47
- Self :: Timestamp ( Utc :: now ( ) . format ( "%Y%m%d%H%M%S" ) . to_string ( ) )
48
- }
49
-
50
- fn sequential ( version : i64 ) -> MigrationOrdering {
51
- Self :: Sequential ( format ! ( "{version:04}" ) )
52
- }
53
-
54
- fn file_prefix ( & self ) -> & str {
55
- match self {
56
- MigrationOrdering :: Timestamp ( prefix) => prefix,
57
- MigrationOrdering :: Sequential ( prefix) => prefix,
58
- }
59
- }
60
-
61
- fn infer ( sequential : bool , timestamp : bool , migrator : & Migrator ) -> Self {
62
- match ( timestamp, sequential) {
63
- ( true , true ) => panic ! ( "Impossible to specify both timestamp and sequential mode" ) ,
64
- ( true , false ) => MigrationOrdering :: timestamp ( ) ,
65
- ( false , true ) => MigrationOrdering :: sequential (
66
- migrator
67
- . iter ( )
68
- . last ( )
69
- . map_or ( 1 , |last_migration| last_migration. version + 1 ) ,
70
- ) ,
71
- ( false , false ) => {
72
- // inferring the naming scheme
73
- let migrations = migrator
74
- . iter ( )
75
- . filter ( |migration| migration. migration_type . is_up_migration ( ) )
76
- . rev ( )
77
- . take ( 2 )
78
- . collect :: < Vec < _ > > ( ) ;
79
- if let [ last, pre_last] = & migrations[ ..] {
80
- // there are at least two migrations, compare the last twothere's only one existing migration
81
- if last. version - pre_last. version == 1 {
82
- // their version numbers differ by 1, infer sequential
83
- MigrationOrdering :: sequential ( last. version + 1 )
84
- } else {
85
- MigrationOrdering :: timestamp ( )
86
- }
87
- } else if let [ last] = & migrations[ ..] {
88
- // there is only one existing migration
89
- if last. version == 0 || last. version == 1 {
90
- // infer sequential if the version number is 0 or 1
91
- MigrationOrdering :: sequential ( last. version + 1 )
92
- } else {
93
- MigrationOrdering :: timestamp ( )
94
- }
95
- } else {
96
- MigrationOrdering :: timestamp ( )
97
- }
98
- }
99
- }
100
- }
101
- }
102
-
103
40
pub async fn add (
104
- migration_source : & str ,
105
- description : & str ,
106
- reversible : bool ,
107
- sequential : bool ,
108
- timestamp : bool ,
41
+ config : & Config ,
42
+ opts : AddMigrationOpts ,
109
43
) -> anyhow:: Result < ( ) > {
110
- fs:: create_dir_all ( migration_source ) . context ( "Unable to create migrations directory" ) ?;
44
+ fs:: create_dir_all ( & opts . source ) . context ( "Unable to create migrations directory" ) ?;
111
45
112
- let migrator = Migrator :: new ( Path :: new ( migration_source) ) . await ?;
113
- // Type of newly created migration will be the same as the first one
114
- // or reversible flag if this is the first migration
115
- let migration_type = MigrationType :: infer ( & migrator, reversible) ;
46
+ let migrator = Migrator :: new ( opts. source . as_ref ( ) ) . await ?;
116
47
117
- let ordering = MigrationOrdering :: infer ( sequential, timestamp, & migrator) ;
118
- let file_prefix = ordering. file_prefix ( ) ;
48
+ let version_prefix = opts. version_prefix ( config, & migrator) ;
119
49
120
- if migration_type . is_reversible ( ) {
50
+ if opts . reversible ( config , & migrator ) {
121
51
create_file (
122
- migration_source ,
123
- file_prefix ,
124
- description,
52
+ & opts . source ,
53
+ & version_prefix ,
54
+ & opts . description ,
125
55
MigrationType :: ReversibleUp ,
126
56
) ?;
127
57
create_file (
128
- migration_source ,
129
- file_prefix ,
130
- description,
58
+ & opts . source ,
59
+ & version_prefix ,
60
+ & opts . description ,
131
61
MigrationType :: ReversibleDown ,
132
62
) ?;
133
63
} else {
134
64
create_file (
135
- migration_source ,
136
- file_prefix ,
137
- description,
65
+ & opts . source ,
66
+ & version_prefix ,
67
+ & opts . description ,
138
68
MigrationType :: Simple ,
139
69
) ?;
140
70
}
141
71
142
72
// if the migrations directory is empty
143
- let has_existing_migrations = fs:: read_dir ( migration_source )
73
+ let has_existing_migrations = fs:: read_dir ( & opts . source )
144
74
. map ( |mut dir| dir. next ( ) . is_some ( ) )
145
75
. unwrap_or ( false ) ;
146
76
147
77
if !has_existing_migrations {
148
- let quoted_source = if migration_source != "migrations" {
149
- format ! ( "{migration_source :?}" )
78
+ let quoted_source = if * opts . source != "migrations" {
79
+ format ! ( "{:?}" , * opts . source )
150
80
} else {
151
81
"" . to_string ( )
152
82
} ;
0 commit comments