Function broot::path::normalize_path

source ·
pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf
Expand description

Improve the path to try remove and solve .. token.

This assumes that a/b/../c is a/c which might be different from what the OS would have chosen when b is a link. This is OK for broot verb arguments but can’t be generally used elsewhere (a more general solution would probably query the FS and just resolve b in case of links).

This function ensures a given path ending with ‘/’ still ends with ‘/’ after normalization.

Examples found in repository?
src/tree_build/bline.rs (line 86)
80
81
82
83
84
85
86
87
88
89
90
91
92
    pub(crate) fn read_dir(&self) -> io::Result<fs::ReadDir> {
        if self.file_type.is_symlink() {
            if let Ok(target) = fs::read_link(&self.path) {
                let mut target_path = PathBuf::from(&target);
                if target_path.is_relative() {
                    target_path = self.path.parent().unwrap().join(target_path);
                    target_path = normalize_path(target_path);
                }
                return fs::read_dir(&target_path);
            }
        }
        fs::read_dir(&self.path)
    }
More examples
Hide additional examples
src/path/from.rs (line 51)
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
pub fn path_from<P: AsRef<Path> + std::fmt::Debug>(
    base_dir: P,
    anchor: PathAnchor,
    input: &str,
) -> PathBuf {
    let tilde = regex!(r"^~(/|$)");
    if input.starts_with('/') {
        // if the input starts with a `/`, we use it as is
        input.into()
    } else if tilde.is_match(input) {
        // if the input starts with `~` as first token, we replace
        // this `~` with the user home directory
        PathBuf::from(
            &*tilde
                .replace(input, |c: &Captures| {
                    if let Some(user_dirs) = UserDirs::new() {
                        format!(
                            "{}{}",
                            user_dirs.home_dir().to_string_lossy(),
                            &c[1],
                        )
                    } else {
                        warn!("no user dirs found, no expansion of ~");
                        c[0].to_string()
                    }
                })
        )
    } else {
        // we put the input behind the source (the selected directory
        // or its parent) and we normalize so that the user can type
        // paths with `../`
        let base_dir = match anchor {
            PathAnchor::Parent => base_dir
                .as_ref()
                .parent()
                .unwrap_or_else(|| base_dir.as_ref())
                .to_path_buf(),
            _ => closest_dir(base_dir.as_ref()),
        };
        normalize_path(base_dir.join(input))
    }
}