Merge pull request #10 from mxcl/fixes

Swift 5 / Xcode 10.2 / Fixes
This commit is contained in:
Max Howell
2019-01-25 11:04:35 -05:00
committed by GitHub
5 changed files with 48 additions and 51 deletions

View File

@@ -15,7 +15,7 @@ xcode_scheme: Path.swift-Package
jobs: jobs:
include: include:
- script: swift test - script: swift test --parallel
name: macOS name: macOS
- &xcodebuild - &xcodebuild
@@ -35,14 +35,19 @@ jobs:
-destination 'platform=watchOS Simulator,OS=latest,name=Apple Watch Series 4 - 40mm' \ -destination 'platform=watchOS Simulator,OS=latest,name=Apple Watch Series 4 - 40mm' \
build | xcpretty build | xcpretty
- env: SWIFT_VERSION=4.2.1 - &linux
env: SWIFT_VERSION=4.2.1
os: linux os: linux
name: Linux name: Linux / Swift 4.2.1
language: generic language: generic
dist: trusty dist: trusty
sudo: false sudo: false
install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
script: swift test script: swift test --parallel
- <<: *linux
env: SWIFT_VERSION='5.0-DEVELOPMENT-SNAPSHOT-2019-01-22-a'
name: Linux / Swift 5.0.0-dev (2019-01-22)
- stage: pretest - stage: pretest
name: Check if Linux tests are up-to-date name: Check if Linux tests are up-to-date

20
Package@swift-5.0.swift Normal file
View File

@@ -0,0 +1,20 @@
// 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"]),
]
)
pkg.platforms = [
.macOS(.v10_10), .iOS(.v8), .tvOS(.v10), .watchOS(.v3)
]
pkg.swiftLanguageVersions = [
.v4_2, .v5
]

View File

@@ -10,17 +10,17 @@ public extension Bundle {
} }
/// Returns the path for the shared-frameworks directory in this bundle. /// Returns the path for the shared-frameworks directory in this bundle.
public var sharedFrameworks: Path? { var sharedFrameworks: Path? {
return sharedFrameworksPath.flatMap(Path.init) return sharedFrameworksPath.flatMap(Path.init)
} }
/// Returns the path for the resources directory in this bundle. /// Returns the path for the resources directory in this bundle.
public var resources: Path? { var resources: Path? {
return resourcePath.flatMap(Path.init) return resourcePath.flatMap(Path.init)
} }
/// Returns the path for this bundle. /// Returns the path for this bundle.
public var path: Path { var path: Path {
return Path(string: bundlePath) return Path(string: bundlePath)
} }
} }

View File

