Browse Source

Allow using filenames in --using= (#401)

remotes/origin/add-with-shims
Gal Schlezinger 4 years ago committed by GitHub
parent
commit
a2aeeb779d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/commands/exec.rs
  2. 4
      src/commands/install.rs
  3. 4
      src/commands/uninstall.rs
  4. 4
      src/commands/use.rs
  5. 1
      src/main.rs
  6. 112
      src/user_version_reader.rs
  7. 26
      src/version_files.rs

14
src/commands/exec.rs

@ -1,10 +1,12 @@
use super::command::Command as Cmd; 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::choose_version_for_user_input::Error as UserInputError;
use crate::config::FnmConfig; use crate::config::FnmConfig;
use crate::outln; use crate::outln;
use crate::user_version::UserVersion; use crate::user_version::UserVersion;
use crate::version_files::get_user_version_from_file; use crate::{
choose_version_for_user_input::choose_version_for_user_input,
user_version_reader::UserVersionReader,
};
use colored::Colorize; use colored::Colorize;
use snafu::{OptionExt, ResultExt, Snafu}; use snafu::{OptionExt, ResultExt, Snafu};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
@ -13,8 +15,9 @@ use structopt::StructOpt;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(setting = structopt::clap::AppSettings::TrailingVarArg)] #[structopt(setting = structopt::clap::AppSettings::TrailingVarArg)]
pub struct Exec { pub struct Exec {
/// Either an explicit version, or a filename with the version written in it
#[structopt(long = "using")] #[structopt(long = "using")]
version: Option<UserVersion>, version: Option<UserVersionReader>,
/// Deprecated. This is the default now. /// Deprecated. This is the default now.
#[structopt(long = "using-file", hidden = true)] #[structopt(long = "using-file", hidden = true)]
using_file: bool, using_file: bool,
@ -34,10 +37,11 @@ impl Cmd for Exec {
let version = self let version = self
.version .version
.or_else(|| { .unwrap_or_else(|| {
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();
get_user_version_from_file(current_dir) UserVersionReader::Path(current_dir)
}) })
.to_user_version()
.context(CantInferVersion)?; .context(CantInferVersion)?;
let applicable_version = choose_version_for_user_input(&version, &config) let applicable_version = choose_version_for_user_input(&version, &config)

4
src/commands/install.rs

@ -6,7 +6,7 @@ use crate::outln;
use crate::remote_node_index; use crate::remote_node_index;
use crate::user_version::UserVersion; use crate::user_version::UserVersion;
use crate::version::Version; use crate::version::Version;
use crate::version_files::get_user_version_from_file; use crate::version_files::get_user_version_for_directory;
use colored::Colorize; use colored::Colorize;
use log::debug; use log::debug;
use snafu::{ensure, OptionExt, ResultExt, Snafu}; use snafu::{ensure, OptionExt, ResultExt, Snafu};
@ -48,7 +48,7 @@ impl super::command::Command for Install {
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();
let current_version = self let current_version = self
.version()? .version()?
.or_else(|| get_user_version_from_file(current_dir)) .or_else(|| get_user_version_for_directory(current_dir))
.context(CantInferVersion)?; .context(CantInferVersion)?;
let version = match current_version.clone() { let version = match current_version.clone() {

4
src/commands/uninstall.rs

@ -5,7 +5,7 @@ use crate::installed_versions;
use crate::outln; use crate::outln;
use crate::user_version::UserVersion; use crate::user_version::UserVersion;
use crate::version::Version; use crate::version::Version;
use crate::version_files::get_user_version_from_file; use crate::version_files::get_user_version_for_directory;
use colored::Colorize; use colored::Colorize;
use log::debug; use log::debug;
use snafu::{ensure, OptionExt, ResultExt, Snafu}; use snafu::{ensure, OptionExt, ResultExt, Snafu};
@ -26,7 +26,7 @@ impl Command for Uninstall {
.version .version
.or_else(|| { .or_else(|| {
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();
get_user_version_from_file(current_dir) get_user_version_for_directory(current_dir)
}) })
.context(CantInferVersion)?; .context(CantInferVersion)?;

4
src/commands/use.rs

@ -7,7 +7,7 @@ use crate::outln;
use crate::system_version; use crate::system_version;
use crate::user_version::UserVersion; use crate::user_version::UserVersion;
use crate::version::Version; use crate::version::Version;
use crate::version_files::get_user_version_from_file; use crate::version_files::get_user_version_for_directory;
use colored::Colorize; use colored::Colorize;
use snafu::{ensure, OptionExt, ResultExt, Snafu}; use snafu::{ensure, OptionExt, ResultExt, Snafu};
use structopt::StructOpt; use structopt::StructOpt;
@ -33,7 +33,7 @@ impl Command for Use {
.version .version
.or_else(|| { .or_else(|| {
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();
get_user_version_from_file(current_dir) get_user_version_for_directory(current_dir)
}) })
.context(CantInferVersion)?; .context(CantInferVersion)?;

1
src/main.rs

@ -15,6 +15,7 @@ mod shell;
mod system_info; mod system_info;
mod system_version; mod system_version;
mod user_version; mod user_version;
mod user_version_reader;
mod version; mod version;
mod version_files; mod version_files;

112
src/user_version_reader.rs

@ -0,0 +1,112 @@
use crate::user_version::UserVersion;
use crate::version_files::{get_user_version_for_directory, get_user_version_for_file};
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Debug)]
pub enum UserVersionReader {
Direct(UserVersion),
Path(PathBuf),
}
impl UserVersionReader {
pub fn to_user_version(self) -> Option<UserVersion> {
match self {
Self::Direct(uv) => Some(uv),
Self::Path(pathbuf) if pathbuf.is_file() => get_user_version_for_file(&pathbuf),
Self::Path(pathbuf) => get_user_version_for_directory(&pathbuf),
}
}
}
impl FromStr for UserVersionReader {
type Err = semver::SemVerError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let pathbuf = PathBuf::from_str(&s);
let user_version = UserVersion::from_str(&s);
match (user_version, pathbuf) {
(_, Ok(pathbuf)) if pathbuf.exists() => Ok(Self::Path(pathbuf)),
(Ok(user_version), _) => Ok(Self::Direct(user_version)),
(Err(user_version_err), _) => Err(user_version_err),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::version::Version;
use pretty_assertions::assert_eq;
use std::io::Write;
use tempfile::{NamedTempFile, TempDir};
#[test]
fn test_file_pathbuf_to_version() {
let mut file = NamedTempFile::new().unwrap();
write!(file, "14").unwrap();
let pathbuf = file.path().to_path_buf();
let user_version = UserVersionReader::Path(pathbuf).to_user_version();
assert_eq!(user_version, Some(UserVersion::OnlyMajor(14)));
}
#[test]
fn test_directory_pathbuf_to_version() {
let directory = TempDir::new().unwrap();
let node_version_path = directory.path().join(".node-version");
std::fs::write(node_version_path, "14").unwrap();
let pathbuf = directory.path().to_path_buf();
let user_version = UserVersionReader::Path(pathbuf).to_user_version();
assert_eq!(user_version, Some(UserVersion::OnlyMajor(14)));
}
#[test]
fn test_direct_to_version() {
let user_version = UserVersionReader::Direct(UserVersion::OnlyMajor(14)).to_user_version();
assert_eq!(user_version, Some(UserVersion::OnlyMajor(14)));
}
#[test]
fn test_from_str_directory() {
let directory = TempDir::new().unwrap();
let node_version_path = directory.path().join(".node-version");
std::fs::write(node_version_path, "14").unwrap();
let pathbuf = directory.path().to_path_buf();
let user_version = UserVersionReader::from_str(pathbuf.to_str().unwrap());
assert!(matches!(user_version, Ok(UserVersionReader::Path(_))));
}
#[test]
fn test_from_str_file() {
let mut file = NamedTempFile::new().unwrap();
write!(file, "14").unwrap();
let pathbuf = file.path().to_path_buf();
let user_version = UserVersionReader::from_str(pathbuf.to_str().unwrap());
assert!(matches!(user_version, Ok(UserVersionReader::Path(_))));
}
#[test]
fn test_non_existing_path() {
let user_version =
UserVersionReader::from_str("/tmp/some_random_text_that_probably_does_not_exist");
assert!(matches!(
user_version,
Ok(UserVersionReader::Direct(UserVersion::Full(
Version::Alias(_)
)))
));
}
#[test]
fn test_a_version_number() {
let user_version = UserVersionReader::from_str("12.0");
assert!(matches!(
user_version,
Ok(UserVersionReader::Direct(UserVersion::MajorMinor(12, 0)))
));
}
}

26
src/version_files.rs

@ -7,7 +7,7 @@ use std::str::FromStr;
const PATH_PARTS: [&str; 2] = [".nvmrc", ".node-version"]; const PATH_PARTS: [&str; 2] = [".nvmrc", ".node-version"];
pub fn get_user_version_from_file(path: impl AsRef<Path>) -> Option<UserVersion> { pub fn get_user_version_for_directory(path: impl AsRef<Path>) -> Option<UserVersion> {
let path = path.as_ref(); let path = path.as_ref();
for path_part in PATH_PARTS.iter() { for path_part in PATH_PARTS.iter() {
@ -17,7 +17,16 @@ pub fn get_user_version_from_file(path: impl AsRef<Path>) -> Option<UserVersion>
new_path.display(), new_path.display(),
new_path.exists() new_path.exists()
); );
if let Ok(file) = std::fs::File::open(new_path) { if let Some(version) = get_user_version_for_file(&new_path) {
return Some(version);
}
}
None
}
pub fn get_user_version_for_file(path: impl AsRef<Path>) -> Option<UserVersion> {
let file = std::fs::File::open(path).ok()?;
let version = { let version = {
let mut reader = DecodeReaderBytes::new(file); let mut reader = DecodeReaderBytes::new(file);
let mut version = String::new(); let mut version = String::new();
@ -25,16 +34,13 @@ pub fn get_user_version_from_file(path: impl AsRef<Path>) -> Option<UserVersion>
}; };
match version { match version {
Err(err) => info!("Can't read file: {}", err), Err(err) => {
info!("Can't read file: {}", err);
None
}
Ok(version) => { Ok(version) => {
info!("Found string {:?} in version file", version); info!("Found string {:?} in version file", version);
if let Ok(ver) = UserVersion::from_str(version.trim()) { UserVersion::from_str(version.trim()).ok()
return Some(ver);
}
}
} }
} }
} }
None
}

Loading…
Cancel
Save