Files
ahab/src/scripts/django.rs

106 lines
2.8 KiB
Rust

use std::fs::{File, OpenOptions, create_dir};
use std::io::Write;
use std::path::{Path, PathBuf};
use anyhow::{Result, anyhow};
use crate::compose::Compose;
use crate::ctx::Ctx;
use crate::scripts::docker_compose;
const DEBUG_TEMPLATE: &str = r#"from django.core.management.base import BaseCommand
class Command(BaseCommand):
def handle(self, *args, **options):
pass
"#;
pub fn make_command(app: &PathBuf, name: &str) -> Result<()> {
let app_name = app.to_string_lossy();
let app_dir = Path::new(&app);
let not_app_exists = !app_dir.is_dir();
if not_app_exists {
return Err(anyhow!("directory {app_name} does not exist"));
}
eprintln!("found app {app_name}");
let management_dir = app_dir.join("management");
let not_management_exists = !management_dir.exists();
if not_management_exists {
create_dir(&management_dir)?;
create_file(management_dir.join("__init__.py"))?;
eprintln!("created module {app_name}.management")
};
let commands_dir = management_dir.join("commands");
let not_commands_exists = !commands_dir.exists();
if not_commands_exists {
create_dir(&commands_dir)?;
create_file(commands_dir.join("__init__.py"))?;
eprintln!("created module {app_name}.management.commands")
};
let mut file = safe_create_file(commands_dir.join(format!("{name}.py")))?;
file.write_all(DEBUG_TEMPLATE.as_bytes())?;
eprintln!("created command {app_name}.management.commands.{name}");
Ok(())
}
pub fn bash(ctx: &Ctx) -> Result<()> {
run(ctx, &["bash".to_string()])
}
pub fn run(ctx: &Ctx, rest: &[String]) -> Result<()> {
let service = Compose::resolve(ctx)?.django()?;
docker_compose::run(ctx, &service, rest)
}
pub fn manage(ctx: &Ctx, rest: &[String]) -> Result<()> {
let mut args = vec!["python".to_string(), "manage.py".to_string()];
args.extend_from_slice(rest);
run(ctx, &args)
}
// shortcuts
pub fn makemigrations(ctx: &Ctx) -> Result<()> {
manage(ctx, &["makemigrations".to_string()])
}
pub fn migrate(ctx: &Ctx, rest: &[String]) -> Result<()> {
let mut full_rest = vec!["migrate".to_string()];
full_rest.extend_from_slice(rest);
manage(ctx, &full_rest)
}
pub fn shell(ctx: &Ctx) -> Result<()> {
manage(ctx, &["shell".to_string()])
}
pub fn test(ctx: &Ctx) -> Result<()> {
manage(ctx, &["test".to_string()])
}
fn safe_create_file(path: PathBuf) -> Result<File, std::io::Error> {
OpenOptions::new().write(true).create_new(true).open(path)
}
// truncate(false) keeps an existing file's contents, which is what callers creating
// an empty __init__.py want
fn create_file(path: PathBuf) -> Result<File, std::io::Error> {
OpenOptions::new()
.write(true)
.create(true)
.truncate(false)
.open(path)
}