Skip to content
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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

macshome
Copy link

@macshome macshome commented Oct 25, 2024

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.

 let relativePath =
          path.hasPrefix(workingDirectory.path) && FileManager.default.currentDirectoryPath != "/"
          ? String(path.dropFirst(workingDirectory.path.count + 1))
          : path
        output =
          URL(fileURLWithPath: relativePath, isDirectory: false, relativeTo: workingDirectory)

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

/tmp % pwd
/tmp

/tmp % ls -l testsf/*.swift 
-rw-r--r--@ 1 josh.wisenbaker  wheel  308 Nov  4  2022 testsf/bp.swift

/tmp % <trimmed>/Products/Debug/swift-format lint -rs .
bp.swift:1:31: warning: [GroupNumericLiterals] group every 3 digits in this decimal literal using a '_' separator

Now works from / as well

% cd /           
/ % pwd                 
/

/ % ls -l /tmp/testsf/*.swift
-rw-r--r--@ 1 josh.wisenbaker  wheel  308 Nov  4  2022 /tmp/testsf/bp.swift

/ % <trimmed>/Products/Debug/swift-format lint -rs /tmp/testsf
/private/tmp/testsf/bp.swift:1:31: warning: [GroupNumericLiterals] group every 3 digits in this decimal literal using a '_' separator

I'll need to spin up a linux VM to test if we get relative paths when running from root.

Added an additional check that tests to see if the working directory is root.
swiftlang#862
Copy link
Member

@ahoppen ahoppen left a 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 != "/"
Copy link
Member

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.

Copy link
Author

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.

Copy link
Author

@macshome macshome Oct 25, 2024

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 != "/"

@macshome
Copy link
Author

macshome commented Oct 25, 2024

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.

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.

@allevato
Copy link
Member

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: ".")

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.

Since just testing for the `/` character at the begining of a path will result in no path ever being relative, we should use `FileManager.default.currentDirectoryPath` to check and see if we are actually running in root.
@macshome
Copy link
Author

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.

I updated the tests to actually use `[URL]` instead of `[String]` when looking at the test results. For the working directory changes it was simplest to actually change the working directory and make sure we aren't dropping the first charcters from the paths.
@macshome
Copy link
Author

macshome commented Oct 28, 2024

@allevato I updated the tests to use [URL] instead of [String] and that let me then actually change the working directory to test that we don't clip names when running from / and that relative names are also used properly when applicable.

It takes the coverage on FileIterator.swift from 95.5% to a mighty 96.4%.

@@ -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 != "/"
Copy link
Member

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?

Copy link
Author

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.

Copy link
Author

@macshome macshome Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

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.

Copy link
Author

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I could also implement the isRoot property from the swift-tools-support-core as well in FileIterator. That way it would work on Windows as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests do fail on Windows when trying to change the working directory. I'll update everything and get it working.

Copy link
Member

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.

Copy link
Author

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.

Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants