Fix PWD cannot point to root paths (#12761)

PR https://github.com/nushell/nushell/pull/12603 made it so that PWD can
never contain a trailing slash. However, a root path (such as `/` or
`C:\`) technically counts as "having a trailing slash", so now `cd /`
doesn't work.

I feel dumb for missing such an obvious edge case. Let's just merge this
quickly before anyone else finds out...

EDIT: It appears I'm too late.
This commit is contained in:
YizhePKU 2024-05-04 18:05:54 +08:00 committed by GitHub
parent 709b2479d9
commit 0d6fbdde4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -923,8 +923,8 @@ impl EngineState {
}
/// Returns the current working directory, which is guaranteed to be an
/// absolute path without trailing slashes, but might contain symlink
/// components.
/// absolute path without trailing slashes (unless it's the root path), but
/// might contain symlink components.
///
/// If `stack` is supplied, also considers modifications to the working
/// directory on the stack that have yet to be merged into the engine state.
@ -941,6 +941,11 @@ impl EngineState {
})
}
// Helper function to check if a path is a root path.
fn is_root(path: &Path) -> bool {
path.parent().is_none()
}
// Helper function to check if a path has trailing slashes.
fn has_trailing_slash(path: &Path) -> bool {
nu_path::components(path).last()
@ -958,7 +963,9 @@ impl EngineState {
if let Value::String { val, .. } = pwd {
let path = PathBuf::from(val);
if has_trailing_slash(&path) {
// Technically, a root path counts as "having trailing slashes", but
// for the purpose of PWD, a root path is acceptable.
if !is_root(&path) && has_trailing_slash(&path) {
error("$env.PWD contains trailing slashes")
} else if !path.is_absolute() {
error("$env.PWD is not an absolute path")
@ -1235,6 +1242,18 @@ mod test_cwd {
engine_state.cwd(None).unwrap_err();
}
#[test]
fn pwd_points_to_root() {
#[cfg(windows)]
let root = Path::new(r"C:\");
#[cfg(not(windows))]
let root = Path::new("/");
let engine_state = engine_state_with_pwd(root);
let cwd = engine_state.cwd(None).unwrap();
assert_path_eq!(cwd, root);
}
#[test]
fn pwd_points_to_normal_file() {
let file = NamedTempFile::new().unwrap();