You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.9 KiB

use super::command::Command as Cmd;
use crate::choose_version_for_user_input::choose_version_for_user_input;
use crate::choose_version_for_user_input::Error as UserInputError;
use crate::config::FnmConfig;
use crate::outln;
use crate::user_version::UserVersion;
use crate::version_files::get_user_version_from_file;
use colored::Colorize;
use snafu::{OptionExt, ResultExt, Snafu};
use std::process::{Command, Stdio};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct Exec {
binary: String,
arguments: Vec<String>,
#[structopt(long = "using")]
version: Option<UserVersion>,
/// Deprecated. This is the default now.
#[structopt(long = "using-file", hidden = true)]
using_file: bool,
}
impl Cmd for Exec {
type Error = Error;
fn apply(self, config: &FnmConfig) -> Result<(), Self::Error> {
if self.using_file {
outln!(config#Error, "{} {} is deprecated. This is now the default.", "warning:".yellow().bold(), "--using-file".italic());
}
let version = self
.version
.or_else(|| {
let current_dir = std::env::current_dir().unwrap();
get_user_version_from_file(current_dir)
})
.context(CantInferVersion)?;
let applicable_version = choose_version_for_user_input(&version, &config)
.context(ApplicableVersionError)?
.context(VersionNotFound { version })?;
#[cfg(windows)]
let bin_path = applicable_version.path().to_path_buf();
#[cfg(unix)]
let bin_path = applicable_version.path().join("bin");
let path_env = {
let paths_env = std::env::var_os("PATH").context(CantReadPathVariable)?;
let mut paths: Vec<_> = std::env::split_paths(&paths_env).collect();
paths.insert(0, bin_path);
std::env::join_paths(paths).context(CantAddPathToEnvironment)?
};
let exit_status = Command::new(&self.binary)
.args(self.arguments)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.env("PATH", path_env)
.spawn()
.expect("Can't spawn program")
.wait()
.expect("Failed to grab exit code");
std::process::exit(exit_status.code().unwrap());
}
}
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("Can't read path environment variable"))]
CantReadPathVariable,
#[snafu(display("Can't add path to environment variable: {}", source))]
CantAddPathToEnvironment {
source: std::env::JoinPathsError,
},
#[snafu(display(
"Can't find version in dotfiles. Please provide a version manually to the command."
))]
CantInferVersion,
#[snafu(display("Requested version {} is not currently installed", version))]
VersionNotFound {
version: UserVersion,
},
ApplicableVersionError {
source: UserInputError,
},
}