Compare commits

..

13 Commits

Author SHA1 Message Date
Max Howell
f324b4a562 Merge pull request #47 from mxcl/fix-symlink-delete
Adds `kind` fixes deleting broken symlinks
2019-03-18 19:56:39 -04:00
Max Howell
0e061f9cc8 Adds kind fixes deleting broken symlinks
`delete()` and other functions would check `exists` to do certain behaviors, but `exists` will validate a symlink if the entry is a symlink, thus instead we check if the path is an actual entry now instead.
2019-03-18 19:47:49 -04:00
Max Howell
7e774b6cf5 Use 10.2 image for pretest
Also some tidy
2019-03-06 15:55:51 -05:00
Max Howell
8b371fa5d2 Allow initialization from Substring etc. 2019-03-06 15:55:51 -05:00
Max Howell
02fd579f19 mxcl.github.io -> mxcl.dev
[ci skip]
2019-02-28 18:40:19 -05:00
repo-ranger[bot]
e915bc0cfb Merge pull request #43 from mxcl/Bundle.executable
Add Bundle.executable
2019-02-17 15:14:17 +00:00
Max Howell
f4c2c75aa1 Add Bundle.executable 2019-02-17 10:05:30 -05:00
repo-ranger[bot]
dc7affa28c Merge pull request #42 from mxcl/path-components
Add Path.components
2019-02-15 18:49:13 +00:00
Max Howell
476cdc1461 Add Path.components 2019-02-15 13:38:36 -05:00
Max Howell
a644208c62 Test Swift 4.0.3 also 2019-02-13 21:34:35 -05:00
Max Howell
d7a9819350 Fix publishing the release in the deploy stage
[ci skip]
2019-02-13 20:52:39 -05:00
repo-ranger[bot]
24a54c2ee0 Merge pull request #39 from mxcl/less-manifests-test
You can specify future Swifts in a 4.2 manifest!
2019-02-14 01:00:02 +00:00
Max Howell
3735ed4476 You can specify future Swifts in a 4.2 manifest! 2019-02-13 19:40:07 -05:00
12 changed files with 173 additions and 82 deletions

22
.github/deploy vendored
View File

