use super::{Argv, Cmd}; use crate::ctx::Ctx; // compose prints its own progress, which --quiet has to ask it to stop fn compose(quiet: bool) -> Argv { let argv = Argv::new("docker").arg("compose"); match quiet { true => argv.flag("--progress", "quiet"), false => argv, } } // the compose commands, each already knowing whether -q asked compose to stop // narrating. the flag was a field every construction site set by hand, and // three of them did not, so `ahab -q` still had compose talking over the output pub struct Compose<'a> { ctx: &'a Ctx, } impl<'a> Compose<'a> { pub(crate) fn new(ctx: &'a Ctx) -> Self { Self { ctx } } pub fn up(&self) -> Up { Up { quiet: self.ctx.quiet, } } pub fn stop(&self) -> Stop { Stop { quiet: self.ctx.quiet, } } pub fn start(&self, service: &'a str) -> Start<'a> { Start { service, quiet: self.ctx.quiet, } } // reading the project says nothing, so there is no progress to quieten pub fn config(&self) -> Config { Config } pub fn ps(&self, service: &str) -> Ps { Ps { service: service.to_string(), } } } // docker compose run --rm, which runs the image's entrypoint and so fixes up the // container user before handing over pub struct Run { service: String, inner: Argv, quiet: bool, } impl Run { // only reached through Cmd::in_service, which takes the context, so the // progress flag cannot be left off by forgetting a builder call pub(super) fn wrapping(ctx: &Ctx, service: &str, inner: Argv) -> Self { Self { service: service.to_string(), inner, quiet: ctx.quiet, } } } impl Cmd for Run { fn argv(&self) -> Argv { compose(self.quiet) .arg("run") .arg("--rm") .arg(&self.service) .args(self.inner.words()) } } // the merged project file, with every extends and env_file resolved pub struct Config; impl Cmd for Config { fn argv(&self) -> Argv { compose(false).arg("config").flag("--format", "json") } } // the container id a service is running as, empty when it is not running pub struct Ps { service: String, } impl Cmd for Ps { fn argv(&self) -> Argv { compose(false).arg("ps").arg("--quiet").arg(&self.service) } } pub struct Up { quiet: bool, } impl Cmd for Up { fn argv(&self) -> Argv { compose(self.quiet).arg("up").arg("--detach") } } pub struct Start<'a> { service: &'a str, quiet: bool, } impl Cmd for Start<'_> { fn argv(&self) -> Argv { compose(self.quiet).arg("start").arg(self.service) } } pub struct Stop { quiet: bool, } impl Cmd for Stop { fn argv(&self) -> Argv { compose(self.quiet).arg("stop") } }