From 78ad2bf7012afa593b92857c937573780855b361 Mon Sep 17 00:00:00 2001 From: qpismont Date: Thu, 17 Sep 2026 14:49:41 +0000 Subject: [PATCH] translate comment --- crates/devcontainer-rs/src/container.rs | 112 ++++++++++++------------ crates/devcontainer-rs/src/lib.rs | 6 +- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/crates/devcontainer-rs/src/container.rs b/crates/devcontainer-rs/src/container.rs index a2ce142..54b2f3a 100644 --- a/crates/devcontainer-rs/src/container.rs +++ b/crates/devcontainer-rs/src/container.rs @@ -1,20 +1,20 @@ -//! Container lifecycle primitives for a parsed [`DevContainer`]. +//! Primitives de cycle de vie de container pour un [`DevContainer`] analysé. //! -//! This module shells out to a container runtime (`docker` or `podman`) to build -//! the devcontainer image, start a container with the workspace mounted, run the -//! `postCreateCommand` / `postStartCommand` hooks and execute commands inside the -//! running container. +//! Ce module invoque un runtime de containers (`docker` ou `podman`) pour construire +//! l'image devcontainer, démarrer un container avec le workspace monté, exécuter les +//! hooks `postCreateCommand` / `postStartCommand` et lancer des commandes à l'intérieur +//! du container en cours d'exécution. //! -//! It is intentionally runtime-agnostic: any binary exposing the `docker` CLI -//! surface (including `podman`) can be used via [`ContainerRuntime::new`]. +//! Il est volontairement agnostique du runtime : tout binaire exposant l'interface +//! CLI `docker` (y compris `podman`) peut être utilisé via [`ContainerRuntime::new`]. //! //! # Isolation //! -//! Each sandbox gets its own image tag, its own container and its own network. -//! The container starts attached to that network so the `postCreateCommand` / -//! `postStartCommand` hooks can fetch dependencies (e.g. `npm install`); once the -//! hooks have run, the container is disconnected from the network for the rest of -//! its lifetime. Every command is bounded by a timeout. +//! Chaque sandbox dispose de son propre tag d'image, de son propre container et de +//! son propre réseau. Le container démarre attaché à ce réseau afin que les hooks +//! `postCreateCommand` / `postStartCommand` puissent récupérer des dépendances +//! (par ex. `npm install`) ; une fois les hooks exécutés, le container est déconnecté +//! du réseau pour le reste de sa durée de vie. Chaque commande est bornée par un timeout. use std::{ path::{Path, PathBuf}, @@ -26,16 +26,16 @@ use tokio::process::Command; use crate::DevContainer; -/// Timeout applied to build/run/stop/remove operations. +/// Timeout appliqué aux opérations de build/run/stop/remove. const DEFAULT_COMMAND_TIMEOUT: Duration = Duration::from_secs(600); -/// Timeout applied to commands executed inside a running container. +/// Timeout appliqué aux commandes exécutées dans un container en cours d'exécution. const DEFAULT_EXEC_TIMEOUT: Duration = Duration::from_secs(60); -/// Result of a command executed inside a container. +/// Résultat d'une commande exécutée dans un container. #[derive(Debug, Clone)] pub struct ExecOutput { - /// Exit code, or `-1` if the process was terminated by a signal. + /// Code de sortie, ou `-1` si le processus a été terminé par un signal. pub status: i32, pub stdout: String, pub stderr: String, @@ -46,7 +46,7 @@ impl ExecOutput { self.status == 0 } - /// Turns a non-zero exit code into a [`ContainerError::Command`]. + /// Transforme un code de sortie non nul en [`ContainerError::Command`]. pub fn ensure_success(self, program: &str, args: &[String]) -> Result { if self.success() { return Ok(self); @@ -85,7 +85,7 @@ pub enum ContainerError { }, } -/// A container runtime binary exposing the `docker` CLI surface. +/// Un binaire de runtime de containers exposant l'interface CLI `docker`. #[derive(Debug, Clone)] pub struct ContainerRuntime { program: String, @@ -108,7 +108,7 @@ impl ContainerRuntime { Self::new("podman") } - /// Overrides the timeout applied to build/run/stop/remove operations. + /// Remplace le timeout appliqué aux opérations de build/run/stop/remove. pub fn with_timeout(mut self, timeout: Duration) -> Self { self.timeout = timeout; self @@ -122,7 +122,7 @@ impl ContainerRuntime { self.timeout } - /// Checks that the runtime binary is present and responsive. + /// Vérifie que le binaire du runtime est présent et répond. pub async fn available(&self) -> bool { Command::new(&self.program) .arg("version") @@ -135,15 +135,15 @@ impl ContainerRuntime { .unwrap_or(false) } - /// Runs the runtime with the given arguments, capturing stdout/stderr. + /// Exécute le runtime avec les arguments donnés, en capturant stdout/stderr. /// - /// Only spawn failures and timeouts are reported as errors; a non-zero exit - /// code is returned in the [`ExecOutput`] so callers can decide how to react. + /// Seuls les échecs de lancement (spawn) et les timeouts sont des erreurs ; un + /// code non nul est renvoyé dans [`ExecOutput`] afin que les appelants réagissent. pub async fn run(&self, args: &[String]) -> Result { self.run_with_timeout(args, self.timeout).await } - /// Like [`run`](Self::run) with an explicit timeout. + /// Comme [`run`](Self::run), mais avec un timeout explicite. pub async fn run_with_timeout( &self, args: &[String], @@ -174,7 +174,7 @@ impl ContainerRuntime { } } -/// A running devcontainer. +/// Un devcontainer en cours d'exécution. #[derive(Debug, Clone)] pub struct Container { runtime: ContainerRuntime, @@ -194,10 +194,10 @@ impl Container { &self.workspace_folder } - /// Executes a command inside the container, returning its output. + /// Exécute une commande dans le container et renvoie sa sortie. /// - /// The command is passed as an argv vector (no shell), so no quoting or - /// interpolation is performed. + /// La commande est transmise sous forme de vecteur d'arguments (argv, sans shell), + /// donc aucun échappement ni interpolation n'est effectué. pub async fn exec(&self, cmd: &[&str]) -> Result { self.exec_with_timeout(cmd, DEFAULT_EXEC_TIMEOUT).await } @@ -220,12 +220,12 @@ impl Container { self.runtime.run_with_timeout(&args, timeout).await } - /// Executes a shell script inside the container via `sh -c`. + /// Exécute un script shell dans le container via `sh -c`. pub async fn exec_shell(&self, script: &str) -> Result { self.exec(&["sh", "-c", script]).await } - /// Stops the container. + /// Arrête le container. pub async fn stop(&self) -> Result<(), ContainerError> { let args = vec!["stop".to_string(), self.name.clone()]; self.runtime @@ -235,9 +235,9 @@ impl Container { Ok(()) } - /// Removes the container, its network and its image. + /// Supprime le container, son réseau et son image. /// - /// Network and image removal are best-effort: they may already be gone. + /// La suppression du réseau et de l'image est best-effort : ils peuvent déjà être absents. pub async fn remove(&self) -> Result<(), ContainerError> { let args = vec![ "rm".to_string(), @@ -265,21 +265,21 @@ impl Container { } impl DevContainer { - /// Base image name derived from the devcontainer name. + /// Nom de l'image de base dérivé du nom du devcontainer. pub fn image_name(&self) -> String { let base = self.name.as_deref().unwrap_or("devcontainer"); format!("devcontainer-rs/{}", sanitize(base)) } - /// Unique image tag for a single sandbox run. + /// Tag d'image unique pour une exécution de sandbox donnée. /// - /// Uniqueness matters: two concurrent sandboxes (possibly for different - /// repositories sharing a devcontainer name) must not race on a shared tag. + /// L'unicité est importante : deux sandboxes concurrentes (éventuellement pour des + /// dépôts différents partageant un nom de devcontainer) ne doivent pas se disputer le même tag. pub fn image_tag(&self) -> String { format!("{}:{}", self.image_name(), unique_suffix()) } - /// Arguments passed to `docker build` (everything after the `build` verb). + /// Arguments passés à `docker build` (tout ce qui suit le verbe `build`). pub fn build_args(&self, image_tag: &str) -> Vec { let context = self .container_file_path @@ -302,7 +302,7 @@ impl DevContainer { args } - /// Arguments passed to `docker run` (everything after the `run` verb). + /// Arguments passés à `docker run` (tout ce qui suit le verbe `run`). pub fn run_args( &self, workspace_dir: &Path, @@ -340,27 +340,27 @@ impl DevContainer { args.extend(self.run_args.iter().cloned()); args.push(image_tag.to_string()); - // Keep the container alive so we can `exec` into it. + // Maintient le container en vie pour pouvoir y exécuter `exec`. args.push("sleep".to_string()); args.push("infinity".to_string()); args } - /// Workspace folder inside the container, defaulting to `/workspaces/workspace`. + /// Dossier de workspace dans le container, par défaut `/workspaces/workspace`. pub fn workspace_folder(&self) -> String { self.workspace_folder .clone() .unwrap_or_else(|| "/workspaces/workspace".to_string()) } - /// Unique container name for this run. + /// Nom de container unique pour cette exécution. pub fn container_name(&self) -> String { let base = self.name.as_deref().unwrap_or("devcontainer"); format!("devcontainer-rs-{}-{}", sanitize(base), unique_suffix()) } - /// Builds the devcontainer image under `image_tag`. + /// Construit l'image devcontainer sous `image_tag`. pub async fn build( &self, runtime: &ContainerRuntime, @@ -377,12 +377,12 @@ impl DevContainer { Ok(()) } - /// Builds the image, starts the container with the workspace mounted, runs - /// the `postCreateCommand` / `postStartCommand` hooks with network access, - /// then disconnects the container from the network. + /// Construit l'image, démarre le container avec le workspace monté, exécute les + /// hooks `postCreateCommand` / `postStartCommand` avec accès au réseau, puis + /// déconnecte le container du réseau. /// - /// On any failure the container, network and image are cleaned up before - /// returning, so no resource is leaked. + /// En cas d'échec, le container, le réseau et l'image sont nettoyés avant de + /// renvoyer l'erreur, afin qu'aucune ressource ne soit laissée en place. pub async fn up( &self, runtime: &ContainerRuntime, @@ -394,7 +394,7 @@ impl DevContainer { let name = self.container_name(); let network = format!("{name}-net"); - // Dedicated network so connectivity can be cut after the hooks. + // Réseau dédié afin de pouvoir couper la connectivité après les hooks. let args = vec!["network".to_string(), "create".to_string(), network.clone()]; if let Err(err) = runtime .run(&args) @@ -429,13 +429,13 @@ impl DevContainer { image: Some(image_tag), }; - // Hooks run with network access (dependency installation, etc.). + // Les hooks s'exécutent avec accès au réseau (installation de dépendances, etc.). if let Err(err) = self.run_hooks(&container).await { let _ = container.remove().await; return Err(err); } - // Cut network access for the rest of the sandbox lifetime. + // Coupe l'accès réseau pour le reste de la durée de vie de la sandbox. let args = vec![ "network".to_string(), "disconnect".to_string(), @@ -455,8 +455,8 @@ impl DevContainer { } async fn run_hooks(&self, container: &Container) -> Result<(), ContainerError> { - // Hooks may install dependencies, so they get the long command timeout - // rather than the short one used for tool execution. + // Les hooks peuvent installer des dépendances, ils utilisent donc le timeout + // long des commandes plutôt que le court réservé à l'exécution des outils. let timeout = container.runtime.timeout(); for command in [&self.post_create_command, &self.post_start_command] @@ -476,7 +476,7 @@ impl DevContainer { } } -/// Sanitizes a string so it can be used as a docker image/container name. +/// Nettoie une chaîne pour qu'elle puisse servir de nom d'image/container docker. fn sanitize(input: &str) -> String { let sanitized: String = input .chars() @@ -497,7 +497,7 @@ fn sanitize(input: &str) -> String { } } -/// Suffix unique to a sandbox run, combining the process id and a timestamp. +/// Suffixe unique à une exécution de sandbox, combinant l'identifiant de processus et un horodatage. fn unique_suffix() -> String { let nanos = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -507,8 +507,8 @@ fn unique_suffix() -> String { format!("{}-{}", std::process::id(), nanos) } -/// Lexically normalizes a path, resolving `.` and `..` without touching the -/// filesystem. Returns `None` if the path escapes its root. +/// Normalise lexicalement un chemin, en résolvant `.` et `..` sans toucher au +/// système de fichiers. Renvoie `None` si le chemin sort de sa racine. pub fn normalize(path: &Path) -> Option { use std::path::Component; diff --git a/crates/devcontainer-rs/src/lib.rs b/crates/devcontainer-rs/src/lib.rs index 8743f0a..67914b9 100644 --- a/crates/devcontainer-rs/src/lib.rs +++ b/crates/devcontainer-rs/src/lib.rs @@ -119,9 +119,9 @@ impl TryFrom<(DevContainerSchema, PathBuf)> for DevContainer { } } -/// Resolves `${localEnv:VAR}` and `${localEnv:VAR:default}` references using the -/// current process environment, as described by the devcontainer specification. -/// Unresolved variables without a default expand to an empty string. +/// Résout les références `${localEnv:VAR}` et `${localEnv:VAR:default}` à l'aide de +/// l'environnement du processus courant, comme décrit par la spécification devcontainer. +/// Les variables non résolues sans valeur par défaut sont remplacées par une chaîne vide. fn substitute_local_env(input: &str) -> String { const PREFIX: &str = "${localEnv:";