use crate::generator::{GeneratedFile, Generator};
use crate::generators::bootstrap_migrations::{
apply_bootstrap_migrations, storage_config_section, storage_migration_installed,
};
use crate::generators::migration_support::{MIGRATION_LIB_BASE, MIGRATION_SRC_DIR};
use doido_core::Result;
pub struct StorageInstallGenerator;
fn config_file(path: &str, active: &str) -> Option<GeneratedFile> {
let existing = std::fs::read_to_string(path).ok()?;
if existing.contains("storage:") {
return None;
}
Some(GeneratedFile {
path: path.to_string(),
content: format!(
"{}\n{}",
existing.trim_end(),
storage_config_section(active)
),
})
}
impl Generator for StorageInstallGenerator {
fn name(&self) -> &str {
"storage:install"
}
fn generate(&self, _args: &[&str]) -> Result<Vec<GeneratedFile>> {
let lib_path = format!("{MIGRATION_SRC_DIR}/lib.rs");
let existing =
std::fs::read_to_string(&lib_path).unwrap_or_else(|_| MIGRATION_LIB_BASE.to_string());
let mut files = Vec::new();
if storage_migration_installed(&existing) {
files.push(GeneratedFile {
path: lib_path,
content: existing,
});
} else {
let (lib, migrations) = apply_bootstrap_migrations(&existing, false);
files.push(GeneratedFile {
path: lib_path,
content: lib,
});
for (module, content) in migrations {
files.push(GeneratedFile {
path: format!("{MIGRATION_SRC_DIR}/{module}.rs"),
content,
});
}
}
if let Some(f) = config_file("config/development.yml", "local") {
files.push(f);
}
if let Some(f) = config_file("config/test.yml", "test") {
files.push(f);
}
Ok(files)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::generators::bootstrap_migrations::STORAGE_MIGRATION_MODULE;
#[test]
fn emits_migration_and_registers_it() {
let files = StorageInstallGenerator.generate(&[]).unwrap();
let migration = files
.iter()
.find(|f| f.path.contains(STORAGE_MIGRATION_MODULE) && f.path.ends_with(".rs"))
.expect("migration file emitted");
assert!(migration.content.contains("storage_blobs"));
assert!(migration.content.contains("storage_attachments"));
assert!(migration.content.contains("storage_variant_records"));
assert!(migration
.content
.contains("impl MigrationName for Migration"));
assert!(!migration.content.contains("DeriveMigrationName"));
let module = migration
.path
.strip_prefix("db/migration/src/")
.unwrap()
.strip_suffix(".rs")
.unwrap();
assert!(migration.content.contains(&format!("\"{module}\"")));
let lib = files
.iter()
.find(|f| f.path.ends_with("lib.rs"))
.expect("lib.rs emitted");
assert!(lib.content.contains(STORAGE_MIGRATION_MODULE));
}
}