History, more test coverage improvements, and refactorings. (#3217)

Improvements overall to Nu. Also among the changes here, we can also be more confident towards incorporating `3041`. End to end tests for checking envs properly exported to externals is not added here (since it's in the other PR)

A few things added in this PR (probably forgetting some too)

* no writes happen to history during test runs.
* environment syncing end to end coverage added.
* clean up / refactorings few areas.
* testing API for finer control (can write tests passing more than one pipeline)
* can pass environment variables in tests that nu will inherit when running.

* No longer needed.

* no longer under a module. No need to use super.
This commit is contained in:
Andrés N. Robalino
2021-03-27 00:08:03 -05:00
committed by GitHub
parent b243b3ee1d
commit 8fc8fc89aa
31 changed files with 483 additions and 241 deletions

View File

@ -1,5 +1,6 @@
mod conf;
mod nuconfig;
pub mod path;
pub mod tests;
@ -185,7 +186,7 @@ pub fn default_path_for(file: &Option<PathBuf>) -> Result<PathBuf, ShellError> {
let file: &Path = file
.as_ref()
.map(AsRef::as_ref)
.unwrap_or_else(|| "config.toml".as_ref());
.unwrap_or_else(|| self::path::DEFAULT_CONFIG_LOCATION.as_ref());
filename.push(file);
Ok(filename)

View File

@ -1,7 +1,9 @@
use nu_protocol::Value;
use std::any::Any;
use std::fmt::Debug;
pub trait Conf: Debug + Send {
fn as_any(&self) -> &dyn Any;
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>>;
fn var(&self, key: &str) -> Option<Value>;
fn env(&self) -> Option<Value>;
@ -11,6 +13,10 @@ pub trait Conf: Debug + Send {
}
impl Conf for Box<dyn Conf> {
fn as_any(&self) -> &dyn Any {
self
}
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
(**self).is_modified()
}

View File

@ -2,15 +2,22 @@ use crate::config::{last_modified, read, Conf, Status};
use indexmap::IndexMap;
use nu_protocol::Value;
use nu_source::Tag;
use std::any::Any;
use std::fmt::Debug;
use std::path::PathBuf;
#[derive(Debug, Clone, Default)]
pub struct NuConfig {
pub source_file: Option<std::path::PathBuf>,
pub vars: IndexMap<String, Value>,
pub modified_at: Status,
}
impl Conf for NuConfig {
fn as_any(&self) -> &dyn Any {
self
}
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
self.is_modified()
}
@ -30,7 +37,7 @@ impl Conf for NuConfig {
fn reload(&mut self) {
let vars = &mut self.vars;
if let Ok(variables) = read(Tag::unknown(), &None) {
if let Ok(variables) = read(Tag::unknown(), &self.source_file) {
vars.extend(variables);
self.modified_at = if let Ok(status) = last_modified(&None) {
@ -60,6 +67,7 @@ impl NuConfig {
};
NuConfig {
source_file: source_file.clone(),
vars,
modified_at: NuConfig::get_last_modified(&source_file),
}
@ -75,11 +83,16 @@ impl NuConfig {
};
NuConfig {
source_file: None,
vars,
modified_at: NuConfig::get_last_modified(&None),
}
}
pub fn history_path(&self) -> PathBuf {
super::path::history(self)
}
pub fn get_last_modified(config_file: &Option<std::path::PathBuf>) -> Status {
if let Ok(status) = last_modified(config_file) {
status
@ -91,15 +104,17 @@ impl NuConfig {
pub fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
let modified_at = &self.modified_at;
Ok(match (NuConfig::get_last_modified(&None), modified_at) {
(Status::LastModified(left), Status::LastModified(right)) => {
let left = left.duration_since(std::time::UNIX_EPOCH)?;
let right = (*right).duration_since(std::time::UNIX_EPOCH)?;
Ok(
match (NuConfig::get_last_modified(&self.source_file), modified_at) {
(Status::LastModified(left), Status::LastModified(right)) => {
let left = left.duration_since(std::time::UNIX_EPOCH)?;
let right = (*right).duration_since(std::time::UNIX_EPOCH)?;
left != right
}
(_, _) => false,
})
left != right
}
(_, _) => false,
},
)
}
pub fn var(&self, key: &str) -> Option<Value> {

View File

@ -0,0 +1,32 @@
use crate::config::NuConfig;
use std::path::PathBuf;
pub const DEFAULT_CONFIG_LOCATION: &str = "config.toml";
const DEFAULT_HISTORY_LOCATION: &str = "history.txt";
pub fn history(config: &NuConfig) -> PathBuf {
let default_path = crate::config::user_data()
.map(|mut p| {
p.push(DEFAULT_HISTORY_LOCATION);
p
})
.unwrap_or_else(|_| PathBuf::from(DEFAULT_HISTORY_LOCATION));
let path = &config.var("history-path");
path.as_ref().map_or(default_path.clone(), |custom_path| {
match custom_path.as_string() {
Ok(path) => PathBuf::from(path),
Err(_) => default_path,
}
})
}
pub fn source_file(config: &NuConfig) -> PathBuf {
match &config.source_file {
Some(path) => PathBuf::from(path),
None => {
crate::config::default_path().unwrap_or_else(|_| PathBuf::from(DEFAULT_CONFIG_LOCATION))
}
}
}

View File

@ -1,5 +1,6 @@
use crate::config::{Conf, NuConfig, Status};
use nu_protocol::Value;
use std::any::Any;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone)]
@ -9,6 +10,10 @@ pub struct FakeConfig {
}
impl Conf for FakeConfig {
fn as_any(&self) -> &dyn Any {
self
}
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
self.is_modified()
}