mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 13:46:03 +02:00
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:
committed by
GitHub
parent
50cbf91bc5
commit
10d4edc7af
@ -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>,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user