@@ -85,7 +85,7 @@ use crate::str::FromStr;
85
85
use crate :: sync:: Arc ;
86
86
87
87
use crate :: ffi:: { OsStr , OsString } ;
88
-
88
+ use crate :: sys ;
89
89
use crate :: sys:: path:: { is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR } ;
90
90
91
91
////////////////////////////////////////////////////////////////////////////////
@@ -3164,3 +3164,79 @@ impl Error for StripPrefixError {
3164
3164
"prefix not found"
3165
3165
}
3166
3166
}
3167
+
3168
+ /// Makes the path absolute without accessing the filesystem.
3169
+ ///
3170
+ /// If the path is relative, the current directory is used as the base directory.
3171
+ /// All intermediate components will be resolved according to platforms-specific
3172
+ /// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not
3173
+ /// resolve symlinks and may succeed even if the path does not exist.
3174
+ ///
3175
+ /// If the `path` is empty or getting the
3176
+ /// [current directory][crate::env::current_dir] fails then an error will be
3177
+ /// returned.
3178
+ ///
3179
+ /// # Examples
3180
+ ///
3181
+ /// ## Posix paths
3182
+ ///
3183
+ /// ```
3184
+ /// #![feature(absolute_path)]
3185
+ /// # #[cfg(unix)]
3186
+ /// fn main() -> std::io::Result<()> {
3187
+ /// use std::path::{self, Path};
3188
+ ///
3189
+ /// // Relative to absolute
3190
+ /// let absolute = path::absolute("foo/./bar")?;
3191
+ /// assert!(absolute.ends_with("foo/bar"));
3192
+ ///
3193
+ /// // Absolute to absolute
3194
+ /// let absolute = path::absolute("/foo//test/.././bar.rs")?;
3195
+ /// assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
3196
+ /// Ok(())
3197
+ /// }
3198
+ /// # #[cfg(not(unix))]
3199
+ /// # fn main() {}
3200
+ /// ```
3201
+ ///
3202
+ /// The paths is resolved using [POSIX semantics][posix-semantics] except that
3203
+ /// it stops short of resolving symlinks. This means it will keep `..`
3204
+ /// components and trailing slashes.
3205
+ ///
3206
+ /// ## Windows paths
3207
+ ///
3208
+ /// ```
3209
+ /// #![feature(absolute_path)]
3210
+ /// # #[cfg(windows)]
3211
+ /// fn main() -> std::io::Result<()> {
3212
+ /// use std::path::{self, Path};
3213
+ ///
3214
+ /// // Relative to absolute
3215
+ /// let absolute = path::absolute("foo/./bar")?;
3216
+ /// assert!(absolute.ends_with(r"foo\bar"));
3217
+ ///
3218
+ /// // Absolute to absolute
3219
+ /// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
3220
+ ///
3221
+ /// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
3222
+ /// Ok(())
3223
+ /// }
3224
+ /// # #[cfg(not(windows))]
3225
+ /// # fn main() {}
3226
+ /// ```
3227
+ ///
3228
+ /// For verbatim paths this will simply return the path as given. For other
3229
+ /// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path]
3230
+ /// This may change in the future.
3231
+ ///
3232
+ /// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
3233
+ /// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
3234
+ #[ unstable( feature = "absolute_path" , issue = "none" ) ]
3235
+ pub fn absolute < P : AsRef < Path > > ( path : P ) -> io:: Result < PathBuf > {
3236
+ let path = path. as_ref ( ) ;
3237
+ if path. as_os_str ( ) . is_empty ( ) {
3238
+ Err ( io:: const_io_error!( io:: ErrorKind :: InvalidInput , "cannot make an empty path absolute" , ) )
3239
+ } else {
3240
+ sys:: path:: absolute ( path)
3241
+ }
3242
+ }
0 commit comments