Skip to content

Commit c98cfc2

Browse files
authored
Add some general-purpose path utilities from swift-driver (#173)
* Add array-accepting overloads of appending(components:) to path types * Add basenameWithoutExt to RelativePath to match the AbsolutePath version
1 parent 3ae103e commit c98cfc2

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

Sources/TSCBasic/Path.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,17 @@ public struct AbsolutePath: Hashable {
157157
/// This method should only be used in cases where the input is guaranteed
158158
/// to be a valid path component (i.e., it cannot be empty, contain a path
159159
/// separator, or be a pseudo-path like '.' or '..').
160-
public func appending(components names: String...) -> AbsolutePath {
160+
public func appending(components names: [String]) -> AbsolutePath {
161161
// FIXME: This doesn't seem a particularly efficient way to do this.
162162
return names.reduce(self, { path, name in
163163
path.appending(component: name)
164164
})
165165
}
166166

167+
public func appending(components names: String...) -> AbsolutePath {
168+
appending(components: names)
169+
}
170+
167171
/// NOTE: We will most likely want to add other `appending()` methods, such
168172
/// as `appending(suffix:)`, and also perhaps `replacing()` methods,
169173
/// such as `replacing(suffix:)` or `replacing(basename:)` for some
@@ -243,6 +247,14 @@ public struct RelativePath: Hashable {
243247
return _impl.basename
244248
}
245249

250+
/// Returns the basename without the extension.
251+
public var basenameWithoutExt: String {
252+
if let ext = self.extension {
253+
return String(basename.dropLast(ext.count + 1))
254+
}
255+
return basename
256+
}
257+
246258
/// Suffix (including leading `.` character) if any. Note that a basename
247259
/// that starts with a `.` character is not considered a suffix, nor is a
248260
/// trailing `.` character.
@@ -288,12 +300,16 @@ public struct RelativePath: Hashable {
288300
/// This method should only be used in cases where the input is guaranteed
289301
/// to be a valid path component (i.e., it cannot be empty, contain a path
290302
/// separator, or be a pseudo-path like '.' or '..').
291-
public func appending(components names: String...) -> RelativePath {
303+
public func appending(components names: [String]) -> RelativePath {
292304
// FIXME: This doesn't seem a particularly efficient way to do this.
293305
return names.reduce(self, { path, name in
294306
path.appending(component: name)
295307
})
296308
}
309+
310+
public func appending(components names: String...) -> RelativePath {
311+
appending(components: names)
312+
}
297313
}
298314

299315
extension AbsolutePath: Codable {

Tests/TSCBasicTests/PathTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,29 @@ class PathTests: XCTestCase {
149149
XCTAssertEqual(RelativePath(".").basename, ".")
150150
}
151151

152+
func testBaseNameWithoutExt() {
153+
XCTAssertEqual(AbsolutePath("/").basenameWithoutExt, "/")
154+
XCTAssertEqual(AbsolutePath("/a").basenameWithoutExt, "a")
155+
XCTAssertEqual(AbsolutePath("/./a").basenameWithoutExt, "a")
156+
XCTAssertEqual(AbsolutePath("/../..").basenameWithoutExt, "/")
157+
XCTAssertEqual(RelativePath("../..").basenameWithoutExt, "..")
158+
XCTAssertEqual(RelativePath("../a").basenameWithoutExt, "a")
159+
XCTAssertEqual(RelativePath("../a/..").basenameWithoutExt, "..")
160+
XCTAssertEqual(RelativePath("a/..").basenameWithoutExt, ".")
161+
XCTAssertEqual(RelativePath("./..").basenameWithoutExt, "..")
162+
XCTAssertEqual(RelativePath("a/../////../////./////").basenameWithoutExt, "..")
163+
XCTAssertEqual(RelativePath("abc").basenameWithoutExt, "abc")
164+
XCTAssertEqual(RelativePath("").basenameWithoutExt, ".")
165+
XCTAssertEqual(RelativePath(".").basenameWithoutExt, ".")
166+
167+
XCTAssertEqual(AbsolutePath("/a.txt").basenameWithoutExt, "a")
168+
XCTAssertEqual(AbsolutePath("/./a.txt").basenameWithoutExt, "a")
169+
XCTAssertEqual(RelativePath("../a.bc").basenameWithoutExt, "a")
170+
XCTAssertEqual(RelativePath("abc.swift").basenameWithoutExt, "abc")
171+
XCTAssertEqual(RelativePath("../a.b.c").basenameWithoutExt, "a.b")
172+
XCTAssertEqual(RelativePath("abc.xyz.123").basenameWithoutExt, "abc.xyz")
173+
}
174+
152175
func testSuffixExtraction() {
153176
XCTAssertEqual(RelativePath("a").suffix, nil)
154177
XCTAssertEqual(RelativePath("a").extension, nil)

0 commit comments

Comments
 (0)