Merge branch 'errors' into direnv-rewrite

This commit is contained in:
Sam Hedin 2020-06-23 19:20:36 +02:00
commit b0db689065
3 changed files with 32 additions and 19 deletions

View File

@ -1,6 +1,8 @@
use crate::commands::{self, autoenv::Trusted}; use crate::commands::{self, autoenv::Trusted};
use commands::autoenv; use commands::autoenv;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use nu_errors::ShellError;
use nu_source::Span;
use std::{ use std::{
collections::hash_map::DefaultHasher, collections::hash_map::DefaultHasher,
ffi::OsString, ffi::OsString,
@ -32,36 +34,42 @@ impl DirectorySpecificEnvironment {
} }
} }
fn toml_if_directory_is_trusted(&self, mut wdirenv: PathBuf) -> std::io::Result<toml::Value> { fn toml_if_directory_is_trusted(
&self,
wdirenv: PathBuf,
) -> Result<toml::Value, ShellError> {
if let Some(trusted) = &self.trusted { if let Some(trusted) = &self.trusted {
wdirenv.push(".nu-env"); let content = std::fs::read_to_string(&wdirenv)?;
if wdirenv.exists() { let mut hasher = DefaultHasher::new();
let content = std::fs::read_to_string(&wdirenv)?; content.hash(&mut hasher);
let mut hasher = DefaultHasher::new();
content.hash(&mut hasher); if trusted.files.get(wdirenv.to_str().unwrap()) == Some(&hasher.finish().to_string()) {
if trusted.files.get(wdirenv.to_str().unwrap()) return Ok(content.parse::<toml::Value>().or_else(|_| {
== Some(&hasher.finish().to_string()) Err(ShellError::untagged_runtime_error(
{ "Could not parse .nu-env file. Is it well-formed?",
return Ok(content.parse::<toml::Value>()?); ))
} })?);
} }
return Err(ShellError::untagged_runtime_error("Found untrusted .nu-env file in this directory. Run 'autoenv trust' and restart nushell to allow it. This needs to be done after each change to the file."));
} }
Err(Error::new(ErrorKind::Other, "No trusted directories")) Err(ShellError::untagged_runtime_error("No trusted directories"))
} }
pub fn env_vars_to_add(&mut self) -> std::io::Result<IndexMap<EnvKey, EnvVal>> { pub fn env_vars_to_add(&mut self) -> Result<IndexMap<EnvKey, EnvVal>, ShellError> {
let current_dir = std::env::current_dir()?; let current_dir = std::env::current_dir()?;
let mut working_dir = Some(current_dir.as_path()); let mut working_dir = Some(current_dir.as_path());
let mut vars_to_add = IndexMap::new(); let mut vars_to_add = IndexMap::new();
//Start in the current directory, then traverse towards the root with working_dir to see if we are in a subdirectory of a valid directory. //Start in the current directory, then traverse towards the root with working_dir to see if we are in a subdirectory of a valid directory.
while let Some(wdir) = working_dir { while let Some(wdir) = working_dir {
if let Ok(toml_doc) = self.toml_if_directory_is_trusted(wdir.to_path_buf()) { let wdirenv = wdir.join(".nu-env");
if wdirenv.exists() {
let toml_doc = self.toml_if_directory_is_trusted(wdirenv)?;
toml_doc toml_doc
.get("env") .get("env")
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "env section missing"))? .ok_or_else(|| Error::new(ErrorKind::InvalidData, "env section missing in .nu-env"))?
.as_table() .as_table()
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "env section malformed"))? .ok_or_else(|| Error::new(ErrorKind::InvalidData, "malformed env section in .nu-env"))?
.iter() .iter()
.for_each(|(dir_env_key, dir_env_val)| { .for_each(|(dir_env_key, dir_env_val)| {
let dir_env_val: EnvVal = dir_env_val.as_str().unwrap().into(); let dir_env_val: EnvVal = dir_env_val.as_str().unwrap().into();
@ -88,7 +96,7 @@ impl DirectorySpecificEnvironment {
//If the user has left directories which added env vars through .nu, we clear those vars //If the user has left directories which added env vars through .nu, we clear those vars
//once they are marked for deletion, remove them from added_env_vars //once they are marked for deletion, remove them from added_env_vars
pub fn env_vars_to_delete(&mut self) -> std::io::Result<IndexSet<EnvKey>> { pub fn env_vars_to_delete(&mut self) -> Result<IndexSet<EnvKey>, ShellError> {
let current_dir = std::env::current_dir()?; let current_dir = std::env::current_dir()?;
let mut working_dir = Some(current_dir.as_path()); let mut working_dir = Some(current_dir.as_path());

View File

@ -4,6 +4,7 @@ use indexmap::{indexmap, IndexSet};
use nu_protocol::{UntaggedValue, Value}; use nu_protocol::{UntaggedValue, Value};
use std::ffi::OsString; use std::ffi::OsString;
use std::fmt::Debug; use std::fmt::Debug;
use nu_errors::ShellError;
pub trait Env: Debug + Send { pub trait Env: Debug + Send {
fn env(&self) -> Option<Value>; fn env(&self) -> Option<Value>;
@ -57,7 +58,7 @@ impl Environment {
} }
} }
pub fn maintain_directory_environment(&mut self) -> std::io::Result<()> { pub fn maintain_directory_environment(&mut self) -> Result<(), ShellError> {
self.direnv.env_vars_to_delete()?.iter().for_each(|k| { self.direnv.env_vars_to_delete()?.iter().for_each(|k| {
self.remove_env(&k); self.remove_env(&k);
}); });

View File

@ -3,6 +3,8 @@ use crate::data::config::{Conf, NuConfig};
use crate::env::environment::{Env, Environment}; use crate::env::environment::{Env, Environment};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc; use std::sync::Arc;
use nu_errors::ShellError;
use nu_source::Text;
pub struct EnvironmentSyncer { pub struct EnvironmentSyncer {
pub env: Arc<Mutex<Box<Environment>>>, pub env: Arc<Mutex<Box<Environment>>>,
@ -44,7 +46,9 @@ impl EnvironmentSyncer {
pub fn sync_env_vars(&mut self, ctx: &mut Context) { pub fn sync_env_vars(&mut self, ctx: &mut Context) {
let mut environment = self.env.lock(); let mut environment = self.env.lock();
environment.maintain_directory_environment().ok(); if let Err(e) = environment.maintain_directory_environment() {
crate::cli::print_err(e, &Text::from(""));
}
if environment.env().is_some() { if environment.env().is_some() {
for (name, value) in ctx.with_host(|host| host.vars()) { for (name, value) in ctx.with_host(|host| host.vars()) {
if name != "path" && name != "PATH" { if name != "path" && name != "PATH" {