diff --git a/README.md b/README.md index 6b09e01..ed1114c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Provides injectable Filesystem and Network resources to make code more testable. #### std::fs alternatives -- [ ] `std::fs::canonicalize` - `path(path).canonicalize()` - Returns the canonical, absolute form of a path with all intermediate components normalized and symbolic links resolved. +- [x] `std::fs::canonicalize` - `path(path).canonicalize()` - Returns the canonical, absolute form of a path with all intermediate components normalized and symbolic links resolved. - [x] `std::fs::copy` - `file(path).copy(target)` - Copies the contents of one file to another. This function will also copy the permission bits of the original file to the destination file. - [x] `std::fs::create_dir` - `dir(path).create()` - Creates a new, empty directory at the provided path - [x] `std::fs::create_dir_all` - `dir(path).create_all()` - Recursively create a directory and all of its parent components if they are missing. diff --git a/src/fs/path.rs b/src/fs/path.rs index 0acbe73..2af600d 100644 --- a/src/fs/path.rs +++ b/src/fs/path.rs @@ -225,6 +225,25 @@ impl<'base, 'path, T: PathType> PathReal<'base, 'path, T> { self.check_error()?; std::fs::rename(self.as_pathbuf(), dest.as_pathbuf()).map_err(Error::Io) } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// ``` + /// # use kxio::fs::Result; + /// # fn main() -> Result<()> { + /// let fs = kxio::fs::temp()?; + /// let path = fs.base().join("foo"); + /// # fs.dir(&path).create()?; + /// let dir = fs.path(&path); + /// let canonical = dir.canonicalize()?; + /// # Ok(()) + /// # } + /// ``` + pub fn canonicalize(&self) -> Result { + self.check_error()?; + self.as_pathbuf().canonicalize().map_err(Error::Io) + } } impl<'base, 'path> From> for PathBuf { fn from(path: PathReal) -> Self { diff --git a/tests/fs.rs b/tests/fs.rs index 3eb5fff..4d974c4 100644 --- a/tests/fs.rs +++ b/tests/fs.rs @@ -580,3 +580,25 @@ mod dir { } } } +mod canonicalize { + use std::path::Path; + + use super::*; + + #[test] + fn should_resolve_symlinks() -> TestResult { + let fs = fs::temp().expect("temp fs"); + let path = fs.base().join("foo"); + let file = fs.file(&path); + file.write("bar").expect("write"); + let link_path = fs.base().join("link"); + let link = fs.symlink(&link_path); + link.create_to(&file).expect("create"); + let canonical = link.canonicalize().expect("canonicalize"); + // macos puts all temp files under /private + let canonical = Path::new("/").join(canonical.strip_prefix("/private").unwrap()); + assert_eq!(canonical, path); + + Ok(()) + } +}