-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Path.Exists -- to replace inefficient FileExists || DirectoryExists #21678
Comments
I would just call it Path.Exists(). It would instantly replace most of my File.Exists() calls, so it'd be nice not to have a unwieldly name like DirectoryOrFileExists(). |
I started working on this, but I'm wondering. I can test on Windows and Linux, but how best to get tests for WinRT to run? Can I do that on a linux / windows box? |
@karelz so.... who should I talk to about how to test the PR I want to do for this one? Specifically, I'm wondering about windows/winRT since I'm doing the changes on linux. I can test on windows as well as I have a machine with windows, but I don't have anything that does winRT. |
@atsushikan It seems like Path is probably in mscorlib and not CoreFX? I don't see an easy path to add Path.Exists given that the implementation of it would presumably live on FileSystem? Am I missing something? cc @karelz |
@stephentoub mentioned wanting to move Path.cs to corefx at some point here: https://github.com/dotnet/coreclr/issues/1104#issuecomment-111193983 I wonder if that has to happen before this can really be done properly as a public API, or is there some magic type-forwarding foo or something else I need to know about to do Path.Exists? |
The Path implementation did move to corefx, and then with all of the .NET Standard 2.0 compatibility work, it moved back.
It doesn't. The API can be added in coreclr, and then exposed from the reference assembly and tested in corefx: But before a PR is submitted for any new APIs, we need to run it through the API review process. |
OK... I get that an API review would be needed. Now, I just want to understand how this works mechanically. Are you saying that the API would be added and implemented in coreclr and we would only have the tests in corefx, or are you saying the implementation would somehow live in corefx? I started down the path of implementing the support in the different FileSystem internal classes. However, then I realized I probably can't expose Path.Exists even if I wanted to using those as the implementation, and instead the implementation would need to live in coreclr. |
@kellypleahy, it can be confusing, I know. When adding an API, there are potentially three pieces: the implementation (src), the reference assembly (ref), and the tests (tests) (and I say potentially three because for some libraries there is no ref). The latter two live in corefx; the former may also live in corefx, or for very core types may live in coreclr. With Path, the implementation is here in coreclr: |
Here's rough info/notes about adding API into CoreCLR and exposing it in CoreFX: https://github.com/dotnet/corefx/wiki/Contributions#expose-api-across-coreclrcorefx We will need API review first -- that requires formal API proposal. @JeremyKuhne please add the "next-steps" info into up-for-grabs bugs in future (see triage rules). Also please use just 1 issue type.
We leave it on developers to decide if they want to test on 1 platform or more platforms locally. It is fine to test on just 1 platform (e.g. Linux) and look at results in CI for the other platforms (Windows, Mac, other Linux distros). I clarified it in new contributor notes "It is ok to test on just 1 platform locally and use CI to test the other platforms. Whatever is more convenient for contributor." |
@karelz thanks for the clarification. Looking forward to working more on this stuff in the future and I'm just trying to get my bearings at this point. All this is very helpful. I'll see if there are tips we can distill into your "notes" on the wiki to help answer the same questions I'm having. |
@kellypleahy Did you just want to work on the new API? Or did you want to fix the existing ones as well? I'm going to create a new issue for the existing improvements, that might be the right way to get started / familiar with the code. |
@karelz Thanks for the comments about testing. Another possible recommendation (tell me if I should file an issue). You said...
It would be really nice if there were a way to run targeted tests in your CI pool for when we are working on a PR. For instance, being able to just push to our local branch before we create the PR and ask something to run tests for specific assembly on that branch (so we can iterate quickly if possible). Think of it sorta like the code/build/test cycle that we would use locally, except it can run tests for us with multiple target platforms. |
@kellypleahy did you check the dotnet-bot? I think it has capabilities like that today. (use "@dotnet-bot help" to get full list of commands, options, etc.) |
BTW: I plan to have link to the static dotnet-bot docs also in our docs -- I just didn't find it yet 😮 |
@karelz where should I do that? I assume doing it in the issue isn't recommended, or will it just PM me the info? I just want to make sure before I do that I don't spam anyone :D |
People do it regularly in PRs - e.g. dotnet/corefx#20819 (comment). |
BTW: I updated the docs to: "@dotnet-bot docs - use command "@dotnet-bot help" in PRs, or search some older one" |
Hi @kellypleahy are you planning to take this one? If so I'll assign it. If not that's fine we might have someone else who can. |
I think so... but other priorities have been in the way recently. If you have someone already ready to jump on this it might make sense to hand it off. I'm hoping to get back to this in a couple weeks or three. |
@kellypleahy OK. @JeremyKuhne this might be a candidate for one of your "team". |
Taking it for now as it should fit well with my team's current schedule. |
@JeremyKuhne @danmosemsft which API shape is the final for API review? The top post is a bit vague ... |
Questions from API review:
|
@JeremyKuhne note questions above. |
My personal opinion is that Re: (3) I believe that, yes, it can be implemented in a performant way on all systems, except maybe for the windows RT/UWP platform (not sure about this one). Re: (2) - I started down the path of making a more general API that would allow you to retrieve the type of a file system entry. I think this is a good thing to have, but I don't think it was ready to be published. That said, I think it is the right "future" for the API, since I often find myself having to resort to using clib / windows API functions to do this stuff, but it might be hard to spec that out at this point. So, I was assuming I'd start by implementing that underlying API (that would be internal/private) and then using that to support I'm sorry I've gotten too busy to help with this, but I would love to still provide feedback on API design if you'll have me ;) |
Past API complete for this one. It is worth pursuing I think. @JeremyKuhne would drive it along. |
@JeremyKuhne do you have opinions on API review feedback above? |
There is already a
Whatever the OS says for the path that would be the logical amalgam of
Yes, if there is a question it should match |
Thanks @JeremyKuhne. I've edited your proposal to match the standard format . @dotnet/area-system-io I've marked |
Can this method (or a variant of it) return whether an existing path is a file or a directory? That seems useful. |
@danmoseley thank you for improving the proposal! I've assigned myself and I'll get it moving from here. |
namespace System.IO
{
public static partial class Path
{
// Implementation is logically equivalent to File.Exists(path) || Directory.Exists(path)
public static bool Exists([NotNullWhenAttribute(true)] string? path);
}
} |
Up for grabs... |
Hey Guys, I'd like to take up this issue, I've created a simple implementation here: Tarun047@81349ba But I am not sure, where or if I should add tests. |
Hi @Tarun047 tests could go with existing Path tests? Thanks! |
@Tarun047 To be able to consume the new API from the tests you need to add it to a reference assembly here: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime/ref/System.Runtime.cs The Path tests can be found here: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs You can reuse some of the tests that were written for I am OK with adding Here you can find how to run the tests: https://github.com/dotnet/runtime/blob/main/docs/workflow/testing/libraries/testing.md Usually what I do is building the entire product and running selected tests from the repo root: .\build.cmd -c Release -subset clr+libs+libs.tests
dotnet build .\src\libraries\System.IO.FileSystem\tests\System.IO.FileSystem.Tests.csproj /p:Configuration=Release /t:Test |
We should implement the code for this internally and look at adding a public API for it. Probably
Path.Exists(string path)
.The internal helper should avoid any sort of path validation/normalization if possible. A bad path, by definition, doesn't exist. At least on the Windows side pre normalizing isn't needed (and wasteful). We should also consider exposing overloads such as
Path.Exists(string path, bool normalize)
to allow users to skip this as well (or perhaps a config switch).[added by @danmoseley --]
Background and motivation
It's fairly common to want to know whether a file path is available to write to, without writing the file. For example, in order to prompt the user for a default save file name. In order to do this using our standard API, one must separately check whether the path matches an existing file, or an existing directory:
A new API can unify both these checks into one call, which is less verbose but more importantly potentially more efficient -- the underlying implementation (eg
lstat
,GetFileAttributesEx
) generally returns all this info with a single call. While it's likely caching at some layer below .NET means that the above will not cause two disk reads, there's certainly inefficiency in performing two syscalls to get the same information.API Proposal
API Usage
Alternative Designs
There is already an abstract method
FileSystemInfo.Exists
which but to make that useable, it would have to change from abstract to virtual, as would theFileSystemInfo
class, which would also need to expose a public constructor. This would also change its nature from representing either a directory or file (chosen at construction time) to representing something that is possibly either. As an instance method it would require newing up an object, which is wasteful. Finally,FileSystemInfo.Exists
is likely less discoverable and readable thanPath.Exists
and discoverability is important since this is a fairly basic operation.Risks
"Paths" in the broadest sense can represent more than traditional files and directories, and
Path.Exists
might imply to some that it could for example on Windows be used to test for the existence of a named pipe or other OS object. I suspect that is unlikely though, as the overwhelming use of the Path class is not with such objects.The text was updated successfully, but these errors were encountered: