@@ -37,10 +37,75 @@ fn create_file(
3737 Ok ( ( ) )
3838}
3939
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 ! ( "{:04}" , version) )
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+
40103pub async fn add (
41104 migration_source : & str ,
42105 description : & str ,
43106 reversible : bool ,
107+ sequential : bool ,
108+ timestamp : bool ,
44109) -> anyhow:: Result < ( ) > {
45110 fs:: create_dir_all ( migration_source) . context ( "Unable to create migrations directory" ) ?;
46111
@@ -50,15 +115,16 @@ pub async fn add(
50115 . unwrap_or ( false ) ;
51116
52117 let migrator = Migrator :: new ( Path :: new ( migration_source) ) . await ?;
53- // This checks if all existing migrations are of the same type as the reverisble flag passed
118+ // This checks if all existing migrations are of the same type as the reversible flag passed
54119 for migration in migrator. iter ( ) {
55120 if migration. migration_type . is_reversible ( ) != reversible {
56121 bail ! ( MigrateError :: InvalidMixReversibleAndSimple ) ;
57122 }
58123 }
59124
60- let dt = Utc :: now ( ) ;
61- let file_prefix = dt. format ( "%Y%m%d%H%M%S" ) . to_string ( ) ;
125+ let ordering = MigrationOrdering :: infer ( sequential, timestamp, & migrator) ;
126+ let file_prefix = ordering. file_prefix ( ) ;
127+
62128 if reversible {
63129 create_file (
64130 migration_source,
0 commit comments