mirror of
https://github.com/nushell/nushell
synced 2024-12-27 21:43:09 +00:00
While starting nu, force PWD to be current working directory (#5751)
* fix current working directory during start * fix tests * always set PWD to current_dir
This commit is contained in:
parent
b6959197bf
commit
c5cb369d8d
3 changed files with 45 additions and 30 deletions
|
@ -9,18 +9,35 @@ use nu_protocol::{
|
||||||
};
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use nu_utils::enable_vt_processing;
|
use nu_utils::enable_vt_processing;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
// This will collect environment variables from std::env and adds them to a stack.
|
// This will collect environment variables from std::env and adds them to a stack.
|
||||||
//
|
//
|
||||||
// In order to ensure the values have spans, it first creates a dummy file, writes the collected
|
// In order to ensure the values have spans, it first creates a dummy file, writes the collected
|
||||||
// env vars into it (in a "NAME"="value" format, quite similar to the output of the Unix 'env'
|
// env vars into it (in a "NAME"="value" format, quite similar to the output of the Unix 'env'
|
||||||
// tool), then uses the file to get the spans. The file stays in memory, no filesystem IO is done.
|
// tool), then uses the file to get the spans. The file stays in memory, no filesystem IO is done.
|
||||||
pub fn gather_parent_env_vars(engine_state: &mut EngineState) {
|
//
|
||||||
gather_env_vars(std::env::vars(), engine_state);
|
// The "PWD" env value will be forced to `init_cwd`.
|
||||||
|
// The reason to use `init_cwd`:
|
||||||
|
//
|
||||||
|
// While gathering parent env vars, the parent `PWD` may not be the same as `current working directory`.
|
||||||
|
// Consider to the following command as the case (assume we execute command inside `/tmp`):
|
||||||
|
//
|
||||||
|
// tmux split-window -v -c "#{pane_current_path}"
|
||||||
|
//
|
||||||
|
// Here nu execute external command `tmux`, and tmux starts a new `nushell`, with `init_cwd` value "#{pane_current_path}".
|
||||||
|
// But at the same time `PWD` still remains to be `/tmp`.
|
||||||
|
//
|
||||||
|
// In this scenario, the new `nushell`'s PWD should be "#{pane_current_path}" rather init_cwd.
|
||||||
|
pub fn gather_parent_env_vars(engine_state: &mut EngineState, init_cwd: &Path) {
|
||||||
|
gather_env_vars(std::env::vars(), engine_state, init_cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_env_vars(vars: impl Iterator<Item = (String, String)>, engine_state: &mut EngineState) {
|
fn gather_env_vars(
|
||||||
|
vars: impl Iterator<Item = (String, String)>,
|
||||||
|
engine_state: &mut EngineState,
|
||||||
|
init_cwd: &Path,
|
||||||
|
) {
|
||||||
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
|
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
report_error(
|
report_error(
|
||||||
|
@ -43,37 +60,33 @@ fn gather_env_vars(vars: impl Iterator<Item = (String, String)>, engine_state: &
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut fake_env_file = String::new();
|
let mut fake_env_file = String::new();
|
||||||
let mut has_pwd = false;
|
|
||||||
|
|
||||||
// Write all the env vars into a fake file
|
// Write all the env vars into a fake file
|
||||||
for (name, val) in vars {
|
for (name, val) in vars {
|
||||||
if name == "PWD" {
|
|
||||||
has_pwd = true;
|
|
||||||
}
|
|
||||||
put_env_to_fake_file(&name, &val, &mut fake_env_file);
|
put_env_to_fake_file(&name, &val, &mut fake_env_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has_pwd {
|
match init_cwd.to_str() {
|
||||||
match std::env::current_dir() {
|
Some(cwd) => {
|
||||||
Ok(cwd) => {
|
put_env_to_fake_file("PWD", cwd, &mut fake_env_file);
|
||||||
put_env_to_fake_file("PWD", &cwd.to_string_lossy(), &mut fake_env_file);
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
None => {
|
||||||
// Could not capture current working directory
|
// Could not capture current working directory
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
report_error(
|
report_error(
|
||||||
&working_set,
|
&working_set,
|
||||||
&ShellError::GenericError(
|
&ShellError::GenericError(
|
||||||
"Current directory not found".to_string(),
|
"Current directory is not a valid utf-8 path".to_string(),
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
None,
|
None,
|
||||||
Some(format!("Retrieving current directory failed: {:?}", e)),
|
Some(format!(
|
||||||
|
"Retrieving current directory failed: {:?} not a valid utf-8 path",
|
||||||
|
init_cwd
|
||||||
|
)),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Lex the fake file, assign spans to all environment variables and add them
|
// Lex the fake file, assign spans to all environment variables and add them
|
||||||
// to stack
|
// to stack
|
||||||
|
@ -314,6 +327,7 @@ mod test {
|
||||||
]
|
]
|
||||||
.into_iter(),
|
.into_iter(),
|
||||||
&mut engine_state,
|
&mut engine_state,
|
||||||
|
Path::new("t"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let env = engine_state.render_env_vars();
|
let env = engine_state.render_env_vars();
|
||||||
|
|
|
@ -67,7 +67,8 @@ macro_rules! nu {
|
||||||
let target_cwd = $crate::fs::in_directory(&$cwd);
|
let target_cwd = $crate::fs::in_directory(&$cwd);
|
||||||
|
|
||||||
let mut process = match Command::new($crate::fs::executable_path())
|
let mut process = match Command::new($crate::fs::executable_path())
|
||||||
.env("PWD", &target_cwd) // setting PWD is enough to set cwd
|
.env("PWD", &target_cwd)
|
||||||
|
.current_dir(target_cwd)
|
||||||
.env(NATIVE_PATH_ENV_VAR, paths_joined)
|
.env(NATIVE_PATH_ENV_VAR, paths_joined)
|
||||||
// .arg("--skip-plugins")
|
// .arg("--skip-plugins")
|
||||||
// .arg("--no-history")
|
// .arg("--no-history")
|
||||||
|
|
|
@ -194,7 +194,7 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, set up env vars as strings only
|
// First, set up env vars as strings only
|
||||||
gather_parent_env_vars(&mut engine_state);
|
gather_parent_env_vars(&mut engine_state, &init_cwd);
|
||||||
let mut stack = nu_protocol::engine::Stack::new();
|
let mut stack = nu_protocol::engine::Stack::new();
|
||||||
|
|
||||||
if let Some(commands) = &binary_args.commands {
|
if let Some(commands) = &binary_args.commands {
|
||||||
|
|
Loading…
Reference in a new issue