Don't include trailing separator when expanding tilde (#4974)

* Fix path when expanding tilde

Expanding tilde with no other relative paths would result in:
`$HOME/` instead of `$HOME`. This occurs when users run `cd` with
no extra arguments. In that case, the user's PWD would include the
trailing separator. This does not happen when explicitly passing
a value, such as `cd ~`, because in that case, the path would be
canonicalized.

This happens because std::path::PathBuf::push always adds a separator,
even if adding an empty path, which is what happens when `cd` is
invoked.

* Add test

* Fix test on Windows

Co-authored-by: Hristo Filaretov <h.filaretov@protonmail.com>
This commit is contained in:
Hristo Filaretov 2022-03-26 18:28:31 +01:00 committed by GitHub
parent 8a9cc33aac
commit 7a789d68a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -16,7 +16,14 @@ fn expand_tilde_with_home(path: impl AsRef<Path>, home: Option<PathBuf>) -> Path
path.strip_prefix("~").unwrap_or(path).into()
} else {
if let Ok(p) = path.strip_prefix("~/") {
h.push(p)
// Corner case: `p` is empty;
// Don't append extra '/', just keep `h` as is.
// This happens because PathBuf.push will always
// add a separator if the pushed path is relative,
// even if it's empty
if p != Path::new("") {
h.push(p)
}
}
h
}
@ -33,6 +40,7 @@ pub fn expand_tilde(path: impl AsRef<Path>) -> PathBuf {
#[cfg(test)]
mod tests {
use super::*;
use std::path::MAIN_SEPARATOR;
fn check_expanded(s: &str) {
let home = Path::new("/home");
@ -71,6 +79,15 @@ mod tests {
check_not_expanded("1~1");
}
#[test]
fn path_does_not_include_trailing_separator() {
let home = Path::new("/home");
let buf = Some(PathBuf::from(home));
let expanded = expand_tilde_with_home(Path::new("~"), buf);
let expanded_str = expanded.to_str().unwrap();
assert!(!expanded_str.ends_with(MAIN_SEPARATOR));
}
#[cfg(windows)]
#[test]
fn string_with_tilde_backslash() {