@@ -5,7 +5,7 @@ import PMKFoundation // PromiseKit/Foundation ~> 3.3
import LegibleError // @mxcl ~> 1.0 import LegibleError // @mxcl ~> 1.0
import Foundation import Foundation
import PromiseKit // @mxcl ~> 6.8 import PromiseKit // @mxcl ~> 6.8
import Path // mxcl/Path.swift == master import Path // mxcl/Path.swift ~> 0.15
let env = ProcessInfo.processInfo.environment let env = ProcessInfo.processInfo.environment
let token = env["GITHUB_TOKEN"] ?? env["GITHUB_ACCESS_TOKEN"]! let token = env["GITHUB_TOKEN"] ?? env["GITHUB_ACCESS_TOKEN"]!
@@ -17,13 +17,7 @@ func fatal(message: String) -> Never {
exit(1) exit(1)
} }
func fatal(error: Error) -> Never { func fatal(error: Error) -> Never {
fatal(message: error.legibleLocalizedDescription) fatal(message: "\(error.legibleLocalizedDescription)\n\n\(error.legibleDescription)")
}
guard let licenseFile = try Path.cwd.ls().files.first(where: {
$0.basename().hasPrefix("LICENSE")
})?.basename() else {
fatal(message: "no LICENSE file found")
} }
struct Repo: Decodable { struct Repo: Decodable {
@@ -121,12 +115,12 @@ func podspec(repo: Repo, user: User, pkg: Package) -> (Substring, String) {
return (name, """ return (name, """
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = '\(name)' s.name = '\(name)'
s.version = '\(tag)'
s.summary = '\(repo.description)'
s.homepage = "https://github.com/\(slug)"
s.license = { type: '\(repo.license.spdx_id)', file: '\(licenseFile)' }
s.author = { '\(user.name)': '\(user.email)' } s.author = { '\(user.name)': '\(user.email)' }
s.source = { git: "https://github.com/\(slug).git", tag: '\(tag)' } s.source = { git: "https://github.com/\(slug).git", tag: '\(tag)' }
s.version = '\(tag)'
s.summary = '\(repo.description)'
s.license = '\(repo.license.spdx_id)'
s.homepage = "https://github.com/\(slug)"
s.social_media_url = 'https://twitter.com/\(owner)' s.social_media_url = 'https://twitter.com/\(owner)'
s.osx.deployment_target = '10.10' s.osx.deployment_target = '10.10'
s.ios.deployment_target = '8.0' s.ios.deployment_target = '8.0'
@@ -140,8 +134,8 @@ func podspec(repo: Repo, user: User, pkg: Package) -> (Substring, String) {
func publishRelease() throws -> Promise<Void> { func publishRelease() throws -> Promise<Void> {
struct Input: Encodable { struct Input: Encodable {
var tag_name: String { return tag } let tag_name = tag
var name: String { return tag } let name = tag
let body = "" let body = ""
} }

View File

@@ -15,8 +15,12 @@ xcode_scheme: Path.swift-Package
jobs: jobs:
include: include:
- name: macOS / Swift 4.0.3
script: swift test --parallel -Xswiftc -swift-version -Xswiftc 4
- name: macOS / Swift 4.2.1 - name: macOS / Swift 4.2.1
script: swift test --parallel script: swift test --parallel
- name: macOS / Swift 5.0 - name: macOS / Swift 5.0
osx_image: xcode10.2 osx_image: xcode10.2
script: swift test --parallel script: swift test --parallel
@@ -26,9 +30,11 @@ jobs:
xcode_destination: platform=iOS Simulator,OS=latest,name=iPhone XS xcode_destination: platform=iOS Simulator,OS=latest,name=iPhone XS
name: iOS / Swift 4.2.1 name: iOS / Swift 4.2.1
after_success: bash <(curl -s https://codecov.io/bash) after_success: bash <(curl -s https://codecov.io/bash)
- <<: *xcodebuild - <<: *xcodebuild
xcode_destination: platform=tvOS Simulator,OS=latest,name=Apple TV xcode_destination: platform=tvOS Simulator,OS=latest,name=Apple TV
name: tvOS / Swift 4.2.1 name: tvOS / Swift 4.2.1
- <<: *xcodebuild - <<: *xcodebuild
name: watchOS / Swift 4.2.1 name: watchOS / Swift 4.2.1
script: | script: |
@@ -52,12 +58,13 @@ jobs:
- <<: *linux - <<: *linux
env: SWIFT_VERSION='5.0-DEVELOPMENT-SNAPSHOT-2019-01-22-a' env: SWIFT_VERSION='5.0-DEVELOPMENT-SNAPSHOT-2019-01-22-a'
name: Linux / Swift 5.0.0-dev+2019-01-22 name: Linux / Swift 5.0.0-dev+2019.01.22
- stage: pretest - stage: pretest
name: Check Linux tests are syncd name: Check Linux tests are syncd
install: swift test --generate-linuxmain install: swift test --generate-linuxmain
script: git diff --exit-code script: git diff --exit-code
osx_image: xcode10.2
- stage: deploy - stage: deploy
name: Jazzy name: Jazzy

View File

@@ -10,5 +10,5 @@ let pkg = Package(
.target(name: "Path", path: "Sources"), .target(name: "Path", path: "Sources"),
.testTarget(name: "PathTests", dependencies: ["Path"]), .testTarget(name: "PathTests", dependencies: ["Path"]),
], ],
swiftLanguageVersions: [.v4, .v4_2] swiftLanguageVersions: [.v4, .v4_2, .version("5")]
) )

View File

@@ -1,14 +0,0 @@
// swift-tools-version:5.0
import PackageDescription
let pkg = Package(
name: "Path.swift",
products: [
.library(name: "Path", targets: ["Path"]),
],
targets: [
.target(name: "Path", path: "Sources"),
.testTarget(name: "PathTests", dependencies: ["Path"]),
],
swiftLanguageVersions: [.v4, .v4_2, .v5]
)

View File

@@ -53,7 +53,7 @@ help me continue my work, I appreciate it x
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160"> <img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a> </a>
[Other donation/tipping options](http://mxcl.github.io/donate/) [Other donation/tipping options](http://mxcl.dev/#donate)
# Handbook # Handbook
@@ -258,9 +258,15 @@ for that as the check was deemed too expensive to be worthwhile.
equality check is required. equality check is required.
* There are several symlink paths on Mac that are typically automatically * There are several symlink paths on Mac that are typically automatically
resolved by Foundation, eg. `/private`, we attempt to do the same for resolved by Foundation, eg. `/private`, we attempt to do the same for
functions that you would expect it (notably `realpath`), but we do *not* for functions that you would expect it (notably `realpath`), we *do* the same for
`Path.init`, *nor* if you are joining a path that ends up being one of these `Path.init`, but *do not* if you are joining a path that ends up being one of
paths, (eg. `Path.root.join("var/private')`). these paths, (eg. `Path.root.join("var/private')`).
If a `Path` is a symlink but the destination of the link does not exist `exists`
returns `false`. This seems to be the correct thing to do since symlinks are
meant to be an abstraction for filesystems. To instead verify that there is
no filesystem entry there at all check if `kind` is `nil`.
## We do not provide change directory functionality ## We do not provide change directory functionality
@@ -316,7 +322,7 @@ pursuit of getting it *right*)! We will tag 1.0 as soon as possible.
### Get push notifications for new releases ### Get push notifications for new releases
https://codebasesaga.com/canopy/ https://mxcl.dev/canopy/
# Alternatives # Alternatives
@@ -328,7 +334,7 @@ https://codebasesaga.com/canopy/
[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgrey.svg [badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgrey.svg
[badge-languages]: https://img.shields.io/badge/swift-4.2%20%7C%205.0-orange.svg [badge-languages]: https://img.shields.io/badge/swift-4.2%20%7C%205.0-orange.svg
[docs]: https://mxcl.github.io/Path.swift/Structs/Path.html [docs]: https://mxcl.dev/Path.swift/Structs/Path.html
[badge-jazzy]: https://raw.githubusercontent.com/mxcl/Path.swift/gh-pages/badge.svg?sanitize=true [badge-jazzy]: https://raw.githubusercontent.com/mxcl/Path.swift/gh-pages/badge.svg?sanitize=true
[badge-codecov]: https://codecov.io/gh/mxcl/Path.swift/branch/master/graph/badge.svg [badge-codecov]: https://codecov.io/gh/mxcl/Path.swift/branch/master/graph/badge.svg
[badge-ci]: https://travis-ci.com/mxcl/Path.swift.svg [badge-ci]: https://travis-ci.com/mxcl/Path.swift.svg

View File

@@ -34,6 +34,11 @@ public extension Bundle {
var path: Path { var path: Path {
return Path(string: bundlePath) return Path(string: bundlePath)
} }
/// Returns the executable for this bundle, if there is one, not all bundles have one hence `Optional`.
var executable: Path? {
return executablePath.flatMap(Path.init)
}
} }
/// Extensions on `String` that work with `Path` rather than `String` or `URL` /// Extensions on `String` that work with `Path` rather than `String` or `URL`

View File

@@ -83,4 +83,22 @@ public extension Path {
#endif #endif
return self return self
} }
enum Kind {
case file, symlink, directory
}
var kind: Kind? {
var buf = stat()
guard lstat(string, &buf) == 0 else {
return nil
}
if buf.st_mode & S_IFMT == S_IFLNK {
return .symlink
} else if buf.st_mode & S_IFMT == S_IFDIR {
return .directory
} else {
return .file
}
}
} }

View File

@@ -25,11 +25,11 @@ public extension Path {
*/ */
@discardableResult @discardableResult
func copy(to: Path, overwrite: Bool = false) throws -> Path { func copy(to: Path, overwrite: Bool = false) throws -> Path {
if overwrite, to.isFile, isFile { if overwrite, let tokind = to.kind, tokind != .directory, kind != .directory {
try FileManager.default.removeItem(at: to.url) try FileManager.default.removeItem(at: to.url)
} }
#if os(Linux) && !swift(>=5.1) // check if fixed #if os(Linux) && !swift(>=5.1) // check if fixed
if !overwrite, to.isFile { if !overwrite, to.kind != nil {
throw CocoaError.error(.fileWriteFileExists) throw CocoaError.error(.fileWriteFileExists)
} }
#endif #endif
@@ -61,15 +61,15 @@ public extension Path {
*/ */
@discardableResult @discardableResult
func copy(into: Path, overwrite: Bool = false) throws -> Path { func copy(into: Path, overwrite: Bool = false) throws -> Path {
if !into.exists { if into.kind == nil {
try into.mkdir(.p) try into.mkdir(.p)
} }
let rv = into/basename() let rv = into/basename()
if overwrite, rv.isFile { if overwrite, let kind = rv.kind, kind != .directory {
try rv.delete() try FileManager.default.removeItem(at: rv.url)
} }
#if os(Linux) && !swift(>=5.1) // check if fixed #if os(Linux) && !swift(>=5.1) // check if fixed
if !overwrite, rv.isFile { if !overwrite, rv.kind != nil {
throw CocoaError.error(.fileWriteFileExists) throw CocoaError.error(.fileWriteFileExists)
} }
#endif #endif
@@ -95,7 +95,7 @@ public extension Path {
*/ */
@discardableResult @discardableResult
func move(to: Path, overwrite: Bool = false) throws -> Path { func move(to: Path, overwrite: Bool = false) throws -> Path {
if overwrite, to.isFile { if overwrite, let kind = to.kind, kind != .directory {
try FileManager.default.removeItem(at: to.url) try FileManager.default.removeItem(at: to.url)
} }
try FileManager.default.moveItem(at: url, to: to.url) try FileManager.default.moveItem(at: url, to: to.url)
@@ -119,17 +119,21 @@ public extension Path {
*/ */
@discardableResult @discardableResult
func move(into: Path, overwrite: Bool = false) throws -> Path { func move(into: Path, overwrite: Bool = false) throws -> Path {
if !into.exists { switch into.kind {
case nil:
try into.mkdir(.p) try into.mkdir(.p)
} else if !into.isDirectory { fallthrough
throw CocoaError.error(.fileWriteFileExists) case .directory?:
}
let rv = into/basename() let rv = into/basename()
if overwrite, rv.isFile { if overwrite, let rvkind = rv.kind, rvkind != .directory {
try FileManager.default.removeItem(at: rv.url) try FileManager.default.removeItem(at: rv.url)
} }
try FileManager.default.moveItem(at: url, to: rv.url) try FileManager.default.moveItem(at: url, to: rv.url)
return rv return rv
case .file?, .symlink?:
throw CocoaError.error(.fileWriteFileExists)
}
} }
/** /**
@@ -138,11 +142,12 @@ public extension Path {
*Path.swift* doesnt error if desired end result preexists. *Path.swift* doesnt error if desired end result preexists.
- Note: On UNIX will this function will succeed if the parent directory is writable and the current user has permission. - Note: On UNIX will this function will succeed if the parent directory is writable and the current user has permission.
- Note: This function will fail if the file or directory is locked - Note: This function will fail if the file or directory is locked
- Note: If entry is a symlink, deletes the symlink.
- SeeAlso: `lock()` - SeeAlso: `lock()`
*/ */
@inlinable @inlinable
func delete() throws { func delete() throws {
if exists { if kind != nil {
try FileManager.default.removeItem(at: url) try FileManager.default.removeItem(at: url)
} }
} }
@@ -154,7 +159,7 @@ public extension Path {
@inlinable @inlinable
@discardableResult @discardableResult
func touch() throws -> Path { func touch() throws -> Path {
if !exists { if kind == nil {
guard FileManager.default.createFile(atPath: string, contents: nil) else { guard FileManager.default.createFile(atPath: string, contents: nil) else {
throw CocoaError.error(.fileWriteUnknown) throw CocoaError.error(.fileWriteUnknown)
} }
@@ -228,14 +233,17 @@ public extension Path {
*/ */
@discardableResult @discardableResult
func symlink(into dir: Path) throws -> Path { func symlink(into dir: Path) throws -> Path {
if !dir.exists { switch dir.kind {
case nil, .symlink?:
try dir.mkdir(.p) try dir.mkdir(.p)
} else if !dir.isDirectory { fallthrough
throw CocoaError.error(.fileWriteFileExists) case .directory?:
}
let dst = dir/basename() let dst = dir/basename()
try FileManager.default.createSymbolicLink(atPath: dst.string, withDestinationPath: string) try FileManager.default.createSymbolicLink(atPath: dst.string, withDestinationPath: string)
return dst return dst
case .file?:
throw CocoaError.error(.fileWriteFileExists)
}
} }
} }

View File

@@ -8,7 +8,10 @@ import Darwin
public extension Path { public extension Path {
//MARK: Filesystem Properties //MARK: Filesystem Properties
/// Returns true if the path represents an actual filesystem entry. /**
- Returns: `true` if the path represents an actual filesystem entry.
- Note: If `self` is a symlink the return value represents the destination.
*/
var exists: Bool { var exists: Bool {
return FileManager.default.fileExists(atPath: string) return FileManager.default.fileExists(atPath: string)
} }

View File

@@ -53,11 +53,25 @@ public struct Path: Equatable, Hashable, Comparable {
- Note: On macOS, removes an initial component of /private/var/automount, /var/automount, or /private from the path, if the result still indicates an existing file or directory (checked by consulting the file system). - Note: On macOS, removes an initial component of /private/var/automount, /var/automount, or /private from the path, if the result still indicates an existing file or directory (checked by consulting the file system).
- Returns: The path or `nil` if fed a relative path or a `~foo` string where there is no user `foo`. - Returns: The path or `nil` if fed a relative path or a `~foo` string where there is no user `foo`.
*/ */
public init?(_ description: String) { public init?<S: StringProtocol>(_ description: S) {
var pathComponents = description.split(separator: "/") var pathComponents = description.split(separator: "/")
switch description.first { switch description.first {
case "/": case "/":
break #if os(macOS)
func ifExists(withPrefix prefix: String, removeFirst n: Int) {
assert(prefix.split(separator: "/").count == n)
if description.hasPrefix(prefix), FileManager.default.fileExists(atPath: String(description)) {
pathComponents.removeFirst(n)
}
}
ifExists(withPrefix: "/private/var/automount", removeFirst: 3)
ifExists(withPrefix: "/var/automount", removeFirst: 2)
ifExists(withPrefix: "/private", removeFirst: 1)
#endif
self.string = join_(prefix: "/", pathComponents: pathComponents)
case "~": case "~":
if description == "~" { if description == "~" {
self = Path.home self = Path.home
@@ -82,26 +96,11 @@ public struct Path: Equatable, Hashable, Comparable {
#endif #endif
} }
pathComponents.remove(at: 0) pathComponents.remove(at: 0)
pathComponents.insert(contentsOf: tilded.split(separator: "/"), at: 0) self.string = join_(prefix: tilded, pathComponents: pathComponents)
default: default:
return nil return nil
} }
#if os(macOS)
func ifExists(withPrefix prefix: String, removeFirst n: Int) {
assert(prefix.split(separator: "/").count == n)
if description.hasPrefix(prefix), FileManager.default.fileExists(atPath: description) {
pathComponents.removeFirst(n)
}
}
ifExists(withPrefix: "/private/var/automount", removeFirst: 3)
ifExists(withPrefix: "/var/automount", removeFirst: 2)
ifExists(withPrefix: "/private", removeFirst: 1)
#endif
self.string = join_(prefix: "/", pathComponents: pathComponents)
} }
/** /**
@@ -200,6 +199,15 @@ public struct Path: Equatable, Hashable, Comparable {
} }
} }
/**
Splits the string representation on the directory separator.
- Important: The first element is always "/" to be consistent with `NSString.pathComponents`.
*/
@inlinable
public var components: [String] {
return ["/"] + string.split(separator: "/").map(String.init)
}
//MARK: Pathing //MARK: Pathing
/** /**

View File

@@ -69,9 +69,18 @@ class PathTests: XCTestCase {
XCTAssertEqual((Path.root/"tmp/foo/bar").relative(to: .root/"tmp/baz"), "../foo/bar") XCTAssertEqual((Path.root/"tmp/foo/bar").relative(to: .root/"tmp/baz"), "../foo/bar")
} }
func testExists() { func testExists() throws {
XCTAssert(Path.root.exists) XCTAssert(Path.root.exists)
XCTAssert((Path.root/"bin").exists) XCTAssert((Path.root/"bin").exists)
try Path.mktemp { tmpdir in
XCTAssertTrue(tmpdir.exists)
XCTAssertFalse(try tmpdir.bar.symlink(as: tmpdir.foo).exists)
XCTAssertTrue(tmpdir.foo.kind == .symlink)
XCTAssertTrue(try tmpdir.bar.touch().symlink(as: tmpdir.baz).exists)
XCTAssertTrue(tmpdir.bar.kind == .file)
XCTAssertTrue(tmpdir.kind == .directory)
}
} }
func testIsDirectory() { func testIsDirectory() {
@@ -379,6 +388,21 @@ class PathTests: XCTestCase {
#if !os(Linux) #if !os(Linux)
XCTAssertThrowsError(try tmpdir.bar3.touch().lock().delete()) XCTAssertThrowsError(try tmpdir.bar3.touch().lock().delete())
#endif #endif
// regression test: can delete a symlink that points to a non-existent file
let bar5 = try tmpdir.bar4.symlink(as: tmpdir.bar5)
XCTAssertEqual(bar5.kind, .symlink)
XCTAssertFalse(bar5.exists)
XCTAssertNoThrow(try bar5.delete())
XCTAssertEqual(bar5.kind, nil)
// test that deleting a symlink *only* deletes the symlink
let bar7 = try tmpdir.bar6.touch().symlink(as: tmpdir.bar7)
XCTAssertEqual(bar7.kind, .symlink)
XCTAssertTrue(bar7.exists)
XCTAssertNoThrow(try bar7.delete())
XCTAssertEqual(bar7.kind, nil)
XCTAssertEqual(tmpdir.bar6.kind, .file)
} }
} }
@@ -403,6 +427,7 @@ class PathTests: XCTestCase {
XCTAssertEqual(bndl.privateFrameworks, tmpdir.Frameworks) XCTAssertEqual(bndl.privateFrameworks, tmpdir.Frameworks)
XCTAssertEqual(bndl.resources, tmpdir) XCTAssertEqual(bndl.resources, tmpdir)
XCTAssertNil(bndl.path(forResource: "foo", ofType: "bar")) XCTAssertNil(bndl.path(forResource: "foo", ofType: "bar"))
XCTAssertNil(bndl.executable)
#if os(macOS) #if os(macOS)
XCTAssertEqual(bndl.defaultSharedFrameworksPath, tmpdir.Contents.Frameworks) XCTAssertEqual(bndl.defaultSharedFrameworksPath, tmpdir.Contents.Frameworks)
@@ -588,4 +613,29 @@ class PathTests: XCTestCase {
XCTAssertNil(Path("../foo")) XCTAssertNil(Path("../foo"))
XCTAssertNil(Path("./foo")) XCTAssertNil(Path("./foo"))
} }
func testPathComponents() throws {
XCTAssertEqual(Path.root.foo.bar.components, ["/", "foo", "bar"])
XCTAssertEqual(Path.root.components, ["/"])
}
func testFlatMap() throws {
// testing compile works
let foo: String? = "/a"
_ = foo.flatMap(Path.init)
let bar: Substring? = "/a"
_ = bar.flatMap(Path.init)
let baz: String.SubSequence? = "/a/b:1".split(separator: ":").first
_ = baz.flatMap(Path.init)
}
func testKind() throws {
try Path.mktemp { tmpdir in
let foo = try tmpdir.foo.touch()
let bar = try foo.symlink(as: tmpdir.bar)
XCTAssertEqual(tmpdir.kind, .directory)
XCTAssertEqual(foo.kind, .file)
XCTAssertEqual(bar.kind, .symlink)
}
}
} }

View File

@@ -1,7 +1,11 @@
#if !canImport(ObjectiveC)
import XCTest import XCTest
extension PathTests { extension PathTests {
static let __allTests = [ // DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__PathTests = [
("testBasename", testBasename), ("testBasename", testBasename),
("testBundleExtensions", testBundleExtensions), ("testBundleExtensions", testBundleExtensions),
("testCodable", testCodable), ("testCodable", testCodable),
@@ -19,15 +23,18 @@ extension PathTests {
("testFileHandleExtensions", testFileHandleExtensions), ("testFileHandleExtensions", testFileHandleExtensions),
("testFileReference", testFileReference), ("testFileReference", testFileReference),
("testFilesystemAttributes", testFilesystemAttributes), ("testFilesystemAttributes", testFilesystemAttributes),
("testFlatMap", testFlatMap),
("testInitializerForRelativePath", testInitializerForRelativePath), ("testInitializerForRelativePath", testInitializerForRelativePath),
("testIsDirectory", testIsDirectory), ("testIsDirectory", testIsDirectory),
("testJoin", testJoin), ("testJoin", testJoin),
("testKind", testKind),
("testLock", testLock), ("testLock", testLock),
("testMkpathIfExists", testMkpathIfExists), ("testMkpathIfExists", testMkpathIfExists),
("testMktemp", testMktemp), ("testMktemp", testMktemp),
("testMoveInto", testMoveInto), ("testMoveInto", testMoveInto),
("testMoveTo", testMoveTo), ("testMoveTo", testMoveTo),
("testNoUndesiredSymlinkResolution", testNoUndesiredSymlinkResolution), ("testNoUndesiredSymlinkResolution", testNoUndesiredSymlinkResolution),
("testPathComponents", testPathComponents),
("testReadlinkOnFileReturnsSelf", testReadlinkOnFileReturnsSelf), ("testReadlinkOnFileReturnsSelf", testReadlinkOnFileReturnsSelf),
("testReadlinkOnNonExistantFileThrows", testReadlinkOnNonExistantFileThrows), ("testReadlinkOnNonExistantFileThrows", testReadlinkOnNonExistantFileThrows),
("testReadlinkOnRelativeSymlink", testReadlinkOnRelativeSymlink), ("testReadlinkOnRelativeSymlink", testReadlinkOnRelativeSymlink),
@@ -47,10 +54,9 @@ extension PathTests {
] ]
} }
#if !os(macOS)
public func __allTests() -> [XCTestCaseEntry] { public func __allTests() -> [XCTestCaseEntry] {
return [ return [
testCase(PathTests.__allTests), testCase(PathTests.__allTests__PathTests),
] ]
} }
#endif #endif