diff options
Diffstat (limited to 'src/cli')
| -rw-r--r-- | src/cli/make_migrations.rs | 65 | 
1 files changed, 63 insertions, 2 deletions
diff --git a/src/cli/make_migrations.rs b/src/cli/make_migrations.rs index 767639f..f4edf94 100644 --- a/src/cli/make_migrations.rs +++ b/src/cli/make_migrations.rs @@ -1,5 +1,8 @@  use std::collections::HashMap; +use std::fs; +use std::path::PathBuf; +use quote::{quote, ToTokens};  use structopt::StructOpt;  use crate::{Settings, UrlMap, db::backend::Connectable}; @@ -21,6 +24,36 @@ struct TableState {      fields: Vec<Field>,  } +impl AppTablesState { +    fn changes_to(self, dest: AppTablesState) -> Vec<impl ToTokens> { +        let mut result = vec![]; +        for table in dest.db.keys() { +            if !self.db.contains_key(table) { +                let fields = &dest.db[table].fields.iter().map(|field| { +                    match field { +                        Field::CharField { name, max_length: Some(max_length) } => quote! { Field::CharField { name: #name, max_length: Some(#max_length) } }, +                        Field::CharField { name, max_length: None } => quote! { Field::CharField { name: #name, max_length: None } }, + +                        Field::DateTimeField { name } => quote! { Field::DateTimeField { name: #name } }, +                         +                        Field::IntField { name } => quote! { Field::IntField { name: #name } }, +                    } +                }).collect::<Vec<_>>(); +                result.push(quote! { +                    DatabaseChange::CreateModel { +                        name: #table, +                        fields: &[ +                            #(#fields),* +                        ], +                        options: &[], +                    } +                }); +            } +        } +        result +    } +} +  impl From<&[ModelMeta]> for AppTablesState {      fn from(models: &[ModelMeta]) -> Self {          let mut db = HashMap::new(); @@ -59,8 +92,36 @@ impl MakeMigrations {          for app in settings.installed_apps {              let expected_table_state = AppTablesState::from(app.models);              let actual_table_state = AppTablesState::from(app.migrations); -            dbg!(expected_table_state, actual_table_state); -            todo!(); +            let next_id = app.migrations.iter().map(|m| m.id).max().map_or(1, |x| x + 1); +            let name = "auto"; // TODO names +            let changes = actual_table_state.changes_to(expected_table_state); +            if changes.is_empty() { continue; } +            let migration = quote! { +                Migration { +                    id: #next_id, +                    name: #name, +                    prereqs: &[], // TODO +                    changes: &[ #(#changes),* ], +                } +            }; +            let file = quote! { +                use crate::db::migration::Migration; + +                pub const MIGRATION: Migration = #migration; +            }; +            let file_name = format!("m_{:04}_{}.rs", next_id, name); +            let file_text = file.into_token_stream().to_string(); +            let app_folder = app.name.split("::") +                .skip(1) +                .collect::<PathBuf>(); +            // TODO don't explode if running in a weird place +            let file_path = PathBuf::from("src") +                .join(app_folder) +                .join("migrations") +                .join(file_name); +            println!("Saving migration to {}...", file_path.display()); +            fs::write(file_path, file_text).unwrap(); +            // TODO cargo fmt          }      }  }  |