Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14 feature implement citrus migrations library #15

Merged
merged 2 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions crates/citrus-migrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
description = "A library of database migration functions for citrus."
repository = "https://github.com/davidkurilla/citrus"
readme = "../../docs/README.md"

[dependencies]
diesel = { version = "2.1.6", features = ["postgres"] }
diesel_migrations = "2.1.0"
toml = "0.5"
123 changes: 115 additions & 8 deletions crates/citrus-migrations/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,121 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
use std::string::String;
use toml::Value;
use diesel::{pg::PgConnection, Connection};
use diesel_migrations::{FileBasedMigrations, HarnessWithOutput, MigrationHarness};

pub struct InputData {
username: String,
password: String,
dbname: String,
host: String,
port: u16
}

fn get_str_or_default(toml: &Value, key: &str) -> String {
let value = toml.get(key);

let str =
if value.is_none() {
eprintln!("Could not read toml field: \"{}\"", key);
""
} else {
value.unwrap().as_str().unwrap_or_default()
};

String::from(str)
}
fn get_int_or_default(toml: &Value, key: &str) -> i64 {
let value = toml.get(key);

if value.is_none() {
eprintln!("Could not read toml field: \"{}\"", key);
0
} else {
value.unwrap().as_integer().unwrap_or_default()
}
}

impl InputData {
pub fn read(toml: &Value) -> InputData {
InputData {
username: get_str_or_default(toml, "username"),
password: get_str_or_default(toml, "password"),
dbname: get_str_or_default(toml, "dbname"),
host: get_str_or_default(toml, "host"),
port: get_int_or_default(toml, "port") as u16
}
}

pub fn postgres_url(&self) -> String {
format!(
"postgres://{}:{}@{}:{}/{}",
self.username,
self.password,
self.host,
self.port,
self.dbname
)
}
}

pub fn run_migration(toml_file_path: std::path::PathBuf, toml_table: String) {

let toml_file = toml_file_path;
let table_name = toml_table;

let toml_contents = match std::fs::read_to_string(toml_file) {
Ok(contents) => contents,
Err(e) => {
eprintln!("Error reading TOML file: {}", e);
return;
}
};

let toml_data: Value = match toml_contents.parse() {
Ok(data) => data,
Err(e) => {
eprintln!("Error parsing TOML file: {}", e);
return;
}
};

let table = get_toml_table(&table_name, &toml_data);

let input = InputData::read(table);

let db_url = input.postgres_url();

println!("Attempting to connect to {}", db_url);

let mut conn = PgConnection::establish(&db_url)
.expect("Unable to connect");

let migrations = FileBasedMigrations::find_migrations_directory()
.expect("Could not read migrations directory");

let mut harness = HarnessWithOutput::write_to_stdout(&mut conn);

harness.run_pending_migrations(migrations).expect("Couldn't run migrations");

println!("Successfully ran migrations")
}


pub fn get_toml_table<'a>(table_name: &'a str, toml_data: &'a Value) -> &'a Value{
if !table_name.is_empty() {
let table = toml_data.get(&table_name);
if table.is_none() {
eprintln!("Unable to find toml table: \"{}\"", &table_name);
std::process::abort()
}

table.unwrap()
} else {
&toml_data
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}