Skip to content

Commit

Permalink
Fix file lookup in parser keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
kubouch committed Jul 29, 2022
1 parent 9e24e45 commit 3515aeb
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 14 deletions.
32 changes: 18 additions & 14 deletions crates/nu-parser/src/parse_keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2834,25 +2834,29 @@ pub fn parse_register(

/// This helper function is used to find files during parsing
///
/// Checks whether the file is:
/// 1. relative to the directory of the file currently being parsed
/// 2. relative to the current working directory
/// 3. within one of the NU_LIB_DIRS entries
/// First, the actual current working directory is selected as
/// a) the directory of a file currently being parsed
/// b) current working directory (PWD)
///
/// Always returns absolute path
/// 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
fn find_in_dirs(
filename: &str,
working_set: &StateWorkingSet,
cwd: &str,
dirs_env: &str,
) -> Option<PathBuf> {
if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
if let Ok(p) = canonicalize_with(filename, currently_parsed_cwd) {
Some(p)
} else {
None
}
} else if let Ok(p) = canonicalize_with(filename, cwd) {
// Choose whether to use file-relative or PWD-relative path
let actual_cwd = if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
currently_parsed_cwd.as_path()
} else {
Path::new(cwd)
};

if let Ok(p) = canonicalize_with(filename, actual_cwd) {
Some(p)
} else {
let path = Path::new(filename);
Expand All @@ -2862,8 +2866,8 @@ fn find_in_dirs(
if let Ok(dirs) = lib_dirs.as_list() {
for lib_dir in dirs {
if let Ok(dir) = lib_dir.as_path() {
if let Ok(dir_abs) = canonicalize_with(&dir, cwd) {
// make sure the dir is absolute path
// make sure the dir is absolute path
if let Ok(dir_abs) = canonicalize_with(&dir, actual_cwd) {
if let Ok(path) = canonicalize_with(filename, dir_abs) {
return Some(path);
}
Expand Down
115 changes: 115 additions & 0 deletions tests/shell/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use super::nu_repl::nu_repl;
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};

#[cfg(feature = "which-support")]
Expand Down Expand Up @@ -56,3 +59,115 @@ fn do_not_panic_if_broken_pipe() {

assert!(child_output.stderr.is_empty());
}

#[test]
fn nu_lib_dirs_repl() {
Playground::setup("nu_lib_dirs_repl", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);

let inp = &[
r#"let-env NU_LIB_DIRS = [ ('scripts' | path expand) ]"#,
r#"source foo.nu"#,
r#"$env.FOO"#,
];

let actual_repl = nu_repl(dirs.test().to_str().unwrap(), inp);

assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}

#[test]
fn nu_lib_dirs_script() {
Playground::setup("nu_lib_dirs_script", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)])
.with_files(vec![FileWithContentToBeTrimmed(
"main.nu",
r#"
source foo.nu
"#,
)]);

let inp = &[
r#"let-env NU_LIB_DIRS = [ ('scripts' | path expand) ]"#,
r#"source main.nu"#,
r#"$env.FOO"#,
];

let actual_repl = nu_repl(dirs.test().to_str().unwrap(), inp);

assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}

#[test]
fn nu_lib_dirs_relative_repl() {
Playground::setup("nu_lib_dirs_relative_repl", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);

let inp = &[
r#"let-env NU_LIB_DIRS = [ 'scripts' ]"#,
r#"source foo.nu"#,
r#"$env.FOO"#,
];

let actual_repl = nu_repl(dirs.test().to_str().unwrap(), inp);

assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}

#[test]
fn nu_lib_dirs_relative_script() {
Playground::setup("nu_lib_dirs_relative_script", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/main.nu",
r#"
source ../foo.nu
"#,
)])
.with_files(vec![FileWithContentToBeTrimmed(
"foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);

let inp = &[
r#"let-env NU_LIB_DIRS = [ 'scripts' ]"#,
r#"source scripts/main.nu"#,
r#"$env.FOO"#,
];

let actual_repl = nu_repl(dirs.test().to_str().unwrap(), inp);

assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}

0 comments on commit 3515aeb

Please sign in to comment.