diff --git a/src/cli/django.rs b/src/cli/django.rs index fa6e88c..44d312e 100644 --- a/src/cli/django.rs +++ b/src/cli/django.rs @@ -2,28 +2,38 @@ use std::path::PathBuf; use clap::Parser; +// TODO: (matej) dsu template command + #[derive(Parser, Debug)] pub enum Django { /// Prepare empty management command 'command' in app 'app'. + #[clap(alias("mc"))] MakeCommand { #[arg(value_enum)] app: PathBuf, #[arg(value_enum)] - command: String, + name: String, }, /// Run Django's manage.py makemigrations. + #[clap(alias("mm"))] Makemigrations, /// Pass arguments to Django's manage.py. + #[clap(alias("m"))] Manage { #[arg(value_enum)] rest: Vec, }, /// Run Django's manage.py migrate. - Migrate, + #[clap(alias("mg"))] + Migrate { + #[arg(value_enum)] + rest: Vec, + }, /// Run Django's manage.py shell. + #[clap(alias("s"))] Shell, } diff --git a/src/cli/docker.rs b/src/cli/docker.rs index 3945c00..a9b80e2 100644 --- a/src/cli/docker.rs +++ b/src/cli/docker.rs @@ -3,5 +3,6 @@ use clap::Parser; #[derive(Parser, Debug)] pub enum Docker { /// Stop all containers via `docker stop $(docker ps -q)` + #[clap(alias("sa"))] StopAll, } diff --git a/src/cli/docker_compose.rs b/src/cli/docker_compose.rs index 70b066f..2defc2a 100644 --- a/src/cli/docker_compose.rs +++ b/src/cli/docker_compose.rs @@ -4,23 +4,30 @@ use clap::Subcommand; #[derive(Subcommand, Debug)] pub enum DockerCompose { /// Build containers. + #[clap(alias("b"))] Build, /// Down containers. + #[clap(alias("d"))] Down, /// Stop, build and start containers. + #[clap(alias("rb"))] Rebuild, /// Stop and start containers. + #[clap(alias("rs"))] Restart, /// Start containers. + #[clap(alias("st"))] Start, /// Stop containers. + #[clap(alias("s"))] Stop, /// Up containers. + #[clap(alias("u"))] Up, } diff --git a/src/cli/postgres.rs b/src/cli/postgres.rs index 3a0b71f..9808e6e 100644 --- a/src/cli/postgres.rs +++ b/src/cli/postgres.rs @@ -5,12 +5,14 @@ use clap::Subcommand; #[derive(Subcommand, Debug)] pub enum Postgres { /// Import dump via pg_restore + #[clap(alias("i"))] Import { #[arg(value_enum)] path: PathBuf, }, /// Dump via pg_dump with format=c + #[clap(alias("d"))] Dump { #[arg(value_enum)] path: PathBuf, diff --git a/src/main.rs b/src/main.rs index 14f4e65..50d844f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,15 @@ mod scripts; use anyhow::Result; use clap::Parser; +use std::env; fn main() -> Result<()> { // always load dotenv on start dotenvy::dotenv().ok(); + // TODO: (matej) some prints about project + // eg: DJANGO_SETTINGS_MODULE for django projects, used docker-compose, etc. + let args = cli::Ahab::parse(); match args.command { @@ -26,12 +30,10 @@ fn main() -> Result<()> { cli::DockerCompose::Up => scripts::docker_compose::up(), }, cli::Commands::Dj { command } => match command { - cli::Django::MakeCommand { app, command } => { - scripts::django::make_command(&app, &command) - } + cli::Django::MakeCommand { app, name } => scripts::django::make_command(&app, &name), cli::Django::Makemigrations => scripts::django::makemigrations(), cli::Django::Manage { rest } => scripts::django::manage(&rest), - cli::Django::Migrate => scripts::django::migrate(), + cli::Django::Migrate { rest } => scripts::django::migrate(&rest), cli::Django::Shell => scripts::django::shell(), }, cli::Commands::Pg { command } => match command { diff --git a/src/scripts/django.rs b/src/scripts/django.rs index 96297ca..db39830 100644 --- a/src/scripts/django.rs +++ b/src/scripts/django.rs @@ -1,20 +1,73 @@ -use anyhow::Result; -use std::path::PathBuf; +use crate::scripts::{create_file, safe_create_file}; -pub fn make_command(app: &PathBuf, command: &str) -> Result<()> { - println!("{app:?} and {command:?}"); - todo!() +use super::DockerCommand; +use anyhow::{anyhow, Result}; +use std::env; +use std::fs::create_dir; +use std::path::{Path, PathBuf}; + +fn get_django_settings_module() -> Result { + Ok(env::var("DJANGO_SETTINGS_MODULE")?) } + +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")); + } + + println!("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"))?; + + println!("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"))?; + + println!("created module {app_name}.management.commands") + }; + + safe_create_file(commands_dir.join(name))?; + println!("created command {app_name}.management.commands.{name}"); + Ok(()) +} + pub fn makemigrations() -> Result<()> { - todo!() + let dsm = get_django_settings_module()?; + let command = format!("manage makemigrations --settings={dsm}"); + DockerCommand::docker_compose().args(&command).spawn_wait() } -pub fn manage(command: &[String]) -> Result<()> { - println!("{command:?}"); - todo!() + +pub fn manage(rest: &[String]) -> Result<()> { + let dsm = get_django_settings_module()?; + let joined = rest.join(" "); + let command = format!("manage {joined} --settings={dsm}"); + DockerCommand::docker_compose().args(&command).spawn_wait() } -pub fn migrate() -> Result<()> { - todo!() + +pub fn migrate(rest: &[String]) -> Result<()> { + let dsm = get_django_settings_module()?; + let joined = rest.join(" "); + let command = format!("manage migrate {joined} --settings={dsm}"); + DockerCommand::docker_compose().args(&command).spawn_wait() } + pub fn shell() -> Result<()> { - todo!() + let dsm = get_django_settings_module()?; + let command = format!("manage shell --settings={dsm}"); + DockerCommand::docker_compose().args(&command).spawn_wait() } diff --git a/src/scripts/docker.rs b/src/scripts/docker.rs index ca9b53f..aa8eeb7 100644 --- a/src/scripts/docker.rs +++ b/src/scripts/docker.rs @@ -3,6 +3,11 @@ use anyhow::Result; pub fn stop_all() -> Result<()> { let running_containers = DockerCommand::docker().args("ps -q").stdout()?; + + if running_containers.is_empty() { + return Ok(()); + } + DockerCommand::docker() .args(&format!("stop {running_containers}")) .spawn_wait() diff --git a/src/scripts/mod.rs b/src/scripts/mod.rs index fa98285..48f2808 100644 --- a/src/scripts/mod.rs +++ b/src/scripts/mod.rs @@ -3,7 +3,12 @@ pub mod docker; pub mod docker_compose; pub mod postgres; -use std::{ffi::OsStr, process::Command}; +use std::{ + ffi::OsStr, + fs::{File, OpenOptions}, + path::PathBuf, + process::Command, +}; use anyhow::{Context, Result}; @@ -43,3 +48,11 @@ impl DockerCommand { Ok(()) } } + +fn safe_create_file(path: PathBuf) -> Result { + OpenOptions::new().write(true).create_new(true).open(path) +} + +fn create_file(path: PathBuf) -> Result { + OpenOptions::new().write(true).create(true).open(path) +}