use std::path::{Path, PathBuf};
pub fn realpath<P: AsRef<Path>>(path: P) -> PathBuf {
let path = path.as_ref();
std::fs::canonicalize(path).unwrap_or_else(|_| {
if path.is_absolute() {
path.to_path_buf()
} else {
std::env::current_dir()
.unwrap_or_else(|_| PathBuf::from("."))
.join(path)
}
})
}
pub fn join<I, P>(components: I) -> PathBuf
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
let mut iter = components.into_iter(); let mut acc = match iter.next() {
Some(first) => first.as_ref().to_path_buf(),
None => return PathBuf::new(),
};
for c in iter {
acc.push(c.as_ref());
}
acc }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn realpath_of_cwd_is_absolute() {
let p = realpath(".");
assert!(
p.is_absolute(),
"realpath('.') should be absolute, got {:?}",
p
);
}
#[test]
fn realpath_of_missing_path_is_absolute_join_with_cwd() {
let p = realpath("does-not-exist-powerliners-test");
assert!(
p.is_absolute(),
"realpath of missing path should still be absolute, got {:?}",
p
);
}
#[test]
fn join_concatenates_components_in_order() {
let p = join(["a", "b", "c"]);
assert_eq!(p, PathBuf::from("a").join("b").join("c"));
}
#[test]
fn join_empty_returns_empty_path() {
let p: PathBuf = join(Vec::<&str>::new());
assert_eq!(p, PathBuf::new());
}
#[test]
fn join_absolute_component_resets() {
let p = join(["a", "/b", "c"]);
assert_eq!(p, PathBuf::from("/b").join("c"));
}
}