From be92c3ff6e027a318dcf00f0ab44255fde13dbe1 Mon Sep 17 00:00:00 2001 From: Sergio Medina Date: Thu, 22 Jun 2023 16:15:19 +0100 Subject: [PATCH 1/2] Allow to run arbitrary commands in conainers using cross-util run ... --- CHANGELOG.md | 2 + src/bin/commands/mod.rs | 2 + src/bin/commands/run.rs | 108 ++++++++++++++++++++++++++++++++++++++++ src/bin/cross-util.rs | 7 +++ src/docker/image.rs | 2 +- src/docker/local.rs | 4 +- src/docker/mod.rs | 6 ++- src/docker/remote.rs | 59 ++++++++++++---------- src/docker/shared.rs | 2 +- src/lib.rs | 19 +++++-- 10 files changed, 173 insertions(+), 38 deletions(-) create mode 100644 src/bin/commands/run.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f4e09d48e..4ac2e5807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate +- #1266 Allow to run arbitrary commands in containers using `cross-util run --target --command ` + ## [v0.2.5] - 2023-02-04 ## Fixed diff --git a/src/bin/commands/mod.rs b/src/bin/commands/mod.rs index 30a1c771a..2f63ea608 100644 --- a/src/bin/commands/mod.rs +++ b/src/bin/commands/mod.rs @@ -1,7 +1,9 @@ mod clean; mod containers; mod images; +mod run; pub use self::clean::*; pub use self::containers::*; pub use self::images::*; +pub use self::run::*; diff --git a/src/bin/commands/run.rs b/src/bin/commands/run.rs new file mode 100644 index 000000000..d331b3748 --- /dev/null +++ b/src/bin/commands/run.rs @@ -0,0 +1,108 @@ +use clap::Args as ClapArgs; +use cross::config::Config; +use cross::shell::{MessageInfo, Verbosity}; +use cross::SafeCommand; +use cross::{ + cargo_metadata_with_args, cli::Args, docker, rustc, setup, toml, CargoVariant, CrossSetup, + Target, +}; +use eyre::Context; + +#[derive(ClapArgs, Debug)] +pub struct Run { + /// Provide verbose diagnostic output. + #[clap(short, long)] + pub verbose: bool, + /// Do not print cross log messages. + #[clap(short, long)] + pub quiet: bool, + /// Coloring: auto, always, never + #[clap(long)] + pub color: Option, + /// Container engine (such as docker or podman). + #[clap(long)] + pub engine: Option, + + #[clap(short, long)] + pub target: String, + + #[clap(short, long)] + pub command: String, +} + +impl Run { + pub fn run(&self, engine: docker::Engine, msg_info: &mut MessageInfo) -> cross::Result<()> { + let target_list = rustc::target_list(&mut Verbosity::Quiet.into())?; + let target = Target::from(&self.target, &target_list); + + let cwd = std::env::current_dir()?; + let host_version_meta = rustc::version_meta()?; + + let args = Args { + cargo_args: vec![], + rest_args: vec![], + subcommand: None, + channel: None, + target: Some(target.clone()), + features: vec![], + target_dir: None, + manifest_path: None, + version: false, + verbose: if self.verbose { 1 } else { 0 }, + quiet: self.quiet, + color: self.color.clone(), + }; + + if let Some(metadata) = cargo_metadata_with_args(None, Some(&args), msg_info)? { + let CrossSetup { toolchain, .. } = + match setup(&host_version_meta, &metadata, &args, target_list, msg_info)? { + Some(setup) => setup, + _ => { + eyre::bail!("Error: cannot setup cross environment"); + } + }; + + let toml = toml(&metadata, msg_info)?; + let config = Config::new(toml); + + let image = match docker::get_image(&config, &target, false) { + Ok(i) => i, + Err(err) => { + msg_info.warn(&err)?; + eyre::bail!("Error: {}", &err); + } + }; + + let image = image.to_definite_with(&engine, msg_info); + + let paths = docker::DockerPaths::create(&engine, metadata, cwd, toolchain, msg_info)?; + let options = + docker::DockerOptions::new(engine, target, config, image, CargoVariant::None, None); + + let command = SafeCommand::new("sh"); + let mut args = vec![String::from("-c")]; + args.push(self.command.clone()); + + docker::run(options, paths, command, &args, None, msg_info) + .wrap_err("could not run container")?; + } + + Ok(()) + } + + pub fn engine(&self) -> Option<&str> { + self.engine.as_deref() + } + + pub fn verbose(&self) -> bool { + self.verbose + } + + pub fn quiet(&self) -> bool { + self.quiet + } + + pub fn color(&self) -> Option<&str> { + self.color.as_deref() + } +} diff --git a/src/bin/cross-util.rs b/src/bin/cross-util.rs index cc90a6824..df5f67a96 100644 --- a/src/bin/cross-util.rs +++ b/src/bin/cross-util.rs @@ -37,6 +37,8 @@ enum Commands { /// Work with cross containers in local storage. #[clap(subcommand)] Containers(commands::Containers), + /// Run in cross container. + Run(commands::Run), /// Clean all cross data in local storage. Clean(commands::Clean), } @@ -103,6 +105,11 @@ pub fn main() -> cross::Result<()> { let engine = get_engine!(args, false, msg_info)?; args.run(engine, &mut msg_info)?; } + Commands::Run(args) => { + let mut msg_info = get_msg_info!(args)?; + let engine = get_engine!(args, false, msg_info)?; + args.run(engine, &mut msg_info)?; + } } Ok(()) diff --git a/src/docker/image.rs b/src/docker/image.rs index 4ff4562bb..ae5429c9c 100644 --- a/src/docker/image.rs +++ b/src/docker/image.rs @@ -27,7 +27,7 @@ pub struct PossibleImage { } impl PossibleImage { - pub(crate) fn to_definite_with(&self, engine: &Engine, msg_info: &mut MessageInfo) -> Image { + pub fn to_definite_with(&self, engine: &Engine, msg_info: &mut MessageInfo) -> Image { if self.toolchain.is_empty() { Image { name: self.name.clone(), diff --git a/src/docker/local.rs b/src/docker/local.rs index 5b8ec195a..f46032ede 100644 --- a/src/docker/local.rs +++ b/src/docker/local.rs @@ -5,7 +5,7 @@ use std::sync::atomic::Ordering; use super::shared::*; use crate::errors::Result; -use crate::extensions::CommandExt; +use crate::extensions::{CommandExt, SafeCommand}; use crate::file::{PathExt, ToUtf8}; use crate::shell::{MessageInfo, Stream}; use eyre::Context; @@ -29,6 +29,7 @@ fn mount( pub(crate) fn run( options: DockerOptions, paths: DockerPaths, + mut cmd: SafeCommand, args: &[String], msg_info: &mut MessageInfo, ) -> Result { @@ -36,7 +37,6 @@ pub(crate) fn run( let toolchain_dirs = paths.directories.toolchain_directories(); let package_dirs = paths.directories.package_directories(); - let mut cmd = options.cargo_variant.safe_command(); cmd.args(args); let mut docker = engine.subcommand("run"); diff --git a/src/docker/mod.rs b/src/docker/mod.rs index 7be9790e4..55c95e858 100644 --- a/src/docker/mod.rs +++ b/src/docker/mod.rs @@ -17,6 +17,7 @@ pub use image::{Architecture, Image, ImagePlatform, Os as ContainerOs, PossibleI use std::process::ExitStatus; use crate::errors::*; +use crate::extensions::SafeCommand; use crate::shell::MessageInfo; #[derive(Debug)] @@ -44,6 +45,7 @@ pub fn image_name(target: &str, sub: Option<&str>, repository: &str, tag: &str) pub fn run( options: DockerOptions, paths: DockerPaths, + command: SafeCommand, args: &[String], subcommand: Option, msg_info: &mut MessageInfo, @@ -55,9 +57,9 @@ pub fn run( ); } if options.is_remote() { - remote::run(options, paths, args, subcommand, msg_info) + remote::run(options, paths, command, args, subcommand, msg_info) .wrap_err("could not complete remote run") } else { - local::run(options, paths, args, msg_info) + local::run(options, paths, command, args, msg_info) } } diff --git a/src/docker/remote.rs b/src/docker/remote.rs index b3a4eed57..8e4f459e5 100644 --- a/src/docker/remote.rs +++ b/src/docker/remote.rs @@ -10,12 +10,12 @@ use super::engine::Engine; use super::shared::*; use crate::config::bool_from_envvar; use crate::errors::Result; -use crate::extensions::CommandExt; +use crate::extensions::{CommandExt, SafeCommand}; use crate::file::{self, PathExt, ToUtf8}; use crate::rustc::{self, QualifiedToolchain, VersionMetaExt}; use crate::shell::{MessageInfo, Stream}; -use crate::temp; use crate::TargetTriple; +use crate::{temp, CargoVariant}; // prevent further commands from running if we handled // a signal earlier, and the volume is exited. @@ -667,6 +667,7 @@ impl QualifiedToolchain { pub(crate) fn run( options: DockerOptions, paths: DockerPaths, + mut cmd: SafeCommand, args: &[String], subcommand: Option, msg_info: &mut MessageInfo, @@ -895,34 +896,38 @@ pub(crate) fn run( } } - // `clean` doesn't handle symlinks: it will just unlink the target - // directory, so we should just substitute it our target directory - // for it. we'll still have the same end behavior - let mut final_args = vec![]; - let mut iter = args.iter().cloned(); - let mut has_target_dir = false; - while let Some(arg) = iter.next() { - if arg == "--target-dir" { - has_target_dir = true; - final_args.push(arg); - if iter.next().is_some() { - final_args.push(target_dir.clone()); - } - } else if arg.starts_with("--target-dir=") { - has_target_dir = true; - if arg.split_once('=').is_some() { - final_args.push(format!("--target-dir={target_dir}")); + if options.cargo_variant != CargoVariant::None { + // `clean` doesn't handle symlinks: it will just unlink the target + // directory, so we should just substitute it our target directory + // for it. we'll still have the same end behavior + let mut final_args = vec![]; + let mut iter = args.iter().cloned(); + let mut has_target_dir = false; + while let Some(arg) = iter.next() { + if arg == "--target-dir" { + has_target_dir = true; + final_args.push(arg); + if iter.next().is_some() { + final_args.push(target_dir.clone()); + } + } else if arg.starts_with("--target-dir=") { + has_target_dir = true; + if arg.split_once('=').is_some() { + final_args.push(format!("--target-dir={target_dir}")); + } + } else { + final_args.push(arg); } - } else { - final_args.push(arg); } + if !has_target_dir && subcommand.map_or(true, |s| s.needs_target_in_command()) { + final_args.push("--target-dir".to_owned()); + final_args.push(target_dir.clone()); + } + + cmd.args(final_args); + } else { + cmd.args(args); } - if !has_target_dir && subcommand.map_or(true, |s| s.needs_target_in_command()) { - final_args.push("--target-dir".to_owned()); - final_args.push(target_dir.clone()); - } - let mut cmd = options.cargo_variant.safe_command(); - cmd.args(final_args); // 5. create symlinks for copied data let mut symlink = vec!["set -e pipefail".to_owned()]; diff --git a/src/docker/shared.rs b/src/docker/shared.rs index 314a0c657..c8dcad439 100644 --- a/src/docker/shared.rs +++ b/src/docker/shared.rs @@ -1271,7 +1271,7 @@ pub fn get_image_name(config: &Config, target: &Target, uses_zig: bool) -> Resul .image_name(CROSS_IMAGE, version)) } -pub(crate) fn get_image(config: &Config, target: &Target, uses_zig: bool) -> Result { +pub fn get_image(config: &Config, target: &Target, uses_zig: bool) -> Result { if let Some(image) = config.image(target)? { return Ok(image); } diff --git a/src/lib.rs b/src/lib.rs index b89fbdd18..8aeb98a75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ use self::errors::Context; use self::shell::{MessageInfo, Verbosity}; pub use self::errors::{install_panic_hook, install_termination_hook, Result}; -pub use self::extensions::{CommandExt, OutputExt}; +pub use self::extensions::{CommandExt, OutputExt, SafeCommand}; pub use self::file::{pretty_path, ToUtf8}; pub use self::rustc::{TargetList, VersionMetaExt}; @@ -447,6 +447,7 @@ pub enum CargoVariant { Cargo, Xargo, Zig, + None, } impl CargoVariant { @@ -464,6 +465,7 @@ impl CargoVariant { CargoVariant::Cargo => "cargo", CargoVariant::Xargo => "xargo", CargoVariant::Zig => "cargo-zigbuild", + CargoVariant::None => "", } } @@ -615,9 +617,16 @@ pub fn run( &options, msg_info, )?; - - let status = docker::run(options, paths, &filtered_args, args.subcommand, msg_info) - .wrap_err("could not run container")?; + let cmd = options.cargo_variant.safe_command(); + let status = docker::run( + options, + paths, + cmd, + &filtered_args, + args.subcommand, + msg_info, + ) + .wrap_err("could not run container")?; let needs_host = args.subcommand.map_or(false, |sc| sc.needs_host(is_remote)); if !status.success() { warn_on_failure(&target, &toolchain, msg_info)?; @@ -864,7 +873,7 @@ macro_rules! commit_info { /// /// The values from `CROSS_CONFIG` or `Cross.toml` are concatenated with the package /// metadata in `Cargo.toml`, with `Cross.toml` having the highest priority. -fn toml(metadata: &CargoMetadata, msg_info: &mut MessageInfo) -> Result> { +pub fn toml(metadata: &CargoMetadata, msg_info: &mut MessageInfo) -> Result> { let root = &metadata.workspace_root; let cross_config_path = match env::var("CROSS_CONFIG") { Ok(var) => PathBuf::from(var), From 1aab4cf835847f20a142f4ae1fedbe9778aa0506 Mon Sep 17 00:00:00 2001 From: Sergio Medina Date: Fri, 23 Jun 2023 11:42:27 +0100 Subject: [PATCH 2/2] Add interactive mode to `cross-util run` --- .changes/1280.json | 6 ++++++ CHANGELOG.md | 2 -- src/bin/commands/run.rs | 26 +++++++++++++++--------- src/docker/custom.rs | 2 +- src/docker/local.rs | 9 +++++++-- src/docker/mod.rs | 6 ++---- src/docker/remote.rs | 14 +++++++++---- src/docker/shared.rs | 17 +++++++++------- src/lib.rs | 45 +++++++++++++++++++---------------------- 9 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 .changes/1280.json diff --git a/.changes/1280.json b/.changes/1280.json new file mode 100644 index 000000000..e06cce5d5 --- /dev/null +++ b/.changes/1280.json @@ -0,0 +1,6 @@ +{ + "description": "Allow to run arbitrary commands in containers using `cross-util run ...`", + "issues": [1266], + "type": "added", + "breaking": false +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ac2e5807..f4e09d48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -- #1266 Allow to run arbitrary commands in containers using `cross-util run --target --command ` - ## [v0.2.5] - 2023-02-04 ## Fixed diff --git a/src/bin/commands/run.rs b/src/bin/commands/run.rs index d331b3748..08c1aad65 100644 --- a/src/bin/commands/run.rs +++ b/src/bin/commands/run.rs @@ -1,9 +1,8 @@ use clap::Args as ClapArgs; use cross::config::Config; use cross::shell::{MessageInfo, Verbosity}; -use cross::SafeCommand; use cross::{ - cargo_metadata_with_args, cli::Args, docker, rustc, setup, toml, CargoVariant, CrossSetup, + cargo_metadata_with_args, cli::Args, docker, rustc, setup, toml, CommandVariant, CrossSetup, Target, }; use eyre::Context; @@ -22,11 +21,14 @@ pub struct Run { /// Container engine (such as docker or podman). #[clap(long)] pub engine: Option, - + /// Target #[clap(short, long)] pub target: String, - - #[clap(short, long)] + /// Interactive session + #[clap(short, long, default_value = "false")] + pub interactive: bool, + /// Command to run, will be run in a shell + #[clap(last = true)] pub command: String, } @@ -76,14 +78,20 @@ impl Run { let image = image.to_definite_with(&engine, msg_info); let paths = docker::DockerPaths::create(&engine, metadata, cwd, toolchain, msg_info)?; - let options = - docker::DockerOptions::new(engine, target, config, image, CargoVariant::None, None); + let options = docker::DockerOptions::new( + engine, + target, + config, + image, + CommandVariant::Shell, + None, + self.interactive, + ); - let command = SafeCommand::new("sh"); let mut args = vec![String::from("-c")]; args.push(self.command.clone()); - docker::run(options, paths, command, &args, None, msg_info) + docker::run(options, paths, &args, None, msg_info) .wrap_err("could not run container")?; } diff --git a/src/docker/custom.rs b/src/docker/custom.rs index 841f72bf1..d71825710 100644 --- a/src/docker/custom.rs +++ b/src/docker/custom.rs @@ -85,7 +85,7 @@ impl<'a> Dockerfile<'a> { build_args: impl IntoIterator, impl AsRef)>, msg_info: &mut MessageInfo, ) -> Result { - let uses_zig = options.cargo_variant.uses_zig(); + let uses_zig = options.command_variant.uses_zig(); let mut docker_build = options.engine.command(); docker_build.invoke_build_command(); docker_build.disable_scan_suggest(); diff --git a/src/docker/local.rs b/src/docker/local.rs index f46032ede..4f3653459 100644 --- a/src/docker/local.rs +++ b/src/docker/local.rs @@ -5,7 +5,7 @@ use std::sync::atomic::Ordering; use super::shared::*; use crate::errors::Result; -use crate::extensions::{CommandExt, SafeCommand}; +use crate::extensions::CommandExt; use crate::file::{PathExt, ToUtf8}; use crate::shell::{MessageInfo, Stream}; use eyre::Context; @@ -29,7 +29,6 @@ fn mount( pub(crate) fn run( options: DockerOptions, paths: DockerPaths, - mut cmd: SafeCommand, args: &[String], msg_info: &mut MessageInfo, ) -> Result { @@ -37,6 +36,7 @@ pub(crate) fn run( let toolchain_dirs = paths.directories.toolchain_directories(); let package_dirs = paths.directories.package_directories(); + let mut cmd = options.command_variant.safe_command(); cmd.args(args); let mut docker = engine.subcommand("run"); @@ -134,6 +134,11 @@ pub(crate) fn run( if io::Stdin::is_atty() && io::Stdout::is_atty() && io::Stderr::is_atty() { docker.arg("-t"); } + + if options.interactive { + docker.arg("-i"); + } + let mut image_name = options.image.name.clone(); if options.needs_custom_image() { image_name = options diff --git a/src/docker/mod.rs b/src/docker/mod.rs index 55c95e858..7be9790e4 100644 --- a/src/docker/mod.rs +++ b/src/docker/mod.rs @@ -17,7 +17,6 @@ pub use image::{Architecture, Image, ImagePlatform, Os as ContainerOs, PossibleI use std::process::ExitStatus; use crate::errors::*; -use crate::extensions::SafeCommand; use crate::shell::MessageInfo; #[derive(Debug)] @@ -45,7 +44,6 @@ pub fn image_name(target: &str, sub: Option<&str>, repository: &str, tag: &str) pub fn run( options: DockerOptions, paths: DockerPaths, - command: SafeCommand, args: &[String], subcommand: Option, msg_info: &mut MessageInfo, @@ -57,9 +55,9 @@ pub fn run( ); } if options.is_remote() { - remote::run(options, paths, command, args, subcommand, msg_info) + remote::run(options, paths, args, subcommand, msg_info) .wrap_err("could not complete remote run") } else { - local::run(options, paths, command, args, msg_info) + local::run(options, paths, args, msg_info) } } diff --git a/src/docker/remote.rs b/src/docker/remote.rs index 8e4f459e5..9a6d3185b 100644 --- a/src/docker/remote.rs +++ b/src/docker/remote.rs @@ -10,12 +10,12 @@ use super::engine::Engine; use super::shared::*; use crate::config::bool_from_envvar; use crate::errors::Result; -use crate::extensions::{CommandExt, SafeCommand}; +use crate::extensions::CommandExt; use crate::file::{self, PathExt, ToUtf8}; use crate::rustc::{self, QualifiedToolchain, VersionMetaExt}; use crate::shell::{MessageInfo, Stream}; +use crate::temp; use crate::TargetTriple; -use crate::{temp, CargoVariant}; // prevent further commands from running if we handled // a signal earlier, and the volume is exited. @@ -667,7 +667,6 @@ impl QualifiedToolchain { pub(crate) fn run( options: DockerOptions, paths: DockerPaths, - mut cmd: SafeCommand, args: &[String], subcommand: Option, msg_info: &mut MessageInfo, @@ -896,7 +895,9 @@ pub(crate) fn run( } } - if options.cargo_variant != CargoVariant::None { + let mut cmd = options.command_variant.safe_command(); + + if !options.command_variant.is_shell() { // `clean` doesn't handle symlinks: it will just unlink the target // directory, so we should just substitute it our target directory // for it. we'll still have the same end behavior @@ -976,6 +977,11 @@ symlink_recurse \"${{prefix}}\" docker.add_cwd(&paths)?; docker.arg(&container_id); docker.add_build_command(toolchain_dirs, &cmd); + + if options.interactive { + docker.arg("-i"); + } + bail_container_exited!(); let status = docker .run_and_get_status(msg_info, false) diff --git a/src/docker/shared.rs b/src/docker/shared.rs index c8dcad439..83ec3bfc9 100644 --- a/src/docker/shared.rs +++ b/src/docker/shared.rs @@ -17,7 +17,7 @@ use crate::file::{self, write_file, PathExt, ToUtf8}; use crate::id; use crate::rustc::QualifiedToolchain; use crate::shell::{ColorChoice, MessageInfo, Verbosity}; -use crate::{CargoVariant, OutputExt, Target, TargetTriple}; +use crate::{CommandVariant, OutputExt, Target, TargetTriple}; use rustc_version::Version as RustcVersion; @@ -33,9 +33,10 @@ pub struct DockerOptions { pub target: Target, pub config: Config, pub image: Image, - pub cargo_variant: CargoVariant, + pub command_variant: CommandVariant, // not all toolchains will provide this pub rustc_version: Option, + pub interactive: bool, } impl DockerOptions { @@ -44,16 +45,18 @@ impl DockerOptions { target: Target, config: Config, image: Image, - cargo_variant: CargoVariant, + cargo_variant: CommandVariant, rustc_version: Option, + interactive: bool, ) -> DockerOptions { DockerOptions { engine, target, config, image, - cargo_variant, + command_variant: cargo_variant, rustc_version, + interactive, } } @@ -928,8 +931,8 @@ fn validate_env_var<'a>( Ok((key, value)) } -impl CargoVariant { - pub(crate) fn safe_command(self) -> SafeCommand { +impl CommandVariant { + pub(crate) fn safe_command(&self) -> SafeCommand { SafeCommand::new(self.to_str()) } } @@ -1041,7 +1044,7 @@ impl DockerCommandExt for Command { ]) .args(["-e", "CARGO_TARGET_DIR=/target"]) .args(["-e", &cross_runner]); - if options.cargo_variant.uses_zig() { + if options.command_variant.uses_zig() { // otherwise, zig has a permission error trying to create the cache self.args(["-e", "XDG_CACHE_HOME=/target/.zig-cache"]); } diff --git a/src/lib.rs b/src/lib.rs index 8aeb98a75..a7964b31f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -443,38 +443,42 @@ impl Serialize for Target { } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CargoVariant { +pub enum CommandVariant { Cargo, Xargo, Zig, - None, + Shell, } -impl CargoVariant { - pub fn create(uses_zig: bool, uses_xargo: bool) -> Result { +impl CommandVariant { + pub fn create(uses_zig: bool, uses_xargo: bool) -> Result { match (uses_zig, uses_xargo) { (true, true) => eyre::bail!("cannot use both zig and xargo"), - (true, false) => Ok(CargoVariant::Zig), - (false, true) => Ok(CargoVariant::Xargo), - (false, false) => Ok(CargoVariant::Cargo), + (true, false) => Ok(CommandVariant::Zig), + (false, true) => Ok(CommandVariant::Xargo), + (false, false) => Ok(CommandVariant::Cargo), } } pub fn to_str(self) -> &'static str { match self { - CargoVariant::Cargo => "cargo", - CargoVariant::Xargo => "xargo", - CargoVariant::Zig => "cargo-zigbuild", - CargoVariant::None => "", + CommandVariant::Cargo => "cargo", + CommandVariant::Xargo => "xargo", + CommandVariant::Zig => "cargo-zigbuild", + CommandVariant::Shell => "sh", } } pub fn uses_xargo(self) -> bool { - self == CargoVariant::Xargo + self == CommandVariant::Xargo } pub fn uses_zig(self) -> bool { - self == CargoVariant::Zig + self == CommandVariant::Zig + } + + pub(crate) fn is_shell(self) -> bool { + self == CommandVariant::Shell } } @@ -606,8 +610,9 @@ pub fn run( target.clone(), config, image, - crate::CargoVariant::create(uses_zig, uses_xargo)?, + crate::CommandVariant::create(uses_zig, uses_xargo)?, rustc_version, + false, ); install_interpreter_if_needed( @@ -617,16 +622,8 @@ pub fn run( &options, msg_info, )?; - let cmd = options.cargo_variant.safe_command(); - let status = docker::run( - options, - paths, - cmd, - &filtered_args, - args.subcommand, - msg_info, - ) - .wrap_err("could not run container")?; + let status = docker::run(options, paths, &filtered_args, args.subcommand, msg_info) + .wrap_err("could not run container")?; let needs_host = args.subcommand.map_or(false, |sc| sc.needs_host(is_remote)); if !status.success() { warn_on_failure(&target, &toolchain, msg_info)?;