Compare commits

..

11 Commits

Author SHA1 Message Date
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
9 changed files with 76 additions and 55 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
@@ -316,7 +316,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 +328,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

@@ -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

@@ -403,6 +403,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 +589,19 @@ 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)
}
} }

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,6 +23,7 @@ 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),
@@ -28,6 +33,7 @@ extension PathTests {
("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 +53,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