diff --git a/Cargo.lock b/Cargo.lock index b0c2413..5320396 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cave" -version = "0.1.6" +version = "0.1.7" dependencies = [ "anyhow", "assert_cmd", diff --git a/Cargo.toml b/Cargo.toml index 8c0a80d..ffe1296 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cave" -version = "0.1.6" +version = "0.1.7" authors = ["Simvia "] edition = "2021" description = "CLI for managing code_aster versions" diff --git a/src/cli.rs b/src/cli.rs index 2670cb7..5aa88ec 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -27,6 +27,8 @@ pub enum Command { #[arg(value_name = "ARGS")] args: Vec, }, + ///Start an interactive shell in the container + Shell, ///List downloaded images List { ///Optionnal Expression to match, ex : "cave list 16" diff --git a/src/docker.rs b/src/docker.rs index 02ca988..5904b18 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -209,29 +209,35 @@ pub fn pull_version(version: &str) -> Result<(), CaveError> { } -/// Runs code_aster with Docker with the given version, optional export file, and arguments. -/// Envoie ensuite les données d'exécution via gRPC si l'exécution n'est pas interactive. +pub enum DockerMode<'a> { + RunAster { export_file: &'a Option, args: &'a Vec }, + Shell, +} + +/// Runs code_aster with Docker with the given version and mode. +/// +/// - [`DockerMode::RunAster`]: sources the activate script and runs `run_aster` with the given args and export file. +/// - [`DockerMode::Shell`]: drops the user into an interactive bash shell inside the container. /// /// # Example /// ``` -/// docker_aster("22.0", &Some("output.msh".to_string()), &vec!["command".to_string()]) +/// docker_aster("22.0", DockerMode::RunAster { export_file: &Some("output.msh".to_string()), args: &vec![] }) /// .expect("Failed to run Code_Aster in Docker"); +/// docker_aster("22.0", DockerMode::Shell).expect("Failed to start shell"); /// ``` -pub fn docker_aster(version: &str, export_file: &Option, args: &Vec) -> Result<(), CaveError> { +pub fn docker_aster(version: &str, mode: DockerMode) -> Result<(), CaveError> { let start = std::time::Instant::now(); let current_dir = std::env::current_dir().map_err(CaveError::IoError)?; let volume_arg = format!("{}:/home/user/data", current_dir.display()); let image = format!("simvia/code_aster:{}", version); - let export = export_file.clone().unwrap_or_default(); - let docker_command = format!("source /opt/activate.sh && run_aster {} {}", args.join(" "), export); // Get the current user's UID and GID to avoid permission issues let (uid, gid) = get_uid_gid(); let user_arg = format!("{}:{}", uid, gid); - let mut child = Command::new("docker") - .arg("run") + let mut cmd = Command::new("docker"); + cmd.arg("run") .arg("--rm") .arg("-it") .arg("--user") @@ -240,11 +246,22 @@ pub fn docker_aster(version: &str, export_file: &Option, args: &Vec { + let export = export_file.clone().unwrap_or_default(); + let docker_command = format!("source /opt/activate.sh && run_aster {} {}", args.join(" "), export); + cmd.arg("/bin/bash").arg("-i").arg("-c").arg(docker_command); + } + DockerMode::Shell => { + cmd.arg("/bin/bash"); + } + } + + let mut child = cmd .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) @@ -258,9 +275,8 @@ pub fn docker_aster(version: &str, export_file: &Option, args: &Vec io::Result<()> { Command::Use { version } => set_version(version, true), Command::Pin { version } => set_version(version, false), Command::Run { args } => run_aster(&args), + Command::Shell {} => shell_aster(), Command::List { prefix } => print_local_versions(prefix.unwrap_or_default()), Command::Available { prefix } => print_remote_versions(prefix.unwrap_or_default()), Command::Config { action } => { diff --git a/src/manage.rs b/src/manage.rs index 86ba5a3..aabb342 100644 --- a/src/manage.rs +++ b/src/manage.rs @@ -209,10 +209,28 @@ pub fn run_aster(args: &Vec) -> Result<(), CaveError> { _ => (None, args.to_vec()), }; - docker_aster(&version, &export, &rest_args)?; + docker_aster(&version, DockerMode::RunAster { export_file: &export, args: &rest_args })?; Ok(()) } +/// Start interactive shell in the container +/// +/// # Errors +/// - [`CaveError::VersionNotInstalled`] if the configured version is not installed locally. +/// - [`CaveError::FileNotFound`] if the `.export` file does not exist. +/// - Any error returned by [`docker_aster`]. + +pub fn shell_aster() -> Result<(), CaveError> { + let version = read_cave_version()?; + if !exists_locally(&version)? { + return Err(CaveError::VersionNotInstalled(version)); + } + + docker_aster(&version, DockerMode::Shell)?; + Ok(()) +} + + /// Prints a list of locally available versions filtered by an optionnal prefix. /// /// # Example