Skip to content

Commit dd904b9

Browse files
committed
feat: add Shell command and interactive mode for Docker
1 parent 998b8d2 commit dd904b9

4 files changed

Lines changed: 54 additions & 16 deletions

File tree

src/cli.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub enum Command {
2727
#[arg(value_name = "ARGS")]
2828
args: Vec<String>,
2929
},
30+
///Start an interactive shell in the container
31+
Shell,
3032
///List downloaded images
3133
List {
3234
///Optionnal Expression to match, ex : "cave list 16"

src/docker.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -209,29 +209,35 @@ pub fn pull_version(version: &str) -> Result<(), CaveError> {
209209
}
210210

211211

212-
/// Runs code_aster with Docker with the given version, optional export file, and arguments.
213-
/// Envoie ensuite les données d'exécution via gRPC si l'exécution n'est pas interactive.
212+
pub enum DockerMode<'a> {
213+
RunAster { export_file: &'a Option<String>, args: &'a Vec<String> },
214+
Shell,
215+
}
216+
217+
/// Runs code_aster with Docker with the given version and mode.
218+
///
219+
/// - [`DockerMode::RunAster`]: sources the activate script and runs `run_aster` with the given args and export file.
220+
/// - [`DockerMode::Shell`]: drops the user into an interactive bash shell inside the container.
214221
///
215222
/// # Example
216223
/// ```
217-
/// docker_aster("22.0", &Some("output.msh".to_string()), &vec!["command".to_string()])
224+
/// docker_aster("22.0", DockerMode::RunAster { export_file: &Some("output.msh".to_string()), args: &vec![] })
218225
/// .expect("Failed to run Code_Aster in Docker");
226+
/// docker_aster("22.0", DockerMode::Shell).expect("Failed to start shell");
219227
/// ```
220-
pub fn docker_aster(version: &str, export_file: &Option<String>, args: &Vec<String>) -> Result<(), CaveError> {
228+
pub fn docker_aster(version: &str, mode: DockerMode) -> Result<(), CaveError> {
221229
let start = std::time::Instant::now();
222230

223231
let current_dir = std::env::current_dir().map_err(CaveError::IoError)?;
224232
let volume_arg = format!("{}:/home/user/data", current_dir.display());
225233
let image = format!("simvia/code_aster:{}", version);
226-
let export = export_file.clone().unwrap_or_default();
227-
let docker_command = format!("source /opt/activate.sh && run_aster {} {}", args.join(" "), export);
228234

229235
// Get the current user's UID and GID to avoid permission issues
230236
let (uid, gid) = get_uid_gid();
231237
let user_arg = format!("{}:{}", uid, gid);
232238

233-
let mut child = Command::new("docker")
234-
.arg("run")
239+
let mut cmd = Command::new("docker");
240+
cmd.arg("run")
235241
.arg("--rm")
236242
.arg("-it")
237243
.arg("--user")
@@ -240,11 +246,22 @@ pub fn docker_aster(version: &str, export_file: &Option<String>, args: &Vec<Stri
240246
.arg(&volume_arg)
241247
.arg("-w")
242248
.arg("/home/user/data")
243-
.arg(&image)
244-
.arg("/bin/bash")
245-
.arg("-i")
246-
.arg("-c")
247-
.arg(&docker_command)
249+
.arg(&image);
250+
251+
let is_shell = matches!(mode, DockerMode::Shell);
252+
253+
match mode {
254+
DockerMode::RunAster { export_file, args } => {
255+
let export = export_file.clone().unwrap_or_default();
256+
let docker_command = format!("source /opt/activate.sh && run_aster {} {}", args.join(" "), export);
257+
cmd.arg("/bin/bash").arg("-i").arg("-c").arg(docker_command);
258+
}
259+
DockerMode::Shell => {
260+
cmd.arg("/bin/bash");
261+
}
262+
}
263+
264+
let mut child = cmd
248265
.stdin(Stdio::inherit())
249266
.stdout(Stdio::inherit())
250267
.stderr(Stdio::inherit())
@@ -258,9 +275,8 @@ pub fn docker_aster(version: &str, export_file: &Option<String>, args: &Vec<Stri
258275
})?;
259276

260277
let status = child.wait().map_err(CaveError::IoError)?;
261-
let interactive = args.contains(&"-i".to_string());
262278

263-
if !interactive {
279+
if !is_shell {
264280
debug!("Début de la telemetry");
265281
debug!("Début de la collecte des données du run");
266282

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ fn main() -> io::Result<()> {
7575
Command::Use { version } => set_version(version, true),
7676
Command::Pin { version } => set_version(version, false),
7777
Command::Run { args } => run_aster(&args),
78+
Command::Shell {} => shell_aster(),
7879
Command::List { prefix } => print_local_versions(prefix.unwrap_or_default()),
7980
Command::Available { prefix } => print_remote_versions(prefix.unwrap_or_default()),
8081
Command::Config { action } => {

src/manage.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::config::read_config;
1515
use crate::docker::*;
1616
use colored::*;
1717
use regex::Regex;
18+
use uuid::NonNilUuid;
1819
use std::{
1920
cmp::Ordering,
2021
fmt, fs,
@@ -209,10 +210,28 @@ pub fn run_aster(args: &Vec<String>) -> Result<(), CaveError> {
209210
_ => (None, args.to_vec()),
210211
};
211212

212-
docker_aster(&version, &export, &rest_args)?;
213+
docker_aster(&version, DockerMode::RunAster { export_file: &export, args: &rest_args })?;
213214
Ok(())
214215
}
215216

217+
/// Start interactive shell in the container
218+
///
219+
/// # Errors
220+
/// - [`CaveError::VersionNotInstalled`] if the configured version is not installed locally.
221+
/// - [`CaveError::FileNotFound`] if the `.export` file does not exist.
222+
/// - Any error returned by [`docker_aster`].
223+
224+
pub fn shell_aster() -> Result<(), CaveError> {
225+
let version = read_cave_version()?;
226+
if !exists_locally(&version)? {
227+
return Err(CaveError::VersionNotInstalled(version));
228+
}
229+
230+
docker_aster(&version, DockerMode::Shell)?;
231+
Ok(())
232+
}
233+
234+
216235
/// Prints a list of locally available versions filtered by an optionnal prefix.
217236
///
218237
/// # Example

0 commit comments

Comments
 (0)