-
Notifications
You must be signed in to change notification settings - Fork 232
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
Fix support for FileIterator
when working directory is /
#865
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening a PR and addressing this issue @macshome.
To test this, what do you think about making workingDirectory
an argument to FileIterator.init
and just default it to URL(fileURLWithPath: ".")
? That way you could set the working directory and we can also craft tests for Windows to ensure we don’t have any issues there.
@@ -145,7 +145,7 @@ public struct FileIterator: Sequence, IteratorProtocol { | |||
// be displayed as relative paths. Otherwise, they will still be displayed as absolute | |||
// paths. | |||
let relativePath = | |||
path.hasPrefix(workingDirectory.path) | |||
path.hasPrefix(workingDirectory.path) && path.first != "/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn’t this mean that we never relativize paths on Unix because all paths will start with a /
? Don’t you want to check that workingDirectory
is /
? I might be misunderstanding your change though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... You seem to be correct here. As far as I can tell the reason for using relative paths is just for nice diagnostic output.
// We attempt to relativize the URLs based on the current working directory, not the
// directory being iterated over, so that they can be displayed better in diagnostics. Thus,
// if the user passes paths that are relative to the current working directory, they will
// be displayed as relative paths. Otherwise, they will still be displayed as absolute
// paths.
And with workingDirectory
being a constant of .
this may take a bit more work. If we did change workingDirectory
to be passed in then it would also allow for easier testing. I'll work on it a bit more and see what I can come up with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed a quick update to actually check if the current working directory is root or not rather than checking for a string of /
.
path.hasPrefix(workingDirectory.path) && FileManager.default.currentDirectoryPath != "/"
That's what I had thought about for setting a working directory, but that value is a constant in the code... private let workingDirectory = URL(fileURLWithPath: ".") Making it the default would probably work fine though. |
If you pass it in the initializer, you could make that the default value but then let tests specify whatever they want there. It's a member property, so it can certainly be changed by the initializer. |
I'll take a trip down this path and see about getting it covered with tests so it doesn't break again. |
@allevato I updated the tests to use It takes the coverage on |
@@ -145,7 +145,7 @@ public struct FileIterator: Sequence, IteratorProtocol { | |||
// be displayed as relative paths. Otherwise, they will still be displayed as absolute | |||
// paths. | |||
let relativePath = | |||
path.hasPrefix(workingDirectory.path) | |||
path.hasPrefix(workingDirectory.path) && FileManager.default.currentDirectoryPath != "/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@compnerd What will this do on Windows? Probably not what's intended, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was my concern, I don't know how Foundation will deal with that there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it might be OK.
(Giving up on trying to make it look pretty here in the comment.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FileManager.default.currentDirectoryPath
will never be /
on Windows because Windows always has a drive letter, eg. C:\
. Checking if a URL is a root path on Windows is not quite trivial because you also need to account for networks shares eg. \\your-server\blah
and the only good way of doing it issuing the PathCchIsRoot
Windows API (eg. https://github.com/swiftlang/swift-tools-support-core/blob/5b130e04cc939373c4713b91704b0c47ceb36170/Sources/TSCBasic/Path.swift#L491).
But maybe it’s not really an issue on Windows anyway, depending on how test output looks like. This is why I suggested making workingDirectory
changeable from tests and then we can just check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know that it is an issue on Windows either. Most people seem to have discovered it when using WASM. Are there Windows and Linux runners for CI so that we can see if this breaks anything? Otherwise I can install a toolchain on Windows here and check.
I can still make workingDirectory
changeable from tests, but at this point I'm worried about the validity of the entire approach on Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don’t have a Windows machine to test this on, just write code that works to the best of you knowledge and some test cases for it. We have Windows PR testing (we just need to approve runs) and I’m happy to get the Windows code over the finish line if there are minor issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I set a toolchain up yesterday on my gaming machine so I will at least be sure that we pass the tests everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that’s great. Let me know if you have any questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do. Hoping to get back to this today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know when you think the PR is ready for review again.
Converting to draft while I work out the Windows stuff. |
@ahoppen OK, I'm throwing in the towel on getting things to work as I expect on Windows. In the meantime I skipped the test for iterating in root on Windows. If someone who is better versed in Windows Foundation wants to take a swing at it that would be great. All tests pass on macOS and Windows now, I've run Issues I'm running into on WindowsAfter digging around in the Foundation sources it seems like // The Swift Programming Language
// https://docs.swift.org/swift-book
import WinSDK
import Foundation
var pwd = FileManager.default.currentDirectoryPath
print(pwd) //Output: C:\Users\macsh\Swift\pwd\pwd
var isRoot = pwd.withCString(encodedAs: UTF16.self, PathCchIsRoot)
print(isRoot) //Output: false
FileManager.default.changeCurrentDirectoryPath("/")
pwd = FileManager.default.currentDirectoryPath
isRoot = pwd.withCString(encodedAs: UTF16.self, PathCchIsRoot)
print(pwd) //Output: C:\
print(isRoot) //Output: true That looks great! So I made a simple extension to |
Without checking the implementation, the thing that comes to mind is incorrect API usage. |
Thanks for your work on this change @macshome. I looked at the getting the tests passing on Windows as well and these are the changes I came up with. ahoppen@fe056af Do you want to incorporate them into your PR? |
Yeah there are a lot of different callers flying around and I had the thought that maybe something was just taking a misstep somewhere. I'll take another look and see if I can reduce that particular issue more. |
Sure I can pull those changes in and then update my PR. |
@ahoppen I synced up with |
@macshome Instead of merging main into your branch, could you rebase your branch? Otherwise LGTM. |
I meant to rebase onto |
Since I had been clicking the update button in GitHub along the way, there are a few merges to try to get rid of. It's probably easiest to just make a clean branch from main and then rebase the changes onto it. I'll need to create a new PR, but at least we can get the changes in. |
You can rebase your changes and then force-push your branch to update this PR. There’s no need to create a new branch or open a new PR. |
OK, I'll give that a spin. I figured a force-push was a non-starter. |
Alright, I was on PTO for a wedding for a while (Not mine, but it was out of town) and I will get back to cleaning up the PR now. |
@ahoppen Phew. git, am I right? Hopefully the diff is now ready to test. |
It looks like the git history got a little confused and there’s still a merge conflict. Could you rebase your commits so there’s no merge conflict and maybe also squash your commits into one? |
I rebased interactively, fixed the conflict, and squashed into one commit. Each commit still shows on it's own also, I don't think that's an issue, but let me know if you want me to try and resolve that with a new PR linked to this one. |
Not entirely sure what went on with your branch but I just rebased and squashed the commits. Maybe things got more complicated because this PR is from the |
I can take care of the CI failures |
8d330cc
to
e3a2ef4
Compare
Added an additional check that tests to see if the working directory is root. swiftlang#862
Yeah, it ended up being more changes than I expected. I'll make sure to be clean and regular on the next one. Thanks for all the help! |
Added an additional check that tests to see if the working directory is root to solve #862.
Simple Fix
Simple check that looks to see if the working directory is root.
Testing
I couldn't find a non-intrusive way to simulate changing the working directory of the unit tests. This path remains uncovered as a result of that.
Manual testing with the debug build. The behavior of #862 is resolved.
Works from
/tmp
Now works from
/
as wellI'll need to spin up a linux VM to test if we get relative paths when running from root.