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
ref(path): Rework basename and dirname to be coreutils compatible #3089
Conversation
686dcef
to
e147ea4
Compare
path/_util.ts
Outdated
@@ -26,8 +26,12 @@ export function isPosixPathSeparator(code: number): boolean { | |||
return code === CHAR_FORWARD_SLASH; | |||
} | |||
|
|||
export function isWindowsPathSeparator(code: number): boolean { |
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.
In windows system, both the forward slash and back slash are directory separator. See https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
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's why I only use it in isPathSeprator
, but agree that the naming might be confusing. Will change that for sure.
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.
Then you should not export it. Right?
Aligning to coreutils makes sense to me.
This also seems ok to me. |
I explained the issue in this thread: https://twitter.com/kamilogorek/status/1610743549510680590 |
Can you give more examples of breaking changes by this PR?
If we introduce this change, I think we should also update
I think |
It's true that |
f581021
to
50e82f4
Compare
50e82f4
to
092a0f2
Compare
092a0f2
to
94ef6f9
Compare
This PR is now complete, with some breaking changes, that are all making it coreutils-compliant. All coreutils tests are now also passing with both Changes:
|
path/_util.ts
Outdated
let matchedNonSeparator = false; | ||
let end = path.length; | ||
|
||
for (let i = path.length - 1; i >= 0; --i) { |
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 >= 0
should be i >= start
.
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.
Good catch. It also exposed one bug, which I also fixed.
path/basename_test.ts
Outdated
[["/aaa/bbb", "bb"], "b"], | ||
[["C:"], ""], | ||
[["C:."], "."], | ||
[["C:\\"], ""], |
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.
Because the result of posix.basename('/')
is /
, so i think the result of win32.basename('C:\\')
is \\
.
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.
Fixed
path/basename_test.ts
Outdated
[["aaa\\bbb", "bb"], "b"], | ||
[["aaa\\bbb", "b"], "bb"], | ||
[["/aaa/bbb", "bb"], "b"], | ||
[["C:"], "\\"], |
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.
Should the result be ""
? The result of posix.basename('')
is ""
.
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.
The input here is C:
, which is just a "root" directory, which for posix
returns a fallback value /
, see line 15: [["/"], "/"],
~ ❯ basename /
/
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.
Your test assumes an empty input, which would be [[""], [""]]
, and we do have this test for both win32 and posix :)
~ ❯ basename ""
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.
C:
represents a relative path from the current directory of the C: drive. C:\\
represents a root directory of the C: dirve. I get it from https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
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.
Ah, great catch, thanks! Updated
Trying to summarize the major breaking changes introduced by this, by examples:
These changes are introuced by aligning the API to
I think this change just make sense. It feels rather strange if it keeps double or triple slashes in the middle. The below change is also introduced inspired by the change of
This also looks reasonable to me. I'm in favor of landing these changes. |
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.
LGTM
Note: tests are failing due to
parse
assertions being affected by this change.This whole PR will invalidate some of the behaviors of
parse
function, which means that it would need to be reworked as well. However it's slightly more work, so before doing this, I'd like to ask what you even think about the expected behavior.Should we follow
coreutils
? Should we followNode.js
?Would it also be reasonable to implement
parse
as a superset ofbasename/dirname/extname
calls instead? This way it would never get out of sync.basename
now passes allcoreutils
tests // https://github.com/coreutils/coreutils/blob/master/tests/misc/basename.pl which it did not before.After reworking, the whole core is shared between
posix
andwin32
modules.Some behaviors, like
basename(".js", ".js") === ""
are not valid anymore, as per spec, the suffix cannot consume the whole path.Tests had to be factored out into table-test, as they also should be shared between
win32
/posix
.Some test variants are definitely doubled, but I did not want to remove any of them just for the sake of removing lines of code.
Implemented behavior is based on https://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html and https://pubs.opengroup.org/onlinepubs/9699919799/functions/basename.html.
Fixes #3063