Slim down configuration readings and nu_cli clean up. (#2559)

We continue refactoring nu_cli and slim down a bit configuration
readings with a naive metadata `modified` field check.
This commit is contained in:
Andrés N. Robalino
2020-09-16 18:22:58 -05:00
committed by GitHub
parent 50cbf91bc5
commit 10d4edc7af
12 changed files with 632 additions and 387 deletions

View File

@ -204,6 +204,33 @@ pub fn user_data() -> Result<PathBuf, ShellError> {
Ok(std::path::PathBuf::from("/"))
}
#[derive(Debug, Clone)]
pub enum Status {
LastModified(std::time::SystemTime),
Unavailable,
}
impl Default for Status {
fn default() -> Self {
Status::Unavailable
}
}
pub fn last_modified(at: &Option<PathBuf>) -> Result<Status, Box<dyn std::error::Error>> {
let filename = default_path()?;
let filename = match at {
None => filename,
Some(ref file) => file.clone(),
};
if let Ok(time) = filename.metadata()?.modified() {
return Ok(Status::LastModified(time));
}
Ok(Status::Unavailable)
}
pub fn read(
tag: impl Into<Tag>,
at: &Option<PathBuf>,

View File

@ -2,13 +2,23 @@ use nu_protocol::Value;
use std::fmt::Debug;
pub trait Conf: Debug + Send {
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>>;
fn var(&self, key: &str) -> Option<Value>;
fn env(&self) -> Option<Value>;
fn path(&self) -> Option<Value>;
fn reload(&self);
fn reload(&mut self);
fn clone_box(&self) -> Box<dyn Conf>;
}
impl Conf for Box<dyn Conf> {
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
(**self).is_modified()
}
fn var(&self, key: &str) -> Option<Value> {
(**self).var(key)
}
fn env(&self) -> Option<Value> {
(**self).env()
}
@ -17,7 +27,7 @@ impl Conf for Box<dyn Conf> {
(**self).path()
}
fn reload(&self) {
fn reload(&mut self) {
(**self).reload();
}

View File

@ -1,17 +1,24 @@
use crate::config::{read, Conf};
use crate::config::{last_modified, read, Conf, Status};
use indexmap::IndexMap;
use nu_protocol::Value;
use nu_source::Tag;
use parking_lot::Mutex;
use std::fmt::Debug;
use std::sync::Arc;
#[derive(Debug, Clone, Default)]
pub struct NuConfig {
pub vars: Arc<Mutex<IndexMap<String, Value>>>,
pub vars: IndexMap<String, Value>,
pub modified_at: Status,
}
impl Conf for NuConfig {
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
self.is_modified()
}
fn var(&self, key: &str) -> Option<Value> {
self.var(key)
}
fn env(&self) -> Option<Value> {
self.env()
}
@ -20,11 +27,17 @@ impl Conf for NuConfig {
self.path()
}
fn reload(&self) {
let mut vars = self.vars.lock();
fn reload(&mut self) {
let vars = &mut self.vars;
if let Ok(variables) = read(Tag::unknown(), &None) {
vars.extend(variables);
self.modified_at = if let Ok(status) = last_modified(&None) {
status
} else {
Status::Unavailable
};
}
}
@ -34,6 +47,24 @@ impl Conf for NuConfig {
}
impl NuConfig {
pub fn with(config_file: Option<std::path::PathBuf>) -> NuConfig {
match &config_file {
None => NuConfig::new(),
Some(_) => {
let vars = if let Ok(variables) = read(Tag::unknown(), &config_file) {
variables
} else {
IndexMap::default()
};
NuConfig {
vars,
modified_at: NuConfig::get_last_modified(&config_file),
}
}
}
}
pub fn new() -> NuConfig {
let vars = if let Ok(variables) = read(Tag::unknown(), &None) {
variables
@ -42,12 +73,45 @@ impl NuConfig {
};
NuConfig {
vars: Arc::new(Mutex::new(vars)),
vars,
modified_at: NuConfig::get_last_modified(&None),
}
}
pub fn get_last_modified(config_file: &Option<std::path::PathBuf>) -> Status {
if let Ok(status) = last_modified(config_file) {
status
} else {
Status::Unavailable
}
}
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)?;
left != right
}
(_, _) => false,
})
}
pub fn var(&self, key: &str) -> Option<Value> {
let vars = &self.vars;
if let Some(value) = vars.get(key) {
return Some(value.clone());
}
None
}
pub fn env(&self) -> Option<Value> {
let vars = self.vars.lock();
let vars = &self.vars;
if let Some(env_vars) = vars.get("env") {
return Some(env_vars.clone());
@ -57,7 +121,7 @@ impl NuConfig {
}
pub fn path(&self) -> Option<Value> {
let vars = self.vars.lock();
let vars = &self.vars;
if let Some(env_vars) = vars.get("path") {
return Some(env_vars.clone());

View File

@ -1,17 +1,22 @@
use crate::config::{read, Conf, NuConfig};
use indexmap::IndexMap;
use crate::config::{Conf, NuConfig, Status};
use nu_protocol::Value;
use nu_source::Tag;
use parking_lot::Mutex;
use std::path::{Path, PathBuf};
use std::sync::Arc;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct FakeConfig {
pub config: NuConfig,
source_file: Option<PathBuf>,
}
impl Conf for FakeConfig {
fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
self.is_modified()
}
fn var(&self, key: &str) -> Option<Value> {
self.config.var(key)
}
fn env(&self) -> Option<Value> {
self.config.env()
}
@ -20,8 +25,8 @@ impl Conf for FakeConfig {
self.config.path()
}
fn reload(&self) {
// no-op
fn reload(&mut self) {
self.reload()
}
fn clone_box(&self) -> Box<dyn Conf> {
@ -31,18 +36,31 @@ impl Conf for FakeConfig {
impl FakeConfig {
pub fn new(config_file: &Path) -> FakeConfig {
let config_file = PathBuf::from(config_file);
let vars = if let Ok(variables) = read(Tag::unknown(), &Some(config_file)) {
variables
} else {
IndexMap::default()
};
let config_file = Some(PathBuf::from(config_file));
FakeConfig {
config: NuConfig {
vars: Arc::new(Mutex::new(vars)),
},
config: NuConfig::with(config_file.clone()),
source_file: config_file,
}
}
pub fn is_modified(&self) -> Result<bool, Box<dyn std::error::Error>> {
let modified_at = &self.config.modified_at;
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,
},
)
}
pub fn reload(&mut self) {
self.config = NuConfig::with(self.source_file.clone());
}
}