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. 40
      src/version_files.rs

14
src/commands/exec.rs

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

4
src/commands/install.rs

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

4
src/commands/uninstall.rs

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

4
src/commands/use.rs

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

1
src/main.rs

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

112
src/user_version_reader.rs

@ -0,0 +1,112 @@ @@ -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)))
));
}
}

40
src/version_files.rs

@ -7,7 +7,7 @@ use std::str::FromStr; @@ -7,7 +7,7 @@ use std::str::FromStr;
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();
for path_part in PATH_PARTS.iter() {
@ -17,24 +17,30 @@ pub fn get_user_version_from_file(path: impl AsRef<Path>) -> Option<UserVersion> @@ -17,24 +17,30 @@ pub fn get_user_version_from_file(path: impl AsRef<Path>) -> Option<UserVersion>
new_path.display(),
new_path.exists()
);
if let Ok(file) = std::fs::File::open(new_path) {
let version = {
let mut reader = DecodeReaderBytes::new(file);
let mut version = String::new();
reader.read_to_string(&mut version).map(|_| version)
};
match version {
Err(err) => info!("Can't read file: {}", err),
Ok(version) => {
info!("Found string {:?} in version file", version);
if let Ok(ver) = UserVersion::from_str(version.trim()) {
return Some(ver);
}
}
}
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 mut reader = DecodeReaderBytes::new(file);
let mut version = String::new();
reader.read_to_string(&mut version).map(|_| version)
};
match version {
Err(err) => {
info!("Can't read file: {}", err);
None
}
Ok(version) => {
info!("Found string {:?} in version file", version);
UserVersion::from_str(version.trim()).ok()
}
}
}

Loading…
Cancel
Save