Repository navigation
Tracking Issue for std::path::absolute #92750
Description
Activity
- addedC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]
on Jan 10, 2022 Ok, so cards on the table. My personal motivation for this function is to expose the Windows function GetFullPathNameW (or something similar) into the standard library in a way that can be used cross-platform. This is already used by the standard library for making verbatim paths (absolute paths that aren't limited by
MAX_PATH). I've also heard from Linux users who want a way to make absolute paths that won't break on Windows. Previous related discussions include these internals thread where I explore other possibilities:I'd like to address the unresolved issues of not resolving
..on *nix: it was felt that resolving this is undesirable as it would change the meaning of the path. Whereas on Windows it does not. This is a fundamental difference between POSIX and Windows. On Windows,..is resolved lexically (aka without reference to the filesystem) whereas on POSIX systems it's essentially a symlink that can take you anywhere in the filesystem. It's not possible to resolve this dissonance so maybe we shouldn't hide it.Reacted by Patrick Poitras, Kraktus, Cherry, CEbbinghaus, Wessel Kronemeijer and teorShould we prepend the current directory, or skip that step? The user can typically join with the current directory afterwards.
I feel this is mistaken. On Windows, when you pass a path to
File::openor otherfsoperation, there is a fair amount of parsing done to get the "real" absolute path which is then passed to the kernel. It is often desirable to know exactly what path is actually being used to avoid surprises.Here are some examples of the potential differences between using
absoluteandPath::join. I'm usingcmd.exewhich initially sets the current directory toC:\Users\Chris. I then change the current directory toD:\Chris\rust.Input std::path::absolutecurrent_dir()?.joinaux\\.\auxD:\Chris\rust\auxC:file.txtC:\Users\Chris\file.txtC:file.txtfolder.\file... ..D:\Chris\rust\folder\fileD:\Chris\rust\folder.\file.. ..The idea of
absoluteis that it gives you the path the kernel will see so there are no surprises. Some of the Windows behaviour (in particular the legacy ones) can be very unintuitive. Theabsolutefunction avoids having to know much of the weirdness involved with user paths because it "knows" how to parse it the same way the OS does.whereas on POSIX systems it's essentially a symlink that can take you anywhere in the filesystem.
Could you elaborate on that? I get that
/foo/aand/bar/acould point to the same directoryaif, for example/bar/ais a symlink; do you mean that stripping the..in/bar/a/..is required to take you to the "physical" parent of the directory,/foo, thus requiring a filesystem access to resolve?Yes. sorry I worded that badly. The
absolutefunction doesn't use the file system to resolve paths so it can't know which directory..should resolve to. Instead, canonicalize must be used to properly resolve such paths. It's the same reason why Path::components normalizes.but not...Is there a particular reason this is added to the
pathmodule and not on thePathtype like other path methods?Reacted by Andrew BaxterMainly just to be more or less a drop-in replacement for
fs::canonicalize. And to avoid issues like: shouldPath::absolutetake a base path? That said, I don't personally have any objection to it being aPathmethod.The
pathmodule doesn't have any other path function currently, so I think adding it toPathas a drop-in forPath::canonicalizemakes sense.Resolving
..seems like a really useful usecase too, but it's probably better to makefs::canonicalizebehave better on Windows for that.Reacted by Kornel and Cauê Baasch de SouzaThinking things over a bit I think we may want 2 functions.
absolutewhich does only what is necessary to convert the path into an absolute form, so no resolving of.and... It's intended to be a fast and as pure as possible path manipulation function with no filesystem access. This way it behaves in a consistent manner with regards to...resolvewhich converts the path to absolute form and only fails ifabsolutewould. Additional it resolves.and..by best effort using filesystem access if necessary, but it keeps.and..instead of failing. It may resolve symlinks. This would use arealpathcall per..component andGetFullPathNameon Windows. This is more expensive and is intended to produce more readable paths.
Reacted by KornelWhat advantage would
resolvehave overcanonicalize? "more readable paths" on Windows seems like it would be served just as well byabsolute, and on Unix you can just usecanonicalize.- addedA-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`Area: `std::io`, `std::fs`, `std::net` and `std::path`
on Apr 2, 2023 What advantage would
resolvehave overcanonicalize?It would work on Windows in more scenarios and on paths which may partially exist or not exist at all. It can avoid filesystem access if there's no
..component on Unix. It should perhaps do case and Unicode normalization however."more readable paths" on Windows seems like it would be served just as well by
absolute, and on Unix you can just usecanonicalize.You seem to suggest that end user programs should call different functions on Windows and Unix. That's not great for a portable API.
Reacted by raylu and CEbbinghausThe
path::absolutefunction, as it stands, gives an "OS view" of the path. By which I mean, you see essentially the same path as the OS sees right before it starts doing filesystem stuff (e.g. resolving symlinks, etc). This is useful because it helps to ensure the application and OS are interpreting the path similarly. In some situations it can also be a useful diagnostic to log the path before symlinks are resolved, albeit cleaned up as much as possible.Libraries could build on this primitive to provide a number of other useful functions. They can't however unbuild it. If std only provides higher level functions, then it will not allow experimenting outside of std without those libraries having to reimplement it themselves.
Reacted by jyn, Diana, Alex Andreba, IronSpecs, Mick Dekkers and teorThis is useful because it helps to ensure the application and OS are interpreting the path similarly. In some situations it can also be a useful diagnostic to log the path before symlinks are resolved, albeit cleaned up as much as possible.
I agree this is useful. I want something close to this for implementing support for hyperlinks in ripgrep. Say, for example, a user is in
/home/andrewand finds a result in/home/andrew/foo/bar.txt. The user then clicks on the hyperlinked/home/andrew/foo/bar.txt, but it winds up opening the path/home/andrew/some/deeply/nested/directory/bar.txtinstead. It's the same file, but because symlinks are resolved, the path that is opened is different from the one I clicked on. This leads to a surprise, and may even lead to undesirable behavior (albeit not necessarily).But in order for
absoluteto work for the hyperlink use case, I think it would need to resolve...17 remaining items
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
Reacted by Be, Diana, Jamil Hajjar and kevin61416- addedto-announceAnnounce this issue on triage meetingAnnounce this issue on triage meeting
on Apr 24, 2024 - added 3 commits that reference this issue
on Apr 24, 2024 - added a commit that references this issue
on Apr 25, 2024 - added a commit that references this issue
on Apr 25, 2024 - removedto-announceAnnounce this issue on triage meetingAnnounce this issue on triage meeting
on Apr 29, 2024 Now that #124335 is merged, should this issue be closed?
Mainly just to be more or less a drop-in replacement for
fs::canonicalize. And to avoid issues like: shouldPath::absolutetake a base path? That said, I don't personally have any objection to it being aPathmethod.Was there any reason why a method wasn't also introduced for
Path? Sort of like howPath.canonicalizeis an alias forfs::canonicalizeI don't think there's any particular reason. It might be enough for someone to create a PR adding it and then one of the team can nominate that for libs discussion.
View all comments
Feature gate:
#![feature(absolute_path)]This is a tracking issue for
std::path::absolutefor making relative paths absolute without touching the filesystem. It is a drop-in replacement forstd::fs::canonicalize.Public API
Steps / History
std::path::absolute#91673std::path::absolute#124335Unresolved Questions
GetFullPathNameW, which isn't quite a "pure" function (in some special cases, e.g.D:file.txt, it can use hidden environment variables, set by cmd.exe, to resolve the path's root).absolute(a.join(b)), whereais an alternative current directory to usingstd::env::current_dir?..actually the right call? It does seem consistent with the POSIX docs, but may not be the most intuitive behavior (particularly given that Windows doesn't do that).