forked from extern/nushell
Move from source
to source-env
(#6277)
* start working on source-env * WIP * Get most tests working, still one to go * Fix file-relative paths; Report parser error * Fix merge conflicts; Restore source as deprecated * Tests: Use source-env; Remove redundant tests * Fmt * Respect hidden env vars * Fix file-relative eval for source-env * Add file-relative eval to "overlay use" * Use FILE_PWD only in source-env and "overlay use" * Ignore new tests for now This will be another issue * Throw an error if setting FILE_PWD manually * Fix source-related test failures * Fix nu-check to respect FILE_PWD * Fix corrupted spans in source-env shell errors * Fix up some references to old source * Remove deprecation message * Re-introduce deleted tests Co-authored-by: kubouch <kubouch@gmail.com>
This commit is contained in:
@ -5,6 +5,8 @@ use nu_protocol::ast::PathMember;
|
||||
use nu_protocol::engine::{EngineState, Stack};
|
||||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
|
||||
use nu_path::canonicalize_with;
|
||||
|
||||
use crate::eval_block;
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -16,6 +18,8 @@ const ENV_PATH_NAME: &str = "PATH";
|
||||
|
||||
const ENV_CONVERSIONS: &str = "ENV_CONVERSIONS";
|
||||
|
||||
static LIB_DIRS_ENV: &str = "NU_LIB_DIRS";
|
||||
|
||||
enum ConversionResult {
|
||||
Ok(Value),
|
||||
ConversionError(ShellError), // Failure during the conversion itself
|
||||
@ -226,6 +230,76 @@ pub fn path_str(
|
||||
env_to_string(pathname, &pathval, engine_state, stack)
|
||||
}
|
||||
|
||||
/// This helper function is used to find files during eval
|
||||
///
|
||||
/// First, the actual current working directory is selected as
|
||||
/// a) the directory of a file currently being parsed
|
||||
/// b) current working directory (PWD)
|
||||
///
|
||||
/// Then, if the file is not found in the actual cwd, NU_LIB_DIRS is checked.
|
||||
/// If there is a relative path in NU_LIB_DIRS, it is assumed to be relative to the actual cwd
|
||||
/// determined in the first step.
|
||||
///
|
||||
/// Always returns an absolute path
|
||||
pub fn find_in_dirs_env(
|
||||
filename: &str,
|
||||
engine_state: &EngineState,
|
||||
stack: &Stack,
|
||||
) -> Result<Option<PathBuf>, ShellError> {
|
||||
// Choose whether to use file-relative or PWD-relative path
|
||||
let cwd = if let Some(pwd) = stack.get_env_var(engine_state, "FILE_PWD") {
|
||||
match env_to_string("FILE_PWD", &pwd, engine_state, stack) {
|
||||
Ok(cwd) => {
|
||||
if Path::new(&cwd).is_absolute() {
|
||||
cwd
|
||||
} else {
|
||||
return Err(ShellError::GenericError(
|
||||
"Invalid current directory".to_string(),
|
||||
format!("The 'FILE_PWD' environment variable must be set to an absolute path. Found: '{}'", cwd),
|
||||
Some(pwd.span()?),
|
||||
None,
|
||||
Vec::new()
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
} else {
|
||||
current_dir_str(engine_state, stack)?
|
||||
};
|
||||
|
||||
if let Ok(p) = canonicalize_with(filename, &cwd) {
|
||||
Ok(Some(p))
|
||||
} else {
|
||||
let path = Path::new(filename);
|
||||
|
||||
if path.is_relative() {
|
||||
if let Some(lib_dirs) = stack.get_env_var(engine_state, LIB_DIRS_ENV) {
|
||||
if let Ok(dirs) = lib_dirs.as_list() {
|
||||
for lib_dir in dirs {
|
||||
if let Ok(dir) = lib_dir.as_path() {
|
||||
// make sure the dir is absolute path
|
||||
if let Ok(dir_abs) = canonicalize_with(&dir, &cwd) {
|
||||
if let Ok(path) = canonicalize_with(filename, dir_abs) {
|
||||
return Ok(Some(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_converted_value(
|
||||
engine_state: &EngineState,
|
||||
stack: &Stack,
|
||||
|
@ -173,6 +173,7 @@ pub fn eval_call(
|
||||
|
||||
/// Redirect the environment from callee to the caller.
|
||||
pub fn redirect_env(engine_state: &EngineState, caller_stack: &mut Stack, callee_stack: &Stack) {
|
||||
// Grab all environment variables from the callee
|
||||
let caller_env_vars = caller_stack.get_env_var_names(engine_state);
|
||||
|
||||
// remove env vars that are present in the caller but not in the callee
|
||||
|
Reference in New Issue
Block a user