Auto merge of #14750 - epage:normalize, r=weihanglo

fix(util): Respect all `..`s in `normalize_path`

### What does this PR try to resolve?

The fact that `normalize_path` was only designed for absolute paths bit us when working out #14497 and so I decided to make sure it worked.  The other alternative I considered was having it assert that the path was absolute.

Since I did try out the assert and Cargo tests hit it, this likely fixes something but I haven't dug through to be able to say what.

### How should we test and review this PR?

### Additional information
This commit is contained in:
bors 2024-11-01 02:27:41 +00:00
commit 2fcc3755a3

View File

@ -94,11 +94,18 @@ pub fn normalize_path(path: &Path) -> PathBuf {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => {
ret.push(component.as_os_str());
ret.push(Component::RootDir);
}
Component::CurDir => {}
Component::ParentDir => {
ret.pop();
if ret.ends_with(Component::ParentDir) {
ret.push(Component::ParentDir);
} else {
let popped = ret.pop();
if !popped && !ret.has_root() {
ret.push(Component::ParentDir);
}
}
}
Component::Normal(c) => {
ret.push(c);
@ -856,9 +863,43 @@ fn exclude_from_time_machine(path: &Path) {
#[cfg(test)]
mod tests {
use super::join_paths;
use super::normalize_path;
use super::write;
use super::write_atomic;
#[test]
fn test_normalize_path() {
let cases = &[
("", ""),
(".", ""),
(".////./.", ""),
("/", "/"),
("/..", "/"),
("/foo/bar", "/foo/bar"),
("/foo/bar/", "/foo/bar"),
("/foo/bar/./././///", "/foo/bar"),
("/foo/bar/..", "/foo"),
("/foo/bar/../..", "/"),
("/foo/bar/../../..", "/"),
("foo/bar", "foo/bar"),
("foo/bar/", "foo/bar"),
("foo/bar/./././///", "foo/bar"),
("foo/bar/..", "foo"),
("foo/bar/../..", ""),
("foo/bar/../../..", ".."),
("../../foo/bar", "../../foo/bar"),
("../../foo/bar/", "../../foo/bar"),
("../../foo/bar/./././///", "../../foo/bar"),
("../../foo/bar/..", "../../foo"),
("../../foo/bar/../..", "../.."),
("../../foo/bar/../../..", "../../.."),
];
for (input, expected) in cases {
let actual = normalize_path(std::path::Path::new(input));
assert_eq!(actual, std::path::Path::new(expected), "input: {input}");
}
}
#[test]
fn write_works() {
let original_contents = "[dependencies]\nfoo = 0.1.0";