@@ -84,7 +84,7 @@ use crate::str::FromStr;
8484use crate :: sync:: Arc ;
8585
8686use crate :: ffi:: { OsStr , OsString } ;
87-
87+ use crate :: sys ;
8888use crate :: sys:: path:: { is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR } ;
8989
9090////////////////////////////////////////////////////////////////////////////////
@@ -3141,3 +3141,81 @@ impl Error for StripPrefixError {
31413141 "prefix not found"
31423142 }
31433143}
3144+
3145+ /// Makes the path absolute without accessing the filesystem.
3146+ ///
3147+ /// If the path is relative, the current directory is used as the base directory.
3148+ /// All intermediate components will be resolved according to platforms-specific
3149+ /// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not
3150+ /// resolve symlinks and may succeed even if the path does not exist.
3151+ ///
3152+ /// If the `path` is empty or getting the
3153+ /// [current directory][crate::env::current_dir] fails then an error will be
3154+ /// returned.
3155+ ///
3156+ /// # Examples
3157+ ///
3158+ /// ## Posix paths
3159+ ///
3160+ /// ```
3161+ /// #![feature(absolute_path)]
3162+ /// # #[cfg(unix)]
3163+ /// fn main() -> std::io::Result<()> {
3164+ /// use std::path::{self, Path};
3165+ ///
3166+ /// // Relative to absolute
3167+ /// let absolute = path::absolute("foo/./bar")?;
3168+ /// assert!(absolute.ends_with("foo/bar"));
3169+ ///
3170+ /// // Absolute to absolute
3171+ /// let absolute = path::absolute("/foo//test/.././bar.rs")?;
3172+ /// assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
3173+ /// Ok(())
3174+ /// }
3175+ /// # #[cfg(not(unix))]
3176+ /// # fn main() {}
3177+ /// ```
3178+ ///
3179+ /// The paths is resolved using [POSIX semantics][posix-semantics] except that
3180+ /// it stops short of resolving symlinks. This means it will keep `..`
3181+ /// components and trailing slashes.
3182+ ///
3183+ /// ## Windows paths
3184+ ///
3185+ /// ```
3186+ /// #![feature(absolute_path)]
3187+ /// # #[cfg(windows)]
3188+ /// fn main() -> std::io::Result<()> {
3189+ /// use std::path::{self, Path};
3190+ ///
3191+ /// // Relative to absolute
3192+ /// let absolute = path::absolute("foo/./bar")?;
3193+ /// assert!(absolute.ends_with(r"foo\bar"));
3194+ ///
3195+ /// // Absolute to absolute
3196+ /// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
3197+ ///
3198+ /// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
3199+ /// Ok(())
3200+ /// }
3201+ /// # #[cfg(not(windows))]
3202+ /// # fn main() {}
3203+ /// ```
3204+ ///
3205+ /// For verbatim paths this will simply return the path as given. For other
3206+ /// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path]
3207+ /// This may change in the future.
3208+ ///
3209+ /// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
3210+ /// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
3211+ #[ unstable( feature = "absolute_path" , issue = "none" ) ]
3212+ pub fn absolute < P : AsRef < Path > > ( path : P ) -> io:: Result < PathBuf > {
3213+ let path = path. as_ref ( ) ;
3214+ if path. as_os_str ( ) . is_empty ( ) {
3215+ return Err ( io:: Error :: new_const (
3216+ io:: ErrorKind :: InvalidInput ,
3217+ & "cannot make an empty path absolute" ,
3218+ ) ) ;
3219+ }
3220+ sys:: path:: absolute ( path)
3221+ }
0 commit comments