use std::ffi::OsString; use std::path::Path; use super::{Argv, Cmd}; // docker exec, around a command that runs inside the container pub struct Exec { container: String, interactive: bool, tty: bool, inner: Argv, } impl Exec { pub fn wrapping(container: &str, inner: Argv) -> Self { Self { container: container.to_string(), interactive: false, tty: false, inner, } } // a terminal, for a command that is a shell rather than a pipe stage pub fn tty(mut self, tty: bool) -> Self { self.tty = tty; self } // keep stdin open, for a command that is fed a dump pub fn interactive(mut self) -> Self { self.interactive = true; self } } impl Cmd for Exec { fn argv(&self) -> Argv { let mut argv = Argv::new("docker").arg("exec"); if self.interactive { argv = argv.arg("--interactive"); } if self.tty { argv = argv.arg("--tty"); } argv.arg(&self.container).args(self.inner.words()) } } // docker cp, in either direction. the local side stays an OsString: it is a // path the user named, and a lossy one would copy something else pub struct Cp { from: OsString, to: OsString, } impl Cp { pub fn into_container(local: &Path, container: &str, remote: &str) -> Self { Self { from: local.as_os_str().to_owned(), to: OsString::from(format!("{container}:{remote}")), } } pub fn out_of_container(container: &str, remote: &str, local: &Path) -> Self { Self { from: OsString::from(format!("{container}:{remote}")), to: local.as_os_str().to_owned(), } } } impl Cmd for Cp { fn argv(&self) -> Argv { // -L has no long form; it copies what a symlink points at Argv::new("docker") .arg("cp") .arg("-L") .arg(&self.from) .arg(&self.to) } }