-
Notifications
You must be signed in to change notification settings - Fork 126
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
[DNM] Refactor Path APIs with SwiftSystem #219
base: main
Are you sure you want to change the base?
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.
This LGTM. I'm not a domain expert on SPM or this use case. @compnerd what do you think about this approach?
(Sorry for the delay. I had a 90% completed review but got distracted before I could finish, and forgot about it)
/// Public initializer from String. | ||
init(_ string: String) | ||
|
||
/// Convenience initializer that verifies that the path lexically. |
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.
What does it verify?
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 initializer will throw if the argument isn’t a valid relative/absolute path.
/// component: the `.` string. | ||
/// | ||
/// NOTE: Path components no longer include the root. Use `root` instead. | ||
var components: [String] { get } |
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.
What's the main reason for this protocol in SPM?
Also, should these methods be customization hooks or should they just be on the extension? How many of them should be dropped or superseded by FilePath
?
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.
What's the main reason for this protocol in SPM?
These are just common APIs of RelativePath
and AbsolutePath
.
How many of them should be dropped or superseded by
FilePath
?
I don’t think I’m capable enough of answering this question. If we’d like to drop any of them, maybe we’d get other TSC specialists in here.
return "." | ||
} | ||
return filepath.string | ||
} |
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.
We might want to put this on FilePath and Component itself, actually. We went with ""
as the canonical empty path over "."
because that's what it is at the OS layer as well as Collection
semantics, but a common convention is to produce "."
.
We'd want to come up with a good name for it for both FilePath
and Component
. Something better than stringOrCurrentDirectory
.
You could consider extending FilePath to add it, picking your preferred name. I don't know if that's an easier way to structure your code for the future. Let me ask some folk's opinion on extending types from dependencies: @lorentey @natecook1000
public var pathString: String { filepath.isEmpty ? "." : filepath.string }
return "." | ||
} | ||
return dirname | ||
} |
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.
public var dirname: String { filepath.removingLastComponent().pathString }
return AbsolutePath("/") | ||
#else | ||
if let drive = ProcessEnv.vars["SystemDrive"] ?? ProcessEnv.vars["HomeDrive"] { | ||
return AbsolutePath(drive + "\\") |
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.
Why the trailing backslash?
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.
%SystemDrive%
appears like C:
, and C:\
is the file path of its root.
Package.swift
Outdated
@@ -28,7 +28,9 @@ let package = Package( | |||
name: "TSCTestSupport", | |||
targets: ["TSCTestSupport"]), | |||
], | |||
dependencies: [], | |||
dependencies: [ | |||
.package(url: "https://github.com/apple/swift-system.git", .upToNextMinor(from: "0.0.1")) |
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 this be 0.0.1
or 0.0.2
?
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.
It should be 0.0.3
given that the first two releases actually not compiles (0.0.2
only compiles with release config).
upToNextMinor()
indicates the latest 0.0.x
, once 0.0.3
is released it should resolve.
} | ||
|
||
public func appending(components names: [String]) -> Self { | ||
let components = names.map(FilePath.Component.init) |
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.
You can also consider throwing in a .lazy
.
/// Root directory (whose string representation is just a path separator). | ||
public static let root = AbsolutePath(PathImpl.root) | ||
/// Returns the lowest common ancestor path. | ||
public func lowestCommonAncestor(with path: AbsolutePath) -> AbsolutePath? { |
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.
Common ancestor queries is also a good candidate for FilePath. We had operations like lexicallyRelative(to:)
in earlier pitches.
// Special case, which is a plain path without `..` components. It | ||
// might be an empty path (when self and the base are equal). | ||
let relComps = pathComps.dropFirst(baseComps.count) | ||
public func relative(to base: AbsolutePath) throws -> RelativePath { |
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.
Another candidate for FilePath
.
} else if self.pathString.hasPrefix(dir.pathString + "/") { | ||
return "./" + self.relative(to: dir).pathString | ||
if let first = rel.components.first, | ||
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.
What is the situation you're checking here? ..
s should be removed as part of lexical normalization except at the start of relative paths.
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 just copied the old behavior here. The old code shows that the returned string starts with either ..
or .
.
@stevapple what is the status of this work? is this something you want and have the time to bring over the finish line? we are very interested in this. |
@tomerd I’m afraid not yet. Here’s a simple checklist:
@milseman also suggests to move some implementation details to |
@stevapple @compnerd we now have swift-system integrated into the main branch of TSC and can start making use of it / reduce code to help support windows paths etc better |
IMO My suggested migration path is to directly rewriting TSC's clients with I'm also working on a high-level and cross-platform path package (something like karwa/swift-url, but I think that help little to TSC. |
While it's still undecided whether we're able to split I introduced a convention that will automatically rebase a One big breaking change now is that |
Some tests are failing / skipped because of:
|
For anyone who may be concerned, you can start to review the code now. I would investigate the impact upon TSC clients and open corresponding PR to test it with CI. |
This patch contains API changes. Minor version bump required.
Refactor Path APIs with SwiftSystem, and meanwhile align some APIs’ behavior. This includes:
""
. This was in the doc but not actually taken into practice.AbsolutePath.components
.public var root: String? { get }
for allPath
instances.RelativePath
against anotherAbsolutePath
may throw now, becauseAbsolutePath
s could have different roots on Windows.AbsolutePath.root
for better stability and clearer usage.TBD:
This PR may require parallel changes in all the dependent packages: