Start using autoenv

This commit is contained in:
Sam Hedin 2020-06-22 15:13:30 +02:00
parent e35c423796
commit 3a0ada6486
5 changed files with 52 additions and 65 deletions

View File

@ -4,19 +4,43 @@ use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::path::PathBuf;
use std::io::Read;
pub struct Autoenv; pub struct Autoenv;
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize, Debug, Default)]
pub struct Allowed { pub struct Trusted {
pub files: IndexMap<String, String>, pub files: IndexMap<String, String>,
} }
impl Allowed { impl Trusted {
pub fn new() -> Self { pub fn new() -> Self {
Allowed { Trusted {
files: IndexMap::new(), files: IndexMap::new(),
} }
} }
pub fn read_trusted() -> Result<Self, ShellError> {
let config_path = config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?;
let mut file = match std::fs::OpenOptions::new()
.read(true)
.create(true)
.write(true)
.open(config_path.clone())
{
Ok(p) => p,
Err(_) => {
return Err(ShellError::untagged_runtime_error(
"Couldn't open nu-env.toml",
));
}
};
let mut doc = String::new();
file.read_to_string(&mut doc)?;
let allowed: Trusted = toml::from_str(doc.as_str()).unwrap_or_else(|_| Trusted::new());
Ok(allowed)
}
} }
#[async_trait] #[async_trait]
impl WholeStreamCommand for Autoenv { impl WholeStreamCommand for Autoenv {

View File

@ -1,12 +1,11 @@
use super::{autoenv::Allowed, cd::CdArgs}; use super::autoenv::Trusted;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::{path, prelude::*}; use crate::{path, prelude::*};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::SyntaxShape; use nu_protocol::SyntaxShape;
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io::Read; use std::{fs, collections::hash_map::DefaultHasher, path::PathBuf};
use std::{collections::hash_map::DefaultHasher, fs, path::PathBuf};
pub struct AutoenvTrust; pub struct AutoenvTrust;
#[async_trait] #[async_trait]
@ -50,32 +49,13 @@ impl WholeStreamCommand for AutoenvTrust {
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
content.hash(&mut hasher); content.hash(&mut hasher);
let config_path = config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?; let file_to_trust = file_to_trust.to_string_lossy().to_string();
let mut allowed = Trusted::read_trusted()?;
let mut file = match std::fs::OpenOptions::new()
.read(true)
.create(true)
.write(true)
.open(config_path.clone())
{
Ok(p) => p,
Err(_) => {
return Err(ShellError::untagged_runtime_error(
"Couldn't open nu-env.toml",
));
}
};
let mut doc = String::new();
file.read_to_string(&mut doc)?;
let mut allowed: Allowed = toml::from_str(doc.as_str()).unwrap_or_else(|_| Allowed::new());
let file_to_untrust = file_to_trust.to_string_lossy().to_string();
allowed allowed
.files .files
.insert(file_to_untrust, hasher.finish().to_string()); .insert(file_to_trust, hasher.finish().to_string());
let config_path = config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?;
fs::write(config_path, toml::to_string(&allowed).unwrap()) fs::write(config_path, toml::to_string(&allowed).unwrap())
.expect("Couldn't write to toml file"); .expect("Couldn't write to toml file");

View File

@ -3,9 +3,9 @@ use crate::prelude::*;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::SyntaxShape; use nu_protocol::SyntaxShape;
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
use std::io::{Read, Write}; use std::io::Read;
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use super::autoenv::Allowed; use super::autoenv::Trusted;
pub struct AutoenvUnTrust; pub struct AutoenvUnTrust;
@ -62,7 +62,7 @@ impl WholeStreamCommand for AutoenvUnTrust {
let mut doc = String::new(); let mut doc = String::new();
file.read_to_string(&mut doc)?; file.read_to_string(&mut doc)?;
let mut allowed: Allowed = toml::from_str(doc.as_str()).unwrap_or_else(|_| Allowed::new()); let mut allowed: Trusted = toml::from_str(doc.as_str()).unwrap_or_else(|_| Trusted::new());
let file_to_untrust = file_to_untrust.to_string_lossy().to_string(); let file_to_untrust = file_to_untrust.to_string_lossy().to_string();

View File

@ -1,48 +1,31 @@
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use nu_protocol::{Primitive, UntaggedValue, Value};
use std::{ use std::{
ffi::OsString, ffi::OsString,
fmt::Debug, fmt::Debug,
io::{Error, ErrorKind, Result}, io::{Error, ErrorKind},
path::PathBuf, path::PathBuf,
}; };
use crate::commands::{autoenv::Trusted, self};
use commands::autoenv;
type EnvKey = String; type EnvKey = String;
type EnvVal = OsString; type EnvVal = OsString;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct DirectorySpecificEnvironment { pub struct DirectorySpecificEnvironment {
allowed_directories: IndexSet<PathBuf>, trusted: Option<Trusted>,
//Directory -> Env key. If an environment var has been added from a .nu in a directory, we track it here so we can remove it when the user leaves the directory. //Directory -> Env key. If an environment var has been added from a .nu in a directory, we track it here so we can remove it when the user leaves the directory.
added_env_vars: IndexMap<PathBuf, IndexSet<EnvKey>>, added_env_vars: IndexMap<PathBuf, IndexSet<EnvKey>>,
} }
impl DirectorySpecificEnvironment { impl DirectorySpecificEnvironment {
pub fn new(allowed_directories: Option<Value>) -> DirectorySpecificEnvironment { pub fn new() -> DirectorySpecificEnvironment {
let allowed_directories = if let Some(Value { let trusted = match autoenv::Trusted::read_trusted() {
value: UntaggedValue::Table(ref wrapped_directories), Ok(t) => Some(t),
tag: _, Err(_) => None
}) = allowed_directories
{
wrapped_directories
.iter()
.filter_map(|dirval| {
if let Value {
value: UntaggedValue::Primitive(Primitive::String(ref dir)),
tag: _,
} = dirval
{
return Some(PathBuf::from(&dir));
}
None
})
.collect()
} else {
IndexSet::new()
}; };
DirectorySpecificEnvironment { DirectorySpecificEnvironment {
allowed_directories, trusted,
added_env_vars: IndexMap::new(), added_env_vars: IndexMap::new(),
} }
} }
@ -54,7 +37,8 @@ impl DirectorySpecificEnvironment {
//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 self.allowed_directories.contains(wdir) { // if self.allowed_directories.contains(wdir) {
if true {
let toml_doc = std::fs::read_to_string(wdir.join(".nu-env").as_path())? let toml_doc = std::fs::read_to_string(wdir.join(".nu-env").as_path())?
.parse::<toml::Value>()?; .parse::<toml::Value>()?;
@ -89,7 +73,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) -> Result<IndexSet<EnvKey>> { pub fn env_vars_to_delete(&mut self) -> std::io::Result<IndexSet<EnvKey>> {
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

@ -43,18 +43,17 @@ impl Environment {
Environment { Environment {
environment_vars: None, environment_vars: None,
path_vars: None, path_vars: None,
direnv: DirectorySpecificEnvironment::new(None), direnv: DirectorySpecificEnvironment::new(),
} }
} }
pub fn from_config<T: Conf>(configuration: &T) -> Environment { pub fn from_config<T: Conf>(configuration: &T) -> Environment {
let env = configuration.env(); let env = configuration.env();
let path = configuration.path(); let path = configuration.path();
Environment { Environment {
environment_vars: env, environment_vars: env,
path_vars: path, path_vars: path,
direnv: DirectorySpecificEnvironment::new(configuration.nu_env_dirs()), direnv: DirectorySpecificEnvironment::new(),
} }
} }