Use only $nu.env.PWD for getting the current directory (#587)

* Use only $nu.env.PWD for getting current directory

Because setting and reading to/from std::env changes the global state
shich is problematic if we call `cd` from multiple threads (e.g., in a
`par-each` block).

With this change, when engine-q starts, it will either inherit existing
PWD env var, or create a new one from `std::env::current_dir()`.
Otherwise, everything that needs the current directory will get it from
`$nu.env.PWD`. Each spawned external command will get its current
directory per-process which should be thread-safe.

One thing left to do is to patch nu-path for this as well since it uses
`std::env::current_dir()` in its expansions.

* Rename nu-path functions

*_with is not *_relative which should be more descriptive and frees
"with" for use in a followup commit.

* Clone stack every each iter; Fix some commands

Cloning the stack each iteration of `each` makes sure we're not reusing
PWD between iterations.

Some fixes in commands to make them use the new PWD.

* Post-rebase cleanup, fmt, clippy

* Change back _relative to _with in nu-path funcs

Didn't use the idea I had for the new "_with".

* Remove leftover current_dir from rebase

* Add cwd sync at merge_delta()

This makes sure the parser and completer always have up-to-date cwd.

* Always pass absolute path to glob in ls

* Do not allow PWD a relative path; Allow recovery

Makes it possible to recover PWD by proceeding with the REPL cycle.

* Clone stack in each also for byte/string stream

* (WIP) Start moving env variables to engine state

* (WIP) Move env vars to engine state (ugly)

Quick and dirty code.

* (WIP) Remove unused mut and args; Fmt

* (WIP) Fix dataframe tests

* (WIP) Fix missing args after rebase

* (WIP) Clone only env vars, not the whole stack

* (WIP) Add env var clone to `for` loop as well

* Minor edits

* Refactor merge_delta() to include stack merging.

Less error-prone than doing it manually.

* Clone env for each `update` command iteration

* Mark env var hidden only when found in eng. state

* Fix clippt warnings

* Add TODO about env var reading

* Do not clone empty environment in loops

* Remove extra cwd collection

* Split current_dir() into str and path; Fix autocd

* Make completions respect PWD env var
This commit is contained in:
Jakub Žádník
2022-01-05 00:30:34 +02:00
committed by GitHub
parent 8f6843c600
commit 74dcd91cc3
30 changed files with 424 additions and 177 deletions

View File

@ -104,9 +104,18 @@ impl NuCompleter {
| nu_parser::FlatShape::String => {
let prefix = working_set.get_span_contents(flat.0);
let results = working_set.find_commands_by_prefix(prefix);
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD")
{
match d.as_string() {
Ok(s) => s,
Err(_) => "".to_string(),
}
} else {
"".to_string()
};
let prefix = String::from_utf8_lossy(prefix).to_string();
let results2 = file_path_completion(flat.0, &prefix)
let results2 = file_path_completion(flat.0, &prefix, &cwd)
.into_iter()
.map(move |x| {
(
@ -137,8 +146,17 @@ impl NuCompleter {
| nu_parser::FlatShape::ExternalArg => {
let prefix = working_set.get_span_contents(flat.0);
let prefix = String::from_utf8_lossy(prefix).to_string();
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD")
{
match d.as_string() {
Ok(s) => s,
Err(_) => "".to_string(),
}
} else {
"".to_string()
};
let results = file_path_completion(flat.0, &prefix);
let results = file_path_completion(flat.0, &prefix, &cwd);
return results
.into_iter()
@ -212,6 +230,7 @@ impl Completer for NuCompleter {
fn file_path_completion(
span: nu_protocol::Span,
partial: &str,
cwd: &str,
) -> Vec<(nu_protocol::Span, String)> {
use std::path::{is_separator, Path};
@ -238,7 +257,7 @@ fn file_path_completion(
(base, rest)
};
let base_dir = nu_path::expand_path(&base_dir_name);
let base_dir = nu_path::expand_path_with(&base_dir_name, cwd);
// This check is here as base_dir.read_dir() with base_dir == "" will open the current dir
// which we don't want in this case (if we did, base_dir would already be ".")
if base_dir == Path::new("") {