From de4fb3ae470ccd07831eb4f9b34905e16bcc35e5 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Tue, 22 Jan 2019 17:57:28 -0500 Subject: [PATCH 1/8] Remove replaceContents, user can use String.write --- Sources/Path+FileManager.swift | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/Sources/Path+FileManager.swift b/Sources/Path+FileManager.swift index 2202229..0ab6be8 100644 --- a/Sources/Path+FileManager.swift +++ b/Sources/Path+FileManager.swift @@ -23,8 +23,8 @@ public extension Path { If the destination does not exist, this function creates the directory first. - // Create ~/.local/bin, copy `ls` there and make the new copy executable - try Path.root.join("bin/ls").copy(into: Path.home.join(".local/bin").mkpath()).chmod(0o500) + // Create ~/.local/bin, copy `ls` there and make the new copy executable + try Path.root.join("bin/ls").copy(into: Path.home.join(".local/bin").mkpath()).chmod(0o500) - Note: `throws` if `into` is a file. - Parameter into: Destination directory @@ -155,33 +155,4 @@ public extension Path { } return self } - - /** - Replaces the contents of the file at this path with the provided string. - - Note: If file doesn’t 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 - } } From ca9f1e0a74c51954d0d5db43a5d4a9fb85a07c2f Mon Sep 17 00:00:00 2001 From: Max Howell Date: Wed, 23 Jan 2019 11:25:51 -0500 Subject: [PATCH 2/8] Parallelize tests --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 61e0dca..3bd94d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ xcode_scheme: Path.swift-Package jobs: include: - - script: swift test + - script: swift test --parallel name: macOS - &xcodebuild @@ -42,7 +42,7 @@ jobs: dist: trusty sudo: false install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" - script: swift test + script: swift test --parallel - stage: pretest name: Check if Linux tests are up-to-date From 9eca479f7b5375f1f1cfbd91f11ca8908aaafa48 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Thu, 24 Jan 2019 14:43:45 -0500 Subject: [PATCH 3/8] Fix mtime return so it is as per doc contract --- Sources/Path+Attributes.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Path+Attributes.swift b/Sources/Path+Attributes.swift index 613c473..d10d2c7 100644 --- a/Sources/Path+Attributes.swift +++ b/Sources/Path+Attributes.swift @@ -51,7 +51,7 @@ public extension Path { public var mtime: Date { do { 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 { //TODO log error return Date(timeIntervalSince1970: 0) From 80960f5876a473b86519ebf5d3626f36c32a4251 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Thu, 24 Jan 2019 14:44:01 -0500 Subject: [PATCH 4/8] =?UTF-8?q?Don=E2=80=99t=20overwrite=20a=20file=20with?= =?UTF-8?q?=20a=20directory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/Path+FileManager.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/Path+FileManager.swift b/Sources/Path+FileManager.swift index 0ab6be8..6e4fb6f 100644 --- a/Sources/Path+FileManager.swift +++ b/Sources/Path+FileManager.swift @@ -5,13 +5,14 @@ public extension Path { Copies a file. - Note: `throws` if `to` is a directory. - 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 - SeeAlso: `copy(into:overwrite:)` */ @discardableResult public 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.copyItem(atPath: string, toPath: to.string) @@ -23,8 +24,8 @@ public extension Path { If the destination does not exist, this function creates the directory first. - // Create ~/.local/bin, copy `ls` there and make the new copy executable - try Path.root.join("bin/ls").copy(into: Path.home.join(".local/bin").mkpath()).chmod(0o500) + // Create ~/.local/bin, copy `ls` there and make the new copy executable + try Path.root.join("bin/ls").copy(into: Path.home.join(".local/bin").mkpath()).chmod(0o500) - Note: `throws` if `into` is a file. - Parameter into: Destination directory From 2388c384a1418e58a3118811fad56d418fc1361a Mon Sep 17 00:00:00 2001 From: Max Howell Date: Thu, 24 Jan 2019 19:44:14 +0000 Subject: [PATCH 5/8] Swift 5 Manifest (untested until Travis catches up) --- Package@swift-5.0.swift | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Package@swift-5.0.swift diff --git a/Package@swift-5.0.swift b/Package@swift-5.0.swift new file mode 100644 index 0000000..126ddc1 --- /dev/null +++ b/Package@swift-5.0.swift @@ -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 +] From fdff3bcc056cdb39e8001d31202103dfad837056 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Thu, 24 Jan 2019 15:02:03 -0500 Subject: [PATCH 6/8] Swift 5 --warnings --- Sources/Extensions.swift | 6 +++--- Sources/Path+Attributes.swift | 8 ++++---- Sources/Path+FileManager.swift | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Sources/Extensions.swift b/Sources/Extensions.swift index b3184ea..be9ec0a 100644 --- a/Sources/Extensions.swift +++ b/Sources/Extensions.swift @@ -10,17 +10,17 @@ public extension Bundle { } /// Returns the path for the shared-frameworks directory in this bundle. - public var sharedFrameworks: Path? { + var sharedFrameworks: Path? { return sharedFrameworksPath.flatMap(Path.init) } /// Returns the path for the resources directory in this bundle. - public var resources: Path? { + var resources: Path? { return resourcePath.flatMap(Path.init) } /// Returns the path for this bundle. - public var path: Path { + var path: Path { return Path(string: bundlePath) } } diff --git a/Sources/Path+Attributes.swift b/Sources/Path+Attributes.swift index d10d2c7..c30b940 100644 --- a/Sources/Path+Attributes.swift +++ b/Sources/Path+Attributes.swift @@ -4,7 +4,7 @@ public extension Path { /// - Note: If file is already locked, does nothing /// - Note: If file doesn’t exist, throws @discardableResult - public func lock() throws -> Path { + func lock() throws -> Path { var attrs = try FileManager.default.attributesOfItem(atPath: string) let b = attrs[.immutable] as? Bool ?? false if !b { @@ -17,7 +17,7 @@ public extension Path { /// - Note: If file isn‘t locked, does nothing /// - Note: If file doesn’t exist, does nothing @discardableResult - public func unlock() throws -> Path { + func unlock() throws -> Path { var attrs: [FileAttributeKey: Any] do { attrs = try FileManager.default.attributesOfItem(atPath: string) @@ -38,7 +38,7 @@ public extension Path { Path.home.join("foo").chmod(0o555) */ @discardableResult - public func chmod(_ octal: Int) throws -> Path { + func chmod(_ octal: Int) throws -> Path { try FileManager.default.setAttributes([.posixPermissions: octal], ofItemAtPath: string) return self } @@ -48,7 +48,7 @@ public extension Path { - 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. */ - public var mtime: Date { + var mtime: Date { do { let attrs = try FileManager.default.attributesOfItem(atPath: string) return attrs[.modificationDate] as? Date ?? attrs[.creationDate] as? Date ?? Date(timeIntervalSince1970: 0) diff --git a/Sources/Path+FileManager.swift b/Sources/Path+FileManager.swift index 6e4fb6f..498f028 100644 --- a/Sources/Path+FileManager.swift +++ b/Sources/Path+FileManager.swift @@ -11,7 +11,7 @@ public extension Path { - SeeAlso: `copy(into:overwrite:)` */ @discardableResult - public func copy(to: Path, overwrite: Bool = false) throws -> Path { + func copy(to: Path, overwrite: Bool = false) throws -> Path { if overwrite, to.isFile, isFile { try FileManager.default.removeItem(at: to.url) } @@ -34,7 +34,7 @@ public extension Path { - SeeAlso: `copy(into:overwrite:)` */ @discardableResult - public func copy(into: Path, overwrite: Bool = false) throws -> Path { + func copy(into: Path, overwrite: Bool = false) throws -> Path { if !into.exists { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) } @@ -64,7 +64,7 @@ public extension Path { - SeeAlso: move(into:overwrite:) */ @discardableResult - public func move(to: Path, overwrite: Bool = false) throws -> Path { + func move(to: Path, overwrite: Bool = false) throws -> Path { if overwrite, to.exists { try FileManager.default.removeItem(at: to.url) } @@ -84,7 +84,7 @@ public extension Path { - SeeAlso: move(into:overwrite:) */ @discardableResult - public func move(into: Path) throws -> Path { + func move(into: Path) throws -> Path { if !into.exists { try into.mkpath() } else if !into.isDirectory { @@ -97,7 +97,7 @@ public extension Path { /// Deletes the path, recursively if a directory. @inlinable - public func delete() throws { + func delete() throws { try FileManager.default.removeItem(at: url) } @@ -137,7 +137,7 @@ public extension Path { - Returns: `self` to allow chaining. */ @discardableResult - public func mkdir() throws -> Path { + func mkdir() throws -> Path { try _foo { try FileManager.default.createDirectory(at: self.url, withIntermediateDirectories: false, attributes: nil) } @@ -150,7 +150,7 @@ public extension Path { - Returns: `self` to allow chaining. */ @discardableResult - public func mkpath() throws -> Path { + func mkpath() throws -> Path { try _foo { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) } From 5f364fe21b207c324bda105c93d9e00823e4ce3f Mon Sep 17 00:00:00 2001 From: Max Howell Date: Fri, 25 Jan 2019 10:20:45 -0500 Subject: [PATCH 7/8] Test against Swift 5 snapshot --- .travis.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3bd94d1..598f1fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,15 +35,20 @@ jobs: -destination 'platform=watchOS Simulator,OS=latest,name=Apple Watch Series 4 - 40mm' \ build | xcpretty - - env: SWIFT_VERSION=4.2.1 + - &linux + env: SWIFT_VERSION=4.2.1 os: linux - name: Linux + name: Linux / Swift 4.2.1 language: generic dist: trusty sudo: false install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" 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 name: Check if Linux tests are up-to-date install: swift test --generate-linuxmain From b0bf0d00744999290792bd6137dba9cfe3af5aca Mon Sep 17 00:00:00 2001 From: Max Howell Date: Fri, 25 Jan 2019 10:55:02 -0500 Subject: [PATCH 8/8] This is not yet fixed in Linux Swift 5.0 --- Sources/Path+FileManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Path+FileManager.swift b/Sources/Path+FileManager.swift index 498f028..26ce038 100644 --- a/Sources/Path+FileManager.swift +++ b/Sources/Path+FileManager.swift @@ -43,7 +43,7 @@ public extension Path { try rv.delete() } #if os(Linux) - #if swift(>=5) + #if swift(>=5.1) // check if fixed #else if !overwrite, rv.isFile {