@@ -4,7 +4,7 @@ public extension Path {
/// - Note: If file is already locked, does nothing /// - Note: If file is already locked, does nothing
/// - Note: If file doesnt exist, throws /// - Note: If file doesnt exist, throws
@discardableResult @discardableResult
public func lock() throws -> Path { func lock() throws -> Path {
var attrs = try FileManager.default.attributesOfItem(atPath: string) var attrs = try FileManager.default.attributesOfItem(atPath: string)
let b = attrs[.immutable] as? Bool ?? false let b = attrs[.immutable] as? Bool ?? false
if !b { if !b {
@@ -17,7 +17,7 @@ public extension Path {
/// - Note: If file isnt locked, does nothing /// - Note: If file isnt locked, does nothing
/// - Note: If file doesnt exist, does nothing /// - Note: If file doesnt exist, does nothing
@discardableResult @discardableResult
public func unlock() throws -> Path { func unlock() throws -> Path {
var attrs: [FileAttributeKey: Any] var attrs: [FileAttributeKey: Any]
do { do {
attrs = try FileManager.default.attributesOfItem(atPath: string) attrs = try FileManager.default.attributesOfItem(atPath: string)
@@ -38,7 +38,7 @@ public extension Path {
Path.home.join("foo").chmod(0o555) Path.home.join("foo").chmod(0o555)
*/ */
@discardableResult @discardableResult
public func chmod(_ octal: Int) throws -> Path { func chmod(_ octal: Int) throws -> Path {
try FileManager.default.setAttributes([.posixPermissions: octal], ofItemAtPath: string) try FileManager.default.setAttributes([.posixPermissions: octal], ofItemAtPath: string)
return self return self
} }
@@ -48,10 +48,10 @@ public extension Path {
- Note: Returns the creation time if there is no modification time. - Note: Returns the creation time if there is no modification time.
- Note: Returns UNIX-time-zero if neither are available, though this *should* be impossible. - Note: Returns UNIX-time-zero if neither are available, though this *should* be impossible.
*/ */
public var mtime: Date { var mtime: Date {
do { do {
let attrs = try FileManager.default.attributesOfItem(atPath: string) let attrs = try FileManager.default.attributesOfItem(atPath: string)
return attrs[.modificationDate] as? Date ?? attrs[.creationDate] as? Date ?? Date() return attrs[.modificationDate] as? Date ?? attrs[.creationDate] as? Date ?? Date(timeIntervalSince1970: 0)
} catch { } catch {
//TODO log error //TODO log error
return Date(timeIntervalSince1970: 0) return Date(timeIntervalSince1970: 0)

View File

@@ -5,13 +5,14 @@ public extension Path {
Copies a file. Copies a file.
- Note: `throws` if `to` is a directory. - Note: `throws` if `to` is a directory.
- Parameter to: Destination filename. - Parameter to: Destination filename.
- Parameter overwrite: If true overwrites any file that already exists at `to`. - Parameter overwrite: If `true` and both `self` and `to` are files, overwrites `to`.
- Note: If either `self` or `to are directories, `overwrite` is ignored.
- Returns: `to` to allow chaining - Returns: `to` to allow chaining
- SeeAlso: `copy(into:overwrite:)` - SeeAlso: `copy(into:overwrite:)`
*/ */
@discardableResult @discardableResult
public func copy(to: Path, overwrite: Bool = false) throws -> Path { func copy(to: Path, overwrite: Bool = false) throws -> Path {
if overwrite, to.exists { if overwrite, to.isFile, isFile {
try FileManager.default.removeItem(at: to.url) try FileManager.default.removeItem(at: to.url)
} }
try FileManager.default.copyItem(atPath: string, toPath: to.string) try FileManager.default.copyItem(atPath: string, toPath: to.string)
@@ -33,7 +34,7 @@ public extension Path {
- SeeAlso: `copy(into:overwrite:)` - SeeAlso: `copy(into:overwrite:)`
*/ */
@discardableResult @discardableResult
public func copy(into: Path, overwrite: Bool = false) throws -> Path { func copy(into: Path, overwrite: Bool = false) throws -> Path {
if !into.exists { if !into.exists {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
} }
@@ -42,7 +43,7 @@ public extension Path {
try rv.delete() try rv.delete()
} }
#if os(Linux) #if os(Linux)
#if swift(>=5) #if swift(>=5.1)
// check if fixed // check if fixed
#else #else
if !overwrite, rv.isFile { if !overwrite, rv.isFile {
@@ -63,7 +64,7 @@ public extension Path {
- SeeAlso: move(into:overwrite:) - SeeAlso: move(into:overwrite:)
*/ */
@discardableResult @discardableResult
public func move(to: Path, overwrite: Bool = false) throws -> Path { func move(to: Path, overwrite: Bool = false) throws -> Path {
if overwrite, to.exists { if overwrite, to.exists {
try FileManager.default.removeItem(at: to.url) try FileManager.default.removeItem(at: to.url)
} }
@@ -83,7 +84,7 @@ public extension Path {
- SeeAlso: move(into:overwrite:) - SeeAlso: move(into:overwrite:)
*/ */
@discardableResult @discardableResult
public func move(into: Path) throws -> Path { func move(into: Path) throws -> Path {
if !into.exists { if !into.exists {
try into.mkpath() try into.mkpath()
} else if !into.isDirectory { } else if !into.isDirectory {
@@ -96,7 +97,7 @@ public extension Path {
/// Deletes the path, recursively if a directory. /// Deletes the path, recursively if a directory.
@inlinable @inlinable
public func delete() throws { func delete() throws {
try FileManager.default.removeItem(at: url) try FileManager.default.removeItem(at: url)
} }
@@ -136,7 +137,7 @@ public extension Path {
- Returns: `self` to allow chaining. - Returns: `self` to allow chaining.
*/ */
@discardableResult @discardableResult
public func mkdir() throws -> Path { func mkdir() throws -> Path {
try _foo { try _foo {
try FileManager.default.createDirectory(at: self.url, withIntermediateDirectories: false, attributes: nil) try FileManager.default.createDirectory(at: self.url, withIntermediateDirectories: false, attributes: nil)
} }
@@ -149,39 +150,10 @@ public extension Path {
- Returns: `self` to allow chaining. - Returns: `self` to allow chaining.
*/ */
@discardableResult @discardableResult
public func mkpath() throws -> Path { func mkpath() throws -> Path {
try _foo { try _foo {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
} }
return self return self
} }
/**
Replaces the contents of the file at this path with the provided string.
- Note: If file doesnt exist, creates file
- Note: If file is not writable, makes writable first, resetting permissions after the write
- Parameter contents: The string that will become the contents of this file.
- Parameter atomically: If `true` the operation will be performed atomically.
- Parameter encoding: The string encoding to use.
- Returns: `self` to allow chaining.
*/
@discardableResult
public func replaceContents(with contents: String, atomically: Bool = false, encoding: String.Encoding = .utf8) throws -> Path {
let resetPerms: Int?
if exists, !isWritable {
resetPerms = try FileManager.default.attributesOfItem(atPath: string)[.posixPermissions] as? Int
let perms = resetPerms ?? 0o777
try chmod(perms | 0o200)
} else {
resetPerms = nil
}
defer {
_ = try? resetPerms.map(self.chmod)
}
try contents.write(to: self)
return self
}
} }