From a9292e37c48d605d708cbd8b003b26fb9eff6537 Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Wed, 17 Aug 2016 13:28:19 -0500 Subject: [PATCH 01/54] Initial run through xcode auto-conversion --- FileKit.xcodeproj/project.pbxproj | 3 + Sources/DataFile.swift | 12 +- Sources/DataType.swift | 16 +- Sources/DirectoryEnumerator.swift | 6 +- Sources/DispatchEvent.swift | 24 +-- Sources/DispatchWatcher.swift | 82 ++++---- Sources/File.swift | 44 ++--- Sources/FileKitError.swift | 52 +++--- Sources/FilePermissions.swift | 10 +- Sources/FileProtection.swift | 56 +++--- Sources/FileType.swift | 42 ++--- Sources/Image+FileKit.swift | 16 +- Sources/NSArray+FileKit.swift | 4 +- Sources/NSBundle+FileKit.swift | 2 +- Sources/NSData+FileKit.swift | 10 +- Sources/NSDictionary+FileKit.swift | 4 +- Sources/Operators.swift | 25 ++- Sources/Path.swift | 290 ++++++++++++++--------------- Sources/Process+FileKit.swift | 2 +- Sources/String+FileKit.swift | 16 +- Sources/TextFile.swift | 72 +++---- 21 files changed, 401 insertions(+), 387 deletions(-) diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 4492d7b..068659d 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -458,6 +458,7 @@ }; 5204B8571B96B85E00AA473F = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 0800; }; 5263A9031B96BA3D00635A93 = { CreatedOnToolsVersion = 7.0; @@ -887,6 +888,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -907,6 +909,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index 93d1edd..53e357d 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -30,9 +30,9 @@ import Foundation /// A representation of a filesystem data file. /// /// The data type is NSData. -public typealias DataFile = File +public typealias DataFile = File -extension File where Data: NSData { +extension File where Data: Foundation.Data { /// Reads the file and returns its data. /// - Parameter options: A mask that specifies write options @@ -40,7 +40,7 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. - public func read(options: NSDataReadingOptions) throws -> Data { + public func read(_ options: Foundation.Data.ReadingOptions) throws -> Data { return try Data.readFromPath(path, options: options) } @@ -52,11 +52,11 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(data: Data, options: NSDataWritingOptions) throws { + public func write(_ data: Data, options: Foundation.Data.WritingOptions) throws { do { - try data.writeToFile(self.path._safeRawValue, options: options) + try data.write(toFile: self.path._safeRawValue, options: options) } catch { - throw FileKitError.WriteToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path) } } diff --git a/Sources/DataType.swift b/Sources/DataType.swift index a6461ce..3b4ae09 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -39,7 +39,7 @@ public protocol Readable { /// /// - Parameter path: The path being read from. /// - static func readFromPath(path: Path) throws -> Self + static func readFromPath(_ path: Path) throws -> Self } @@ -61,7 +61,7 @@ extension Readable { public protocol Writable { /// Writes `self` to a Path. - func writeToPath(path: Path) throws + func writeToPath(_ path: Path) throws /// Writes `self` to a Path. /// @@ -71,7 +71,7 @@ public protocol Writable { /// file. If `false`, the data is written to /// the file directly. /// - func writeToPath(path: Path, atomically useAuxiliaryFile: Bool) throws + func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws } @@ -81,7 +81,7 @@ extension Writable { /// /// - Parameter path: The path being written to. /// - public func writeToPath(path: Path) throws { // swiftlint:disable:this valid_docs + public func writeToPath(_ path: Path) throws { // swiftlint:disable:this valid_docs try writeToPath(path, atomically: true) } @@ -101,7 +101,7 @@ public protocol WritableToFile: Writable { /// - Returns: `true` if the writing completed successfully, or `false` if /// the writing failed. /// - func writeToFile(path: String, atomically useAuxiliaryFile: Bool) -> Bool + func writeToFile(_ path: String, atomically useAuxiliaryFile: Bool) -> Bool } @@ -119,9 +119,9 @@ extension WritableToFile { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func writeToPath(path: Path, atomically useAuxiliaryFile: Bool) throws { + public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { guard writeToFile(path._safeRawValue, atomically: useAuxiliaryFile) else { - throw FileKitError.WriteToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path) } } @@ -154,7 +154,7 @@ extension WritableConvertible { /// `FileKitError.WriteToFileFail`, /// `FileKitError.WritableConvertiblePropertyNil` /// - public func writeToPath(path: Path, atomically useAuxiliaryFile: Bool) throws { + public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { try writable.writeToPath(path, atomically: useAuxiliaryFile) } diff --git a/Sources/DirectoryEnumerator.swift b/Sources/DirectoryEnumerator.swift index c245459..3be8d78 100644 --- a/Sources/DirectoryEnumerator.swift +++ b/Sources/DirectoryEnumerator.swift @@ -29,16 +29,16 @@ import Foundation /// An enumerator for the contents of a directory that returns the paths of all /// files and directories contained within that directory. -public struct DirectoryEnumerator: GeneratorType { +public struct DirectoryEnumerator: IteratorProtocol { - private let _path: Path, _enumerator: NSDirectoryEnumerator? + fileprivate let _path: Path, _enumerator: FileManager.DirectoryEnumerator? /// Creates a directory enumerator for the given path. /// /// - Parameter path: The path a directory enumerator to be created for. public init(path: Path) { _path = path - _enumerator = NSFileManager().enumeratorAtPath(path._safeRawValue) + _enumerator = FileManager().enumerator(atPath: path._safeRawValue) } /// Returns the next path in the enumeration. diff --git a/Sources/DispatchEvent.swift b/Sources/DispatchEvent.swift index f12c65c..2869225 100644 --- a/Sources/DispatchEvent.swift +++ b/Sources/DispatchEvent.swift @@ -26,30 +26,30 @@ public struct DispatchSourceType { /// Vnode Events. -public struct DispatchVnodeEvents: OptionSetType, CustomStringConvertible, CustomDebugStringConvertible { +public struct DispatchVnodeEvents: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Events /// The file-system object was deleted from the namespace. - public static let Delete = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_DELETE) + public static let Delete = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.delete.rawValue) /// The file-system object data changed. - public static let Write = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_WRITE) + public static let Write = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.write.rawValue) /// The file-system object changed in size. - public static let Extend = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_EXTEND) + public static let Extend = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.extend.rawValue) /// The file-system object metadata changed. - public static let Attribute = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_ATTRIB) + public static let Attribute = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.attrib.rawValue) /// The file-system object link count changed. - public static let Link = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_LINK) + public static let Link = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.link.rawValue) /// The file-system object was renamed in the namespace. - public static let Rename = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_RENAME) + public static let Rename = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.rename.rawValue) /// The file-system object was revoked. - public static let Revoke = DispatchVnodeEvents(rawValue: DISPATCH_VNODE_REVOKE) + public static let Revoke = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.revoke.rawValue) /// The file-system object was created. public static let Create = DispatchVnodeEvents(rawValue: 0x1000) @@ -77,25 +77,25 @@ public struct DispatchVnodeEvents: OptionSetType, CustomStringConvertible, Custo /// A textual representation of `self`. public var description: String { var result = "" - for (index, element) in DispatchVnodeEvents.allEvents.enumerate() { + for (index, element) in DispatchVnodeEvents.allEvents.enumerated() { if self.contains(element) { let name = DispatchVnodeEvents.allEventNames[index] result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(type(of: self)) + "[\(result)]" } /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { var result = "" - for (index, element) in DispatchVnodeEvents.allEvents.enumerate() { + for (index, element) in DispatchVnodeEvents.allEvents.enumerated() { if self.contains(element) { let name = DispatchVnodeEvents.allEventNames[index] + "(\(element.rawValue))" result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(type(of: self)) + "[\(result)]" } // MARK: - Initialization diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index aec033c..e7e0d6b 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -16,33 +16,33 @@ public protocol DispatchVnodeWatcherDelegate: class { // MARK: - Protocol /// Call when the file-system object was deleted from the namespace. - func fsWatcherDidObserveDelete(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveDelete(_ watch: DispatchVnodeWatcher) /// Call when the file-system object data changed. - func fsWatcherDidObserveWrite(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveWrite(_ watch: DispatchVnodeWatcher) /// Call when the file-system object changed in size. - func fsWatcherDidObserveExtend(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveExtend(_ watch: DispatchVnodeWatcher) /// Call when the file-system object metadata changed. - func fsWatcherDidObserveAttrib(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveAttrib(_ watch: DispatchVnodeWatcher) /// Call when the file-system object link count changed. - func fsWatcherDidObserveLink(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveLink(_ watch: DispatchVnodeWatcher) /// Call when the file-system object was renamed in the namespace. - func fsWatcherDidObserveRename(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveRename(_ watch: DispatchVnodeWatcher) /// Call when the file-system object was revoked. - func fsWatcherDidObserveRevoke(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveRevoke(_ watch: DispatchVnodeWatcher) /// Call when the file-system object was created. - func fsWatcherDidObserveCreate(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveCreate(_ watch: DispatchVnodeWatcher) /// Call when the directory changed (additions, deletions, and renamings). /// /// Calls `fsWatcherDidObserveWrite` by default. - func fsWatcherDidObserveDirectoryChange(watch: DispatchVnodeWatcher) + func fsWatcherDidObserveDirectoryChange(_ watch: DispatchVnodeWatcher) } // Optional func and default func for `GCDFSWatcherDelegate` @@ -52,63 +52,63 @@ public extension DispatchVnodeWatcherDelegate { // MARK: - Extension /// Call when the file-system object was deleted from the namespace. - public func fsWatcherDidObserveDelete(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveDelete(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object data changed. - public func fsWatcherDidObserveWrite(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveWrite(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object changed in size. - public func fsWatcherDidObserveExtend(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveExtend(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object metadata changed. - public func fsWatcherDidObserveAttrib(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveAttrib(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object link count changed. - public func fsWatcherDidObserveLink(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveLink(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object was renamed in the namespace. - public func fsWatcherDidObserveRename(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveRename(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object was revoked. - public func fsWatcherDidObserveRevoke(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveRevoke(_ watch: DispatchVnodeWatcher) { } /// Call when the file-system object was created. - public func fsWatcherDidObserveCreate(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveCreate(_ watch: DispatchVnodeWatcher) { } /// Call when the directory changed (additions, deletions, and renamings). /// /// Calls `fsWatcherDidObserveWrite` by default. - public func fsWatcherDidObserveDirectoryChange(watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveDirectoryChange(_ watch: DispatchVnodeWatcher) { fsWatcherDidObserveWrite(watch) } } /// Watcher for Vnode events -public class DispatchVnodeWatcher { +open class DispatchVnodeWatcher { // MARK: - Properties /// The paths being watched. - public let path: Path + open let path: Path /// The events used to create the watcher. - public let events: DispatchVnodeEvents + open let events: DispatchVnodeEvents /// The delegate to call when events happen weak var delegate: DispatchVnodeWatcherDelegate? @@ -117,21 +117,21 @@ public class DispatchVnodeWatcher { weak var createWatcher: DispatchVnodeWatcher? /// The callback for vnode events. - private let callback: ((DispatchVnodeWatcher) -> Void)? + fileprivate let callback: ((DispatchVnodeWatcher) -> Void)? /// The queue for the watcher. - private let queue: dispatch_queue_t? + fileprivate let queue: DispatchQueue? /// A file descriptor for the path. - private var fileDescriptor: CInt = -1 + fileprivate var fileDescriptor: CInt = -1 /// A dispatch source to monitor a file descriptor created from the path. - private var source: dispatch_source_t? + fileprivate var source: DispatchSource? /// Current events - public var currentEvent: DispatchVnodeEvents? { + open var currentEvent: DispatchVnodeEvents? { if let source = source { - return DispatchVnodeEvents(rawValue: dispatch_source_get_data(source)) + return DispatchVnodeEvents(rawValue: source.data) } if createWatcher != nil { return .Create @@ -151,7 +151,7 @@ public class DispatchVnodeWatcher { /// This method does follow links. init(path: Path, events: DispatchVnodeEvents, - queue: dispatch_queue_t, + queue: DispatchQueue, callback: ((DispatchVnodeWatcher) -> Void)? ) { self.path = path.absolute @@ -174,7 +174,7 @@ public class DispatchVnodeWatcher { /// If `callback` is set, call the `callback`. Else if `delegate` is set, call the `delegate` /// /// - Parameter eventType: The current event to be watched. - private func dispatchDelegate(eventType: DispatchVnodeEvents) { + fileprivate func dispatchDelegate(_ eventType: DispatchVnodeEvents) { if let callback = self.callback { callback(self) } else if let delegate = self.delegate { @@ -215,7 +215,7 @@ public class DispatchVnodeWatcher { /// Start watching. /// /// This method does follow links. - public func startWatching() -> Bool { + open func startWatching() -> Bool { // create a watcher for CREATE event if path not exists and events contains CREATE if !path.exists { @@ -263,20 +263,20 @@ public class DispatchVnodeWatcher { } // Define the block to call when a file change is detected. - dispatch_source_set_event_handler(source!) { //[unowned self] () in - let eventType = DispatchVnodeEvents(rawValue: dispatch_source_get_data(self.source!)) + source!.setEventHandler { //[unowned self] () in + let eventType = DispatchVnodeEvents(rawValue: self.source!.data) self.dispatchDelegate(eventType) } // Define a cancel handler to ensure the path is closed when the source is cancelled. - dispatch_source_set_cancel_handler(source!) { //[unowned self] () in + source!.setCancelHandler { //[unowned self] () in Darwin.close(self.fileDescriptor) self.fileDescriptor = -1 self.source = nil } // Start monitoring the path via the source. - dispatch_resume(source!) + source!.resume() return true } } @@ -290,14 +290,14 @@ public class DispatchVnodeWatcher { /// Stop watching. /// /// **Note:** make sure call this func, or `self` will not release - public func stopWatching() { + open func stopWatching() { if source != nil { - dispatch_source_cancel(source!) + source!.cancel() } } /// Closes the watcher. - public func close() { + open func close() { createWatcher?.stopWatching() Darwin.close(self.fileDescriptor) self.fileDescriptor = -1 @@ -318,8 +318,8 @@ extension Path { /// - Parameter queue: The queue to be run within. /// - Parameter delegate: The delegate to call when events happen. /// - Parameter callback: The callback to be called on changes. - public func watch2(events: DispatchVnodeEvents = .All, - queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + public func watch2(_ events: DispatchVnodeEvents = .All, + queue: DispatchQueue = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default), delegate: DispatchVnodeWatcherDelegate? = nil, callback: ((DispatchVnodeWatcher) -> Void)? = nil ) -> DispatchVnodeWatcher { @@ -339,8 +339,8 @@ extension Path { /// - Parameter queue: The queue to be run within. /// - Parameter delegate: The delegate to call when events happen. /// - Parameter callback: The callback to be called on changes. - public func watch(events: DispatchVnodeEvents = .All, - queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + public func watch(_ events: DispatchVnodeEvents = .All, + queue: DispatchQueue = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default), delegate: DispatchVnodeWatcherDelegate? = nil, callback: ((DispatchVnodeWatcher) -> Void)? = nil ) -> DispatchVnodeWatcher { diff --git a/Sources/File.swift b/Sources/File.swift index 99e5738..a7e6e35 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -32,15 +32,15 @@ import Foundation /// - Precondition: The data type must conform to DataType. /// /// All method do not follow links. -public class File: Comparable { +open class File: Comparable { // MARK: - Properties /// The file's filesystem path. - public var path: Path + open var path: Path /// The file's name. - public var name: String { + open var name: String { return path.fileName } @@ -57,12 +57,12 @@ public class File: Comparable { /// True if the item exists and is a regular file. /// /// this method does not follow links. - public var exists: Bool { + open var exists: Bool { return path.isRegular } /// The size of `self` in bytes. - public var size: UInt64? { + open var size: UInt64? { return path.fileSize } @@ -81,7 +81,7 @@ public class File: Comparable { /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. - public func read() throws -> Data { + open func read() throws -> Data { return try Data.readFromPath(path) } @@ -93,7 +93,7 @@ public class File: Comparable { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(data: Data) throws { + open func write(_ data: Data) throws { try self.write(data, atomically: true) } @@ -107,7 +107,7 @@ public class File: Comparable { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(data: Data, atomically useAuxiliaryFile: Bool) throws { + open func write(_ data: Data, atomically useAuxiliaryFile: Bool) throws { try data.writeToPath(path, atomically: useAuxiliaryFile) } @@ -117,7 +117,7 @@ public class File: Comparable { /// /// - Throws: `FileKitError.CreateFileFail` /// - public func create() throws { + open func create() throws { try path.createFile() } @@ -127,7 +127,7 @@ public class File: Comparable { /// /// - Throws: `FileKitError.DeleteFileFail` /// - public func delete() throws { + open func delete() throws { try path.deleteFile() } @@ -140,7 +140,7 @@ public class File: Comparable { /// - Parameter path: The path to move the file to. /// - Throws: `FileKitError.MoveFileFail` /// - public func moveToPath(path: Path) throws { + open func moveToPath(_ path: Path) throws { try self.path.moveFileToPath(path) self.path = path } @@ -154,7 +154,7 @@ public class File: Comparable { /// - Parameter path: The path to copy the file to. /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// - public func copyToPath(path: Path) throws { + open func copyToPath(_ path: Path) throws { try self.path.copyFileToPath(path) } @@ -172,7 +172,7 @@ public class File: Comparable { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// - public func symlinkToPath(path: Path) throws { + open func symlinkToPath(_ path: Path) throws { try self.path.symlinkFileToPath(path) } @@ -190,21 +190,21 @@ public class File: Comparable { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateHardlinkFail` /// - public func hardlinkToPath(path: Path) throws { + open func hardlinkToPath(_ path: Path) throws { try self.path.hardlinkFileToPath(path) } // MARK: - FileType /// The FileType attribute for `self`. - public var type: FileType? { + open var type: FileType? { return path.fileType } // MARK: - FilePermissions /// The file permissions for `self`. - public var permissions: FilePermissions { + open var permissions: FilePermissions { return FilePermissions(forFile: self) } @@ -212,19 +212,19 @@ public class File: Comparable { /// Returns a file handle for reading from `self`, or `nil` if `self` /// doesn't exist. - public var handleForReading: NSFileHandle? { + open var handleForReading: FileHandle? { return path.fileHandleForReading } /// Returns a file handle for writing to `self`, or `nil` if `self` doesn't /// exist. - public var handleForWriting: NSFileHandle? { + open var handleForWriting: FileHandle? { return path.fileHandleForWriting } /// Returns a file handle for reading from and writing to `self`, or `nil` /// if `self` doesn't exist. - public var handleForUpdating: NSFileHandle? { + open var handleForUpdating: FileHandle? { return path.fileHandleForUpdating } @@ -232,7 +232,7 @@ public class File: Comparable { /// Returns an input stream that reads data from `self`, or `nil` if `self` /// doesn't exist. - public func inputStream() -> NSInputStream? { + open func inputStream() -> InputStream? { return path.inputStream() } @@ -243,7 +243,7 @@ public class File: Comparable { /// appended to any existing file contents, /// `false` otherwise. Default value is `false`. /// - public func outputStream(append shouldAppend: Bool = false) -> NSOutputStream? { + open func outputStream(append shouldAppend: Bool = false) -> OutputStream? { return path.outputStream(append: shouldAppend) } @@ -255,7 +255,7 @@ extension File: CustomStringConvertible { /// A textual representation of `self`. public var description: String { - return String(self.dynamicType) + "('" + path.description + "')" + return String(type(of: self)) + "('" + path.description + "')" } } diff --git a/Sources/FileKitError.swift b/Sources/FileKitError.swift index 5d300ea..5abc928 100644 --- a/Sources/FileKitError.swift +++ b/Sources/FileKitError.swift @@ -28,82 +28,82 @@ import Foundation /// An error that can be thrown by FileKit. -public enum FileKitError: ErrorType { +public enum FileKitError: Error { // MARK: FileKitError /// The reason for why the error occured. public var message: String { switch self { - case let FileDoesNotExist(path): + case let .fileDoesNotExist(path): return "File does not exist at \"\(path)\"" - case let ChangeDirectoryFail(fromPath, toPath): + case let .changeDirectoryFail(fromPath, toPath): return "Could not change the directory from \"\(fromPath)\" to \"\(toPath)\"" - case let CreateSymlinkFail(fromPath, toPath): + case let .createSymlinkFail(fromPath, toPath): return "Could not create symlink from \"\(fromPath)\" to \"\(toPath)\"" - case let CreateHardlinkFail(fromPath, toPath): + case let .createHardlinkFail(fromPath, toPath): return "Could not create a hard link from \"\(fromPath)\" to \"\(toPath)\"" - case let CreateFileFail(path): + case let .createFileFail(path): return "Could not create file at \"\(path)\"" - case let CreateDirectoryFail(path): + case let .createDirectoryFail(path): return "Could not create a directory at \"\(path)\"" - case let DeleteFileFail(path): + case let .deleteFileFail(path): return "Could not delete file at \"\(path)\"" - case let ReadFromFileFail(path): + case let .readFromFileFail(path): return "Could not read from file at \"\(path)\"" - case let WriteToFileFail(path): + case let .writeToFileFail(path): return "Could not write to file at \"\(path)\"" - case let MoveFileFail(fromPath, toPath): + case let .moveFileFail(fromPath, toPath): return "Could not move file at \"\(fromPath)\" to \"\(toPath)\"" - case let CopyFileFail(fromPath, toPath): + case let .copyFileFail(fromPath, toPath): return "Could not copy file from \"\(fromPath)\" to \"\(toPath)\"" - case let AttributesChangeFail(path): + case let .attributesChangeFail(path): return "Could not change file attrubutes at \"\(path)\"" } } /// A file does not exist. - case FileDoesNotExist(path: Path) + case fileDoesNotExist(path: Path) /// Could not change the current directory. - case ChangeDirectoryFail(from: Path, to: Path) + case changeDirectoryFail(from: Path, to: Path) /// A symbolic link could not be created. - case CreateSymlinkFail(from: Path, to: Path) + case createSymlinkFail(from: Path, to: Path) /// A hard link could not be created. - case CreateHardlinkFail(from: Path, to: Path) + case createHardlinkFail(from: Path, to: Path) /// A file could not be created. - case CreateFileFail(path: Path) + case createFileFail(path: Path) /// A directory could not be created. - case CreateDirectoryFail(path: Path) + case createDirectoryFail(path: Path) /// A file could not be deleted. - case DeleteFileFail(path: Path) + case deleteFileFail(path: Path) /// A file could not be read from. - case ReadFromFileFail(path: Path) + case readFromFileFail(path: Path) /// A file could not be written to. - case WriteToFileFail(path: Path) + case writeToFileFail(path: Path) /// A file could not be moved. - case MoveFileFail(from: Path, to: Path) + case moveFileFail(from: Path, to: Path) /// A file could not be copied. - case CopyFileFail(from: Path, to: Path) + case copyFileFail(from: Path, to: Path) /// One or many attributes could not be changed. - case AttributesChangeFail(path: Path) + case attributesChangeFail(path: Path) } extension FileKitError: CustomStringConvertible { // MARK: - CustomStringConvertible /// A textual representation of `self`. public var description: String { - return String(self.dynamicType) + "(" + message + ")" + return String(type(of: self)) + "(" + message + ")" } } diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index 5b66261..33e548d 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -28,7 +28,7 @@ import Foundation /// The permissions of a file. -public struct FilePermissions: OptionSetType, CustomStringConvertible { +public struct FilePermissions: OptionSet, CustomStringConvertible { /// The file can be read from. public static let Read = FilePermissions(rawValue: 1) @@ -57,7 +57,7 @@ public struct FilePermissions: OptionSetType, CustomStringConvertible { } } } - return String(self.dynamicType) + "[" + description + "]" + return String(type(of: self)) + "[" + description + "]" } /// Creates a set of file permissions. @@ -74,9 +74,9 @@ public struct FilePermissions: OptionSetType, CustomStringConvertible { /// public init(forPath path: Path) { var permissions = FilePermissions(rawValue: 0) - if path.isReadable { permissions.unionInPlace(.Read) } - if path.isWritable { permissions.unionInPlace(.Write) } - if path.isExecutable { permissions.unionInPlace(.Execute) } + if path.isReadable { permissions.formUnion(.Read) } + if path.isWritable { permissions.formUnion(.Write) } + if path.isExecutable { permissions.formUnion(.Execute) } self = permissions } diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index f488b3e..847823c 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -55,14 +55,14 @@ public enum FileProtection: String { /// public init?(rawValue: String) { switch rawValue { - case NSFileProtectionNone: - self = None - case NSFileProtectionComplete: - self = Complete - case NSFileProtectionCompleteUnlessOpen: - self = CompleteUnlessOpen - case NSFileProtectionCompleteUntilFirstUserAuthentication: - self = CompleteUntilFirstUserAuthentication + case FileProtectionType.none: + self = .None + case FileProtectionType.complete: + self = .Complete + case FileProtectionType.completeUnlessOpen: + self = .CompleteUnlessOpen + case FileProtectionType.completeUntilFirstUserAuthentication: + self = .CompleteUntilFirstUserAuthentication default: return nil } @@ -72,27 +72,27 @@ public enum FileProtection: String { public var rawValue: String { switch self { case .None: - return NSFileProtectionNone + return FileProtectionType.none case .Complete: - return NSFileProtectionComplete + return FileProtectionType.complete case .CompleteUnlessOpen: - return NSFileProtectionCompleteUnlessOpen + return FileProtectionType.completeUnlessOpen case .CompleteUntilFirstUserAuthentication: - return NSFileProtectionCompleteUntilFirstUserAuthentication + return FileProtectionType.completeUntilFirstUserAuthentication } } /// Return the equivalent NSDataWritingOptions - public var dataWritingOption: NSDataWritingOptions { + public var dataWritingOption: NSData.WritingOptions { switch self { case .None: - return .DataWritingFileProtectionNone + return .noFileProtection case .Complete: - return .DataWritingFileProtectionComplete + return .completeFileProtection case .CompleteUnlessOpen: - return .DataWritingFileProtectionCompleteUnlessOpen + return .completeFileProtectionUnlessOpen case .CompleteUntilFirstUserAuthentication: - return .DataWritingFileProtectionCompleteUntilFirstUserAuthentication + return .completeFileProtectionUntilFirstUserAuthentication } } @@ -104,8 +104,8 @@ extension Path { /// The protection of the file at the path. public var fileProtection: FileProtection? { - guard let value = attributes[NSFileProtectionKey] as? String, - protection = FileProtection(rawValue: value) else { + guard let value = attributes[FileAttributeKey.protectionKey] as? String, + let protection = FileProtection(rawValue: value) else { return nil } return protection @@ -119,11 +119,11 @@ extension Path { /// /// - Throws: `FileKitError.CreateFileFail` /// - public func createFile(fileProtection: FileProtection) throws { - let manager = NSFileManager() - let attributes = [NSFileProtectionKey : fileProtection.rawValue] - if !manager.createFileAtPath(_safeRawValue, contents: nil, attributes: attributes) { - throw FileKitError.CreateFileFail(path: self) + public func createFile(_ fileProtection: FileProtection) throws { + let manager = FileManager() + let attributes = [FileAttributeKey.protectionKey : fileProtection.rawValue] + if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { + throw FileKitError.createFileFail(path: self) } } @@ -146,13 +146,13 @@ extension File { /// /// - Throws: `FileKitError.CreateFileFail` /// - public func create(fileProtection: FileProtection) throws { + public func create(_ fileProtection: FileProtection) throws { try path.createFile(fileProtection) } } -extension File where Data: NSData { +extension File where Data: Foundation.Data { /// Writes data to the file. /// @@ -165,10 +165,10 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(data: Data, fileProtection: FileProtection, atomically: Bool = true) throws { + public func write(_ data: Data, fileProtection: FileProtection, atomically: Bool = true) throws { var options = fileProtection.dataWritingOption if atomically { - options.unionInPlace(NSDataWritingOptions.DataWritingAtomic) + options.formUnion(Foundation.Data.WritingOptions.atomic) } try self.write(data, options: options) } diff --git a/Sources/FileType.swift b/Sources/FileType.swift index a09caba..7335ee7 100644 --- a/Sources/FileType.swift +++ b/Sources/FileType.swift @@ -56,20 +56,20 @@ public enum FileType: String { /// - Parameter rawValue: The raw value to create from. public init?(rawValue: String) { switch rawValue { - case NSFileTypeDirectory: - self = Directory - case NSFileTypeRegular: - self = Regular - case NSFileTypeSymbolicLink: - self = SymbolicLink - case NSFileTypeSocket: - self = Socket - case NSFileTypeCharacterSpecial: - self = CharacterSpecial - case NSFileTypeBlockSpecial: - self = BlockSpecial - case NSFileTypeUnknown: - self = Unknown + case FileAttributeType.typeDirectory: + self = .Directory + case FileAttributeType.typeRegular: + self = .Regular + case FileAttributeType.typeSymbolicLink: + self = .SymbolicLink + case FileAttributeType.typeSocket: + self = .Socket + case FileAttributeType.typeCharacterSpecial: + self = .CharacterSpecial + case FileAttributeType.typeBlockSpecial: + self = .BlockSpecial + case FileAttributeType.typeUnknown: + self = .Unknown default: return nil } @@ -79,19 +79,19 @@ public enum FileType: String { public var rawValue: String { switch self { case .Directory: - return NSFileTypeDirectory + return FileAttributeType.typeDirectory case .Regular: - return NSFileTypeRegular + return FileAttributeType.typeRegular case .SymbolicLink: - return NSFileTypeSymbolicLink + return FileAttributeType.typeSymbolicLink case .Socket: - return NSFileTypeSocket + return FileAttributeType.typeSocket case .CharacterSpecial: - return NSFileTypeCharacterSpecial + return FileAttributeType.typeCharacterSpecial case .BlockSpecial: - return NSFileTypeBlockSpecial + return FileAttributeType.typeBlockSpecial case .Unknown: - return NSFileTypeUnknown + return FileAttributeType.typeUnknown } } diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index d9e1174..a0db1fb 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -48,29 +48,29 @@ extension Image: DataType, WritableConvertible { /// - Parameter path: The path to be returned the image for. /// - Throws: FileKitError.ReadFromFileFail /// - public class func readFromPath(path: Path) throws -> Self { + public class func readFromPath(_ path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } return contents } /// Returns `TIFFRepresentation` on OS X and `UIImagePNGRepresentation` on /// iOS, watchOS, and tvOS. - public var writable: NSData { + public var writable: Data { #if os(OSX) return self.TIFFRepresentation ?? NSData() #else - return UIImagePNGRepresentation(self) ?? NSData() + return UIImagePNGRepresentation(self) ?? Data() #endif } /// Retrieves an image from a URL. - public convenience init?(url: NSURL) { + public convenience init?(url: URL) { #if os(OSX) - self.init(contentsOfURL: url) + self.init(contentsOf: url) #else - guard let data = NSData(contentsOfURL: url) else { + guard let data = try? Data(contentsOf: url) else { return nil } self.init(data: data) @@ -79,7 +79,7 @@ extension Image: DataType, WritableConvertible { /// Retrieves an image from a URL string. public convenience init?(urlString string: String) { - guard let url = NSURL(string: string) else { + guard let url = URL(string: string) else { return nil } self.init(url: url) diff --git a/Sources/NSArray+FileKit.swift b/Sources/NSArray+FileKit.swift index 44327e0..d01f395 100644 --- a/Sources/NSArray+FileKit.swift +++ b/Sources/NSArray+FileKit.swift @@ -32,9 +32,9 @@ extension NSArray: DataType, WritableToFile { /// Returns an array read from the given path. /// /// - Parameter path: The path an array to be read from. - public class func readFromPath(path: Path) throws -> Self { + public class func readFromPath(_ path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } return contents } diff --git a/Sources/NSBundle+FileKit.swift b/Sources/NSBundle+FileKit.swift index c958236..cd4f6ef 100644 --- a/Sources/NSBundle+FileKit.swift +++ b/Sources/NSBundle+FileKit.swift @@ -27,7 +27,7 @@ import Foundation -extension NSBundle { +extension Bundle { /// Returns an NSBundle for the given directory path. public convenience init?(path: Path) { diff --git a/Sources/NSData+FileKit.swift b/Sources/NSData+FileKit.swift index 2abea1d..895726d 100644 --- a/Sources/NSData+FileKit.swift +++ b/Sources/NSData+FileKit.swift @@ -27,22 +27,22 @@ import Foundation -extension NSData: DataType, WritableToFile { +extension Data: DataType, WritableToFile { /// Returns data read from the given path. - public class func readFromPath(path: Path) throws -> Self { + public static func readFromPath(_ path: Path) throws -> Data { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } return contents } /// Returns data read from the given path using NSDataReadingOptions. - public class func readFromPath(path: Path, options: NSDataReadingOptions) throws -> Self { + public static func readFromPath(_ path: Path, options: Data.ReadingOptions) throws -> Data { do { return try self.init(contentsOfFile: path._safeRawValue, options: options) } catch { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } } diff --git a/Sources/NSDictionary+FileKit.swift b/Sources/NSDictionary+FileKit.swift index db9130d..a8b358a 100644 --- a/Sources/NSDictionary+FileKit.swift +++ b/Sources/NSDictionary+FileKit.swift @@ -27,9 +27,9 @@ import Foundation extension NSDictionary: DataType, WritableToFile { /// Returns a dictionary read from the given path. - public class func readFromPath(path: Path) throws -> Self { + public class func readFromPath(_ path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } return contents } diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 21d204e..19e44da 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -28,6 +28,17 @@ // swiftlint:disable file_length import Foundation +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + // MARK: - File @@ -97,7 +108,7 @@ infix operator |~ {} /// Return lines of file that match the regex motif. @warn_unused_result public func |~ (file: TextFile, motif: String) -> [String] { - return file.grep(motif, options: NSStringCompareOptions.RegularExpressionSearch) + return file.grep(motif, options: NSString.CompareOptions.regularExpression) } // MARK: - Path @@ -132,7 +143,7 @@ public func + (lhs: Path, rhs: Path) -> Path { if rhs.rawValue.isEmpty || rhs.rawValue == "." { return lhs } switch (lhs.rawValue.hasSuffix(Path.separator), rhs.rawValue.hasPrefix(Path.separator)) { case (true, true): - let rhsRawValue = rhs.rawValue.substringFromIndex(rhs.rawValue.startIndex.successor()) + let rhsRawValue = rhs.rawValue.substring(from: rhs.rawValue.characters.index(after: rhs.rawValue.startIndex)) return Path("\(lhs.rawValue)\(rhsRawValue)") case (false, false): return Path("\(lhs.rawValue)\(Path.separator)\(rhs.rawValue)") @@ -154,12 +165,12 @@ public func + (lhs: Path, rhs: String) -> Path { } /// Appends the right path to the left path. -public func += (inout lhs: Path, rhs: Path) { +public func += (lhs: inout Path, rhs: Path) { lhs = lhs + rhs } /// Appends the path value of the String to the left path. -public func += (inout lhs: Path, rhs: String) { +public func += (lhs: inout Path, rhs: String) { lhs = lhs + rhs } @@ -183,12 +194,12 @@ public func / (lhs: String, rhs: Path) -> Path { } /// Appends the right path to the left path. -public func /= (inout lhs: Path, rhs: Path) { +public func /= (lhs: inout Path, rhs: Path) { lhs += rhs } /// Appends the path value of the String to the left path. -public func /= (inout lhs: Path, rhs: String) { +public func /= (lhs: inout Path, rhs: String) { lhs += rhs } @@ -205,7 +216,7 @@ public func <^> (lhs: Path, rhs: Path) -> Path { infix operator {} /// Runs `closure` with the path as its current working directory. -public func (path: Path, @noescape closure: () throws -> ()) rethrows { +public func (path: Path, closure: () throws -> ()) rethrows { try path.changeDirectory(closure) } diff --git a/Sources/Path.swift b/Sources/Path.swift index c2a341c..d71ce30 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -33,7 +33,7 @@ import Foundation /// /// An Path instance lets you manage files in a much easier way. /// -public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexable { +public struct Path: ExpressibleByStringLiteral, RawRepresentable, Hashable, Indexable { // MARK: - Static Methods and Properties @@ -46,29 +46,29 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// The path of the program's current working directory. public static var Current: Path { get { - return Path(NSFileManager.defaultManager().currentDirectoryPath) + return Path(FileManager.default.currentDirectoryPath) } set { - NSFileManager.defaultManager().changeCurrentDirectoryPath(newValue._safeRawValue) + FileManager.default.changeCurrentDirectoryPath(newValue._safeRawValue) } } /// The paths of the mounted volumes available. - public static func volumes(options: NSVolumeEnumerationOptions = []) -> [Path] { - let volumes = NSFileManager.defaultManager().mountedVolumeURLsIncludingResourceValuesForKeys(nil, + public static func volumes(_ options: FileManager.VolumeEnumerationOptions = []) -> [Path] { + let volumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil, options: options) return (volumes ?? []).flatMap { Path(url: $0) } } // MARK: - Properties - private var _fmWraper = _FMWrapper() + fileprivate var _fmWraper = _FMWrapper() - private class _FMWrapper { - let unsafeFileManager = NSFileManager() - weak var delegate: NSFileManagerDelegate? + fileprivate class _FMWrapper { + let unsafeFileManager = FileManager() + weak var delegate: FileManagerDelegate? /// Safe way to use fileManager - var fileManager: NSFileManager { + var fileManager: FileManager { get { // if delegate == nil { // print("\n\nDelegate is nil\n\n") @@ -82,12 +82,12 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// The delegate for the file manager used by the path. /// /// **Note:** no strong reference stored in path, so make sure keep the delegate or it will be `nil` - public var fileManagerDelegate: NSFileManagerDelegate? { + public var fileManagerDelegate: FileManagerDelegate? { get { return _fmWraper.delegate } set { - if !isUniquelyReferencedNonObjC(&_fmWraper) { + if !isKnownUniquelyReferenced(&_fmWraper) { _fmWraper = _FMWrapper() } _fmWraper.delegate = newValue @@ -95,7 +95,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa } /// The stored path string value. - public private(set) var rawValue: String + public fileprivate(set) var rawValue: String /// The non-empty path string value. For internal use only. /// @@ -108,7 +108,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// The standardized path string value public var standardRawValue: String { get { - return (self.rawValue as NSString).stringByStandardizingPath + return (self.rawValue as NSString).standardizingPath } } @@ -132,11 +132,11 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa return [] } if isAbsolute { - return (absolute.rawValue as NSString).pathComponents.enumerate().flatMap { + return (absolute.rawValue as NSString).pathComponents.enumerated().flatMap { (($0 == 0 || $1 != "/") && $1 != ".") ? Path($1) : nil } } else { - let comps = (self.rawValue as NSString).pathComponents.enumerate() + let comps = (self.rawValue as NSString).pathComponents.enumerated() // remove extraneous `/` and `.` let cleanComps = comps.flatMap { (($0 == 0 || $1 != "/") && $1 != ".") ? Path($1) : nil @@ -146,10 +146,10 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa } /// resolving `..` if possible - private func _cleanComponents(comps: [Path]) -> [Path] { + fileprivate func _cleanComponents(_ comps: [Path]) -> [Path] { var isContinue = false let count = comps.count - let cleanComps: [Path] = comps.enumerate().flatMap { + let cleanComps: [Path] = comps.enumerated().flatMap { if ($1.rawValue != ".." && $0 < count - 1 && comps[$0 + 1].rawValue == "..") || ($1.rawValue == ".." && $0 > 0 && comps[$0 - 1].rawValue != "..") { isContinue = true return nil @@ -167,7 +167,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// A new path created by removing extraneous components from the path. public var standardized: Path { - return Path((self.rawValue as NSString).stringByStandardizingPath) + return Path((self.rawValue as NSString).standardizingPath) } /// The standardized path string value without expanding tilde @@ -184,7 +184,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// A new path created by resolving all symlinks and standardizing the path. public var resolved: Path { - return Path((self.rawValue as NSString).stringByResolvingSymlinksInPath) + return Path((self.rawValue as NSString).resolvingSymlinksInPath) } /// A new path created by making the path absolute. @@ -219,7 +219,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// /// this method does follow links. public var exists: Bool { - return _fmWraper.fileManager.fileExistsAtPath(_safeRawValue) + return _fmWraper.fileManager.fileExists(atPath: _safeRawValue) } /// Returns `true` if a file or directory or symbolic link exists at the path @@ -234,7 +234,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// /// this method does follow links. public var isWritable: Bool { - return _fmWraper.fileManager.isWritableFileAtPath(_safeRawValue) + return _fmWraper.fileManager.isWritableFile(atPath: _safeRawValue) } /// Returns `true` if the current process has read privileges for the file @@ -242,7 +242,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// /// this method does follow links. public var isReadable: Bool { - return _fmWraper.fileManager.isReadableFileAtPath(_safeRawValue) + return _fmWraper.fileManager.isReadableFile(atPath: _safeRawValue) } /// Returns `true` if the current process has execute privileges for the @@ -250,7 +250,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// /// this method does follow links. public var isExecutable: Bool { - return _fmWraper.fileManager.isExecutableFileAtPath(_safeRawValue) + return _fmWraper.fileManager.isExecutableFile(atPath: _safeRawValue) } /// Returns `true` if the current process has delete privileges for the file @@ -258,7 +258,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// /// this method does **not** follow links. public var isDeletable: Bool { - return _fmWraper.fileManager.isDeletableFileAtPath(_safeRawValue) + return _fmWraper.fileManager.isDeletableFile(atPath: _safeRawValue) } /// Returns `true` if the path points to a directory. @@ -266,7 +266,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// this method does follow links. public var isDirectory: Bool { var isDirectory: ObjCBool = false - return _fmWraper.fileManager.fileExistsAtPath(_safeRawValue, isDirectory: &isDirectory) + return _fmWraper.fileManager.fileExists(atPath: _safeRawValue, isDirectory: &isDirectory) && isDirectory } @@ -304,7 +304,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa return (rawValue as NSString).pathExtension } set { - let path = (rawValue as NSString).stringByDeletingPathExtension + let path = (rawValue as NSString).deletingPathExtension rawValue = path + ".\(newValue)" } } @@ -312,7 +312,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa /// The path's parent path. public var parent: Path { if isAbsolute { - return Path((absolute.rawValue as NSString).stringByDeletingLastPathComponent) + return Path((absolute.rawValue as NSString).deletingLastPathComponent) } else { let comps = components if comps.isEmpty { @@ -338,7 +338,7 @@ public struct Path: StringLiteralConvertible, RawRepresentable, Hashable, Indexa public init(_ path: String, expandingTilde: Bool = false) { // empty path may cause crash if expandingTilde { - self.rawValue = (path as NSString).stringByExpandingTildeInPath + self.rawValue = (path as NSString).expandingTildeInPath } else { self.rawValue = path } @@ -354,7 +354,7 @@ extension Path { /// /// - Parameter closure: The block to run while `Path.Current` is changed. /// - public func changeDirectory(@noescape closure: () throws -> ()) rethrows { + public func changeDirectory(closure: () throws -> ()) rethrows { let previous = Path.Current defer { Path.Current = previous } if _fmWraper.fileManager.changeCurrentDirectoryPath(_safeRawValue) { @@ -368,10 +368,10 @@ extension Path { /// Default value is `false`. /// /// this method follow links if recursive is `false`, otherwise not follow links - public func children(recursive recursive: Bool = false) -> [Path] { + public func children(recursive: Bool = false) -> [Path] { let obtainFunc = recursive - ? _fmWraper.fileManager.subpathsOfDirectoryAtPath - : _fmWraper.fileManager.contentsOfDirectoryAtPath + ? _fmWraper.fileManager.subpathsOfDirectory(atPath:) + : _fmWraper.fileManager.contentsOfDirectory(atPath:) return (try? obtainFunc(_safeRawValue))?.map { self + Path($0) } ?? [] } @@ -380,7 +380,7 @@ extension Path { /// - Parameter recursive: Whether to check the paths recursively. /// Default value is `true`. /// - public func isChildOfPath(path: Path, recursive: Bool = true) -> Bool { + public func isChildOfPath(_ path: Path, recursive: Bool = true) -> Bool { if !(isRelative && path.isRelative) && !(isAbsolute && path.isAbsolute) { return self.absolute.isChildOfPath(path.absolute) } @@ -398,7 +398,7 @@ extension Path { /// /// Relative paths can't be compared return `false`. like `../../path1/path2` and `../path2` /// - public func isAncestorOfPath(path: Path) -> Bool { + public func isAncestorOfPath(_ path: Path) -> Bool { if !(isRelative && path.isRelative) && !(isAbsolute && path.isAbsolute) { return self.absolute.isAncestorOfPath(path.absolute) } @@ -415,7 +415,7 @@ extension Path { /// /// Relative path return the most precise path if possible /// - public func commonAncestor(path: Path) -> Path { + public func commonAncestor(_ path: Path) -> Path { if !(isRelative && path.isRelative) && !(isAbsolute && path.isAbsolute) { return self.absolute.commonAncestor(path.absolute) } @@ -503,7 +503,7 @@ extension Path { /// - Returns: An Array containing the paths in `self` that match the /// condition. /// - public func find(searchDepth depth: Int = -1, @noescape condition: (Path) throws -> Bool) rethrows -> [Path] { + public func find(searchDepth depth: Int = -1, condition: (Path) throws -> Bool) rethrows -> [Path] { return try self.find(searchDepth: depth) { path in try condition(path) ? path : nil } @@ -520,7 +520,7 @@ extension Path { /// - Returns: An Array containing the non-nil values for paths found in /// `self`. /// - public func find(searchDepth depth: Int = -1, @noescape transform: (Path) throws -> T?) rethrows -> [T] { + public func find(searchDepth depth: Int = -1, transform: (Path) throws -> T?) rethrows -> [T] { return try self.children().reduce([]) { values, child in if let value = try transform(child) { return values + [value] @@ -556,7 +556,7 @@ extension Path { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// - public func symlinkFileToPath(path: Path) throws { + public func symlinkFileToPath(_ path: Path) throws { // it's possible to create symbolic links to locations that do not yet exist. // guard self.exists else { // throw FileKitError.FileDoesNotExist(path: self) @@ -566,14 +566,14 @@ extension Path { // Throws if linking to an existing non-directory file. guard !linkPath.isAny else { - throw FileKitError.CreateSymlinkFail(from: self, to: path) + throw FileKitError.createSymlinkFail(from: self, to: path) } do { - try _fmWraper.fileManager.createSymbolicLinkAtPath( - linkPath._safeRawValue, withDestinationPath: self._safeRawValue) + try _fmWraper.fileManager.createSymbolicLink( + atPath: linkPath._safeRawValue, withDestinationPath: self._safeRawValue) } catch { - throw FileKitError.CreateSymlinkFail(from: self, to: linkPath) + throw FileKitError.createSymlinkFail(from: self, to: linkPath) } } @@ -589,17 +589,17 @@ extension Path { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateHardlinkFail` /// - public func hardlinkFileToPath(path: Path) throws { + public func hardlinkFileToPath(_ path: Path) throws { let linkPath = path.isDirectory ? path + self.fileName : path guard !linkPath.isAny else { - throw FileKitError.CreateHardlinkFail(from: self, to: path) + throw FileKitError.createHardlinkFail(from: self, to: path) } do { - try _fmWraper.fileManager.linkItemAtPath(self._safeRawValue, toPath: linkPath._safeRawValue) + try _fmWraper.fileManager.linkItem(atPath: self._safeRawValue, toPath: linkPath._safeRawValue) } catch { - throw FileKitError.CreateHardlinkFail(from: self, to: path) + throw FileKitError.createHardlinkFail(from: self, to: path) } } @@ -613,8 +613,8 @@ extension Path { /// /// If a file or symlink exists, this method removes the file or symlink and create regular file public func createFile() throws { - if !_fmWraper.fileManager.createFileAtPath(_safeRawValue, contents: nil, attributes: nil) { - throw FileKitError.CreateFileFail(path: self) + if !_fmWraper.fileManager.createFile(atPath: _safeRawValue, contents: nil, attributes: nil) { + throw FileKitError.createFileFail(path: self) } } @@ -628,10 +628,10 @@ extension Path { /// `FileKitError.CreateFileFail`, /// `FileKitError.AttributesChangeFail` /// - public func touch(updateModificationDate: Bool = true) throws { + public func touch(_ updateModificationDate: Bool = true) throws { if self.exists { if updateModificationDate { - try _setAttribute(NSFileModificationDate, value: NSDate()) + try _setAttribute(FileAttributeKey.modificationDate.rawValue, value: Date() as AnyObject) } } else { try createFile() @@ -655,11 +655,11 @@ extension Path { public func createDirectory(withIntermediateDirectories createIntermediates: Bool = true) throws { do { let manager = _fmWraper.fileManager - try manager.createDirectoryAtPath(_safeRawValue, + try manager.createDirectory(atPath: _safeRawValue, withIntermediateDirectories: createIntermediates, attributes: nil) } catch { - throw FileKitError.CreateDirectoryFail(path: self) + throw FileKitError.createDirectoryFail(path: self) } } @@ -674,9 +674,9 @@ extension Path { /// this method does not follow links. public func deleteFile() throws { do { - try _fmWraper.fileManager.removeItemAtPath(_safeRawValue) + try _fmWraper.fileManager.removeItem(atPath: _safeRawValue) } catch { - throw FileKitError.DeleteFileFail(path: self) + throw FileKitError.deleteFileFail(path: self) } } @@ -687,19 +687,19 @@ extension Path { /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.MoveFileFail` /// /// this method does not follow links. - public func moveFileToPath(path: Path) throws { + public func moveFileToPath(_ path: Path) throws { if self.isAny { if !path.isAny { do { - try _fmWraper.fileManager.moveItemAtPath(self._safeRawValue, toPath: path._safeRawValue) + try _fmWraper.fileManager.moveItem(atPath: self._safeRawValue, toPath: path._safeRawValue) } catch { - throw FileKitError.MoveFileFail(from: self, to: path) + throw FileKitError.moveFileFail(from: self, to: path) } } else { - throw FileKitError.MoveFileFail(from: self, to: path) + throw FileKitError.moveFileFail(from: self, to: path) } } else { - throw FileKitError.FileDoesNotExist(path: self) + throw FileKitError.fileDoesNotExist(path: self) } } @@ -711,19 +711,19 @@ extension Path { /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// /// this method does not follow links. - public func copyFileToPath(path: Path) throws { + public func copyFileToPath(_ path: Path) throws { if self.isAny { if !path.isAny { do { - try _fmWraper.fileManager.copyItemAtPath(self._safeRawValue, toPath: path._safeRawValue) + try _fmWraper.fileManager.copyItem(atPath: self._safeRawValue, toPath: path._safeRawValue) } catch { - throw FileKitError.CopyFileFail(from: self, to: path) + throw FileKitError.copyFileFail(from: self, to: path) } } else { - throw FileKitError.CopyFileFail(from: self, to: path) + throw FileKitError.copyFileFail(from: self, to: path) } } else { - throw FileKitError.FileDoesNotExist(path: self) + throw FileKitError.fileDoesNotExist(path: self) } } @@ -819,64 +819,64 @@ extension Path { /// /// this method does not follow links. public var attributes: [String : AnyObject] { - return (try? _fmWraper.fileManager.attributesOfItemAtPath(_safeRawValue)) ?? [:] + return (try? _fmWraper.fileManager.attributesOfItem(atPath: _safeRawValue) as! [String : AnyObject]?) ?? [:] } /// Modify attributes /// /// this method does not follow links. - private func _setAttributes(attributes: [String : AnyObject]) throws { + fileprivate func _setAttributes(_ attributes: [String : AnyObject]) throws { do { - try _fmWraper.fileManager.setAttributes(attributes, ofItemAtPath: self._safeRawValue) + try _fmWraper.fileManager.setAttributes(attributes as! [FileAttributeKey : Any], ofItemAtPath: self._safeRawValue) } catch { - throw FileKitError.AttributesChangeFail(path: self) + throw FileKitError.attributesChangeFail(path: self) } } /// Modify one attribute - private func _setAttribute(key: String, value: AnyObject) throws { + fileprivate func _setAttribute(_ key: String, value: AnyObject) throws { try _setAttributes([key : value]) } /// The creation date of the file at the path. - public var creationDate: NSDate? { - return attributes[NSFileCreationDate] as? NSDate + public var creationDate: Date? { + return attributes[FileAttributeKey.creationDate] as? Date } /// The modification date of the file at the path. - public var modificationDate: NSDate? { - return attributes[NSFileModificationDate] as? NSDate + public var modificationDate: Date? { + return attributes[FileAttributeKey.modificationDate] as? Date } /// The name of the owner of the file at the path. public var ownerName: String? { - return attributes[NSFileOwnerAccountName] as? String + return attributes[FileAttributeKey.ownerAccountName] as? String } /// The ID of the owner of the file at the path. public var ownerID: UInt? { - if let value = attributes[NSFileOwnerAccountID] as? NSNumber { - return value.unsignedLongValue + if let value = attributes[FileAttributeKey.ownerAccountID] as? NSNumber { + return value.uintValue } return nil } /// The group name of the owner of the file at the path. public var groupName: String? { - return attributes[NSFileGroupOwnerAccountName] as? String + return attributes[FileAttributeKey.groupOwnerAccountName] as? String } /// The group ID of the owner of the file at the path. public var groupID: UInt? { - if let value = attributes[NSFileGroupOwnerAccountID] as? NSNumber { - return value.unsignedLongValue + if let value = attributes[FileAttributeKey.groupOwnerAccountID] as? NSNumber { + return value.uintValue } return nil } /// Indicates whether the extension of the file at the path is hidden. public var extensionIsHidden: Bool? { - if let value = attributes[NSFileExtensionHidden] as? NSNumber { + if let value = attributes[FileAttributeKey.extensionHidden] as? NSNumber { return value.boolValue } return nil @@ -884,32 +884,32 @@ extension Path { /// The POSIX permissions of the file at the path. public var posixPermissions: Int16? { - if let value = attributes[NSFilePosixPermissions] as? NSNumber { - return value.shortValue + if let value = attributes[FileAttributeKey.posixPermissions] as? NSNumber { + return value.int16Value } return nil } /// The number of hard links to a file. public var fileReferenceCount: UInt? { - if let value = attributes[NSFileReferenceCount] as? NSNumber { - return value.unsignedLongValue + if let value = attributes[FileAttributeKey.referenceCount] as? NSNumber { + return value.uintValue } return nil } /// The size of the file at the path in bytes. public var fileSize: UInt64? { - if let value = attributes[NSFileSize] as? NSNumber { - return value.unsignedLongLongValue + if let value = attributes[FileAttributeKey.size] as? NSNumber { + return value.uint64Value } return nil } /// The filesystem number of the file at the path. public var filesystemFileNumber: UInt? { - if let value = attributes[NSFileSystemFileNumber] as? NSNumber { - return value.unsignedLongValue + if let value = attributes[FileAttributeKey.systemFileNumber] as? NSNumber { + return value.uintValue } return nil } @@ -921,7 +921,7 @@ extension Path { /// The FileType attribute for the file at the path. public var fileType: FileType? { - guard let value = attributes[NSFileType] as? String else { + guard let value = attributes[FileAttributeKey.type] as? String else { return nil } return FileType(rawValue: value) @@ -947,16 +947,16 @@ extension Path { /// Creates a new path with given url if possible. /// /// - Parameter url: The url to create a path for. - public init?(url: NSURL) { - guard let path = url.path where url.fileURL else { + public init?(url: URL) { + guard let path = url.path , url.isFileURL else { return nil } rawValue = path } /// - Returns: The `Path` objects url. - public var url: NSURL { - return NSURL(fileURLWithPath: _safeRawValue, isDirectory: self.isDirectory) + public var url: URL { + return URL(fileURLWithPath: _safeRawValue, isDirectory: self.isDirectory) } } @@ -968,13 +968,13 @@ extension Path { /// Creates a new path with given url if possible. /// /// - Parameter bookmarkData: The bookmark data to create a path for. - public init?(bookmarkData bookData: NSData) { + public init?(bookmarkData bookData: Data) { var isStale: ObjCBool = false - let url = try? NSURL( - byResolvingBookmarkData: bookData, + let url = try? (NSURL( + resolvingBookmarkData: bookData, options: [], - relativeToURL: nil, - bookmarkDataIsStale: &isStale) + relativeTo: nil, + bookmarkDataIsStale: &isStale) as URL) guard let fullURL = url else { return nil } @@ -982,11 +982,11 @@ extension Path { } /// - Returns: The `Path` objects bookmarkData. - public var bookmarkData: NSData? { - return try? url.bookmarkDataWithOptions( - .SuitableForBookmarkFile, + public var bookmarkData: Data? { + return try? url.bookmarkData( + options: .suitableForBookmarkFile, includingResourceValuesForKeys: nil, - relativeToURL: nil) + relativeTo: nil) } } @@ -999,7 +999,7 @@ extension Path { /// /// - Parameter groupIdentifier: The group identifier. public init?(groupIdentifier: String) { - guard let url = NSFileManager().containerURLForSecurityApplicationGroupIdentifier(groupIdentifier) else { + guard let url = FileManager().containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier) else { return nil } self.init(url: url) @@ -1013,20 +1013,20 @@ extension Path { /// Returns a file handle for reading the file at the path, or `nil` if no /// file exists. - public var fileHandleForReading: NSFileHandle? { - return NSFileHandle(forReadingAtPath: absolute._safeRawValue) + public var fileHandleForReading: FileHandle? { + return FileHandle(forReadingAtPath: absolute._safeRawValue) } /// Returns a file handle for writing to the file at the path, or `nil` if /// no file exists. - public var fileHandleForWriting: NSFileHandle? { - return NSFileHandle(forWritingAtPath: absolute._safeRawValue) + public var fileHandleForWriting: FileHandle? { + return FileHandle(forWritingAtPath: absolute._safeRawValue) } /// Returns a file handle for reading and writing to the file at the path, /// or `nil` if no file exists. - public var fileHandleForUpdating: NSFileHandle? { - return NSFileHandle(forUpdatingAtPath: absolute._safeRawValue) + public var fileHandleForUpdating: FileHandle? { + return FileHandle(forUpdatingAtPath: absolute._safeRawValue) } } @@ -1037,8 +1037,8 @@ extension Path { /// Returns an input stream that reads data from the file at the path, or /// `nil` if no file exists. - public func inputStream() -> NSInputStream? { - return NSInputStream(fileAtPath: absolute._safeRawValue) + public func inputStream() -> InputStream? { + return InputStream(fileAtPath: absolute._safeRawValue) } /// Returns an output stream for writing to the file at the path, or `nil` @@ -1048,8 +1048,8 @@ extension Path { /// appended to any existing file contents, /// `false` otherwise. Default value is `false`. /// - public func outputStream(append shouldAppend: Bool = false) -> NSOutputStream? { - return NSOutputStream(toFileAtPath: absolute._safeRawValue, append: shouldAppend) + public func outputStream(append shouldAppend: Bool = false) -> OutputStream? { + return OutputStream(toFileAtPath: absolute._safeRawValue, append: shouldAppend) } } @@ -1060,7 +1060,7 @@ extension Path: StringInterpolationConvertible { /// Initializes a path from the string interpolation paths. public init(stringInterpolation paths: Path...) { - self.init(paths.reduce("", combine: { $0 + $1.rawValue })) + self.init(paths.reduce("", { $0 + $1.rawValue })) } /// Initializes a path from the string interpolation segment. @@ -1097,12 +1097,12 @@ extension Path: CustomDebugStringConvertible { } -extension Path: SequenceType { +extension Path: Sequence { // MARK: - SequenceType /// - Returns: A *generator* over the contents of the path. - public func generate() -> DirectoryEnumerator { + public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: self) } @@ -1126,72 +1126,72 @@ extension Path { /// Returns a temporary path for the process. public static var ProcessTemporary: Path { - return Path.UserTemporary + NSProcessInfo.processInfo().globallyUniqueString + return Path.UserTemporary + ProcessInfo.processInfo.globallyUniqueString } /// Returns a unique temporary path. public static var UniqueTemporary: Path { - return Path.ProcessTemporary + NSUUID().UUIDString + return Path.ProcessTemporary + UUID().uuidString } /// Returns the path to the user's caches directory. public static var UserCaches: Path { - return _pathInUserDomain(.CachesDirectory) + return _pathInUserDomain(.cachesDirectory) } /// Returns the path to the user's applications directory. public static var UserApplications: Path { - return _pathInUserDomain(.ApplicationDirectory) + return _pathInUserDomain(.applicationDirectory) } /// Returns the path to the user's application support directory. public static var UserApplicationSupport: Path { - return _pathInUserDomain(.ApplicationSupportDirectory) + return _pathInUserDomain(.applicationSupportDirectory) } /// Returns the path to the user's desktop directory. public static var UserDesktop: Path { - return _pathInUserDomain(.DesktopDirectory) + return _pathInUserDomain(.desktopDirectory) } /// Returns the path to the user's documents directory. public static var UserDocuments: Path { - return _pathInUserDomain(.DocumentDirectory) + return _pathInUserDomain(.documentDirectory) } /// Returns the path to the user's autosaved documents directory. public static var UserAutosavedInformation: Path { - return _pathInUserDomain(.AutosavedInformationDirectory) + return _pathInUserDomain(.autosavedInformationDirectory) } /// Returns the path to the user's downloads directory. public static var UserDownloads: Path { - return _pathInUserDomain(.DownloadsDirectory) + return _pathInUserDomain(.downloadsDirectory) } /// Returns the path to the user's library directory. public static var UserLibrary: Path { - return _pathInUserDomain(.LibraryDirectory) + return _pathInUserDomain(.libraryDirectory) } /// Returns the path to the user's movies directory. public static var UserMovies: Path { - return _pathInUserDomain(.MoviesDirectory) + return _pathInUserDomain(.moviesDirectory) } /// Returns the path to the user's music directory. public static var UserMusic: Path { - return _pathInUserDomain(.MusicDirectory) + return _pathInUserDomain(.musicDirectory) } /// Returns the path to the user's pictures directory. public static var UserPictures: Path { - return _pathInUserDomain(.PicturesDirectory) + return _pathInUserDomain(.picturesDirectory) } /// Returns the path to the user's Public sharing directory. public static var UserSharedPublic: Path { - return _pathInUserDomain(.SharedPublicDirectory) + return _pathInUserDomain(.sharedPublicDirectory) } #if os(OSX) @@ -1210,54 +1210,54 @@ extension Path { /// Returns the path to the system's applications directory. public static var SystemApplications: Path { - return _pathInSystemDomain(.ApplicationDirectory) + return _pathInSystemDomain(.applicationDirectory) } /// Returns the path to the system's application support directory. public static var SystemApplicationSupport: Path { - return _pathInSystemDomain(.ApplicationSupportDirectory) + return _pathInSystemDomain(.applicationSupportDirectory) } /// Returns the path to the system's library directory. public static var SystemLibrary: Path { - return _pathInSystemDomain(.LibraryDirectory) + return _pathInSystemDomain(.libraryDirectory) } /// Returns the path to the system's core services directory. public static var SystemCoreServices: Path { - return _pathInSystemDomain(.CoreServiceDirectory) + return _pathInSystemDomain(.coreServiceDirectory) } /// Returns the path to the system's PPDs directory. public static var SystemPrinterDescription: Path { - return _pathInSystemDomain(.PrinterDescriptionDirectory) + return _pathInSystemDomain(.printerDescriptionDirectory) } /// Returns the path to the system's PreferencePanes directory. public static var SystemPreferencePanes: Path { - return _pathInSystemDomain(.PreferencePanesDirectory) + return _pathInSystemDomain(.preferencePanesDirectory) } /// Returns the paths where resources can occur. public static var AllLibraries: [Path] { - return _pathsInDomains(.AllLibrariesDirectory, .AllDomainsMask) + return _pathsInDomains(.allLibrariesDirectory, .allDomainsMask) } /// Returns the paths where applications can occur public static var AllApplications: [Path] { - return _pathsInDomains(.AllApplicationsDirectory, .AllDomainsMask) + return _pathsInDomains(.allApplicationsDirectory, .allDomainsMask) } - private static func _pathInUserDomain(directory: NSSearchPathDirectory) -> Path { - return _pathsInDomains(directory, .UserDomainMask)[0] + fileprivate static func _pathInUserDomain(_ directory: FileManager.SearchPathDirectory) -> Path { + return _pathsInDomains(directory, .userDomainMask)[0] } - private static func _pathInSystemDomain(directory: NSSearchPathDirectory) -> Path { - return _pathsInDomains(directory, .SystemDomainMask)[0] + fileprivate static func _pathInSystemDomain(_ directory: FileManager.SearchPathDirectory) -> Path { + return _pathsInDomains(directory, .systemDomainMask)[0] } - private static func _pathsInDomains(directory: NSSearchPathDirectory, - _ domainMask: NSSearchPathDomainMask) -> [Path] { + fileprivate static func _pathsInDomains(_ directory: FileManager.SearchPathDirectory, + _ domainMask: FileManager.SearchPathDomainMask) -> [Path] { return NSSearchPathForDirectoriesInDomains(directory, domainMask, true) .map({ Path($0).standardized }) } diff --git a/Sources/Process+FileKit.swift b/Sources/Process+FileKit.swift index c065b52..59f2365 100644 --- a/Sources/Process+FileKit.swift +++ b/Sources/Process+FileKit.swift @@ -25,7 +25,7 @@ // THE SOFTWARE. // -extension Process { +extension CommandLine { /// The working directory for the current process. public static var workingDirectory: Path { diff --git a/Sources/String+FileKit.swift b/Sources/String+FileKit.swift index a6311b7..cfd2782 100644 --- a/Sources/String+FileKit.swift +++ b/Sources/String+FileKit.swift @@ -31,12 +31,12 @@ import Foundation extension String: DataType { /// Creates a string from a path. - public static func readFromPath(path: Path) throws -> String { + public static func readFromPath(_ path: Path) throws -> String { let possibleContents = try? NSString( contentsOfFile: path._safeRawValue, - encoding: NSUTF8StringEncoding) + encoding: String.Encoding.utf8) guard let contents = possibleContents else { - throw FileKitError.ReadFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path) } return contents as String } @@ -45,7 +45,7 @@ extension String: DataType { /// /// - Parameter path: The path being written to. /// - public func writeToPath(path: Path) throws { + public func writeToPath(_ path: Path) throws { try writeToPath(path, atomically: true) } @@ -57,13 +57,13 @@ extension String: DataType { /// file. If `false`, the data is written to /// the file directly. /// - public func writeToPath(path: Path, atomically useAuxiliaryFile: Bool) throws { + public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { do { - try self.writeToFile(path._safeRawValue, + try self.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, - encoding: NSUTF8StringEncoding) + encoding: String.Encoding.utf8) } catch { - throw FileKitError.WriteToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path) } } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index f56e4de..b981a7e 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -30,16 +30,16 @@ import Foundation /// A representation of a filesystem text file. /// /// The data type is String. -public class TextFile: File { +open class TextFile: File { /// The text file's string encoding. - public var encoding: NSStringEncoding + open var encoding: String.Encoding /// Initializes a text file from a path. /// /// - Parameter path: The path to be created a text file from. public override init(path: Path) { - self.encoding = NSUTF8StringEncoding + self.encoding = String.Encoding.utf8 super.init(path: path) } @@ -47,7 +47,7 @@ public class TextFile: File { /// /// - Parameter path: The path to be created a text file from. /// - Parameter encoding: The encoding to be used for the text file. - public init(path: Path, encoding: NSStringEncoding) { + public init(path: Path, encoding: String.Encoding) { self.encoding = encoding super.init(path: path) } @@ -62,11 +62,11 @@ public class TextFile: File { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public override func write(data: String, atomically useAuxiliaryFile: Bool) throws { + open override func write(_ data: String, atomically useAuxiliaryFile: Bool) throws { do { - try data.writeToFile(path._safeRawValue, atomically: useAuxiliaryFile, encoding: encoding) + try data.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, encoding: encoding) } catch { - throw FileKitError.WriteToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path) } } @@ -83,7 +83,7 @@ extension TextFile { /// /// - Returns: the `TextFileStreamReader` @warn_unused_result - public func streamReader(delimiter: String = "\n", + public func streamReader(_ delimiter: String = "\n", chunkSize: Int = 4096) -> TextFileStreamReader? { return TextFileStreamReader( path: self.path, @@ -100,34 +100,34 @@ extension TextFile { /// - Parameter options: optional options for string comparaison /// /// - Returns: the lines - public func grep(motif: String, include: Bool = true, - options: NSStringCompareOptions = []) -> [String] { + public func grep(_ motif: String, include: Bool = true, + options: NSString.CompareOptions = []) -> [String] { guard let reader = streamReader() else { return [] } defer { reader.close() } - return reader.filter {($0.rangeOfString(motif, options: options) != nil) == include } + return reader.filter {($0.range(of: motif, options: options) != nil) == include } } } /// A class to read `TextFile` line by line. -public class TextFileStreamReader { +open class TextFileStreamReader { /// The text encoding. - public let encoding: NSStringEncoding + open let encoding: String.Encoding /// The chunk size when reading. - public let chunkSize: Int + open let chunkSize: Int /// Tells if the position is at the end of file. - public var atEOF: Bool = false + open var atEOF: Bool = false - let fileHandle: NSFileHandle! + let fileHandle: FileHandle! let buffer: NSMutableData! - let delimData: NSData! + let delimData: Data! // MARK: - Initialization @@ -138,15 +138,15 @@ public class TextFileStreamReader { public init?( path: Path, delimiter: String = "\n", - encoding: NSStringEncoding = NSUTF8StringEncoding, + encoding: String.Encoding = String.Encoding.utf8, chunkSize: Int = 4096 ) { self.chunkSize = chunkSize self.encoding = encoding guard let fileHandle = path.fileHandleForReading, - delimData = delimiter.dataUsingEncoding(encoding), - buffer = NSMutableData(capacity: chunkSize) else { + let delimData = delimiter.data(using: encoding), + let buffer = NSMutableData(capacity: chunkSize) else { self.fileHandle = nil self.delimData = nil self.buffer = nil @@ -166,21 +166,21 @@ public class TextFileStreamReader { // MARK: - public methods /// - Returns: The next line, or nil on EOF. - public func nextLine() -> String? { + open func nextLine() -> String? { if atEOF { return nil } // Read data chunks from file until a line delimiter is found. - var range = buffer.rangeOfData(delimData, options: [], range: NSRange(location: 0, length: buffer.length)) + var range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) while range.location == NSNotFound { - let tmpData = fileHandle.readDataOfLength(chunkSize) - if tmpData.length == 0 { + let tmpData = fileHandle.readData(ofLength: chunkSize) + if tmpData.count == 0 { // EOF or read error. atEOF = true if buffer.length > 0 { // Buffer contains last line in file (not terminated by delimiter). - let line = NSString(data: buffer, encoding: encoding) + let line = NSString(data: buffer as Data, encoding: encoding.rawValue) buffer.length = 0 return line as String? @@ -188,39 +188,39 @@ public class TextFileStreamReader { // No more lines. return nil } - buffer.appendData(tmpData) - range = buffer.rangeOfData(delimData, options: [], range: NSRange(location: 0, length: buffer.length)) + buffer.append(tmpData) + range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) } // Convert complete line (excluding the delimiter) to a string. - let line = NSString(data: buffer.subdataWithRange(NSRange(location: 0, length: range.location)), - encoding: encoding) + let line = NSString(data: buffer.subdata(with: NSRange(location: 0, length: range.location)), + encoding: encoding.rawValue) // Remove line (and the delimiter) from the buffer. let cleaningRange = NSRange(location: 0, length: range.location + range.length) - buffer.replaceBytesInRange(cleaningRange, withBytes: nil, length: 0) + buffer.replaceBytes(in: cleaningRange, withBytes: nil, length: 0) return line as? String } /// Start reading from the beginning of file. - public func rewind() -> Void { - fileHandle?.seekToFileOffset(0) + open func rewind() -> Void { + fileHandle?.seek(toFileOffset: 0) buffer.length = 0 atEOF = false } /// Close the underlying file. No reading must be done after calling this method. - public func close() -> Void { + open func close() -> Void { fileHandle?.closeFile() } } // Implement `SequenceType` for `TextFileStreamReader` -extension TextFileStreamReader : SequenceType { +extension TextFileStreamReader : Sequence { /// - Returns: A generator to be used for iterating over a `TextFileStreamReader` object. - public func generate() -> AnyGenerator { - return AnyGenerator { + public func makeIterator() -> AnyIterator { + return AnyIterator { return self.nextLine() } } From 9cf7226acad44db1f76514e788347640eb4883cf Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Wed, 17 Aug 2016 15:13:20 -0500 Subject: [PATCH 02/54] Fixing conversion errors --- Sources/DataFile.swift | 10 ++--- Sources/DataType.swift | 2 +- Sources/DispatchEvent.swift | 53 +++++++++----------------- Sources/DispatchWatcher.swift | 29 +++++++------- Sources/File.swift | 2 +- Sources/FileKitError.swift | 2 +- Sources/FilePermissions.swift | 2 +- Sources/FileProtection.swift | 20 +++++----- Sources/FileType.swift | 28 +++++++------- Sources/Image+FileKit.swift | 4 +- Sources/NSData+FileKit.swift | 8 ++-- Sources/Operators.swift | 71 ++++++++++++++++++----------------- Sources/Path.swift | 62 ++++++++++++++++++++---------- Sources/String+FileKit.swift | 2 +- Sources/TextFile.swift | 2 +- 15 files changed, 153 insertions(+), 144 deletions(-) diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index 53e357d..cb2c3c4 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -30,13 +30,13 @@ import Foundation /// A representation of a filesystem data file. /// /// The data type is NSData. -public typealias DataFile = File +public typealias DataFile = File -extension File where Data: Foundation.Data { +extension File where Data: NSData { /// Reads the file and returns its data. /// - Parameter options: A mask that specifies write options - /// described in `NSDataReadingOptions`. + /// described in `Foundation.Data.ReadingOptions`. /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. @@ -48,7 +48,7 @@ extension File where Data: Foundation.Data { /// /// - Parameter data: The data to be written to the file. /// - Parameter options: A mask that specifies write options - /// described in `NSDataWritingOptions`. + /// described in `Foundation.Data.WritingOptions`. /// /// - Throws: `FileKitError.WriteToFileFail` /// @@ -56,7 +56,7 @@ extension File where Data: Foundation.Data { do { try data.write(toFile: self.path._safeRawValue, options: options) } catch { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: self.path) } } diff --git a/Sources/DataType.swift b/Sources/DataType.swift index 3b4ae09..765770e 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -28,7 +28,7 @@ import Foundation /// A type that can be used to read from and write to File instances. -public typealias DataType = protocol +public typealias DataType = Readable & Writable diff --git a/Sources/DispatchEvent.swift b/Sources/DispatchEvent.swift index 2869225..fe001ef 100644 --- a/Sources/DispatchEvent.swift +++ b/Sources/DispatchEvent.swift @@ -8,59 +8,42 @@ import Foundation -/// Dispatch source type. -public struct DispatchSourceType { - - // MARK: - Static Properties - - /// A dispatch source that monitors a file descriptor for events defined by `dispatch_source_vnode_flags_t`. - public static let Vnode = DISPATCH_SOURCE_TYPE_VNODE - - /// A dispatch source that monitors a file descriptor for pending bytes available to be read. - public static let Read = DISPATCH_SOURCE_TYPE_READ - - /// A dispatch source that monitors a file descriptor for available buffer space to write bytes. - public static let Write = DISPATCH_SOURCE_TYPE_WRITE - -} - - -/// Vnode Events. -public struct DispatchVnodeEvents: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { +/// File System Events. +public struct DispatchFileSystemEvents: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Events /// The file-system object was deleted from the namespace. - public static let Delete = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.delete.rawValue) + public static let Delete = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.delete.rawValue) /// The file-system object data changed. - public static let Write = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.write.rawValue) + public static let Write = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.write.rawValue) /// The file-system object changed in size. - public static let Extend = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.extend.rawValue) + public static let Extend = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.extend.rawValue) /// The file-system object metadata changed. - public static let Attribute = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.attrib.rawValue) + public static let Attribute = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.attrib.rawValue) /// The file-system object link count changed. - public static let Link = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.link.rawValue) + public static let Link = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.link.rawValue) /// The file-system object was renamed in the namespace. - public static let Rename = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.rename.rawValue) + public static let Rename = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.rename.rawValue) /// The file-system object was revoked. - public static let Revoke = DispatchVnodeEvents(rawValue: DispatchSource.FileSystemEvent.revoke.rawValue) + public static let Revoke = DispatchFileSystemEvents(rawValue: DispatchSource.FileSystemEvent.revoke.rawValue) /// The file-system object was created. - public static let Create = DispatchVnodeEvents(rawValue: 0x1000) + public static let Create = DispatchFileSystemEvents(rawValue: 0x1000) /// All of the event IDs. - public static let All: DispatchVnodeEvents = [.Delete, .Write, .Extend, .Attribute, .Link, .Rename, .Revoke, .Create] + public static let All: DispatchFileSystemEvents = [.Delete, .Write, .Extend, .Attribute, .Link, .Rename, .Revoke, .Create] // MARK: - All Events /// An array of all of the events. - public static let allEvents: [DispatchVnodeEvents] = [ + public static let allEvents: [DispatchFileSystemEvents] = [ .Delete, .Write, .Extend, .Attribute, .Link, .Rename, .Revoke, .Create ] @@ -77,25 +60,25 @@ public struct DispatchVnodeEvents: OptionSet, CustomStringConvertible, CustomDeb /// A textual representation of `self`. public var description: String { var result = "" - for (index, element) in DispatchVnodeEvents.allEvents.enumerated() { + for (index, element) in DispatchFileSystemEvents.allEvents.enumerated() { if self.contains(element) { - let name = DispatchVnodeEvents.allEventNames[index] + let name = DispatchFileSystemEvents.allEventNames[index] result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(type(of: self)) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { var result = "" - for (index, element) in DispatchVnodeEvents.allEvents.enumerated() { + for (index, element) in DispatchFileSystemEvents.allEvents.enumerated() { if self.contains(element) { - let name = DispatchVnodeEvents.allEventNames[index] + "(\(element.rawValue))" + let name = DispatchFileSystemEvents.allEventNames[index] + "(\(element.rawValue))" result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(type(of: self)) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } // MARK: - Initialization diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index e7e0d6b..d42993f 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -108,7 +108,7 @@ open class DispatchVnodeWatcher { open let path: Path /// The events used to create the watcher. - open let events: DispatchVnodeEvents + open let events: DispatchFileSystemEvents /// The delegate to call when events happen weak var delegate: DispatchVnodeWatcherDelegate? @@ -126,12 +126,12 @@ open class DispatchVnodeWatcher { fileprivate var fileDescriptor: CInt = -1 /// A dispatch source to monitor a file descriptor created from the path. - fileprivate var source: DispatchSource? + fileprivate var source: DispatchSourceProtocol? /// Current events - open var currentEvent: DispatchVnodeEvents? { + open var currentEvent: DispatchFileSystemEvents? { if let source = source { - return DispatchVnodeEvents(rawValue: source.data) + return DispatchFileSystemEvents(rawValue: source.data) } if createWatcher != nil { return .Create @@ -150,7 +150,7 @@ open class DispatchVnodeWatcher { /// /// This method does follow links. init(path: Path, - events: DispatchVnodeEvents, + events: DispatchFileSystemEvents, queue: DispatchQueue, callback: ((DispatchVnodeWatcher) -> Void)? ) { @@ -174,7 +174,7 @@ open class DispatchVnodeWatcher { /// If `callback` is set, call the `callback`. Else if `delegate` is set, call the `delegate` /// /// - Parameter eventType: The current event to be watched. - fileprivate func dispatchDelegate(_ eventType: DispatchVnodeEvents) { + fileprivate func dispatchDelegate(_ eventType: DispatchFileSystemEvents) { if let callback = self.callback { callback(self) } else if let delegate = self.delegate { @@ -215,6 +215,7 @@ open class DispatchVnodeWatcher { /// Start watching. /// /// This method does follow links. + @discardableResult open func startWatching() -> Bool { // create a watcher for CREATE event if path not exists and events contains CREATE @@ -254,8 +255,8 @@ open class DispatchVnodeWatcher { if fileDescriptor == -1 { return false } var _events = events _events.remove(.Create) - source = dispatch_source_create(DispatchSourceType.Vnode, UInt(fileDescriptor), _events.rawValue, queue) - + source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: DispatchSource.FileSystemEvent(rawValue: _events.rawValue), queue: queue) + // Recheck if open success and source create success if source != nil && fileDescriptor != -1 { guard callback != nil || delegate != nil else { @@ -264,13 +265,13 @@ open class DispatchVnodeWatcher { // Define the block to call when a file change is detected. source!.setEventHandler { //[unowned self] () in - let eventType = DispatchVnodeEvents(rawValue: self.source!.data) + let eventType = DispatchFileSystemEvents(rawValue: self.source!.data) self.dispatchDelegate(eventType) } // Define a cancel handler to ensure the path is closed when the source is cancelled. source!.setCancelHandler { //[unowned self] () in - Darwin.close(self.fileDescriptor) + _ = Darwin.close(self.fileDescriptor) self.fileDescriptor = -1 self.source = nil } @@ -299,7 +300,7 @@ open class DispatchVnodeWatcher { /// Closes the watcher. open func close() { createWatcher?.stopWatching() - Darwin.close(self.fileDescriptor) + _ = Darwin.close(self.fileDescriptor) self.fileDescriptor = -1 self.source = nil } @@ -319,7 +320,7 @@ extension Path { /// - Parameter delegate: The delegate to call when events happen. /// - Parameter callback: The callback to be called on changes. public func watch2(_ events: DispatchVnodeEvents = .All, - queue: DispatchQueue = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default), + queue: DispatchQueue = DispatchQueue.global(qos: .default), delegate: DispatchVnodeWatcherDelegate? = nil, callback: ((DispatchVnodeWatcher) -> Void)? = nil ) -> DispatchVnodeWatcher { @@ -339,8 +340,8 @@ extension Path { /// - Parameter queue: The queue to be run within. /// - Parameter delegate: The delegate to call when events happen. /// - Parameter callback: The callback to be called on changes. - public func watch(_ events: DispatchVnodeEvents = .All, - queue: DispatchQueue = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default), + public func watch(_ events: DispatchFileSystemEvents = .All, + queue: DispatchQueue = DispatchQueue.global(qos: .default), delegate: DispatchVnodeWatcherDelegate? = nil, callback: ((DispatchVnodeWatcher) -> Void)? = nil ) -> DispatchVnodeWatcher { diff --git a/Sources/File.swift b/Sources/File.swift index a7e6e35..b7d8229 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -255,7 +255,7 @@ extension File: CustomStringConvertible { /// A textual representation of `self`. public var description: String { - return String(type(of: self)) + "('" + path.description + "')" + return String(describing: type(of: self)) + "('" + path.description + "')" } } diff --git a/Sources/FileKitError.swift b/Sources/FileKitError.swift index 5abc928..00be2f6 100644 --- a/Sources/FileKitError.swift +++ b/Sources/FileKitError.swift @@ -103,7 +103,7 @@ extension FileKitError: CustomStringConvertible { // MARK: - CustomStringConvertible /// A textual representation of `self`. public var description: String { - return String(type(of: self)) + "(" + message + ")" + return String(describing: type(of: self)) + "(" + message + ")" } } diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index 33e548d..08c7b7b 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -57,7 +57,7 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { } } } - return String(type(of: self)) + "[" + description + "]" + return String(describing: type(of: self)) + "[" + description + "]" } /// Creates a set of file permissions. diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index 847823c..70235a3 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -55,13 +55,13 @@ public enum FileProtection: String { /// public init?(rawValue: String) { switch rawValue { - case FileProtectionType.none: + case FileProtectionType.none.rawValue: self = .None - case FileProtectionType.complete: + case FileProtectionType.complete.rawValue: self = .Complete - case FileProtectionType.completeUnlessOpen: + case FileProtectionType.completeUnlessOpen.rawValue: self = .CompleteUnlessOpen - case FileProtectionType.completeUntilFirstUserAuthentication: + case FileProtectionType.completeUntilFirstUserAuthentication.rawValue: self = .CompleteUntilFirstUserAuthentication default: return nil @@ -72,13 +72,13 @@ public enum FileProtection: String { public var rawValue: String { switch self { case .None: - return FileProtectionType.none + return FileProtectionType.none.rawValue case .Complete: - return FileProtectionType.complete + return FileProtectionType.complete.rawValue case .CompleteUnlessOpen: - return FileProtectionType.completeUnlessOpen + return FileProtectionType.completeUnlessOpen.rawValue case .CompleteUntilFirstUserAuthentication: - return FileProtectionType.completeUntilFirstUserAuthentication + return FileProtectionType.completeUntilFirstUserAuthentication.rawValue } } @@ -121,7 +121,7 @@ extension Path { /// public func createFile(_ fileProtection: FileProtection) throws { let manager = FileManager() - let attributes = [FileAttributeKey.protectionKey : fileProtection.rawValue] + let attributes = [FileAttributeKey.protectionKey.rawValue : fileProtection.rawValue] if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { throw FileKitError.createFileFail(path: self) } @@ -152,7 +152,7 @@ extension File { } -extension File where Data: Foundation.Data { +extension File where Data: NSData { /// Writes data to the file. /// diff --git a/Sources/FileType.swift b/Sources/FileType.swift index 7335ee7..5481525 100644 --- a/Sources/FileType.swift +++ b/Sources/FileType.swift @@ -56,19 +56,19 @@ public enum FileType: String { /// - Parameter rawValue: The raw value to create from. public init?(rawValue: String) { switch rawValue { - case FileAttributeType.typeDirectory: + case FileAttributeType.typeDirectory.rawValue: self = .Directory - case FileAttributeType.typeRegular: + case FileAttributeType.typeRegular.rawValue: self = .Regular - case FileAttributeType.typeSymbolicLink: + case FileAttributeType.typeSymbolicLink.rawValue: self = .SymbolicLink - case FileAttributeType.typeSocket: + case FileAttributeType.typeSocket.rawValue: self = .Socket - case FileAttributeType.typeCharacterSpecial: + case FileAttributeType.typeCharacterSpecial.rawValue: self = .CharacterSpecial - case FileAttributeType.typeBlockSpecial: + case FileAttributeType.typeBlockSpecial.rawValue: self = .BlockSpecial - case FileAttributeType.typeUnknown: + case FileAttributeType.typeUnknown.rawValue: self = .Unknown default: return nil @@ -79,19 +79,19 @@ public enum FileType: String { public var rawValue: String { switch self { case .Directory: - return FileAttributeType.typeDirectory + return FileAttributeType.typeDirectory.rawValue case .Regular: - return FileAttributeType.typeRegular + return FileAttributeType.typeRegular.rawValue case .SymbolicLink: - return FileAttributeType.typeSymbolicLink + return FileAttributeType.typeSymbolicLink.rawValue case .Socket: - return FileAttributeType.typeSocket + return FileAttributeType.typeSocket.rawValue case .CharacterSpecial: - return FileAttributeType.typeCharacterSpecial + return FileAttributeType.typeCharacterSpecial.rawValue case .BlockSpecial: - return FileAttributeType.typeBlockSpecial + return FileAttributeType.typeBlockSpecial.rawValue case .Unknown: - return FileAttributeType.typeUnknown + return FileAttributeType.typeUnknown.rawValue } } diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index a0db1fb..d2476d8 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -57,11 +57,11 @@ extension Image: DataType, WritableConvertible { /// Returns `TIFFRepresentation` on OS X and `UIImagePNGRepresentation` on /// iOS, watchOS, and tvOS. - public var writable: Data { + public var writable: NSData { #if os(OSX) return self.TIFFRepresentation ?? NSData() #else - return UIImagePNGRepresentation(self) ?? Data() + return UIImagePNGRepresentation(self) as NSData? ?? NSData() #endif } diff --git a/Sources/NSData+FileKit.swift b/Sources/NSData+FileKit.swift index 895726d..2f14d72 100644 --- a/Sources/NSData+FileKit.swift +++ b/Sources/NSData+FileKit.swift @@ -27,18 +27,18 @@ import Foundation -extension Data: DataType, WritableToFile { +extension NSData: DataType, WritableToFile { /// Returns data read from the given path. - public static func readFromPath(_ path: Path) throws -> Data { + public static func readFromPath(_ path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { throw FileKitError.readFromFileFail(path: path) } return contents } - /// Returns data read from the given path using NSDataReadingOptions. - public static func readFromPath(_ path: Path, options: Data.ReadingOptions) throws -> Data { + /// Returns data read from the given path using Data.ReadingOptions. + public static func readFromPath(_ path: Path, options: Data.ReadingOptions) throws -> Self { do { return try self.init(contentsOfFile: path._safeRawValue, options: options) } catch { diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 19e44da..eefb545 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -28,6 +28,7 @@ // swiftlint:disable file_length import Foundation + fileprivate func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): @@ -43,18 +44,18 @@ fileprivate func < (lhs: T?, rhs: T?) -> Bool { // MARK: - File /// Returns `true` if both files' paths are the same. -@warn_unused_result + public func ==(lhs: File, rhs: File) -> Bool { return lhs.path == rhs.path } /// Returns `true` if `lhs` is smaller than `rhs` in size. -@warn_unused_result + public func < (lhs: File, rhs: File) -> Bool { return lhs.size < rhs.size } -infix operator |> {} +infix operator |> /// Writes data to a file. /// @@ -69,12 +70,12 @@ public func |> (data: Data, file: File) throws { // MARK: - TextFile /// Returns `true` if both text files have the same path and encoding. -@warn_unused_result + public func == (lhs: TextFile, rhs: TextFile) -> Bool { return lhs.path == rhs.path && lhs.encoding == rhs.encoding } -infix operator |>> {} +infix operator |>> /// Appends a string to a text file. /// @@ -92,21 +93,21 @@ public func |>> (data: String, file: TextFile) throws { } /// Return lines of file that match the motif. -@warn_unused_result + public func | (file: TextFile, motif: String) -> [String] { return file.grep(motif) } -infix operator |- {} +infix operator |- /// Return lines of file that does'nt match the motif. -@warn_unused_result + public func |- (file: TextFile, motif: String) -> [String] { return file.grep(motif, include: false) } -infix operator |~ {} +infix operator |~ /// Return lines of file that match the regex motif. -@warn_unused_result + public func |~ (file: TextFile, motif: String) -> [String] { return file.grep(motif, options: NSString.CompareOptions.regularExpression) } @@ -115,7 +116,7 @@ public func |~ (file: TextFile, motif: String) -> [String] { /// Returns `true` if the standardized form of one path equals that of another /// path. -@warn_unused_result + public func == (lhs: Path, rhs: Path) -> Bool { if lhs.isAbsolute || rhs.isAbsolute { return lhs.absolute.rawValue == rhs.absolute.rawValue @@ -125,7 +126,7 @@ public func == (lhs: Path, rhs: Path) -> Bool { /// Returns `true` if the standardized form of one path not equals that of another /// path. -@warn_unused_result + public func != (lhs: Path, rhs: Path) -> Bool { return !(lhs == rhs) } @@ -137,7 +138,7 @@ public func != (lhs: Path, rhs: Path) -> Bool { /// print(systemLib + "Fonts") // "/System/Library/Fonts" /// ``` /// -@warn_unused_result + public func + (lhs: Path, rhs: Path) -> Path { if lhs.rawValue.isEmpty || lhs.rawValue == "." { return rhs } if rhs.rawValue.isEmpty || rhs.rawValue == "." { return lhs } @@ -153,13 +154,13 @@ public func + (lhs: Path, rhs: Path) -> Path { } /// Converts a `String` to a `Path` and returns the concatenated result. -@warn_unused_result + public func + (lhs: String, rhs: Path) -> Path { return Path(lhs) + rhs } /// Converts a `String` to a `Path` and returns the concatenated result. -@warn_unused_result + public func + (lhs: Path, rhs: String) -> Path { return lhs + Path(rhs) } @@ -176,19 +177,19 @@ public func += (lhs: inout Path, rhs: String) { /// Concatenates two `Path` instances and returns the result. -@warn_unused_result + public func / (lhs: Path, rhs: Path) -> Path { return lhs + rhs } /// Converts a `String` to a `Path` and returns the concatenated result. -@warn_unused_result + public func / (lhs: Path, rhs: String) -> Path { return lhs + rhs } /// Converts a `String` to a `Path` and returns the concatenated result. -@warn_unused_result + public func / (lhs: String, rhs: Path) -> Path { return lhs + rhs } @@ -203,24 +204,26 @@ public func /= (lhs: inout Path, rhs: String) { lhs += rhs } -infix operator <^> { -associativity left +precedencegroup FileCommonAncestorPrecedence { + associativity: left } +infix operator <^> : FileCommonAncestorPrecedence + /// Returns the common ancestor between the two paths. -@warn_unused_result + public func <^> (lhs: Path, rhs: Path) -> Path { return lhs.commonAncestor(rhs) } -infix operator {} +infix operator /// Runs `closure` with the path as its current working directory. public func (path: Path, closure: () throws -> ()) rethrows { try path.changeDirectory(closure) } -infix operator ->> {} +infix operator ->> /// Moves the file at the left path to a path. /// @@ -244,7 +247,7 @@ public func ->> (lhs: File, rhs: Path) throws { try lhs.moveToPath(rhs) } -infix operator ->! {} +infix operator ->! /// Forcibly moves the file at the left path to the right path. /// @@ -279,7 +282,7 @@ public func ->! (lhs: File, rhs: Path) throws { } -infix operator +>> {} +infix operator +>> /// Copies the file at the left path to the right path. /// @@ -303,7 +306,7 @@ public func +>> (lhs: File, rhs: Path) throws { try lhs.copyToPath(rhs) } -infix operator +>! {} +infix operator +>! /// Forcibly copies the file at the left path to the right path. /// @@ -337,7 +340,7 @@ public func +>! (lhs: File, rhs: Path) throws { try lhs +>> rhs } -infix operator =>> {} +infix operator =>> /// Creates a symlink of the left path at the right path. /// @@ -369,7 +372,7 @@ public func =>> (lhs: File, rhs: Path) throws { try lhs.symlinkToPath(rhs) } -infix operator =>! {} +infix operator =>! /// Forcibly creates a symlink of the left path at the right path by deleting /// anything at the right path before creating the symlink. @@ -406,27 +409,27 @@ public func =>! (lhs: File, rhs: Path) throws { try lhs.path =>! rhs } -postfix operator % {} +postfix operator % /// Returns the standardized version of the path. -@warn_unused_result + public postfix func % (path: Path) -> Path { return path.standardized } -postfix operator * {} +postfix operator * /// Returns the resolved version of the path. -@warn_unused_result + public postfix func * (path: Path) -> Path { return path.resolved } -postfix operator ^ {} +postfix operator ^ /// Returns the path's parent path. -@warn_unused_result + public postfix func ^ (path: Path) -> Path { return path.parent } diff --git a/Sources/Path.swift b/Sources/Path.swift index d71ce30..d0497fb 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -267,7 +267,7 @@ public struct Path: ExpressibleByStringLiteral, RawRepresentable, Hashable, Inde public var isDirectory: Bool { var isDirectory: ObjCBool = false return _fmWraper.fileManager.fileExists(atPath: _safeRawValue, isDirectory: &isDirectory) - && isDirectory + && isDirectory.boolValue } /// Returns `true` if the path is a directory file. @@ -354,7 +354,7 @@ extension Path { /// /// - Parameter closure: The block to run while `Path.Current` is changed. /// - public func changeDirectory(closure: () throws -> ()) rethrows { + public func changeDirectory(_ closure: () throws -> ()) rethrows { let previous = Path.Current defer { Path.Current = previous } if _fmWraper.fileManager.changeCurrentDirectoryPath(_safeRawValue) { @@ -631,7 +631,7 @@ extension Path { public func touch(_ updateModificationDate: Bool = true) throws { if self.exists { if updateModificationDate { - try _setAttribute(FileAttributeKey.modificationDate.rawValue, value: Date() as AnyObject) + try _setAttribute(FileAttributeKey.modificationDate, value: Date()) } } else { try createFile() @@ -796,18 +796,38 @@ extension Path { /// /// - Returns: All of the path's elements up to and including the index. /// - public subscript(index: Int) -> Path { + public subscript(position: Int) -> Path { let components = self.components - if index < 0 || index >= components.count { + if position < 0 || position >= components.count { fatalError("Path index out of range") } else { var result = components.first! - for i in 1 ..< index + 1 { + for i in 1 ..< position + 1 { result += components[i] } return result } } + + public subscript(bounds: Range) -> Path { + let components = self.components + if bounds.lowerBound < 0 || bounds.upperBound >= components.count { + fatalError("Path bounds out of range") + } + var result = components[bounds.lowerBound] + for i in (bounds.lowerBound + 1) ..< bounds.upperBound { + result += components[i] + } + return result + } + + public func index(after i: Int) -> Int { + return components.index(after: i) + } + + public func formIndex(after i: inout Int) { + return components.formIndex(after: &i) + } } @@ -818,23 +838,23 @@ extension Path { /// Returns the path's attributes. /// /// this method does not follow links. - public var attributes: [String : AnyObject] { - return (try? _fmWraper.fileManager.attributesOfItem(atPath: _safeRawValue) as! [String : AnyObject]?) ?? [:] + public var attributes: [FileAttributeKey : Any] { + return (try? _fmWraper.fileManager.attributesOfItem(atPath: _safeRawValue)) ?? [:] } /// Modify attributes /// /// this method does not follow links. - fileprivate func _setAttributes(_ attributes: [String : AnyObject]) throws { + fileprivate func _setAttributes(_ attributes: [FileAttributeKey : Any]) throws { do { - try _fmWraper.fileManager.setAttributes(attributes as! [FileAttributeKey : Any], ofItemAtPath: self._safeRawValue) + try _fmWraper.fileManager.setAttributes(attributes, ofItemAtPath: self._safeRawValue) } catch { throw FileKitError.attributesChangeFail(path: self) } } /// Modify one attribute - fileprivate func _setAttribute(_ key: String, value: AnyObject) throws { + fileprivate func _setAttribute(_ key: FileAttributeKey, value: Any) throws { try _setAttributes([key : value]) } @@ -948,10 +968,10 @@ extension Path { /// /// - Parameter url: The url to create a path for. public init?(url: URL) { - guard let path = url.path , url.isFileURL else { + guard url.isFileURL else { return nil } - rawValue = path + rawValue = url.path } /// - Returns: The `Path` objects url. @@ -1054,7 +1074,7 @@ extension Path { } -extension Path: StringInterpolationConvertible { +extension Path: ExpressibleByStringInterpolation { // MARK: - StringInterpolationConvertible @@ -1068,7 +1088,7 @@ extension Path: StringInterpolationConvertible { if let path = expr as? Path { self = path } else { - self = Path(String(expr)) + self = Path(String(describing: expr)) } } @@ -1098,14 +1118,16 @@ extension Path: CustomDebugStringConvertible { } extension Path: Sequence { - - // MARK: - SequenceType - - /// - Returns: A *generator* over the contents of the path. + + // MARK: - Sequence + + public typealias Subsequence = Path + + /// - Returns: An *iterator* over the contents of the path. public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: self) } - + } diff --git a/Sources/String+FileKit.swift b/Sources/String+FileKit.swift index cfd2782..61ad23d 100644 --- a/Sources/String+FileKit.swift +++ b/Sources/String+FileKit.swift @@ -34,7 +34,7 @@ extension String: DataType { public static func readFromPath(_ path: Path) throws -> String { let possibleContents = try? NSString( contentsOfFile: path._safeRawValue, - encoding: String.Encoding.utf8) + encoding: String.Encoding.utf8.rawValue) guard let contents = possibleContents else { throw FileKitError.readFromFileFail(path: path) } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index b981a7e..73a7b42 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -82,7 +82,7 @@ extension TextFile { /// - Parameter chunkSize: size of buffer (default: 4096) /// /// - Returns: the `TextFileStreamReader` - @warn_unused_result + public func streamReader(_ delimiter: String = "\n", chunkSize: Int = 4096) -> TextFileStreamReader? { return TextFileStreamReader( From e4b7034f52d899e49007cacc6b4fa453ee5a1e5c Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Wed, 17 Aug 2016 22:16:21 -0500 Subject: [PATCH 03/54] More errors fixed --- FileKit.xcodeproj/project.pbxproj | 6 +++ Sources/DataFile.swift | 4 +- Sources/DispatchWatcher.swift | 12 +++-- Sources/FileSystemEvent.swift | 26 +++++----- Sources/FileSystemEventStream.swift | 8 ++-- Sources/FileSystemWatcher.swift | 40 +++++++++------- Sources/Image+FileKit.swift | 2 +- Sources/Path.swift | 24 ++++------ Sources/TextFile.swift | 6 +-- Tests/Date+FileKit.swift | 16 +++---- Tests/FileKitTests.swift | 74 ++++++++++++++--------------- 11 files changed, 114 insertions(+), 104 deletions(-) diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 068659d..0e3f0dd 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -455,6 +455,7 @@ TargetAttributes = { 5204B84A1B96B83800AA473F = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 0800; }; 5204B8571B96B85E00AA473F = { CreatedOnToolsVersion = 7.0; @@ -462,6 +463,7 @@ }; 5263A9031B96BA3D00635A93 = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 0800; }; 527612411BAEA3EE00503D0A = { CreatedOnToolsVersion = 7.0; @@ -851,6 +853,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -870,6 +873,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -923,6 +927,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -935,6 +940,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index cb2c3c4..db4693e 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -40,7 +40,7 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. - public func read(_ options: Foundation.Data.ReadingOptions) throws -> Data { + public func read(_ options: NSData.ReadingOptions) throws -> Data { return try Data.readFromPath(path, options: options) } @@ -52,7 +52,7 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(_ data: Data, options: Foundation.Data.WritingOptions) throws { + public func write(_ data: Data, options: NSData.WritingOptions) throws { do { try data.write(toFile: self.path._safeRawValue, options: options) } catch { diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index d42993f..9bc472c 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -319,12 +319,18 @@ extension Path { /// - Parameter queue: The queue to be run within. /// - Parameter delegate: The delegate to call when events happen. /// - Parameter callback: The callback to be called on changes. - public func watch2(_ events: DispatchVnodeEvents = .All, - queue: DispatchQueue = DispatchQueue.global(qos: .default), + public func watch2(_ events: DispatchFileSystemEvents = .All, + queue: DispatchQueue? = nil, delegate: DispatchVnodeWatcherDelegate? = nil, callback: ((DispatchVnodeWatcher) -> Void)? = nil ) -> DispatchVnodeWatcher { - let watcher = DispatchVnodeWatcher(path: self, events: events, queue: queue, callback: callback) + let dispathQueue: DispatchQueue + if #available(OSX 10.10, *) { + dispathQueue = queue ?? DispatchQueue.global(qos: .default) + } else { + dispathQueue = queue ?? DispatchQueue.global(priority: .default) + } + let watcher = DispatchVnodeWatcher(path: self, events: events, queue: dispathQueue, callback: callback) watcher.delegate = delegate watcher.startWatching() return watcher diff --git a/Sources/FileSystemEvent.swift b/Sources/FileSystemEvent.swift index d37e997..5ddbc57 100644 --- a/Sources/FileSystemEvent.swift +++ b/Sources/FileSystemEvent.swift @@ -63,7 +63,7 @@ extension Path { /// - Parameter queue: The queue to be run within. /// - Parameter callback: The callback to handle events. /// - Returns: The `FileSystemWatcher` object. - public func watch(latency: NSTimeInterval = 0, queue: dispatch_queue_t = dispatch_get_main_queue(), callback: (FileSystemEvent) -> Void) -> FileSystemWatcher { + public func watch(_ latency: TimeInterval = 0, queue: DispatchQueue = DispatchQueue.main, callback: @escaping (FileSystemEvent) -> Void) -> FileSystemWatcher { let watcher = FileSystemWatcher(paths: [self], latency: latency, queue: queue, callback: callback) watcher.watch() return watcher @@ -71,7 +71,7 @@ extension Path { } -extension SequenceType where Self.Generator.Element == Path { +extension Sequence where Self.Iterator.Element == Path { // MARK: - Watching @@ -82,7 +82,7 @@ extension SequenceType where Self.Generator.Element == Path { /// - Parameter queue: The queue to be run within. /// - Parameter callback: The callback to handle events. /// - Returns: The `FileSystemWatcher` object. - public func watch(latency: NSTimeInterval = 0, queue: dispatch_queue_t = dispatch_get_main_queue(), callback: (FileSystemEvent) -> Void) -> FileSystemWatcher { + public func watch(_ latency: TimeInterval = 0, queue: DispatchQueue = DispatchQueue.main, callback: @escaping (FileSystemEvent) -> Void) -> FileSystemWatcher { let watcher = FileSystemWatcher(paths: Array(self), latency: latency, queue: queue, callback: callback) watcher.watch() return watcher @@ -93,7 +93,7 @@ extension SequenceType where Self.Generator.Element == Path { /// A set of fileystem event flags. -public struct FileSystemEventFlags: OptionSetType, CustomStringConvertible, CustomDebugStringConvertible { +public struct FileSystemEventFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Options @@ -238,25 +238,25 @@ public struct FileSystemEventFlags: OptionSetType, CustomStringConvertible, Cust /// A textual representation of `self`. public var description: String { var result = "" - for (index, element) in FileSystemEventFlags.allFlags.enumerate() { + for (index, element) in FileSystemEventFlags.allFlags.enumerated() { if self.contains(element) { let name = FileSystemEventFlags.allFlagNames[index] result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { var result = "" - for (index, element) in FileSystemEventFlags.allFlags.enumerate() { + for (index, element) in FileSystemEventFlags.allFlags.enumerated() { if self.contains(element) { let name = FileSystemEventFlags.allFlagNames[index] + "(\(element.rawValue))" result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } // MARK: - Initialization @@ -270,7 +270,7 @@ public struct FileSystemEventFlags: OptionSetType, CustomStringConvertible, Cust /// Flags for creating an event stream. -public struct FileSystemEventStreamCreateFlags: OptionSetType, CustomStringConvertible, CustomDebugStringConvertible { +public struct FileSystemEventStreamCreateFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Options @@ -313,25 +313,25 @@ public struct FileSystemEventStreamCreateFlags: OptionSetType, CustomStringConve /// A textual representation of `self`. public var description: String { var result = "" - for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerate() { + for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerated() { if self.contains(element) { let name = FileSystemEventStreamCreateFlags.allFlagNames[index] result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { var result = "" - for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerate() { + for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerated() { if self.contains(element) { let name = FileSystemEventStreamCreateFlags.allFlagNames[index] + "(\(element.rawValue))" result += result.isEmpty ? "\(name)": ", \(name)" } } - return String(self.dynamicType) + "[\(result)]" + return String(describing: type(of: self)) + "[\(result)]" } // MARK: - Initialization diff --git a/Sources/FileSystemEventStream.swift b/Sources/FileSystemEventStream.swift index 89e1d91..89f06ab 100644 --- a/Sources/FileSystemEventStream.swift +++ b/Sources/FileSystemEventStream.swift @@ -39,8 +39,8 @@ internal struct FileSystemEventStream: RawRepresentable { /// /// - Parameter runLoop: The run loop. /// - Parameter runLoopMode: The run loop mode. - func scheduleWithRunLoop(runLoop: CFRunLoopRef, runLoopMode: CFStringRef) { - FSEventStreamScheduleWithRunLoop(rawValue, runLoop, runLoopMode) + func scheduleWithRunLoop(_ runLoop: CFRunLoop, runLoopMode: CFRunLoopMode) { + FSEventStreamScheduleWithRunLoop(rawValue, runLoop, runLoopMode.rawValue) } /// Invalidates the stream. @@ -62,14 +62,14 @@ internal struct FileSystemEventStream: RawRepresentable { /// /// - Parameter runLoop: The run loop. /// - Parameter runLoopMode: The run loop mode. - func unscheduleFromRunLoop(runLoop: CFRunLoopRef, runLoopMode: CFStringRef) { + func unscheduleFromRunLoop(_ runLoop: CFRunLoop, runLoopMode: CFString) { FSEventStreamUnscheduleFromRunLoop(rawValue, runLoop, runLoopMode) } /// Schedules the stream on the specified dispatch queue /// /// - Parameter queue: The queue to be run within. - func setDispatchQueue(queue: dispatch_queue_t) { + func setDispatchQueue(_ queue: DispatchQueue) { FSEventStreamSetDispatchQueue(rawValue, queue) } diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index b38686f..1c04afd 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -33,24 +33,26 @@ import Foundation public class FileSystemWatcher { // MARK: - Private Static Properties - + /// The event stream callback for when events occur. private static let _eventCallback: FSEventStreamCallback = { (stream: ConstFSEventStreamRef, - contextInfo: UnsafeMutablePointer, + contextInfo: UnsafeMutableRawPointer?, numEvents: Int, - eventPaths: UnsafeMutablePointer, - eventFlags: UnsafePointer, - eventIds: UnsafePointer) in + eventPaths: UnsafeMutableRawPointer, + eventFlags: UnsafePointer?, + eventIds: UnsafePointer?) in defer { - watcher.lastEventId = eventIds[numEvents - 1] + if let lastEventId = eventIds?[numEvents - 1] { + watcher.lastEventId = lastEventId + } } FileSystemWatcher.log("Callback Fired") - let watcher: FileSystemWatcher = unsafeBitCast(contextInfo, FileSystemWatcher.self) - guard let paths = unsafeBitCast(eventPaths, NSArray.self) as? [String] else { + let watcher: FileSystemWatcher = unsafeBitCast(contextInfo, to: FileSystemWatcher.self) + guard let paths = unsafeBitCast(eventPaths, to: NSArray.self) as? [String], let eventFlags = eventFlags, let eventIds = eventIds else { return } @@ -76,13 +78,13 @@ public class FileSystemWatcher { public let latency: CFTimeInterval /// The queue for the watcher. - public let queue: dispatch_queue_t? + public let queue: DispatchQueue? /// The flags used to create the watcher. public let flags: FileSystemEventStreamCreateFlags /// The run loop mode for the watcher. - public var runLoopMode: CFStringRef = kCFRunLoopDefaultMode + public var runLoopMode: CFRunLoopMode = CFRunLoopMode.defaultMode /// The run loop for the watcher. public var runLoop: CFRunLoop = CFRunLoopGetMain() @@ -113,8 +115,8 @@ public class FileSystemWatcher { sinceWhen: FSEventStreamEventId = FileSystemEvent.NowEventId, flags: FileSystemEventStreamCreateFlags = [.UseCFTypes, .FileEvents], latency: CFTimeInterval = 0, - queue: dispatch_queue_t? = nil, - callback: (FileSystemEvent) -> Void + queue: DispatchQueue? = nil, + callback: @escaping (FileSystemEvent) -> Void ) { self.lastEventId = sinceWhen self.paths = paths @@ -135,7 +137,7 @@ public class FileSystemWatcher { /// Processes the event by logging it and then running the callback. /// /// - Parameter event: The file system event to be logged. - private func _processEvent(event: FileSystemEvent) { + private func _processEvent(_ event: FileSystemEvent) { FileSystemWatcher.log("\t\(event.id) - \(event.flags) - \(event.path)") self._callback(event) } @@ -143,7 +145,7 @@ public class FileSystemWatcher { /// Prints the message when in debug mode. /// /// - Parameter message: The message to be logged. - private static func log(message: String) { + private static func log(_ message: String) { #if DEBUG print(message) #endif @@ -164,19 +166,21 @@ public class FileSystemWatcher { copyDescription: nil ) // add self into context - context.info = UnsafeMutablePointer(unsafeAddressOf(self)) + context.info = Unmanaged.passUnretained(self).toOpaque() - let streamRef = FSEventStreamCreate( + guard let streamRef = FSEventStreamCreate( kCFAllocatorDefault, FileSystemWatcher._eventCallback, &context, - paths.map {$0.rawValue}, + paths.map {$0.rawValue} as CFArray, // since when lastEventId, // how long to wait after an event occurs before forwarding it latency, UInt32(flags.rawValue) - ) + ) else { + return + } _stream = FileSystemEventStream(rawValue: streamRef) _stream?.scheduleWithRunLoop(runLoop, runLoopMode: runLoopMode) diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index d2476d8..da47c6c 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -59,7 +59,7 @@ extension Image: DataType, WritableConvertible { /// iOS, watchOS, and tvOS. public var writable: NSData { #if os(OSX) - return self.TIFFRepresentation ?? NSData() + return self.tiffRepresentation as NSData? ?? NSData() #else return UIImagePNGRepresentation(self) as NSData? ?? NSData() #endif diff --git a/Sources/Path.swift b/Sources/Path.swift index d0497fb..85e2dfa 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -33,7 +33,8 @@ import Foundation /// /// An Path instance lets you manage files in a much easier way. /// -public struct Path: ExpressibleByStringLiteral, RawRepresentable, Hashable, Indexable { + +public struct Path { // MARK: - Static Methods and Properties @@ -729,9 +730,9 @@ extension Path { } -extension Path { +extension Path: ExpressibleByStringLiteral { - // MARK: - StringLiteralConvertible + // MARK: - ExpressibleByStringLiteral public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType @@ -754,7 +755,7 @@ extension Path { } -extension Path { +extension Path: RawRepresentable { // MARK: - RawRepresentable @@ -767,7 +768,7 @@ extension Path { } -extension Path { +extension Path: Hashable { // MARK: - Hashable @@ -778,7 +779,7 @@ extension Path { } -extension Path { +extension Path { // : Indexable { // MARK: - Indexable @@ -824,10 +825,6 @@ extension Path { public func index(after i: Int) -> Int { return components.index(after: i) } - - public func formIndex(after i: inout Int) { - return components.formIndex(after: &i) - } } @@ -1105,7 +1102,6 @@ extension Path: CustomStringConvertible { } - extension Path: CustomDebugStringConvertible { // MARK: - CustomDebugStringConvertible @@ -1121,8 +1117,6 @@ extension Path: Sequence { // MARK: - Sequence - public typealias Subsequence = Path - /// - Returns: An *iterator* over the contents of the path. public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: self) @@ -1220,12 +1214,12 @@ extension Path { /// Returns the path to the user scripts folder for the calling application public static var UserApplicationScripts: Path { - return _pathInUserDomain(.ApplicationScriptsDirectory) + return _pathInUserDomain(.applicationScriptsDirectory) } /// Returns the path to the user's trash directory public static var UserTrash: Path { - return _pathInUserDomain(.TrashDirectory) + return _pathInUserDomain(.trashDirectory) } #endif diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 73a7b42..6dc2c90 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -30,10 +30,10 @@ import Foundation /// A representation of a filesystem text file. /// /// The data type is String. -open class TextFile: File { +public class TextFile: File { /// The text file's string encoding. - open var encoding: String.Encoding + public var encoding: String.Encoding /// Initializes a text file from a path. /// @@ -62,7 +62,7 @@ open class TextFile: File { /// /// - Throws: `FileKitError.WriteToFileFail` /// - open override func write(_ data: String, atomically useAuxiliaryFile: Bool) throws { + public override func write(_ data: String, atomically useAuxiliaryFile: Bool) throws { do { try data.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, encoding: encoding) } catch { diff --git a/Tests/Date+FileKit.swift b/Tests/Date+FileKit.swift index 4a2d88c..769776a 100644 --- a/Tests/Date+FileKit.swift +++ b/Tests/Date+FileKit.swift @@ -32,17 +32,17 @@ import Foundation /// - Parameter lhs: The left hand side of the comparison. /// - Parameter rhs: The right hand side of the comparison. /// - Returns: `true` if the two objects are equal, otherwise `false`. -public func == (lhs: NSDate, rhs: NSDate) -> Bool { - return lhs === rhs || lhs.compare(rhs) == .OrderedSame -} +//public func == (lhs: Date, rhs: Date) -> Bool { +// return lhs === rhs || lhs.compare(rhs) == .orderedSame +//} /// Compares two `NSDate` objects. /// /// - Parameter lhs: The left hand side of the comparison. /// - Parameter rhs: The right hand side of the comparison. /// - Returns: `true` if the left hand side is smaller than the right hand side, otherwise `false`. -public func < (lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.compare(rhs) == .OrderedAscending -} - -extension NSDate: Comparable { } +//public func < (lhs: Date, rhs: Date) -> Bool { +// return lhs.compare(rhs) == .orderedAscending +//} +// +//extension Date: Comparable { } diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index c761dfc..495c729 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -35,11 +35,11 @@ class FileKitTests: XCTestCase { // MARK: - Path - class Delegate: NSObject, NSFileManagerDelegate { + class Delegate: NSObject, FileManagerDelegate { var expectedSourcePath: Path = "" var expectedDestinationPath: Path = "" func fileManager( - fileManager: NSFileManager, + _ fileManager: FileManager, shouldCopyItemAtPath srcPath: String, toPath dstPath: String ) -> Bool { @@ -74,7 +74,7 @@ class FileKitTests: XCTestCase { try secondSourcePath +>! destinationPath } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -131,7 +131,7 @@ class FileKitTests: XCTestCase { print("\(i) files under \(parent)") i = 0 - for (_, _) in Path.UserTemporary.enumerate() { + for (_, _) in Path.UserTemporary.enumerated() { i += 1 } } @@ -199,7 +199,7 @@ class FileKitTests: XCTestCase { let directories = children.filter { $0.isDirectory } - guard let directory = directories.first, childOfChild = directory.children().first else { + guard let directory = directories.first, let childOfChild = directory.children().first else { XCTFail("No child of child into \(p)") return } @@ -222,7 +222,7 @@ class FileKitTests: XCTestCase { try "Hello there, sir" |> TextFile(path: a) try b.createDirectory() } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } for p in [a, b] { @@ -303,7 +303,7 @@ class FileKitTests: XCTestCase { XCTAssertEqual(symLinkContents, "FileKit test") } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -347,7 +347,7 @@ class FileKitTests: XCTestCase { XCTAssertNotNil("\(volume)") } - volumes = Path.volumes(.SkipHiddenVolumes) + volumes = Path.volumes(.skipHiddenVolumes) XCTAssertFalse(volumes.isEmpty, "No visible volume") for volume in volumes { @@ -362,7 +362,7 @@ class FileKitTests: XCTestCase { XCTAssertEqual(pathFromURL, path) let subPath = pathFromURL + "test" - XCTAssertEqual(Path(url: url.URLByAppendingPathComponent("test")), subPath) + XCTAssertEqual(Path(url: url.appendingPathComponent("test")), subPath) } else { XCTFail("Not able to create Path from URL") } @@ -412,7 +412,7 @@ class FileKitTests: XCTestCase { XCTAssertTrue(modificationDate < newModificationDate) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -422,14 +422,14 @@ class FileKitTests: XCTestCase { do { if dir.exists { try dir.deleteFile() } } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } defer { do { if dir.exists { try dir.deleteFile() } } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -438,23 +438,23 @@ class FileKitTests: XCTestCase { try dir.createDirectory() XCTAssertTrue(dir.exists) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } do { XCTAssertTrue(dir.exists) try dir.createDirectory(withIntermediateDirectories: false) XCTFail("must throw exception") - } catch FileKitError.CreateDirectoryFail { + } catch FileKitError.createDirectoryFail { print("Create directory fail ok") } catch { - XCTFail("Unknown error: " + String(error)) + XCTFail("Unknown error: " + String(describing: error)) } do { XCTAssertTrue(dir.exists) try dir.createDirectory(withIntermediateDirectories: true) XCTAssertTrue(dir.exists) } catch { - XCTFail("Unexpected error: " + String(error)) + XCTFail("Unexpected error: " + String(describing: error)) } } @@ -507,7 +507,7 @@ class FileKitTests: XCTestCase { try textFile.create() XCTAssertTrue(textFile.exists) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -516,7 +516,7 @@ class FileKitTests: XCTestCase { try textFile.write("This is some test.") try textFile.write("This is another test.", atomically: false) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -533,7 +533,7 @@ class FileKitTests: XCTestCase { XCTAssertTrue(contents.hasSuffix(text + "\n" + text)) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -545,7 +545,7 @@ class FileKitTests: XCTestCase { "Sed non risus" ] let separator = "\n" - try expectedLines.joinWithSeparator(separator) |> textFile + try expectedLines.joined(separator: separator) |> textFile if let reader = textFile.streamReader() { var lines = [String]() @@ -559,7 +559,7 @@ class FileKitTests: XCTestCase { } } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -571,7 +571,7 @@ class FileKitTests: XCTestCase { "Sed non risus" ] let separator = "\n" - try expectedLines.joinWithSeparator(separator) |> textFile + try expectedLines.joined(separator: separator) |> textFile // all var result = textFile | "e" @@ -598,7 +598,7 @@ class FileKitTests: XCTestCase { XCTAssertTrue(result.isEmpty) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -613,7 +613,7 @@ class FileKitTests: XCTestCase { XCTAssert(textFile1 > textFile2) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -631,7 +631,7 @@ class FileKitTests: XCTestCase { try file.createFile() XCTAssertTrue(file.filePermissions.contains([.Read, .Write])) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -650,7 +650,7 @@ class FileKitTests: XCTestCase { XCTAssertEqual(contents, dict) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -667,7 +667,7 @@ class FileKitTests: XCTestCase { XCTAssertEqual(contents, array) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -677,12 +677,12 @@ class FileKitTests: XCTestCase { func testWriteToDataFile() { do { - let data = ("FileKit test" as NSString).dataUsingEncoding(NSUTF8StringEncoding)! + let data = ("FileKit test" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData try dataFile.write(data) let contents = try dataFile.read() XCTAssertEqual(contents, data) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -697,7 +697,7 @@ class FileKitTests: XCTestCase { let contents = try String(contentsOfPath: stringFile.path) XCTAssertEqual(contents, message) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -708,20 +708,20 @@ class FileKitTests: XCTestCase { let contents = try String(contentsOfPath: stringFile.path) XCTAssertEqual(contents, message) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } // MARK: - Image func testImageWriting() { - let url = NSURL(string: "https://raw.githubusercontent.com/nvzqz/FileKit/assets/logo.png")! - let img = Image(contentsOfURL: url) ?? Image() + let url = URL(string: "https://raw.githubusercontent.com/nvzqz/FileKit/assets/logo.png")! + let img = Image(contentsOf: url) ?? Image() do { let path: Path = .UserTemporary + "filekit_imagetest.png" try img.writeToPath(path) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } @@ -735,12 +735,12 @@ class FileKitTests: XCTestCase { let message = "Testing file system event when writing..." try message.writeToPath(pathToWatch, atomically: false) } catch { - XCTFail(String(error)) + XCTFail(String(describing: error)) } } // Do watch test - let expt = self.expectationWithDescription(expectation) + let expt = self.expectation(description: expectation) let watcher = pathToWatch.watch { event in print(event) // XXX here could check expected event type according to operation @@ -750,6 +750,6 @@ class FileKitTests: XCTestCase { watcher.close() } operation() - self.waitForExpectationsWithTimeout(10, handler: nil) + self.waitForExpectations(timeout: 10, handler: nil) } } From c478478e7b34f0c8ab6aca7038e0cf8a435f7f37 Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Wed, 17 Aug 2016 22:35:07 -0500 Subject: [PATCH 04/54] Fixing failing tests --- Sources/DispatchWatcher.swift | 58 +++++++++++++++++------------------ Tests/FileKitTests.swift | 11 ++++--- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index 9bc472c..d0ccf59 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -16,33 +16,33 @@ public protocol DispatchVnodeWatcherDelegate: class { // MARK: - Protocol /// Call when the file-system object was deleted from the namespace. - func fsWatcherDidObserveDelete(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveDelete(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object data changed. - func fsWatcherDidObserveWrite(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveWrite(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object changed in size. - func fsWatcherDidObserveExtend(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveExtend(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object metadata changed. - func fsWatcherDidObserveAttrib(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveAttrib(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object link count changed. - func fsWatcherDidObserveLink(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveLink(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object was renamed in the namespace. - func fsWatcherDidObserveRename(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveRename(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object was revoked. - func fsWatcherDidObserveRevoke(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveRevoke(_ watch: DispatchFileSystemWatcher) /// Call when the file-system object was created. - func fsWatcherDidObserveCreate(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveCreate(_ watch: DispatchFileSystemWatcher) /// Call when the directory changed (additions, deletions, and renamings). /// /// Calls `fsWatcherDidObserveWrite` by default. - func fsWatcherDidObserveDirectoryChange(_ watch: DispatchVnodeWatcher) + func fsWatcherDidObserveDirectoryChange(_ watch: DispatchFileSystemWatcher) } // Optional func and default func for `GCDFSWatcherDelegate` @@ -52,55 +52,55 @@ public extension DispatchVnodeWatcherDelegate { // MARK: - Extension /// Call when the file-system object was deleted from the namespace. - public func fsWatcherDidObserveDelete(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveDelete(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object data changed. - public func fsWatcherDidObserveWrite(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveWrite(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object changed in size. - public func fsWatcherDidObserveExtend(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveExtend(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object metadata changed. - public func fsWatcherDidObserveAttrib(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveAttrib(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object link count changed. - public func fsWatcherDidObserveLink(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveLink(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object was renamed in the namespace. - public func fsWatcherDidObserveRename(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveRename(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object was revoked. - public func fsWatcherDidObserveRevoke(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveRevoke(_ watch: DispatchFileSystemWatcher) { } /// Call when the file-system object was created. - public func fsWatcherDidObserveCreate(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveCreate(_ watch: DispatchFileSystemWatcher) { } /// Call when the directory changed (additions, deletions, and renamings). /// /// Calls `fsWatcherDidObserveWrite` by default. - public func fsWatcherDidObserveDirectoryChange(_ watch: DispatchVnodeWatcher) { + public func fsWatcherDidObserveDirectoryChange(_ watch: DispatchFileSystemWatcher) { fsWatcherDidObserveWrite(watch) } } /// Watcher for Vnode events -open class DispatchVnodeWatcher { +open class DispatchFileSystemWatcher { // MARK: - Properties @@ -114,10 +114,10 @@ open class DispatchVnodeWatcher { weak var delegate: DispatchVnodeWatcherDelegate? /// The watcher for watching creation event - weak var createWatcher: DispatchVnodeWatcher? + weak var createWatcher: DispatchFileSystemWatcher? /// The callback for vnode events. - fileprivate let callback: ((DispatchVnodeWatcher) -> Void)? + fileprivate let callback: ((DispatchFileSystemWatcher) -> Void)? /// The queue for the watcher. fileprivate let queue: DispatchQueue? @@ -152,7 +152,7 @@ open class DispatchVnodeWatcher { init(path: Path, events: DispatchFileSystemEvents, queue: DispatchQueue, - callback: ((DispatchVnodeWatcher) -> Void)? + callback: ((DispatchFileSystemWatcher) -> Void)? ) { self.path = path.absolute self.events = events @@ -322,15 +322,15 @@ extension Path { public func watch2(_ events: DispatchFileSystemEvents = .All, queue: DispatchQueue? = nil, delegate: DispatchVnodeWatcherDelegate? = nil, - callback: ((DispatchVnodeWatcher) -> Void)? = nil - ) -> DispatchVnodeWatcher { + callback: ((DispatchFileSystemWatcher) -> Void)? = nil + ) -> DispatchFileSystemWatcher { let dispathQueue: DispatchQueue if #available(OSX 10.10, *) { dispathQueue = queue ?? DispatchQueue.global(qos: .default) } else { dispathQueue = queue ?? DispatchQueue.global(priority: .default) } - let watcher = DispatchVnodeWatcher(path: self, events: events, queue: dispathQueue, callback: callback) + let watcher = DispatchFileSystemWatcher(path: self, events: events, queue: dispathQueue, callback: callback) watcher.delegate = delegate watcher.startWatching() return watcher @@ -348,10 +348,10 @@ extension Path { /// - Parameter callback: The callback to be called on changes. public func watch(_ events: DispatchFileSystemEvents = .All, queue: DispatchQueue = DispatchQueue.global(qos: .default), - delegate: DispatchVnodeWatcherDelegate? = nil, - callback: ((DispatchVnodeWatcher) -> Void)? = nil - ) -> DispatchVnodeWatcher { - let watcher = DispatchVnodeWatcher(path: self, events: events, queue: queue, callback: callback) + delegate: DispatchFileSystemWatcherDelegate? = nil, + callback: ((DispatchFileSystemWatcher) -> Void)? = nil + ) -> DispatchFileSystemWatcher { + let watcher = DispatchFileSystemWatcher(path: self, events: events, queue: queue, callback: callback) watcher.delegate = delegate watcher.startWatching() return watcher diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 495c729..9c977af 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -641,13 +641,14 @@ class FileKitTests: XCTestCase { func testWriteToDictionaryFile() { do { - let dict = NSMutableDictionary() - dict["FileKit"] = true - dict["Hello"] = "World" + let dict: [NSString: Any] = [ + "FileKit": true, + "Hello": "World" + ] - try dictionaryFile.write(dict) + try dictionaryFile.write(dict as NSDictionary) let contents = try dictionaryFile.read() - XCTAssertEqual(contents, dict) + XCTAssertEqual(contents, dict as NSDictionary) } catch { XCTFail(String(describing: error)) From 818b87468fcf1acb8576db852ca5308045ce4ee8 Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Wed, 17 Aug 2016 23:22:22 -0500 Subject: [PATCH 05/54] Final touch ups --- FileKit.playground/Contents.swift | 3 +- FileKit.xcodeproj/project.pbxproj | 4 --- Sources/DataFile.swift | 4 +-- Sources/File.swift | 4 +-- Sources/FileProtection.swift | 36 +++++++++++------------ Sources/FileType.swift | 46 ++++++++++++++--------------- Sources/Operators.swift | 17 ++++++----- Sources/Path.swift | 20 ++++++------- Sources/RelativePathType.swift | 10 +++---- Sources/TextFile.swift | 6 ++-- Tests/Date+FileKit.swift | 48 ------------------------------- Tests/FileKitTests.swift | 11 ++++--- 12 files changed, 78 insertions(+), 131 deletions(-) delete mode 100644 Tests/Date+FileKit.swift diff --git a/FileKit.playground/Contents.swift b/FileKit.playground/Contents.swift index 21bd8d4..f3afd1d 100644 --- a/FileKit.playground/Contents.swift +++ b/FileKit.playground/Contents.swift @@ -5,9 +5,10 @@ Use this playground to try out FileKit import Cocoa import FileKit import XCPlayground +import PlaygroundSupport extension Path { - static let SharedPlaygroundData = Path(url: XCPlaygroundSharedDataDirectoryURL)! + static let SharedPlaygroundData = Path(url: playgroundSharedDataDirectory)! } let shared = Path.SharedPlaygroundData diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 0e3f0dd..ff575d9 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -114,7 +114,6 @@ 52BF6BB21B99322000F07E13 /* FileKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BF6BB01B99322000F07E13 /* FileKitError.swift */; }; 82F4F2BD1CA95480002C8393 /* FileSystemWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */; }; 82F4F2C01CA956F2002C8393 /* FileSystemEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */; }; - C404F01E1BC7CA7200EF9ED9 /* Date+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C404F01D1BC7CA7200EF9ED9 /* Date+FileKit.swift */; }; C4F7D01F1C08C0DA00EF359B /* FileSystemEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7D01E1C08C0DA00EF359B /* FileSystemEvent.swift */; }; /* End PBXBuildFile section */ @@ -168,7 +167,6 @@ 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemWatcher.swift; sourceTree = ""; }; 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEventStream.swift; sourceTree = ""; }; - C404F01D1BC7CA7200EF9ED9 /* Date+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+FileKit.swift"; sourceTree = ""; }; C4F7D01E1C08C0DA00EF359B /* FileSystemEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEvent.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -269,7 +267,6 @@ isa = PBXGroup; children = ( 5263A9061B96BA3D00635A93 /* FileKitTests.swift */, - C404F01D1BC7CA7200EF9ED9 /* Date+FileKit.swift */, 5263A9081B96BA3D00635A93 /* Info.plist */, ); path = Tests; @@ -665,7 +662,6 @@ buildActionMask = 2147483647; files = ( 5263A9071B96BA3D00635A93 /* FileKitTests.swift in Sources */, - C404F01E1BC7CA7200EF9ED9 /* Date+FileKit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index db4693e..4e21a71 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -36,7 +36,7 @@ extension File where Data: NSData { /// Reads the file and returns its data. /// - Parameter options: A mask that specifies write options - /// described in `Foundation.Data.ReadingOptions`. + /// described in `NSData.ReadingOptions`. /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. @@ -48,7 +48,7 @@ extension File where Data: NSData { /// /// - Parameter data: The data to be written to the file. /// - Parameter options: A mask that specifies write options - /// described in `Foundation.Data.WritingOptions`. + /// described in `NSData.WritingOptions`. /// /// - Throws: `FileKitError.WriteToFileFail` /// diff --git a/Sources/File.swift b/Sources/File.swift index b7d8229..f6a8ce1 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -208,7 +208,7 @@ open class File: Comparable { return FilePermissions(forFile: self) } - // MARK: - NSFileHandle + // MARK: - FileHandle /// Returns a file handle for reading from `self`, or `nil` if `self` /// doesn't exist. @@ -228,7 +228,7 @@ open class File: Comparable { return path.fileHandleForUpdating } - // MARK: - NSStream + // MARK: - Stream /// Returns an input stream that reads data from `self`, or `nil` if `self` /// doesn't exist. diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index 70235a3..bc840c0 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -29,25 +29,25 @@ import Foundation #if os(iOS) || os(watchOS) || os(tvOS) -/// The values that can be obtained from `NSFileProtectionKey` on a +/// The values that can be obtained from `FileAttributeKey.protectionKey` on a /// file's attributes. Only available on iOS, watchOS, and tvOS. public enum FileProtection: String { /// The file has no special protections associated with it. - case None + case none /// The file is stored in an encrypted format on disk and cannot be read /// from or written to while the device is locked or booting. - case Complete + case complete /// The file is stored in an encrypted format on disk. Files can be created /// while the device is locked, but once closed, cannot be opened again /// until the device is unlocked. - case CompleteUnlessOpen + case completeUnlessOpen /// The file is stored in an encrypted format on disk and cannot be accessed /// until after the device has booted. - case CompleteUntilFirstUserAuthentication + case completeUntilFirstUserAuthentication /// Initializes `self` from a file protection value. /// @@ -56,13 +56,13 @@ public enum FileProtection: String { public init?(rawValue: String) { switch rawValue { case FileProtectionType.none.rawValue: - self = .None + self = .none case FileProtectionType.complete.rawValue: - self = .Complete + self = .complete case FileProtectionType.completeUnlessOpen.rawValue: - self = .CompleteUnlessOpen + self = .completeUnlessOpen case FileProtectionType.completeUntilFirstUserAuthentication.rawValue: - self = .CompleteUntilFirstUserAuthentication + self = .completeUntilFirstUserAuthentication default: return nil } @@ -71,27 +71,27 @@ public enum FileProtection: String { /// The file protection string value of `self`. public var rawValue: String { switch self { - case .None: + case .none: return FileProtectionType.none.rawValue - case .Complete: + case .complete: return FileProtectionType.complete.rawValue - case .CompleteUnlessOpen: + case .completeUnlessOpen: return FileProtectionType.completeUnlessOpen.rawValue - case .CompleteUntilFirstUserAuthentication: + case .completeUntilFirstUserAuthentication: return FileProtectionType.completeUntilFirstUserAuthentication.rawValue } } - /// Return the equivalent NSDataWritingOptions + /// Return the equivalent NSData.WritingOptions public var dataWritingOption: NSData.WritingOptions { switch self { - case .None: + case .none: return .noFileProtection - case .Complete: + case .complete: return .completeFileProtection - case .CompleteUnlessOpen: + case .completeUnlessOpen: return .completeFileProtectionUnlessOpen - case .CompleteUntilFirstUserAuthentication: + case .completeUntilFirstUserAuthentication: return .completeFileProtectionUntilFirstUserAuthentication } } diff --git a/Sources/FileType.swift b/Sources/FileType.swift index 5481525..ea4e03b 100644 --- a/Sources/FileType.swift +++ b/Sources/FileType.swift @@ -31,66 +31,66 @@ import Foundation public enum FileType: String { /// The file is a directory. - case Directory + case directory /// The file is a regular file. - case Regular + case regular /// The file is a symbolic link. - case SymbolicLink + case symbolicLink /// The file is a socket. - case Socket + case socket /// The file is a characer special file. - case CharacterSpecial + case characterSpecial /// The file is a block special file. - case BlockSpecial + case blockSpecial /// The type of the file is unknown. - case Unknown + case unknown - /// Creates a FileType from an `NSFileType` attribute. + /// Creates a FileType from an `FileAttributeType` attribute. /// /// - Parameter rawValue: The raw value to create from. public init?(rawValue: String) { switch rawValue { case FileAttributeType.typeDirectory.rawValue: - self = .Directory + self = .directory case FileAttributeType.typeRegular.rawValue: - self = .Regular + self = .regular case FileAttributeType.typeSymbolicLink.rawValue: - self = .SymbolicLink + self = .symbolicLink case FileAttributeType.typeSocket.rawValue: - self = .Socket + self = .socket case FileAttributeType.typeCharacterSpecial.rawValue: - self = .CharacterSpecial + self = .characterSpecial case FileAttributeType.typeBlockSpecial.rawValue: - self = .BlockSpecial + self = .blockSpecial case FileAttributeType.typeUnknown.rawValue: - self = .Unknown + self = .unknown default: return nil } } - /// The `NSFileType` attribute for `self`. + /// The `FileAttributeType` attribute for `self`. public var rawValue: String { switch self { - case .Directory: + case .directory: return FileAttributeType.typeDirectory.rawValue - case .Regular: + case .regular: return FileAttributeType.typeRegular.rawValue - case .SymbolicLink: + case .symbolicLink: return FileAttributeType.typeSymbolicLink.rawValue - case .Socket: + case .socket: return FileAttributeType.typeSocket.rawValue - case .CharacterSpecial: + case .characterSpecial: return FileAttributeType.typeCharacterSpecial.rawValue - case .BlockSpecial: + case .blockSpecial: return FileAttributeType.typeBlockSpecial.rawValue - case .Unknown: + case .unknown: return FileAttributeType.typeUnknown.rawValue } } diff --git a/Sources/Operators.swift b/Sources/Operators.swift index eefb545..17c788d 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -30,17 +30,16 @@ import Foundation fileprivate func < (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } } - // MARK: - File /// Returns `true` if both files' paths are the same. diff --git a/Sources/Path.swift b/Sources/Path.swift index 85e2dfa..9bb85e8 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -275,21 +275,21 @@ public struct Path { /// /// this method does not follow links. public var isDirectoryFile: Bool { - return fileType == .Directory + return fileType == .directory } /// Returns `true` if the path is a symbolic link. /// /// this method does not follow links. public var isSymbolicLink: Bool { - return fileType == .SymbolicLink + return fileType == .symbolicLink } /// Returns `true` if the path is a regular file. /// /// this method does not follow links. public var isRegular: Bool { - return fileType == .Regular + return fileType == .regular } /// Returns `true` if the path exists any fileType item. @@ -436,9 +436,9 @@ extension Path { let ancestorComponents = selfComponents[0.. 1: - return .Ancestor + return .ancestor case ".."?: - return .Parent + return .parent default: - return .Normal + return .normal } } } diff --git a/Sources/RelativePathType.swift b/Sources/RelativePathType.swift index a40c2d8..704804b 100644 --- a/Sources/RelativePathType.swift +++ b/Sources/RelativePathType.swift @@ -12,18 +12,18 @@ import Foundation public enum RelativePathType: String { /// path like "dir/path". - case Normal + case normal /// path like "." and "". - case Current + case current /// path like "../path". - case Ancestor + case ancestor /// path like "..". - case Parent + case parent /// path like "/path". - case Absolute + case absolute } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 6dc2c90..73a7b42 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -30,10 +30,10 @@ import Foundation /// A representation of a filesystem text file. /// /// The data type is String. -public class TextFile: File { +open class TextFile: File { /// The text file's string encoding. - public var encoding: String.Encoding + open var encoding: String.Encoding /// Initializes a text file from a path. /// @@ -62,7 +62,7 @@ public class TextFile: File { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public override func write(_ data: String, atomically useAuxiliaryFile: Bool) throws { + open override func write(_ data: String, atomically useAuxiliaryFile: Bool) throws { do { try data.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, encoding: encoding) } catch { diff --git a/Tests/Date+FileKit.swift b/Tests/Date+FileKit.swift deleted file mode 100644 index 769776a..0000000 --- a/Tests/Date+FileKit.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Date.swift -// FileKitTest -// -// The MIT License (MIT) -// -// Copyright (c) 2015-2016 Nikolai Vazquez -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -/// Checks equality of two `NSDate` objects. -/// -/// - Parameter lhs: The left hand side of the comparison. -/// - Parameter rhs: The right hand side of the comparison. -/// - Returns: `true` if the two objects are equal, otherwise `false`. -//public func == (lhs: Date, rhs: Date) -> Bool { -// return lhs === rhs || lhs.compare(rhs) == .orderedSame -//} - -/// Compares two `NSDate` objects. -/// -/// - Parameter lhs: The left hand side of the comparison. -/// - Parameter rhs: The right hand side of the comparison. -/// - Returns: `true` if the left hand side is smaller than the right hand side, otherwise `false`. -//public func < (lhs: Date, rhs: Date) -> Bool { -// return lhs.compare(rhs) == .orderedAscending -//} -// -//extension Date: Comparable { } diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 9c977af..cfc69e1 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -641,14 +641,13 @@ class FileKitTests: XCTestCase { func testWriteToDictionaryFile() { do { - let dict: [NSString: Any] = [ - "FileKit": true, - "Hello": "World" - ] + let dict = NSMutableDictionary() + dict["FileKit" as NSString] = true + dict["Hello" as NSString] = "World" - try dictionaryFile.write(dict as NSDictionary) + try dictionaryFile.write(dict) let contents = try dictionaryFile.read() - XCTAssertEqual(contents, dict as NSDictionary) + XCTAssertEqual(contents, dict) } catch { XCTFail(String(describing: error)) From 45e2ed4cd73b64260b82bf59dbd5dbb9fa9fec90 Mon Sep 17 00:00:00 2001 From: Jake Heiser Date: Thu, 18 Aug 2016 17:11:15 -0500 Subject: [PATCH 06/54] Fixed vnode -> file system name change --- Sources/DispatchWatcher.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index d0ccf59..7931bf7 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -10,8 +10,8 @@ import Foundation -/// Delegate for `DispatchVnodeWatcher` -public protocol DispatchVnodeWatcherDelegate: class { +/// Delegate for `DispatchFileSystemWatcher` +public protocol DispatchFileSystemWatcherDelegate: class { // MARK: - Protocol @@ -47,7 +47,7 @@ public protocol DispatchVnodeWatcherDelegate: class { // Optional func and default func for `GCDFSWatcherDelegate` // Empty func treated as Optional func -public extension DispatchVnodeWatcherDelegate { +public extension DispatchFileSystemWatcherDelegate { // MARK: - Extension @@ -111,12 +111,12 @@ open class DispatchFileSystemWatcher { open let events: DispatchFileSystemEvents /// The delegate to call when events happen - weak var delegate: DispatchVnodeWatcherDelegate? + weak var delegate: DispatchFileSystemWatcherDelegate? /// The watcher for watching creation event weak var createWatcher: DispatchFileSystemWatcher? - /// The callback for vnode events. + /// The callback for file system events. fileprivate let callback: ((DispatchFileSystemWatcher) -> Void)? /// The queue for the watcher. @@ -321,7 +321,7 @@ extension Path { /// - Parameter callback: The callback to be called on changes. public func watch2(_ events: DispatchFileSystemEvents = .All, queue: DispatchQueue? = nil, - delegate: DispatchVnodeWatcherDelegate? = nil, + delegate: DispatchFileSystemWatcherDelegate? = nil, callback: ((DispatchFileSystemWatcher) -> Void)? = nil ) -> DispatchFileSystemWatcher { let dispathQueue: DispatchQueue From 2621b2429f1b8b9ce93a6b51f56a30e3acd53418 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Thu, 18 Aug 2016 18:59:51 -0400 Subject: [PATCH 07/54] Disable type_name rule for swiftlint --- .swiftlint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index b6c646f..69e4752 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -7,6 +7,7 @@ disabled_rules: - function_body_length - cyclomatic_complexity - variable_name + - type_name # some rules are only opt-in opt_in_rules: From acd0c8cc7f62f74193735169de68b2e1b6872cc8 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Thu, 18 Aug 2016 19:00:18 -0400 Subject: [PATCH 08/54] Use `isEmpty` over `== 0` for data --- Sources/TextFile.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 73a7b42..0304da9 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -175,7 +175,7 @@ open class TextFileStreamReader { var range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) while range.location == NSNotFound { let tmpData = fileHandle.readData(ofLength: chunkSize) - if tmpData.count == 0 { + if tmpData.isEmpty { // EOF or read error. atEOF = true if buffer.length > 0 { From 13bdccf8a317ee8caf5aba63d9064940061437b0 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Thu, 18 Aug 2016 19:01:50 -0400 Subject: [PATCH 09/54] Remove trailing whitespace --- Sources/DispatchWatcher.swift | 2 +- Sources/FileSystemWatcher.swift | 2 +- Sources/Path.swift | 10 +++++----- Sources/TextFile.swift | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index 7931bf7..31fa1c3 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -256,7 +256,7 @@ open class DispatchFileSystemWatcher { var _events = events _events.remove(.Create) source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: DispatchSource.FileSystemEvent(rawValue: _events.rawValue), queue: queue) - + // Recheck if open success and source create success if source != nil && fileDescriptor != -1 { guard callback != nil || delegate != nil else { diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index 1c04afd..9be2744 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -33,7 +33,7 @@ import Foundation public class FileSystemWatcher { // MARK: - Private Static Properties - + /// The event stream callback for when events occur. private static let _eventCallback: FSEventStreamCallback = { (stream: ConstFSEventStreamRef, diff --git a/Sources/Path.swift b/Sources/Path.swift index 9bb85e8..d4869c0 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -809,7 +809,7 @@ extension Path { // : Indexable { return result } } - + public subscript(bounds: Range) -> Path { let components = self.components if bounds.lowerBound < 0 || bounds.upperBound >= components.count { @@ -821,7 +821,7 @@ extension Path { // : Indexable { } return result } - + public func index(after i: Int) -> Int { return components.index(after: i) } @@ -1114,14 +1114,14 @@ extension Path: CustomDebugStringConvertible { } extension Path: Sequence { - + // MARK: - Sequence - + /// - Returns: An *iterator* over the contents of the path. public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: self) } - + } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 0304da9..0f51f71 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -82,7 +82,7 @@ extension TextFile { /// - Parameter chunkSize: size of buffer (default: 4096) /// /// - Returns: the `TextFileStreamReader` - + public func streamReader(_ delimiter: String = "\n", chunkSize: Int = 4096) -> TextFileStreamReader? { return TextFileStreamReader( From 4d928bc99cc075b9d6c0c4293ba472be4b7eed02 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Mon, 29 Aug 2016 21:36:43 -0400 Subject: [PATCH 10/54] Make WatchKit import explicitly for watchOS Also made Image extension only for OS X, iOS, tvOS, and watchOS. --- Sources/Image+FileKit.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index da47c6c..018b410 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -29,18 +29,20 @@ import Cocoa #elseif os(iOS) || os(tvOS) import UIKit -#else +#elseif os(watchOS) import WatchKit #endif #if os(OSX) /// The image type for the current platform. public typealias Image = NSImage -#else +#elseif os(iOS) || os(tvOS) || os(watchOS) /// The image type for the current platform. public typealias Image = UIImage #endif +#if os(OSX) || os(iOS) || os(tvOS) || os(watchOS) + extension Image: DataType, WritableConvertible { /// Returns an image from the given path. @@ -86,3 +88,5 @@ extension Image: DataType, WritableConvertible { } } + +#endif From 29e8c684fdb3018b3fe8ca6b84fe4fb06ef891bf Mon Sep 17 00:00:00 2001 From: phimage Date: Wed, 28 Sep 2016 15:17:21 +0200 Subject: [PATCH 11/54] Rename functions to swift 3 style Array, Dictionary conform to Readable & Writable (using bridged objects) Remove capital from well know directories --- FileKit.xcodeproj/project.pbxproj | 82 +++++-- Sources/Array+File.swift | 53 +++++ Sources/ArrayFile.swift | 9 +- ...dle+FileKit.swift => Bundle+FileKit.swift} | 2 +- Sources/Data+FileKit.swift | 85 ++++++++ Sources/DataFile.swift | 57 +++-- Sources/DataType.swift | 35 ++- Sources/Dictionary+File.swift | 53 +++++ Sources/DictionaryFile.swift | 9 +- Sources/File.swift | 30 +-- Sources/FilePermissions.swift | 25 ++- Sources/FileProtection.swift | 6 +- Sources/Image+FileKit.swift | 10 +- Sources/NSArray+FileKit.swift | 4 +- Sources/NSData+FileKit.swift | 8 +- Sources/NSDataFile.swift | 63 ++++++ Sources/NSDictionary+FileKit.swift | 4 +- Sources/NSString+FileKit.swift | 49 ++++- Sources/Operators.swift | 30 +-- Sources/Path.swift | 78 +++---- Sources/Process+FileKit.swift | 4 +- Sources/RelativePathType.swift | 24 ++- Sources/String+FileKit.swift | 24 ++- Sources/TextFile.swift | 2 +- Tests/FileKitTests.swift | 202 ++++++++++++------ 25 files changed, 709 insertions(+), 239 deletions(-) create mode 100644 Sources/Array+File.swift rename Sources/{NSBundle+FileKit.swift => Bundle+FileKit.swift} (98%) create mode 100644 Sources/Data+FileKit.swift create mode 100644 Sources/Dictionary+File.swift create mode 100644 Sources/NSDataFile.swift diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index ff575d9..7d0fc62 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -40,9 +40,9 @@ 524D31571BC79067008B93D0 /* ArrayFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D31561BC79067008B93D0 /* ArrayFile.swift */; }; 524D31581BC79067008B93D0 /* ArrayFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D31561BC79067008B93D0 /* ArrayFile.swift */; }; 524D31591BC79067008B93D0 /* ArrayFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D31561BC79067008B93D0 /* ArrayFile.swift */; }; - 524D315B1BC79331008B93D0 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* DataFile.swift */; }; - 524D315C1BC79331008B93D0 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* DataFile.swift */; }; - 524D315D1BC79331008B93D0 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* DataFile.swift */; }; + 524D315B1BC79331008B93D0 /* NSDataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* NSDataFile.swift */; }; + 524D315C1BC79331008B93D0 /* NSDataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* NSDataFile.swift */; }; + 524D315D1BC79331008B93D0 /* NSDataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* NSDataFile.swift */; }; 524D315F1BC7A02A008B93D0 /* Image+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315E1BC7A02A008B93D0 /* Image+FileKit.swift */; }; 524D31601BC7A02A008B93D0 /* Image+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315E1BC7A02A008B93D0 /* Image+FileKit.swift */; }; 524D31611BC7A02A008B93D0 /* Image+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315E1BC7A02A008B93D0 /* Image+FileKit.swift */; }; @@ -83,10 +83,10 @@ 52A017011C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A016FF1C01AD4A0045A9C8 /* NSData+FileKit.swift */; }; 52A017021C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A016FF1C01AD4A0045A9C8 /* NSData+FileKit.swift */; }; 52A017031C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A016FF1C01AD4A0045A9C8 /* NSData+FileKit.swift */; }; - 52A017051C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */; }; - 52A017061C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */; }; - 52A017071C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */; }; - 52A017081C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */; }; + 52A017051C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */; }; + 52A017061C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */; }; + 52A017071C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */; }; + 52A017081C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */; }; 52A0170A1C01D5400045A9C8 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017091C01D5400045A9C8 /* FileType.swift */; }; 52A0170B1C01D5400045A9C8 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017091C01D5400045A9C8 /* FileType.swift */; }; 52A0170C1C01D5400045A9C8 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A017091C01D5400045A9C8 /* FileType.swift */; }; @@ -99,7 +99,7 @@ 52B938BD1BF3C42A001B7AEB /* TextFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523C33771B9A7EFC00AB70E4 /* TextFile.swift */; }; 52B938BE1BF3C42A001B7AEB /* DictionaryFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523C337A1B9B68D600AB70E4 /* DictionaryFile.swift */; }; 52B938BF1BF3C42A001B7AEB /* ArrayFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D31561BC79067008B93D0 /* ArrayFile.swift */; }; - 52B938C01BF3C42A001B7AEB /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* DataFile.swift */; }; + 52B938C01BF3C42A001B7AEB /* NSDataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524D315A1BC79331008B93D0 /* NSDataFile.swift */; }; 52B938C11BF3C42A001B7AEB /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5204B7C31B968E8000AA473F /* Path.swift */; }; 52B938C21BF3C42A001B7AEB /* DataType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523C33981B9B764600AB70E4 /* DataType.swift */; }; 52B938C31BF3C42A001B7AEB /* FileKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BF6BB01B99322000F07E13 /* FileKitError.swift */; }; @@ -114,6 +114,22 @@ 52BF6BB21B99322000F07E13 /* FileKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BF6BB01B99322000F07E13 /* FileKitError.swift */; }; 82F4F2BD1CA95480002C8393 /* FileSystemWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */; }; 82F4F2C01CA956F2002C8393 /* FileSystemEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */; }; + C41FC73A1D9BDCB400C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; + C41FC73B1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; + C41FC73C1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; + C41FC73D1D9BDCD200C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; + C41FC73F1D9BE44A00C3A0F1 /* Dictionary+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */; }; + C41FC7411D9BE4DB00C3A0F1 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */; }; + C41FC7421D9BEC7700C3A0F1 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */; }; + C41FC7431D9BEC7800C3A0F1 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */; }; + C41FC7441D9BEC7800C3A0F1 /* DataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */; }; + C41FC7461D9BEEC000C3A0F1 /* Array+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */; }; + C41FC7471D9BEEF300C3A0F1 /* Array+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */; }; + C41FC7491D9BEEF400C3A0F1 /* Array+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */; }; + C41FC74A1D9BEEF400C3A0F1 /* Array+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */; }; + C41FC74B1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */; }; + C41FC74C1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */; }; + C41FC74D1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */; }; C4F7D01F1C08C0DA00EF359B /* FileSystemEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7D01E1C08C0DA00EF359B /* FileSystemEvent.swift */; }; /* End PBXBuildFile section */ @@ -146,7 +162,7 @@ 523C33A01B9B772A00AB70E4 /* File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = ""; }; 523C33A61B9B894A00AB70E4 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = ""; }; 524D31561BC79067008B93D0 /* ArrayFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFile.swift; sourceTree = ""; }; - 524D315A1BC79331008B93D0 /* DataFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataFile.swift; sourceTree = ""; }; + 524D315A1BC79331008B93D0 /* NSDataFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSDataFile.swift; sourceTree = ""; }; 524D315E1BC7A02A008B93D0 /* Image+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Image+FileKit.swift"; sourceTree = ""; }; 5263A9041B96BA3D00635A93 /* FileKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FileKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5263A9061B96BA3D00635A93 /* FileKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileKitTests.swift; sourceTree = ""; }; @@ -158,7 +174,7 @@ 52A016F51C01ACE50045A9C8 /* NSDictionary+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSDictionary+FileKit.swift"; sourceTree = ""; }; 52A016FA1C01AD1E0045A9C8 /* NSArray+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSArray+FileKit.swift"; sourceTree = ""; }; 52A016FF1C01AD4A0045A9C8 /* NSData+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSData+FileKit.swift"; sourceTree = ""; }; - 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+FileKit.swift"; sourceTree = ""; }; + 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+FileKit.swift"; sourceTree = ""; }; 52A017091C01D5400045A9C8 /* FileType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileType.swift; sourceTree = ""; }; 52A0170F1C024D840045A9C8 /* NSString+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSString+FileKit.swift"; sourceTree = ""; }; 52B938B31BF3C3E5001B7AEB /* FileKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -167,6 +183,10 @@ 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemWatcher.swift; sourceTree = ""; }; 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEventStream.swift; sourceTree = ""; }; + C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+FileKit.swift"; sourceTree = ""; }; + C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+File.swift"; sourceTree = ""; }; + C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataFile.swift; sourceTree = ""; }; + C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+File.swift"; sourceTree = ""; }; C4F7D01E1C08C0DA00EF359B /* FileSystemEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEvent.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -276,13 +296,16 @@ isa = PBXGroup; children = ( 520E0E2F1C110CA900BAEA99 /* Process+FileKit.swift */, - 5204B7E51B96ADA100AA473F /* String+FileKit.swift */, 52A0170F1C024D840045A9C8 /* NSString+FileKit.swift */, 52A016F51C01ACE50045A9C8 /* NSDictionary+FileKit.swift */, 52A016FA1C01AD1E0045A9C8 /* NSArray+FileKit.swift */, 52A016FF1C01AD4A0045A9C8 /* NSData+FileKit.swift */, - 52A017041C01AD6F0045A9C8 /* NSBundle+FileKit.swift */, + 52A017041C01AD6F0045A9C8 /* Bundle+FileKit.swift */, + 5204B7E51B96ADA100AA473F /* String+FileKit.swift */, + C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */, 524D315E1BC7A02A008B93D0 /* Image+FileKit.swift */, + C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */, + C41FC7451D9BEEC000C3A0F1 /* Array+File.swift */, ); name = Extensions; sourceTree = ""; @@ -304,9 +327,10 @@ children = ( 523C33A01B9B772A00AB70E4 /* File.swift */, 523C33771B9A7EFC00AB70E4 /* TextFile.swift */, + C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */, + 524D315A1BC79331008B93D0 /* NSDataFile.swift */, 523C337A1B9B68D600AB70E4 /* DictionaryFile.swift */, 524D31561BC79067008B93D0 /* ArrayFile.swift */, - 524D315A1BC79331008B93D0 /* DataFile.swift */, 52B938C81BF402ED001B7AEB /* ImageFile.swift */, ); name = "File Types"; @@ -597,7 +621,7 @@ 52A016E91C01565C0045A9C8 /* FileKit.swift in Sources */, 17217D561CDCD13700723D11 /* RelativePathType.swift in Sources */, 52A017101C024D840045A9C8 /* NSString+FileKit.swift in Sources */, - 52A017051C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */, + 52A017051C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */, 523C33991B9B764600AB70E4 /* DataType.swift in Sources */, 82F4F2BD1CA95480002C8393 /* FileSystemWatcher.swift in Sources */, 523C33A71B9B894A00AB70E4 /* Operators.swift in Sources */, @@ -606,12 +630,15 @@ 82F4F2C01CA956F2002C8393 /* FileSystemEventStream.swift in Sources */, 52A016C41C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, 524D315F1BC7A02A008B93D0 /* Image+FileKit.swift in Sources */, - 524D315B1BC79331008B93D0 /* DataFile.swift in Sources */, + C41FC73F1D9BE44A00C3A0F1 /* Dictionary+File.swift in Sources */, + 524D315B1BC79331008B93D0 /* NSDataFile.swift in Sources */, 520E0E301C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 52A016FB1C01AD1E0045A9C8 /* NSArray+FileKit.swift in Sources */, 52BF6BB11B99322000F07E13 /* FileKitError.swift in Sources */, + C41FC7411D9BE4DB00C3A0F1 /* DataFile.swift in Sources */, 52A017001C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, 52A016F61C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, + C41FC7461D9BEEC000C3A0F1 /* Array+File.swift in Sources */, 52B938C91BF402ED001B7AEB /* ImageFile.swift in Sources */, 17217D5E1CDCD74000723D11 /* DispatchEvent.swift in Sources */, 52255DCB1C042D6E00AC1DA5 /* FilePermissions.swift in Sources */, @@ -619,6 +646,7 @@ 524D31571BC79067008B93D0 /* ArrayFile.swift in Sources */, 523C33A11B9B772A00AB70E4 /* File.swift in Sources */, 52A0170A1C01D5400045A9C8 /* FileType.swift in Sources */, + C41FC73A1D9BDCB400C3A0F1 /* Data+FileKit.swift in Sources */, 17217D5F1CDCD74000723D11 /* DispatchWatcher.swift in Sources */, 523C337B1B9B68D600AB70E4 /* DictionaryFile.swift in Sources */, ); @@ -634,12 +662,15 @@ 52A016EA1C01565C0045A9C8 /* FileKit.swift in Sources */, 52A016FC1C01AD1E0045A9C8 /* NSArray+FileKit.swift in Sources */, 5263A8FF1B96B95100635A93 /* String+FileKit.swift in Sources */, + C41FC73B1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */, 52A016F21C0184CA0045A9C8 /* FileProtection.swift in Sources */, 52A016F71C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, - 52A017061C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */, - 524D315C1BC79331008B93D0 /* DataFile.swift in Sources */, + 52A017061C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */, + 524D315C1BC79331008B93D0 /* NSDataFile.swift in Sources */, 52A0170B1C01D5400045A9C8 /* FileType.swift in Sources */, 523C33A81B9B894A00AB70E4 /* Operators.swift in Sources */, + C41FC74D1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, + C41FC7471D9BEEF300C3A0F1 /* Array+File.swift in Sources */, 52A017111C024D840045A9C8 /* NSString+FileKit.swift in Sources */, 520E0E311C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 523C33791B9A7EFC00AB70E4 /* TextFile.swift in Sources */, @@ -654,6 +685,7 @@ 524D31581BC79067008B93D0 /* ArrayFile.swift in Sources */, 523C33A21B9B772A00AB70E4 /* File.swift in Sources */, 523C337C1B9B68D600AB70E4 /* DictionaryFile.swift in Sources */, + C41FC7421D9BEC7700C3A0F1 /* DataFile.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -675,12 +707,15 @@ 52A016EB1C01565C0045A9C8 /* FileKit.swift in Sources */, 52A016FD1C01AD1E0045A9C8 /* NSArray+FileKit.swift in Sources */, 527612521BAEA45D00503D0A /* String+FileKit.swift in Sources */, + C41FC73C1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */, 52A016F31C0184CA0045A9C8 /* FileProtection.swift in Sources */, 52A016F81C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, - 52A017071C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */, - 524D315D1BC79331008B93D0 /* DataFile.swift in Sources */, + 52A017071C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */, + 524D315D1BC79331008B93D0 /* NSDataFile.swift in Sources */, 52A0170C1C01D5400045A9C8 /* FileType.swift in Sources */, 5276124D1BAEA43600503D0A /* DictionaryFile.swift in Sources */, + C41FC74C1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, + C41FC74A1D9BEEF400C3A0F1 /* Array+File.swift in Sources */, 52A017121C024D840045A9C8 /* NSString+FileKit.swift in Sources */, 520E0E321C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 5276124B1BAEA43600503D0A /* File.swift in Sources */, @@ -695,6 +730,7 @@ 52B938CB1BF402ED001B7AEB /* ImageFile.swift in Sources */, 524D31591BC79067008B93D0 /* ArrayFile.swift in Sources */, 5276124F1BAEA43600503D0A /* DataType.swift in Sources */, + C41FC7431D9BEC7800C3A0F1 /* DataFile.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -708,12 +744,15 @@ 52B938C51BF3C430001B7AEB /* String+FileKit.swift in Sources */, 52A016EC1C01565C0045A9C8 /* FileKit.swift in Sources */, 52A017131C024D840045A9C8 /* NSString+FileKit.swift in Sources */, - 52A017081C01AD6F0045A9C8 /* NSBundle+FileKit.swift in Sources */, + C41FC73D1D9BDCD200C3A0F1 /* Data+FileKit.swift in Sources */, + 52A017081C01AD6F0045A9C8 /* Bundle+FileKit.swift in Sources */, 52A016FE1C01AD1E0045A9C8 /* NSArray+FileKit.swift in Sources */, 52B938C21BF3C42A001B7AEB /* DataType.swift in Sources */, 52B938C41BF3C42A001B7AEB /* Operators.swift in Sources */, 52A016F41C0184CA0045A9C8 /* FileProtection.swift in Sources */, 52B938BD1BF3C42A001B7AEB /* TextFile.swift in Sources */, + C41FC74B1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, + C41FC7491D9BEEF400C3A0F1 /* Array+File.swift in Sources */, 52B938C11BF3C42A001B7AEB /* Path.swift in Sources */, 52A016F91C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, 52A0170D1C01D5400045A9C8 /* FileType.swift in Sources */, @@ -722,12 +761,13 @@ 52A017031C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, 52A016C71C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, 52B938C71BF3C430001B7AEB /* Image+FileKit.swift in Sources */, - 52B938C01BF3C42A001B7AEB /* DataFile.swift in Sources */, + 52B938C01BF3C42A001B7AEB /* NSDataFile.swift in Sources */, 52255DCE1C042D6E00AC1DA5 /* FilePermissions.swift in Sources */, 52B938CC1BF402ED001B7AEB /* ImageFile.swift in Sources */, 52B938C31BF3C42A001B7AEB /* FileKitError.swift in Sources */, 52B938BC1BF3C42A001B7AEB /* File.swift in Sources */, 52B938BF1BF3C42A001B7AEB /* ArrayFile.swift in Sources */, + C41FC7441D9BEC7800C3A0F1 /* DataFile.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Array+File.swift b/Sources/Array+File.swift new file mode 100644 index 0000000..1c53b21 --- /dev/null +++ b/Sources/Array+File.swift @@ -0,0 +1,53 @@ +// +// Array+File.swift +// FileKit +// +// The MIT License (MIT) +// +// Copyright (c) 2016 Nikolai Vazquez +// Copyright (c) 2016 Marchand Eric +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +extension Array: ReadableWritable, WritableConvertible { + + /// Returns an array from the given path. + /// + /// - Parameter path: The path to be returned the array for. + /// - Throws: FileKitError.ReadFromFileFail + /// + public static func read(from path: Path) throws -> Array { + guard let contents = NSArray(contentsOfFile: path._safeRawValue) else { + throw FileKitError.readFromFileFail(path: path) + } + guard let dict = contents as? Array else { + throw FileKitError.readFromFileFail(path: path) + } + return dict + } + + // Return an bridged NSArray value + public var writable: NSArray { + return self as NSArray + } + +} diff --git a/Sources/ArrayFile.swift b/Sources/ArrayFile.swift index f3217d8..81b1fd8 100644 --- a/Sources/ArrayFile.swift +++ b/Sources/ArrayFile.swift @@ -1,5 +1,5 @@ // -// ArrayFile.swift +// NSArrayFile.swift // FileKit // // The MIT License (MIT) @@ -30,4 +30,9 @@ import Foundation /// A representation of a filesystem array file. /// /// The data type is NSArray. -public typealias ArrayFile = File +public typealias NSArrayFile = File + +/// A representation of a filesystem array file. +/// +/// The data type is Array. +public typealias ArrayFile = File> diff --git a/Sources/NSBundle+FileKit.swift b/Sources/Bundle+FileKit.swift similarity index 98% rename from Sources/NSBundle+FileKit.swift rename to Sources/Bundle+FileKit.swift index cd4f6ef..18bf70b 100644 --- a/Sources/NSBundle+FileKit.swift +++ b/Sources/Bundle+FileKit.swift @@ -1,5 +1,5 @@ // -// NSBundle+FileKit.swift +// Bundle+FileKit.swift // FileKit // // The MIT License (MIT) diff --git a/Sources/Data+FileKit.swift b/Sources/Data+FileKit.swift new file mode 100644 index 0000000..e35e87a --- /dev/null +++ b/Sources/Data+FileKit.swift @@ -0,0 +1,85 @@ +// +// Data+FileKit.swift +// FileKit +// +// The MIT License (MIT) +// +// Copyright (c) 2016 Nikolai Vazquez +// Copyright (c) 2016 Marchand Eric +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +extension Data: ReadableWritable { + + /// Returns data read from the given path. + public static func read(from path: Path) throws -> Data { + do { + return try self.init(contentsOf: path.url, options: []) + } + catch { + throw FileKitError.readFromFileFail(path: path) + } + } + + /// Returns data read from the given path using Data.ReadingOptions. + public static func read(from path: Path, options: Data.ReadingOptions) throws -> Data { + do { + return try self.init(contentsOf: path.url, options: options) + } + catch { + throw FileKitError.readFromFileFail(path: path) + } + } + + + /// Writes `self` to a Path. + public func write(to path: Path) throws { + try write(to: path, atomically: true) + } + + /// Writes `self` to a path. + /// + /// - Parameter path: The path being written to. + /// - Parameter useAuxiliaryFile: If `true`, the data is written to an + /// auxiliary file that is then renamed to the + /// file. If `false`, the data is written to + /// the file directly. + /// + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + let options: Data.WritingOptions = useAuxiliaryFile ? [.atomic] : [] + try self.write(to: path, options: options) + } + + /// Writes `self` to a path. + /// + /// - Parameter path: The path being written to. + /// - Parameter options: writing options. + /// + public func write(to path: Path, options: Data.WritingOptions) throws { + do { + try self.write(to: path.url, options: options) + } catch { + throw FileKitError.writeToFileFail(path: path) + } + } + +} diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index 4e21a71..5df1c6f 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -27,37 +27,66 @@ import Foundation + /// A representation of a filesystem data file. /// -/// The data type is NSData. -public typealias DataFile = File - -extension File where Data: NSData { +/// The data type is Data. +open class DataFile: File { /// Reads the file and returns its data. /// - Parameter options: A mask that specifies write options - /// described in `NSData.ReadingOptions`. + /// described in `Data.ReadingOptions`. /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. - public func read(_ options: NSData.ReadingOptions) throws -> Data { - return try Data.readFromPath(path, options: options) + public func read(_ options: Data.ReadingOptions) throws -> Data { + return try Data.read(from: path, options: options) } /// Writes data to the file. /// /// - Parameter data: The data to be written to the file. /// - Parameter options: A mask that specifies write options - /// described in `NSData.WritingOptions`. + /// described in `Data.WritingOptions`. /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(_ data: Data, options: NSData.WritingOptions) throws { - do { - try data.write(toFile: self.path._safeRawValue, options: options) - } catch { - throw FileKitError.writeToFileFail(path: self.path) - } + public func write(_ data: Data, options: Data.WritingOptions) throws { + try data.write(to: self.path, options: options) } } + +/// A representation of a filesystem data file, +/// with options to read or write. +/// +/// The data type is Data. +open class DataFileWithOptions: DataFile { + + open var readingOptions: Data.ReadingOptions = [] + open var writingOptions: Data.WritingOptions? = nil + + /// Initializes a file from a path with options. + /// + /// - Parameter path: The path to be created a text file from. + /// - Parameter readingOptions: The options to be used to read file. + /// - Parameter writingOptions: The options to be used to write file. + /// If nil take into account `useAuxiliaryFile` + public init(path: Path, readingOptions: Data.ReadingOptions = [], writingOptions: Data.WritingOptions? = nil) { + self.readingOptions = readingOptions + self.writingOptions = writingOptions + super.init(path: path) + } + + open override func read() throws -> Data { + return try read(readingOptions) + } + + open override func write(_ data: Data, atomically useAuxiliaryFile: Bool) throws { + // If no option take into account useAuxiliaryFile + let options: Data.WritingOptions = (writingOptions == nil) ? + (useAuxiliaryFile ? Data.WritingOptions.atomic : []) + : writingOptions! + try self.write(data, options: options) + } +} diff --git a/Sources/DataType.swift b/Sources/DataType.swift index 765770e..c7cd1bf 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -1,5 +1,5 @@ // -// DataType.swift +// ReadableWritable.swift // FileKit // // The MIT License (MIT) @@ -28,7 +28,7 @@ import Foundation /// A type that can be used to read from and write to File instances. -public typealias DataType = Readable & Writable +public typealias ReadableWritable = Readable & Writable @@ -39,7 +39,7 @@ public protocol Readable { /// /// - Parameter path: The path being read from. /// - static func readFromPath(_ path: Path) throws -> Self + static func read(from path: Path) throws -> Self } @@ -50,7 +50,7 @@ extension Readable { /// - Parameter path: The path being read from. /// public init(contentsOfPath path: Path) throws { // swiftlint:disable:this valid_docs - self = try Self.readFromPath(path) + self = try Self.read(from: path) } } @@ -61,7 +61,7 @@ extension Readable { public protocol Writable { /// Writes `self` to a Path. - func writeToPath(_ path: Path) throws + func write(to path: Path) throws /// Writes `self` to a Path. /// @@ -71,7 +71,8 @@ public protocol Writable { /// file. If `false`, the data is written to /// the file directly. /// - func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws + func write(to path: Path, atomically useAuxiliaryFile: Bool) throws + } @@ -81,8 +82,8 @@ extension Writable { /// /// - Parameter path: The path being written to. /// - public func writeToPath(_ path: Path) throws { // swiftlint:disable:this valid_docs - try writeToPath(path, atomically: true) + public func write(to path: Path) throws { // swiftlint:disable:this valid_docs + try write(to: path, atomically: true) } } @@ -101,14 +102,12 @@ public protocol WritableToFile: Writable { /// - Returns: `true` if the writing completed successfully, or `false` if /// the writing failed. /// - func writeToFile(_ path: String, atomically useAuxiliaryFile: Bool) -> Bool + func write(toFile path: String, atomically useAuxiliaryFile: Bool) -> Bool } - - extension WritableToFile { - + /// Writes `self` to a Path. /// /// - Parameter path: The path being written to. @@ -119,16 +118,14 @@ extension WritableToFile { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { - guard writeToFile(path._safeRawValue, atomically: useAuxiliaryFile) else { + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + guard write(toFile: path._safeRawValue, atomically: useAuxiliaryFile) else { throw FileKitError.writeToFileFail(path: path) } } - + } - - /// A type that can be converted to a Writable. public protocol WritableConvertible: Writable { @@ -154,8 +151,8 @@ extension WritableConvertible { /// `FileKitError.WriteToFileFail`, /// `FileKitError.WritableConvertiblePropertyNil` /// - public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { - try writable.writeToPath(path, atomically: useAuxiliaryFile) + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + try writable.write(to: path, atomically: useAuxiliaryFile) } } diff --git a/Sources/Dictionary+File.swift b/Sources/Dictionary+File.swift new file mode 100644 index 0000000..035e0d4 --- /dev/null +++ b/Sources/Dictionary+File.swift @@ -0,0 +1,53 @@ +// +// Dictionary+File.swift +// FileKit +// +// The MIT License (MIT) +// +// Copyright (c) 2016 Nikolai Vazquez +// Copyright (c) 2016 Marchand Eric +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +extension Dictionary: ReadableWritable, WritableConvertible { + + /// Returns a dictionary from the given path. + /// + /// - Parameter path: The path to be returned the dictionary for. + /// - Throws: FileKitError.ReadFromFileFail + /// + public static func read(from path: Path) throws -> Dictionary { + guard let contents = NSDictionary(contentsOfFile: path._safeRawValue) else { + throw FileKitError.readFromFileFail(path: path) + } + guard let dict = contents as? Dictionary else { + throw FileKitError.readFromFileFail(path: path) + } + return dict + } + + // Return an bridged NSDictionary value + public var writable: NSDictionary { + return self as NSDictionary + } + +} diff --git a/Sources/DictionaryFile.swift b/Sources/DictionaryFile.swift index ada7d3e..ec3298e 100644 --- a/Sources/DictionaryFile.swift +++ b/Sources/DictionaryFile.swift @@ -1,5 +1,5 @@ // -// DictionaryFile.swift +// NSDictionaryFile.swift // FileKit // // The MIT License (MIT) @@ -30,4 +30,9 @@ import Foundation /// A representation of a filesystem dictionary file. /// /// The data type is NSDictionary. -public typealias DictionaryFile = File +public typealias NSDictionaryFile = File + +/// A representation of a filesystem dictionary file. +/// +/// The data type is DictionaryFile. +public typealias DictionaryFile = File> diff --git a/Sources/File.swift b/Sources/File.swift index f6a8ce1..3797e20 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -29,10 +29,10 @@ import Foundation /// A representation of a filesystem file of a given data type. /// -/// - Precondition: The data type must conform to DataType. +/// - Precondition: The data type must conform to ReadableWritable. /// /// All method do not follow links. -open class File: Comparable { +open class File: Comparable { // MARK: - Properties @@ -81,8 +81,8 @@ open class File: Comparable { /// /// - Throws: `FileKitError.ReadFromFileFail` /// - Returns: The data read from file. - open func read() throws -> Data { - return try Data.readFromPath(path) + open func read() throws -> DataType { + return try DataType.read(from: path) } /// Writes data to the file. @@ -93,7 +93,7 @@ open class File: Comparable { /// /// - Throws: `FileKitError.WriteToFileFail` /// - open func write(_ data: Data) throws { + open func write(_ data: DataType) throws { try self.write(data, atomically: true) } @@ -107,8 +107,8 @@ open class File: Comparable { /// /// - Throws: `FileKitError.WriteToFileFail` /// - open func write(_ data: Data, atomically useAuxiliaryFile: Bool) throws { - try data.writeToPath(path, atomically: useAuxiliaryFile) + open func write(_ data: DataType, atomically useAuxiliaryFile: Bool) throws { + try data.write(to: path, atomically: useAuxiliaryFile) } /// Creates the file. @@ -140,8 +140,8 @@ open class File: Comparable { /// - Parameter path: The path to move the file to. /// - Throws: `FileKitError.MoveFileFail` /// - open func moveToPath(_ path: Path) throws { - try self.path.moveFileToPath(path) + open func move(to path: Path) throws { + try self.path.moveFile(to: path) self.path = path } @@ -154,8 +154,8 @@ open class File: Comparable { /// - Parameter path: The path to copy the file to. /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// - open func copyToPath(_ path: Path) throws { - try self.path.copyFileToPath(path) + open func copy(to path: Path) throws { + try self.path.copyFile(to: path) } /// Symlinks the file to a path. @@ -172,8 +172,8 @@ open class File: Comparable { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// - open func symlinkToPath(_ path: Path) throws { - try self.path.symlinkFileToPath(path) + open func symlink(to path: Path) throws { + try self.path.symlinkFile(to: path) } /// Hardlinks the file to a path. @@ -190,8 +190,8 @@ open class File: Comparable { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateHardlinkFail` /// - open func hardlinkToPath(_ path: Path) throws { - try self.path.hardlinkFileToPath(path) + open func hardlink(to path: Path) throws { + try self.path.hardlinkFile(to: path) } // MARK: - FileType diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index 08c7b7b..debf31f 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -31,13 +31,16 @@ import Foundation public struct FilePermissions: OptionSet, CustomStringConvertible { /// The file can be read from. - public static let Read = FilePermissions(rawValue: 1) + public static let read = FilePermissions(rawValue: 1) /// The file can be written to. - public static let Write = FilePermissions(rawValue: 2) + public static let write = FilePermissions(rawValue: 2) /// The file can be executed. - public static let Execute = FilePermissions(rawValue: 4) + public static let execute = FilePermissions(rawValue: 4) + + /// All FilePermissions + public static let all: [FilePermissions] = [.read, .write, .execute] /// The raw integer value of `self`. public let rawValue: Int @@ -45,14 +48,14 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { /// A textual representation of `self`. public var description: String { var description = "" - for permission in [.Read, .Write, .Execute] as [FilePermissions] { + for permission in FilePermissions.all { if self.contains(permission) { description += !description.isEmpty ? ", " : "" - if permission == .Read { + if permission == .read { description += "Read" - } else if permission == .Write { + } else if permission == .write { description += "Write" - } else if permission == .Execute { + } else if permission == .execute { description += "Execute" } } @@ -74,16 +77,16 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { /// public init(forPath path: Path) { var permissions = FilePermissions(rawValue: 0) - if path.isReadable { permissions.formUnion(.Read) } - if path.isWritable { permissions.formUnion(.Write) } - if path.isExecutable { permissions.formUnion(.Execute) } + if path.isReadable { permissions.formUnion(.read) } + if path.isWritable { permissions.formUnion(.write) } + if path.isExecutable { permissions.formUnion(.execute) } self = permissions } /// Creates a set of permissions for `file`. /// /// - Parameter file: The file to create a set of persmissions for. - public init(forFile file: File) { + public init(forFile file: File) { self.init(forPath: file.path) } diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index bc840c0..ac34160 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -82,7 +82,7 @@ public enum FileProtection: String { } } - /// Return the equivalent NSData.WritingOptions + /// Return the equivalent Data.WritingOptions public var dataWritingOption: NSData.WritingOptions { switch self { case .none: @@ -152,7 +152,7 @@ extension File { } -extension File where Data: NSData { +extension File where DataType: NSData { /// Writes data to the file. /// @@ -165,7 +165,7 @@ extension File where Data: NSData { /// /// - Throws: `FileKitError.WriteToFileFail` /// - public func write(_ data: Data, fileProtection: FileProtection, atomically: Bool = true) throws { + public func write(_ data: DataType, fileProtection: FileProtection, atomically: Bool = true) throws { var options = fileProtection.dataWritingOption if atomically { options.formUnion(Foundation.Data.WritingOptions.atomic) diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index 018b410..c8bab94 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -43,14 +43,14 @@ public typealias Image = UIImage #if os(OSX) || os(iOS) || os(tvOS) || os(watchOS) -extension Image: DataType, WritableConvertible { +extension Image: ReadableWritable, WritableConvertible { /// Returns an image from the given path. /// /// - Parameter path: The path to be returned the image for. /// - Throws: FileKitError.ReadFromFileFail /// - public class func readFromPath(_ path: Path) throws -> Self { + public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { throw FileKitError.readFromFileFail(path: path) } @@ -59,11 +59,11 @@ extension Image: DataType, WritableConvertible { /// Returns `TIFFRepresentation` on OS X and `UIImagePNGRepresentation` on /// iOS, watchOS, and tvOS. - public var writable: NSData { + public var writable: Data { #if os(OSX) - return self.tiffRepresentation as NSData? ?? NSData() + return self.tiffRepresentation ?? Data() #else - return UIImagePNGRepresentation(self) as NSData? ?? NSData() + return UIImagePNGRepresentation(self) ?? Data() #endif } diff --git a/Sources/NSArray+FileKit.swift b/Sources/NSArray+FileKit.swift index d01f395..05c8977 100644 --- a/Sources/NSArray+FileKit.swift +++ b/Sources/NSArray+FileKit.swift @@ -27,12 +27,12 @@ import Foundation -extension NSArray: DataType, WritableToFile { +extension NSArray: ReadableWritable, WritableToFile { /// Returns an array read from the given path. /// /// - Parameter path: The path an array to be read from. - public class func readFromPath(_ path: Path) throws -> Self { + public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { throw FileKitError.readFromFileFail(path: path) } diff --git a/Sources/NSData+FileKit.swift b/Sources/NSData+FileKit.swift index 2f14d72..432c3d2 100644 --- a/Sources/NSData+FileKit.swift +++ b/Sources/NSData+FileKit.swift @@ -1,5 +1,5 @@ // -// NSData+FileKit.swift +// Data+FileKit.swift // FileKit // // The MIT License (MIT) @@ -27,10 +27,10 @@ import Foundation -extension NSData: DataType, WritableToFile { +extension NSData: ReadableWritable, WritableToFile { /// Returns data read from the given path. - public static func readFromPath(_ path: Path) throws -> Self { + public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { throw FileKitError.readFromFileFail(path: path) } @@ -38,7 +38,7 @@ extension NSData: DataType, WritableToFile { } /// Returns data read from the given path using Data.ReadingOptions. - public static func readFromPath(_ path: Path, options: Data.ReadingOptions) throws -> Self { + public class func read(from path: Path, options: NSData.ReadingOptions) throws -> Self { do { return try self.init(contentsOfFile: path._safeRawValue, options: options) } catch { diff --git a/Sources/NSDataFile.swift b/Sources/NSDataFile.swift new file mode 100644 index 0000000..7fcf04e --- /dev/null +++ b/Sources/NSDataFile.swift @@ -0,0 +1,63 @@ +// +// DataFile.swift +// FileKit +// +// The MIT License (MIT) +// +// Copyright (c) 2015-2016 Nikolai Vazquez +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/// A representation of a filesystem data file. +/// +/// The data type is NSData. +public typealias NSDataFile = File + +extension File where DataType: NSData { + + /// Reads the file and returns its data. + /// - Parameter options: A mask that specifies write options + /// described in `NSData.ReadingOptions`. + /// + /// - Throws: `FileKitError.ReadFromFileFail` + /// - Returns: The data read from file. + public func read(_ options: NSData.ReadingOptions) throws -> NSData { + return try NSData.read(from: path, options: options) + } + + /// Writes data to the file. + /// + /// - Parameter data: The data to be written to the file. + /// - Parameter options: A mask that specifies write options + /// described in `NSData.WritingOptions`. + /// + /// - Throws: `FileKitError.WriteToFileFail` + /// + public func write(_ data: NSData, options: NSData.WritingOptions) throws { + do { + try data.write(toFile: self.path._safeRawValue, options: options) + } catch { + throw FileKitError.writeToFileFail(path: self.path) + } + } + +} diff --git a/Sources/NSDictionary+FileKit.swift b/Sources/NSDictionary+FileKit.swift index a8b358a..56c1895 100644 --- a/Sources/NSDictionary+FileKit.swift +++ b/Sources/NSDictionary+FileKit.swift @@ -24,10 +24,10 @@ import Foundation -extension NSDictionary: DataType, WritableToFile { +extension NSDictionary: ReadableWritable, WritableToFile { /// Returns a dictionary read from the given path. - public class func readFromPath(_ path: Path) throws -> Self { + public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { throw FileKitError.readFromFileFail(path: path) } diff --git a/Sources/NSString+FileKit.swift b/Sources/NSString+FileKit.swift index 8674008..9d2f372 100644 --- a/Sources/NSString+FileKit.swift +++ b/Sources/NSString+FileKit.swift @@ -29,10 +29,57 @@ import Foundation extension NSString { - /// Returns an NSString object initialized by copying the characters from + /// Returns an String object initialized by copying the characters from /// the raw value of a given path. public convenience init(path: Path) { self.init(string: path.rawValue) } + +} + +extension NSString: Writable { + /// Writes the string to a path atomically. + /// + /// - Parameter path: The path being written to. + /// + public func write(to path: Path) throws { + try write(to: path, atomically: true) + } + + /// Writes the string to a path with `NSUTF8StringEncoding` encoding. + /// + /// - Parameter path: The path being written to. + /// - Parameter useAuxiliaryFile: If `true`, the data is written to an + /// auxiliary file that is then renamed to the + /// file. If `false`, the data is written to + /// the file directly. + /// + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + do { + try self.write(toFile: path._safeRawValue, + atomically: useAuxiliaryFile, + encoding: String.Encoding.utf8.rawValue) + } catch { + throw FileKitError.writeToFileFail(path: path) + } + } + } + +/* + extension NSString: Readable { + + /// Creates a string from a path. + public class func read(from path: Path) throws -> Self { + let possibleContents = try? NSString( + contentsOfFile: path._safeRawValue, + encoding: String.Encoding.utf8.rawValue) + guard let contents = possibleContents else { + throw FileKitError.readFromFileFail(path: path) + } + return contents + } + } + */ + diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 17c788d..964f639 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -44,13 +44,13 @@ fileprivate func < (lhs: T?, rhs: T?) -> Bool { /// Returns `true` if both files' paths are the same. -public func ==(lhs: File, rhs: File) -> Bool { +public func ==(lhs: File, rhs: File) -> Bool { return lhs.path == rhs.path } /// Returns `true` if `lhs` is smaller than `rhs` in size. -public func < (lhs: File, rhs: File) -> Bool { +public func < (lhs: File, rhs: File) -> Bool { return lhs.size < rhs.size } @@ -60,7 +60,7 @@ infix operator |> /// /// - Throws: `FileKitError.WriteToFileFail` /// -public func |> (data: Data, file: File) throws { +public func |> (data: DataType, file: File) throws { try file.write(data) } @@ -232,7 +232,7 @@ infix operator ->> /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.MoveFileFail` /// public func ->> (lhs: Path, rhs: Path) throws { - try lhs.moveFileToPath(rhs) + try lhs.moveFile(to: rhs) } /// Moves a file to a path. @@ -242,8 +242,8 @@ public func ->> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.MoveFileFail` /// -public func ->> (lhs: File, rhs: Path) throws { - try lhs.moveToPath(rhs) +public func ->> (lhs: File, rhs: Path) throws { + try lhs.move(to: rhs) } infix operator ->! @@ -273,7 +273,7 @@ public func ->! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func ->! (lhs: File, rhs: Path) throws { +public func ->! (lhs: File, rhs: Path) throws { if rhs.isAny { try rhs.deleteFile() } @@ -291,7 +291,7 @@ infix operator +>> /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// public func +>> (lhs: Path, rhs: Path) throws { - try lhs.copyFileToPath(rhs) + try lhs.copyFile(to: rhs) } /// Copies a file to a path. @@ -301,8 +301,8 @@ public func +>> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// -public func +>> (lhs: File, rhs: Path) throws { - try lhs.copyToPath(rhs) +public func +>> (lhs: File, rhs: Path) throws { + try lhs.copy(to: rhs) } infix operator +>! @@ -332,7 +332,7 @@ public func +>! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func +>! (lhs: File, rhs: Path) throws { +public func +>! (lhs: File, rhs: Path) throws { if rhs.isAny { try rhs.deleteFile() } @@ -354,7 +354,7 @@ infix operator =>> /// `FileKitError.CreateSymlinkFail` /// public func =>> (lhs: Path, rhs: Path) throws { - try lhs.symlinkFileToPath(rhs) + try lhs.symlinkFile(to: rhs) } /// Symlinks a file to a path. @@ -367,8 +367,8 @@ public func =>> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CreateSymlinkFail` /// -public func =>> (lhs: File, rhs: Path) throws { - try lhs.symlinkToPath(rhs) +public func =>> (lhs: File, rhs: Path) throws { + try lhs.symlink(to: rhs) } infix operator =>! @@ -404,7 +404,7 @@ public func =>! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func =>! (lhs: File, rhs: Path) throws { +public func =>! (lhs: File, rhs: Path) throws { try lhs.path =>! rhs } diff --git a/Sources/Path.swift b/Sources/Path.swift index d4869c0..c8daf68 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -42,10 +42,10 @@ public struct Path { public static let separator = "/" /// The root path. - public static let Root = Path(separator) + public static let root = Path(separator) /// The path of the program's current working directory. - public static var Current: Path { + public static var current: Path { get { return Path(FileManager.default.currentDirectoryPath) } @@ -198,7 +198,7 @@ public struct Path { public var absolute: Path { return self.isAbsolute ? self.standardized - : (Path.Current + self).standardized + : (Path.current + self).standardized } /// Returns `true` if the path is equal to "/". @@ -332,7 +332,7 @@ public struct Path { /// Initializes a path to root. public init() { - self = .Root + self = .root } /// Initializes a path to the string's value. @@ -356,8 +356,8 @@ extension Path { /// - Parameter closure: The block to run while `Path.Current` is changed. /// public func changeDirectory(_ closure: () throws -> ()) rethrows { - let previous = Path.Current - defer { Path.Current = previous } + let previous = Path.current + defer { Path.current = previous } if _fmWraper.fileManager.changeCurrentDirectoryPath(_safeRawValue) { try closure() } @@ -557,7 +557,7 @@ extension Path { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// - public func symlinkFileToPath(_ path: Path) throws { + public func symlinkFile(to path: Path) throws { // it's possible to create symbolic links to locations that do not yet exist. // guard self.exists else { // throw FileKitError.FileDoesNotExist(path: self) @@ -590,7 +590,7 @@ extension Path { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateHardlinkFail` /// - public func hardlinkFileToPath(_ path: Path) throws { + public func hardlinkFile(to path: Path) throws { let linkPath = path.isDirectory ? path + self.fileName : path guard !linkPath.isAny else { @@ -688,7 +688,7 @@ extension Path { /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.MoveFileFail` /// /// this method does not follow links. - public func moveFileToPath(_ path: Path) throws { + public func moveFile(to path: Path) throws { if self.isAny { if !path.isAny { do { @@ -712,7 +712,7 @@ extension Path { /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// /// this method does not follow links. - public func copyFileToPath(_ path: Path) throws { + public func copyFile(to path: Path) throws { if self.isAny { if !path.isAny { do { @@ -1131,136 +1131,138 @@ extension Path { /// Returns the path to the user's or application's home directory, /// depending on the platform. - public static var UserHome: Path { + public static var userHome: Path { + // same as FileManager.default.homeDirectoryForCurrentUser return Path(NSHomeDirectory()).standardized } /// Returns the path to the user's temporary directory. - public static var UserTemporary: Path { + public static var userTemporary: Path { + // same as FileManager.default.temporaryDirectory return Path(NSTemporaryDirectory()).standardized } /// Returns a temporary path for the process. - public static var ProcessTemporary: Path { - return Path.UserTemporary + ProcessInfo.processInfo.globallyUniqueString + public static var processTemporary: Path { + return Path.userTemporary + ProcessInfo.processInfo.globallyUniqueString } /// Returns a unique temporary path. - public static var UniqueTemporary: Path { - return Path.ProcessTemporary + UUID().uuidString + public static var uniqueTemporary: Path { + return Path.processTemporary + UUID().uuidString } /// Returns the path to the user's caches directory. - public static var UserCaches: Path { + public static var userCaches: Path { return _pathInUserDomain(.cachesDirectory) } /// Returns the path to the user's applications directory. - public static var UserApplications: Path { + public static var userApplications: Path { return _pathInUserDomain(.applicationDirectory) } /// Returns the path to the user's application support directory. - public static var UserApplicationSupport: Path { + public static var userApplicationSupport: Path { return _pathInUserDomain(.applicationSupportDirectory) } /// Returns the path to the user's desktop directory. - public static var UserDesktop: Path { + public static var userDesktop: Path { return _pathInUserDomain(.desktopDirectory) } /// Returns the path to the user's documents directory. - public static var UserDocuments: Path { + public static var userDocuments: Path { return _pathInUserDomain(.documentDirectory) } /// Returns the path to the user's autosaved documents directory. - public static var UserAutosavedInformation: Path { + public static var userAutosavedInformation: Path { return _pathInUserDomain(.autosavedInformationDirectory) } /// Returns the path to the user's downloads directory. - public static var UserDownloads: Path { + public static var userDownloads: Path { return _pathInUserDomain(.downloadsDirectory) } /// Returns the path to the user's library directory. - public static var UserLibrary: Path { + public static var userLibrary: Path { return _pathInUserDomain(.libraryDirectory) } /// Returns the path to the user's movies directory. - public static var UserMovies: Path { + public static var userMovies: Path { return _pathInUserDomain(.moviesDirectory) } /// Returns the path to the user's music directory. - public static var UserMusic: Path { + public static var userMusic: Path { return _pathInUserDomain(.musicDirectory) } /// Returns the path to the user's pictures directory. - public static var UserPictures: Path { + public static var userPictures: Path { return _pathInUserDomain(.picturesDirectory) } /// Returns the path to the user's Public sharing directory. - public static var UserSharedPublic: Path { + public static var userSharedPublic: Path { return _pathInUserDomain(.sharedPublicDirectory) } #if os(OSX) /// Returns the path to the user scripts folder for the calling application - public static var UserApplicationScripts: Path { + public static var userApplicationScripts: Path { return _pathInUserDomain(.applicationScriptsDirectory) } /// Returns the path to the user's trash directory - public static var UserTrash: Path { + public static var userTrash: Path { return _pathInUserDomain(.trashDirectory) } #endif /// Returns the path to the system's applications directory. - public static var SystemApplications: Path { + public static var systemApplications: Path { return _pathInSystemDomain(.applicationDirectory) } /// Returns the path to the system's application support directory. - public static var SystemApplicationSupport: Path { + public static var systemApplicationSupport: Path { return _pathInSystemDomain(.applicationSupportDirectory) } /// Returns the path to the system's library directory. - public static var SystemLibrary: Path { + public static var systemLibrary: Path { return _pathInSystemDomain(.libraryDirectory) } /// Returns the path to the system's core services directory. - public static var SystemCoreServices: Path { + public static var systemCoreServices: Path { return _pathInSystemDomain(.coreServiceDirectory) } /// Returns the path to the system's PPDs directory. - public static var SystemPrinterDescription: Path { + public static var systemPrinterDescription: Path { return _pathInSystemDomain(.printerDescriptionDirectory) } /// Returns the path to the system's PreferencePanes directory. - public static var SystemPreferencePanes: Path { + public static var systemPreferencePanes: Path { return _pathInSystemDomain(.preferencePanesDirectory) } /// Returns the paths where resources can occur. - public static var AllLibraries: [Path] { + public static var allLibraries: [Path] { return _pathsInDomains(.allLibrariesDirectory, .allDomainsMask) } /// Returns the paths where applications can occur - public static var AllApplications: [Path] { + public static var allApplications: [Path] { return _pathsInDomains(.allApplicationsDirectory, .allDomainsMask) } diff --git a/Sources/Process+FileKit.swift b/Sources/Process+FileKit.swift index 59f2365..2443000 100644 --- a/Sources/Process+FileKit.swift +++ b/Sources/Process+FileKit.swift @@ -30,10 +30,10 @@ extension CommandLine { /// The working directory for the current process. public static var workingDirectory: Path { get { - return Path.Current + return Path.current } set { - Path.Current = newValue + Path.current = newValue } } diff --git a/Sources/RelativePathType.swift b/Sources/RelativePathType.swift index 704804b..c5f9a72 100644 --- a/Sources/RelativePathType.swift +++ b/Sources/RelativePathType.swift @@ -2,9 +2,29 @@ // RelativePathType.swift // FileKit // -// Created by ijump on 4/30/16. -// Copyright © 2016 Nikolai Vazquez. All rights reserved. +// The MIT License (MIT) // +// Copyright (c) 2015-2016 Nikolai Vazquez +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + import Foundation diff --git a/Sources/String+FileKit.swift b/Sources/String+FileKit.swift index 61ad23d..c75d9ea 100644 --- a/Sources/String+FileKit.swift +++ b/Sources/String+FileKit.swift @@ -27,29 +27,31 @@ import Foundation -/// Allows String to be used as a DataType. -extension String: DataType { +var ReadableWritableStringEncoding = String.Encoding.utf8 + +/// Allows String to be used as a ReadableWritable. +extension String: ReadableWritable { /// Creates a string from a path. - public static func readFromPath(_ path: Path) throws -> String { - let possibleContents = try? NSString( + public static func read(from path: Path) throws -> String { + let possibleContents = try? String( contentsOfFile: path._safeRawValue, - encoding: String.Encoding.utf8.rawValue) + encoding: ReadableWritableStringEncoding) guard let contents = possibleContents else { throw FileKitError.readFromFileFail(path: path) } - return contents as String + return contents } /// Writes the string to a path atomically. /// /// - Parameter path: The path being written to. /// - public func writeToPath(_ path: Path) throws { - try writeToPath(path, atomically: true) + public func write(to path: Path) throws { + try write(to: path, atomically: true) } - /// Writes the string to a path with `NSUTF8StringEncoding` encoding. + /// Writes the string to a path with `ReadableWritableStringEncoding` encoding. /// /// - Parameter path: The path being written to. /// - Parameter useAuxiliaryFile: If `true`, the data is written to an @@ -57,11 +59,11 @@ extension String: DataType { /// file. If `false`, the data is written to /// the file directly. /// - public func writeToPath(_ path: Path, atomically useAuxiliaryFile: Bool) throws { + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { do { try self.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, - encoding: String.Encoding.utf8) + encoding: ReadableWritableStringEncoding) } catch { throw FileKitError.writeToFileFail(path: path) } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 0f51f71..dae012f 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -218,7 +218,7 @@ open class TextFileStreamReader { // Implement `SequenceType` for `TextFileStreamReader` extension TextFileStreamReader : Sequence { - /// - Returns: A generator to be used for iterating over a `TextFileStreamReader` object. + /// - Returns: An iterator to be used for iterating over a `TextFileStreamReader` object. public func makeIterator() -> AnyIterator { return AnyIterator { return self.nextLine() diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index cfc69e1..02714ef 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -51,7 +51,7 @@ class FileKitTests: XCTestCase { func testPathFileManagerDelegate() { do { - var sourcePath = .UserTemporary + "filekit_test_filemanager_delegate" + var sourcePath = .userTemporary + "filekit_test_filemanager_delegate" let destinationPath = Path("\(sourcePath)1") try sourcePath.createFile() @@ -80,10 +80,10 @@ class FileKitTests: XCTestCase { } func testFindingPaths() { - let homeFolders = Path.UserHome.find(searchDepth: 0) { $0.isDirectory } + let homeFolders = Path.userHome.find(searchDepth: 0) { $0.isDirectory } XCTAssertFalse(homeFolders.isEmpty, "Home folder is not empty") - let rootFiles = Path.Root.find(searchDepth: 1) { !$0.isDirectory } + let rootFiles = Path.root.find(searchDepth: 1) { !$0.isDirectory } XCTAssertFalse(rootFiles.isEmpty) } @@ -97,8 +97,8 @@ class FileKitTests: XCTestCase { } func testPathStringInterpolationConvertible() { - let path: Path = "\(Path.UserTemporary)/testfile_\(10)" - XCTAssertEqual(path.rawValue, Path.UserTemporary.rawValue + "/testfile_10") + let path: Path = "\(Path.userTemporary)/testfile_\(10)" + XCTAssertEqual(path.rawValue, Path.userTemporary.rawValue + "/testfile_10") } func testPathEquality() { @@ -118,26 +118,26 @@ class FileKitTests: XCTestCase { } func testPathIsDirectory() { - let d = Path.SystemApplications + let d = Path.systemApplications XCTAssertTrue(d.isDirectory) } func testSequence() { var i = 0 - let parent = Path.UserTemporary + let parent = Path.userTemporary for _ in parent { i += 1 } print("\(i) files under \(parent)") i = 0 - for (_, _) in Path.UserTemporary.enumerated() { + for (_, _) in Path.userTemporary.enumerated() { i += 1 } } func testPathExtension() { - var path = Path.UserTemporary + "file.txt" + var path = Path.userTemporary + "file.txt" XCTAssertEqual(path.pathExtension, "txt") path.pathExtension = "pdf" XCTAssertEqual(path.pathExtension, "pdf") @@ -155,20 +155,20 @@ class FileKitTests: XCTestCase { } func testPathRecursiveChildren() { - let p: Path = Path.UserTemporary + let p: Path = Path.userTemporary let children = p.children(recursive: true) XCTAssertNotEqual(children, []) } func testRoot() { - let root = Path.Root + let root = Path.root XCTAssertTrue(root.isRoot) XCTAssertEqual(root.standardized, root) XCTAssertEqual(root.parent, root) - var p: Path = Path.UserTemporary + var p: Path = Path.userTemporary XCTAssertFalse(p.isRoot) while !p.isRoot { p = p.parent } @@ -183,7 +183,7 @@ class FileKitTests: XCTestCase { } func testFamily() { - let p: Path = Path.UserTemporary + let p: Path = Path.userTemporary let children = p.children() guard let child = children.first else { @@ -209,15 +209,15 @@ class FileKitTests: XCTestCase { // common ancestor - XCTAssertTrue(p.commonAncestor(Path.Root).isRoot) - XCTAssertEqual(.UserDownloads <^> .UserDocuments, Path.UserHome) + XCTAssertTrue(p.commonAncestor(Path.root).isRoot) + XCTAssertEqual(.userDownloads <^> .userDocuments, Path.userHome) XCTAssertEqual(("~/Downloads" <^> "~/Documents").rawValue, "~") } func testPathAttributes() { - let a = .UserTemporary + "test.txt" - let b = .UserTemporary + "TestDir" + let a = .userTemporary + "test.txt" + let b = .userTemporary + "TestDir" do { try "Hello there, sir" |> TextFile(path: a) try b.createDirectory() @@ -267,7 +267,7 @@ class FileKitTests: XCTestCase { func testPathSymlinking() { do { - let testDir: Path = .UserTemporary + "filekit_test_symlinking" + let testDir: Path = .userTemporary + "filekit_test_symlinking" if testDir.exists && !testDir.isDirectory { try testDir.deleteFile() XCTAssertFalse(testDir.exists) @@ -315,28 +315,28 @@ class FileKitTests: XCTestCase { } func testCurrent() { - let oldCurrent: Path = .Current - let newCurrent: Path = .UserTemporary + let oldCurrent: Path = .current + let newCurrent: Path = .userTemporary XCTAssertNotEqual(oldCurrent, newCurrent) // else there is no test - Path.Current = newCurrent - XCTAssertEqual(Path.Current, newCurrent) + Path.current = newCurrent + XCTAssertEqual(Path.current, newCurrent) - Path.Current = oldCurrent - XCTAssertEqual(Path.Current, oldCurrent) + Path.current = oldCurrent + XCTAssertEqual(Path.current, oldCurrent) } func testChangeDirectory() { - Path.UserTemporary.changeDirectory { - XCTAssertEqual(Path.Current, Path.UserTemporary) + Path.userTemporary.changeDirectory { + XCTAssertEqual(Path.current, Path.userTemporary) } - Path.UserDesktop { - XCTAssertEqual(Path.Current, Path.UserDesktop) + Path.userDesktop { + XCTAssertEqual(Path.current, Path.userDesktop) } - XCTAssertNotEqual(Path.Current, Path.UserTemporary) + XCTAssertNotEqual(Path.current, Path.userTemporary) } func testVolumes() { @@ -356,7 +356,7 @@ class FileKitTests: XCTestCase { } func testURL() { - let path: Path = .UserTemporary + let path: Path = .userTemporary let url = path.url if let pathFromURL = Path(url: url) { XCTAssertEqual(pathFromURL, path) @@ -369,7 +369,7 @@ class FileKitTests: XCTestCase { } func testBookmarkData() { - let path: Path = .UserTemporary + let path: Path = .userTemporary XCTAssertNotNil(path.bookmarkData) if let bookmarkData = path.bookmarkData { @@ -387,7 +387,7 @@ class FileKitTests: XCTestCase { } func testTouch() { - let path: Path = .UserTemporary + "filekit_test.touch" + let path: Path = .userTemporary + "filekit_test.touch" do { if path.exists { try path.deleteFile() } XCTAssertFalse(path.exists) @@ -417,7 +417,7 @@ class FileKitTests: XCTestCase { } func testCreateDirectory() { - let dir: Path = .UserTemporary + "filekit_testdir" + let dir: Path = .userTemporary + "filekit_testdir" do { if dir.exists { try dir.deleteFile() } @@ -460,17 +460,17 @@ class FileKitTests: XCTestCase { func testWellKnownDirectories() { var paths: [Path] = [ - .UserHome, .UserTemporary, .UserCaches, .UserDesktop, .UserDocuments, - .UserAutosavedInformation, .UserDownloads, .UserLibrary, .UserMovies, - .UserMusic, .UserPictures, .UserApplicationSupport, .UserApplications, - .UserSharedPublic + .userHome, .userTemporary, .userCaches, .userDesktop, .userDocuments, + .userAutosavedInformation, .userDownloads, .userLibrary, .userMovies, + .userMusic, .userPictures, .userApplicationSupport, .userApplications, + .userSharedPublic ] paths += [ - .SystemApplications, .SystemApplicationSupport, .SystemLibrary, - .SystemCoreServices, .SystemPreferencePanes /* .SystemPrinterDescription,*/ + .systemApplications, .systemApplicationSupport, .systemLibrary, + .systemCoreServices, .systemPreferencePanes /* .systemPrinterDescription,*/ ] #if os(OSX) - paths += [.UserTrash] // .UserApplicationScripts (not testable) + paths += [.userTrash] // .userApplicationScripts (not testable) #endif for path in paths { @@ -479,20 +479,20 @@ class FileKitTests: XCTestCase { // all - XCTAssertTrue(Path.AllLibraries.contains(.UserLibrary)) - XCTAssertTrue(Path.AllLibraries.contains(.SystemLibrary)) - XCTAssertTrue(Path.AllApplications.contains(.UserApplications)) - XCTAssertTrue(Path.AllApplications.contains(.SystemApplications)) + XCTAssertTrue(Path.allLibraries.contains(.userLibrary)) + XCTAssertTrue(Path.allLibraries.contains(.systemLibrary)) + XCTAssertTrue(Path.allApplications.contains(.userApplications)) + XCTAssertTrue(Path.allApplications.contains(.systemApplications)) // temporary - XCTAssertFalse(Path.ProcessTemporary.exists) - XCTAssertFalse(Path.UniqueTemporary.exists) - XCTAssertNotEqual(Path.UniqueTemporary, Path.UniqueTemporary) + XCTAssertFalse(Path.processTemporary.exists) + XCTAssertFalse(Path.uniqueTemporary.exists) + XCTAssertNotEqual(Path.uniqueTemporary, Path.uniqueTemporary) } // MARK: - TextFile - let textFile = TextFile(path: .UserTemporary + "filekit_test.txt") + let textFile = TextFile(path: .userTemporary + "filekit_test.txt") func testFileName() { XCTAssertEqual(TextFile(path: "/Users/").name, "Users") @@ -605,8 +605,8 @@ class FileKitTests: XCTestCase { // MARK: - FileType func testFileTypeComparable() { - let textFile1 = TextFile(path: .UserTemporary + "filekit_test_comparable1.txt") - let textFile2 = TextFile(path: .UserTemporary + "filekit_test_comparable2.txt") + let textFile1 = TextFile(path: .userTemporary + "filekit_test_comparable1.txt") + let textFile2 = TextFile(path: .userTemporary + "filekit_test_comparable2.txt") do { try "1234567890" |> textFile1 try "12345" |> textFile2 @@ -622,14 +622,14 @@ class FileKitTests: XCTestCase { func testFilePermissions() { let swift: Path = "/usr/bin/swift" if swift.exists { - XCTAssertTrue(swift.filePermissions.contains([.Read, .Execute])) + XCTAssertTrue(swift.filePermissions.contains([.read, .execute])) } - let file: Path = .UserTemporary + "filekit_test_filepermissions" + let file: Path = .userTemporary + "filekit_test_filepermissions" do { try file.createFile() - XCTAssertTrue(file.filePermissions.contains([.Read, .Write])) + XCTAssertTrue(file.filePermissions.contains([.read, .write])) } catch { XCTFail(String(describing: error)) } @@ -637,30 +637,81 @@ class FileKitTests: XCTestCase { // MARK: - DictionaryFile - let dictionaryFile = DictionaryFile(path: .UserTemporary + "filekit_test_dictionary.plist") + let nsDictionaryFile = NSDictionaryFile(path: .userTemporary + "filekit_test_nsdictionary.plist") - func testWriteToDictionaryFile() { + func testWriteToNSDictionaryFile() { do { let dict = NSMutableDictionary() dict["FileKit" as NSString] = true dict["Hello" as NSString] = "World" - try dictionaryFile.write(dict) - let contents = try dictionaryFile.read() + try nsDictionaryFile.write(dict) + let contents = try nsDictionaryFile.read() XCTAssertEqual(contents, dict) } catch { XCTFail(String(describing: error)) } } + + // MARK: - DictionaryFile + + let dictionaryFile = DictionaryFile(path: .userTemporary + "filekit_test_dictionary.plist") + + func testWriteToDictionaryFile() { + do { + var dict: [String: Any] = [:] + dict["FileKit"] = true + dict["Hello"] = "World" + + try dictionaryFile.write(dict) + let contents = try dictionaryFile.read() + + XCTAssertEqual(contents.count, dict.count) + + for (kc, vc) in contents { + let v = dict[kc] + + if let vb = v as? Bool , let vcb = vc as? Bool { + XCTAssertEqual(vb, vcb) + } + else if let vb = v as? String , let vcb = vc as? String { + XCTAssertEqual(vb, vcb) + } + else { + XCTFail("unknow type") + } + } + + } catch { + XCTFail(String(describing: error)) + } + } + + // MARK: - ArrayFile + + let nsArrayFile = NSArrayFile(path: .userTemporary + "filekit_test_nsarray.plist") + + func testWriteToNSArrayFile() { + do { + let array: NSArray = ["ABCD", "WXYZ"] + + try nsArrayFile.write(array) + let contents = try nsArrayFile.read() + XCTAssertEqual(contents, array) + + } catch { + XCTFail(String(describing: error)) + } + } // MARK: - ArrayFile - let arrayFile = ArrayFile(path: .UserTemporary + "filekit_test_array.plist") + let arrayFile = ArrayFile(path: .userTemporary + "filekit_test_array.plist") func testWriteToArrayFile() { do { - let array: NSArray = ["ABCD", "WXYZ"] + let array = ["ABCD", "WXYZ"] try arrayFile.write(array) let contents = try arrayFile.read() @@ -671,13 +722,28 @@ class FileKitTests: XCTestCase { } } - // MARK: - DataFile + // MARK: - NSDataFile - let dataFile = DataFile(path: .UserTemporary + "filekit_test_data") + let nsDataFile = NSDataFile(path: .userTemporary + "filekit_test_nsdata") - func testWriteToDataFile() { + func testWriteToNSDataFile() { do { let data = ("FileKit test" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData + try nsDataFile.write(data) + let contents = try nsDataFile.read() + XCTAssertEqual(contents, data) + } catch { + XCTFail(String(describing: error)) + } + } + + // MARK: - DataFile + + let dataFile = DataFile(path: .userTemporary + "filekit_test_data") + + func testWriteToDataFile() { + do { + let data = "FileKit test".data(using: String.Encoding.utf8)! try dataFile.write(data) let contents = try dataFile.read() XCTAssertEqual(contents, data) @@ -688,7 +754,7 @@ class FileKitTests: XCTestCase { // MARK: - String+FileKit - let stringFile = File(path: .UserTemporary + "filekit_stringtest.txt") + let stringFile = File(path: .userTemporary + "filekit_stringtest.txt") func testStringInitializationFromPath() { do { @@ -704,7 +770,7 @@ class FileKitTests: XCTestCase { func testStringWriting() { do { let message = "Testing string writing..." - try message.writeToPath(stringFile.path) + try message.write(to: stringFile.path) let contents = try String(contentsOfPath: stringFile.path) XCTAssertEqual(contents, message) } catch { @@ -718,8 +784,8 @@ class FileKitTests: XCTestCase { let url = URL(string: "https://raw.githubusercontent.com/nvzqz/FileKit/assets/logo.png")! let img = Image(contentsOf: url) ?? Image() do { - let path: Path = .UserTemporary + "filekit_imagetest.png" - try img.writeToPath(path) + let path: Path = .userTemporary + "filekit_imagetest.png" + try img.write(to: path) } catch { XCTFail(String(describing: error)) } @@ -728,12 +794,12 @@ class FileKitTests: XCTestCase { // MARK: - Watch func testWatch() { - let pathToWatch = .UserTemporary + "filekit_test_watch" + let pathToWatch = .userTemporary + "filekit_test_watch" let expectation = "event" let operation = { do { let message = "Testing file system event when writing..." - try message.writeToPath(pathToWatch, atomically: false) + try message.write(to: pathToWatch, atomically: false) } catch { XCTFail(String(describing: error)) } From dff76db685698e1db4042cc12a8e033dfe54b659 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Wed, 5 Oct 2016 14:06:18 -0400 Subject: [PATCH 12/54] Remove trailing whitespace --- Sources/Array+File.swift | 4 ++-- Sources/Data+FileKit.swift | 8 ++++---- Sources/DataType.swift | 6 +++--- Sources/Dictionary+File.swift | 4 ++-- Sources/FilePermissions.swift | 2 +- Sources/NSString+FileKit.swift | 6 +++--- Tests/FileKitTests.swift | 32 ++++++++++++++++---------------- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Sources/Array+File.swift b/Sources/Array+File.swift index 1c53b21..5ead43c 100644 --- a/Sources/Array+File.swift +++ b/Sources/Array+File.swift @@ -29,7 +29,7 @@ import Foundation extension Array: ReadableWritable, WritableConvertible { - + /// Returns an array from the given path. /// /// - Parameter path: The path to be returned the array for. @@ -44,7 +44,7 @@ extension Array: ReadableWritable, WritableConvertible { } return dict } - + // Return an bridged NSArray value public var writable: NSArray { return self as NSArray diff --git a/Sources/Data+FileKit.swift b/Sources/Data+FileKit.swift index e35e87a..1a54a46 100644 --- a/Sources/Data+FileKit.swift +++ b/Sources/Data+FileKit.swift @@ -29,7 +29,7 @@ import Foundation extension Data: ReadableWritable { - + /// Returns data read from the given path. public static func read(from path: Path) throws -> Data { do { @@ -49,13 +49,13 @@ extension Data: ReadableWritable { throw FileKitError.readFromFileFail(path: path) } } - - + + /// Writes `self` to a Path. public func write(to path: Path) throws { try write(to: path, atomically: true) } - + /// Writes `self` to a path. /// /// - Parameter path: The path being written to. diff --git a/Sources/DataType.swift b/Sources/DataType.swift index c7cd1bf..9db0963 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -72,7 +72,7 @@ public protocol Writable { /// the file directly. /// func write(to path: Path, atomically useAuxiliaryFile: Bool) throws - + } @@ -107,7 +107,7 @@ public protocol WritableToFile: Writable { } extension WritableToFile { - + /// Writes `self` to a Path. /// /// - Parameter path: The path being written to. @@ -123,7 +123,7 @@ extension WritableToFile { throw FileKitError.writeToFileFail(path: path) } } - + } /// A type that can be converted to a Writable. diff --git a/Sources/Dictionary+File.swift b/Sources/Dictionary+File.swift index 035e0d4..1dffccf 100644 --- a/Sources/Dictionary+File.swift +++ b/Sources/Dictionary+File.swift @@ -29,7 +29,7 @@ import Foundation extension Dictionary: ReadableWritable, WritableConvertible { - + /// Returns a dictionary from the given path. /// /// - Parameter path: The path to be returned the dictionary for. @@ -44,7 +44,7 @@ extension Dictionary: ReadableWritable, WritableConvertible { } return dict } - + // Return an bridged NSDictionary value public var writable: NSDictionary { return self as NSDictionary diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index debf31f..d5a7d7e 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -38,7 +38,7 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { /// The file can be executed. public static let execute = FilePermissions(rawValue: 4) - + /// All FilePermissions public static let all: [FilePermissions] = [.read, .write, .execute] diff --git a/Sources/NSString+FileKit.swift b/Sources/NSString+FileKit.swift index 9d2f372..25950e9 100644 --- a/Sources/NSString+FileKit.swift +++ b/Sources/NSString+FileKit.swift @@ -34,7 +34,7 @@ extension NSString { public convenience init(path: Path) { self.init(string: path.rawValue) } - + } extension NSString: Writable { @@ -45,7 +45,7 @@ extension NSString: Writable { public func write(to path: Path) throws { try write(to: path, atomically: true) } - + /// Writes the string to a path with `NSUTF8StringEncoding` encoding. /// /// - Parameter path: The path being written to. @@ -69,7 +69,7 @@ extension NSString: Writable { /* extension NSString: Readable { - + /// Creates a string from a path. public class func read(from path: Path) throws -> Self { let possibleContents = try? NSString( diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 02714ef..6d84d9b 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -653,25 +653,25 @@ class FileKitTests: XCTestCase { XCTFail(String(describing: error)) } } - + // MARK: - DictionaryFile - + let dictionaryFile = DictionaryFile(path: .userTemporary + "filekit_test_dictionary.plist") - + func testWriteToDictionaryFile() { do { var dict: [String: Any] = [:] dict["FileKit"] = true dict["Hello"] = "World" - + try dictionaryFile.write(dict) let contents = try dictionaryFile.read() - + XCTAssertEqual(contents.count, dict.count) - + for (kc, vc) in contents { let v = dict[kc] - + if let vb = v as? Bool , let vcb = vc as? Bool { XCTAssertEqual(vb, vcb) } @@ -682,24 +682,24 @@ class FileKitTests: XCTestCase { XCTFail("unknow type") } } - + } catch { XCTFail(String(describing: error)) } } - + // MARK: - ArrayFile - + let nsArrayFile = NSArrayFile(path: .userTemporary + "filekit_test_nsarray.plist") - + func testWriteToNSArrayFile() { do { let array: NSArray = ["ABCD", "WXYZ"] - + try nsArrayFile.write(array) let contents = try nsArrayFile.read() XCTAssertEqual(contents, array) - + } catch { XCTFail(String(describing: error)) } @@ -736,11 +736,11 @@ class FileKitTests: XCTestCase { XCTFail(String(describing: error)) } } - + // MARK: - DataFile - + let dataFile = DataFile(path: .userTemporary + "filekit_test_data") - + func testWriteToDataFile() { do { let data = "FileKit test".data(using: String.Encoding.utf8)! From 9e075da8e88b200022206e8229120c99ae827aea Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Wed, 5 Oct 2016 14:14:52 -0400 Subject: [PATCH 13/54] Rename FileKit enum to FileKitInfo --- Sources/FileKit.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 21f74c5..d0c4145 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -37,7 +37,7 @@ /// /// - Requires: Xcode 7+, Swift 2.0+ /// -public enum FileKit { +public enum FileKitInfo { /// The current version. /// From 28767c825442cf228177414adeb77f4813b9b6f3 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Wed, 5 Oct 2016 14:19:00 -0400 Subject: [PATCH 14/54] Prepare 4.0.0 release --- FileKit.podspec | 2 +- FileKit.xcodeproj/project.pbxproj | 8 ++++---- README.md | 2 +- Sources/FileKit.swift | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/FileKit.podspec b/FileKit.podspec index a629e4d..d05abce 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "3.0.0" + s.version = "4.0.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 7d0fc62..a295e98 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -801,8 +801,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; - CURRENT_RELEASE_NUMBER = 10; - CURRENT_RELEASE_VERSION = 3.0.0; + CURRENT_RELEASE_NUMBER = 11; + CURRENT_RELEASE_VERSION = 4.0.0; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -851,8 +851,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; - CURRENT_RELEASE_NUMBER = 10; - CURRENT_RELEASE_VERSION = 3.0.0; + CURRENT_RELEASE_NUMBER = 11; + CURRENT_RELEASE_VERSION = 4.0.0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/README.md b/README.md index b622edf..729eca2 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ to learn more. ```ruby use_frameworks! - pod 'FileKit', '~> 3.0.0' + pod 'FileKit', '~> 4.0.0' ``` 2. Run `pod install` and open the `.xcworkspace` file to launch Xcode. diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index d0c4145..371014f 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -33,19 +33,19 @@ /// /// - Copyright: [MIT License](https://opensource.org/licenses/MIT) /// -/// - Version: [v3.0.0](https://github.com/nvzqz/FileKit/releases/tag/v3.0.0) +/// - Version: [v4.0.0](https://github.com/nvzqz/FileKit/releases/tag/v4.0.0) /// -/// - Requires: Xcode 7+, Swift 2.0+ +/// - Requires: Xcode 8, Swift 3.0 /// public enum FileKitInfo { /// The current version. /// /// FileKit follows [Semantic Versioning v2.0.0](http://semver.org/). - public static let version = "v3.0.0" + public static let version = "v4.0.0" /// The current release. - public static let release = 10 + public static let release = 11 /// FileKit is licensed under the [MIT License](https://opensource.org/licenses/MIT). public static let license = "MIT" From d91beae40e3ca830e32eb7177f096063b0d25702 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Wed, 5 Oct 2016 15:37:22 -0400 Subject: [PATCH 15/54] Create .swift-version --- .swift-version | 1 + FileKit.xcodeproj/project.pbxproj | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 .swift-version diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index a295e98..57f8d26 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -180,6 +180,7 @@ 52B938B31BF3C3E5001B7AEB /* FileKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 52B938C81BF402ED001B7AEB /* ImageFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageFile.swift; sourceTree = ""; }; 52BF6BB01B99322000F07E13 /* FileKitError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileKitError.swift; sourceTree = ""; }; + 52EF7A981DA58DE00093B983 /* .swift-version */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".swift-version"; sourceTree = ""; }; 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemWatcher.swift; sourceTree = ""; }; 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEventStream.swift; sourceTree = ""; }; @@ -239,6 +240,7 @@ 5204B7B71B968B8600AA473F /* Products */, 521FC3FB1CDEEC12006C9C3C /* FileKit.playground */, 521FC3FE1CDF0144006C9C3C /* Package.swift */, + 52EF7A981DA58DE00093B983 /* .swift-version */, 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */, ); sourceTree = ""; From 873aa4c0eeebe934feaacb9903c3a476b11b6baf Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Tue, 11 Oct 2016 12:48:41 +0200 Subject: [PATCH 16/54] Update README to swift 3 syntax #30 --- README.md | 59 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 729eca2..bad4047 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ Intermediate directories are created by default. A symbolic link can be created by calling `createSymlinkToPath(_:)` on an `Path`. ```swift -try Path("path/to/MyApp.app").createSymlinkToPath("~/Applications") +try Path("path/to/MyApp.app").symlinkFile(to: "~/Applications") print(Path("~/Applications/MyApp.app").exists) // true ``` @@ -137,7 +137,7 @@ You can find all paths with the ".txt" extension five folders deep into the Desktop with: ```swift -let textFiles = Path.UserDesktop.find(searchDepth: 5) { path in +let textFiles = Path.userDesktop.find(searchDepth: 5) { path in path.pathExtension == "txt" } ``` @@ -148,7 +148,7 @@ against. You can even map a function to paths found and get the non-nil results: ```swift -let documents = Path.UserDocuments.find(searchDepth: 1) { path in +let documents = Path.userDocuments.find(searchDepth: 1) { path in String(path) } ``` @@ -159,7 +159,7 @@ Because `Path` conforms to `SequenceType`, it can be iterated through with a `for` loop. ```swift -for download in Path.UserDownloads { +for download in Path.userDownloads { print("Downloaded file: \(download)") } ``` @@ -172,8 +172,8 @@ To quickly change the current working directory to a path and back, there's the `changeDirectory(_:)` method: ```swift -Path.UserDesktop.changeDirectory { - print(Path.Current) // "/Users/nvzqz/Desktop" +Path.userDesktop.changeDirectory { + print(Path.current) // "/Users/nvzqz/Desktop" } ``` @@ -182,7 +182,7 @@ Path.UserDesktop.changeDirectory { A common ancestor between two paths can be obtained: ```swift -print(Path.Root.commonAncestor(.UserHome)) // "/" +print(Path.root.commonAncestor(.userHome)) // "/" print("~/Desktop" <^> "~/Downloads") // "~" print(.UserLibrary <^> .UserApplicationSupport) // "/Users/nvzqz/Library" ``` @@ -193,7 +193,7 @@ Appends two paths and returns the result ```swift // ~/Documents/My Essay.docx -let essay = Path.UserDocuments + "My Essay.docx" +let essay = Path.userDocuments + "My Essay.docx" ``` It can also be used to concatenate a string and a path, making the string value @@ -208,7 +208,7 @@ let numberedFile: Path = "path/to/dir" + String(10) // "path/to/dir/10" Appends the right path to the left path. Also works with a `String`. ```swift -var photos = Path.UserPictures + "My Photos" // ~/Pictures/My Photos +var photos = Path.userPictures + "My Photos" // ~/Pictures/My Photos photos += "../My Other Photos" // ~/Pictures/My Photos/../My Other Photos ``` @@ -243,9 +243,9 @@ path^ == "~" // true Moves the file at the left path to the right path. -`Path` counterpart: **`moveFileToPath(_:)`** +`Path` counterpart: **`moveFile(to:)`** -`File` counterpart: **`moveToPath(_:)`** +`File` counterpart: **`move(to:)`** ##### `->!` Operator @@ -256,9 +256,9 @@ at the left path before moving the file. Copies the file at the left path to the right path. -`Path` counterpart: **`copyFileToPath(_:)`** +`Path` counterpart: **`copyFile(to:)`** -`File` counterpart: **`copyToPath(_:)`** +`File` counterpart: **`copy(to:)`** ##### `+>!` Operator @@ -269,9 +269,9 @@ at the left path before copying the file. Creates a symlink of the left path at the right path. -`Path` counterpart: **`symlinkFileToPath(_:)`** +`Path` counterpart: **`symlinkFile(to:)`** -`File` counterpart: **`symlinkToPath(_:)`** +`File` counterpart: **`symlink(to:)`** ##### `=>!` Operator @@ -310,7 +310,7 @@ somePath = somePath.resolved A file can be made using `File` with a `DataType` for its data type. ```swift -let plistFile = File(path: Path.UserDesktop + "sample.plist") +let plistFile = File(path: Path.userDesktop + "sample.plist") ``` Files can be compared by size. @@ -323,7 +323,7 @@ Writes the data on the left to the file on the right. ```swift do { - try "My name is Bob." |> TextFile(path: Path.UserDesktop + "name.txt") + try "My name is Bob." |> TextFile(path: Path.userDesktop + "name.txt") } catch { print("I can't write to a desktop file?!") } @@ -346,18 +346,25 @@ try "My Awesome Project" |> readme try "This is an awesome project." |>> readme ``` -#### DictionaryFile +#### NSDictionaryFile A typealias to `File`. -#### ArrayFile +#### NSArrayFile A typealias to `File` -#### DataFile +#### NSDataFile A typealias to `File` +#### DataFile + +The `DataFile` class allows for reading and writing `Data` to a file. + +Although it is a subclass of `File`, `DataFile` offers some functionality +that `File` doesn't. You could specify `Data.ReadingOptions` and `Data.WritingOptions` + ### File Permissions The `FilePermissions` struct allows for seeing the permissions of the current @@ -365,7 +372,7 @@ process for a given file. ```swift let swift: Path = "/usr/bin/swift" -print(swift.filePermissions) // FilePermissions[Read, Execute] +print(swift.filePermissions) // FilePermissions[read, execute] ``` ### Data Types @@ -375,19 +382,19 @@ All types that conform to `DataType` can be used to satisfy the generic type for #### Readable Protocol -A `Readable` type must implement the static method `readFromPath(_:)`. +A `Readable` type must implement the static method `read(from: Path)`. All `Readable` types can be initialized with `init(contentsOfPath:)`. #### Writable Protocol -A `Writable` type must implement `writeToPath(_:atomically:)`. +A `Writable` type must implement `write(to: Path, atomically: Bool)`. -Writing done by `writeToPath(_:)` is done atomically by default. +Writing done by `write(to: Path)` is done atomically by default. ##### WritableToFile -Types that have a `writeToFile(_:atomically:)` method that takes in a `String` +Types that have a `write(toFile:atomically:)` method that takes in a `String` for the file path can conform to `Writable` by simply conforming to `WritableToFile`. @@ -406,7 +413,7 @@ error occurred. ```swift // FileKitError(Could not copy file from "path/to/file" to "path/to/destination") -String(FileKitError.CopyFileFail(from: "path/to/file", to: "path/to/destination")) +String(FileKitError.copyFileFail(from: "path/to/file", to: "path/to/destination")) ``` ## License From 784a094152d7dc37ccded726735a46125a670acf Mon Sep 17 00:00:00 2001 From: phimage Date: Mon, 14 Nov 2016 22:29:41 +0100 Subject: [PATCH 17/54] Create a stream writter for TextFile --- Sources/Operators.swift | 1 + Sources/TextFile.swift | 151 ++++++++++++++++++++++++++++++++------- Tests/FileKitTests.swift | 39 +++++++++- 3 files changed, 163 insertions(+), 28 deletions(-) diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 964f639..89693a9 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -84,6 +84,7 @@ infix operator |>> /// - Throws: `FileKitError.WriteToFileFail` /// public func |>> (data: String, file: TextFile) throws { + // TODO use TextFileStreamWritter var data = data if let contents = try? file.read() { data = contents + "\n" + data diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index dae012f..210fd6f 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -113,55 +113,81 @@ extension TextFile { } -/// A class to read `TextFile` line by line. -open class TextFileStreamReader { - +/// A class to read or write `TextFile`. +open class TextFileStream { + /// The text encoding. open let encoding: String.Encoding + let delimData: Data! + var fileHandle: FileHandle? + + // MARK: - Initialization + public init?( + fileHandle: FileHandle, + delimiter: String, + encoding: String.Encoding = .utf8 + ) { + self.encoding = encoding + self.fileHandle = fileHandle + guard let delimData = delimiter.data(using: encoding) else { + return nil + } + self.delimData = delimData + } + + // MARK: - Deinitialization + + deinit { + self.close() + } + + // MARK: - public methods + + open var offset: UInt64 { + return fileHandle?.offsetInFile ?? 0 + } + + /// Close the underlying file. No reading must be done after calling this method. + open func close() -> Void { + fileHandle?.closeFile() + fileHandle = nil + } +} + +/// A class to read `TextFile` line by line. +open class TextFileStreamReader: TextFileStream { + /// The chunk size when reading. open let chunkSize: Int /// Tells if the position is at the end of file. open var atEOF: Bool = false - let fileHandle: FileHandle! let buffer: NSMutableData! - let delimData: Data! // MARK: - Initialization /// - Parameter path: the file path /// - Parameter delimiter: the line delimiter (default: \n) - /// - Parameter encoding: file encoding (default: NSUTF8StringEncoding) + /// - Parameter encoding: file encoding (default: .utf8) /// - Parameter chunkSize: size of buffer (default: 4096) public init?( path: Path, delimiter: String = "\n", - encoding: String.Encoding = String.Encoding.utf8, + encoding: String.Encoding = .utf8, chunkSize: Int = 4096 ) { self.chunkSize = chunkSize - self.encoding = encoding - guard let fileHandle = path.fileHandleForReading, - let delimData = delimiter.data(using: encoding), let buffer = NSMutableData(capacity: chunkSize) else { - self.fileHandle = nil - self.delimData = nil self.buffer = nil return nil } - self.fileHandle = fileHandle - self.delimData = delimData self.buffer = buffer + super.init(fileHandle: fileHandle, delimiter: delimiter, encoding: encoding) } - // MARK: - Deinitialization - - deinit { - self.close() - } // MARK: - public methods @@ -174,8 +200,8 @@ open class TextFileStreamReader { // Read data chunks from file until a line delimiter is found. var range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) while range.location == NSNotFound { - let tmpData = fileHandle.readData(ofLength: chunkSize) - if tmpData.isEmpty { + let tmpData = fileHandle?.readData(ofLength: chunkSize) + if tmpData == nil || tmpData!.isEmpty { // EOF or read error. atEOF = true if buffer.length > 0 { @@ -188,7 +214,7 @@ open class TextFileStreamReader { // No more lines. return nil } - buffer.append(tmpData) + buffer.append(tmpData!) range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) } @@ -209,11 +235,6 @@ open class TextFileStreamReader { atEOF = false } - /// Close the underlying file. No reading must be done after calling this method. - open func close() -> Void { - fileHandle?.closeFile() - } - } // Implement `SequenceType` for `TextFileStreamReader` @@ -225,3 +246,79 @@ extension TextFileStreamReader : Sequence { } } } + + +// MARK: Line Writter +/// A class to read `TextFile` line by line. +open class TextFileStreamWritter: TextFileStream { + + // MARK: - Initialization + + /// - Parameter path: the file path + /// - Parameter delimiter: the line delimiter (default: \n) + /// - Parameter encoding: file encoding (default: .utf8) + /// - Parameter append: if true append at file end (default: false) + /// - Parameter createIfNotExist: if true create file if not exixt (default: true) + public init?( + path: Path, + delimiter: String = "\n", + encoding: String.Encoding = .utf8, + append: Bool = false, + createIfNotExist: Bool = true + ) { + if createIfNotExist && !path.exists { + try? path.createFile() + } + guard let fileHandle = path.fileHandleForWriting else { + return nil + } + if append { + fileHandle.seekToEndOfFile() + } + super.init(fileHandle: fileHandle, delimiter: delimiter, encoding: encoding) + } + + /// Write a new line in file + /// - Parameter line: the line + /// - Parameter delim: append the delimiter (default: true) + /// + /// - Returns: true if successfully. + @discardableResult + open func write(line: String, delim: Bool = true) -> Bool { + if let handle = fileHandle, let data = line.data(using: self.encoding) { + handle.write(data) + if delim { + handle.write(delimData) + } + return true + } + return false + } + + /// Causes all in-memory data and attributes of the file represented by the receiver to be written to permanent storage. + open func synchronize() { + fileHandle?.synchronizeFile() + } +} + +extension TextFile { + + /// Provide a writter to writte line by line. + /// + /// - Parameter delimiter: the line delimiter (default: \n) + /// - Parameter append: if true append at file end (default: false) + /// + /// - Returns: the `TextFileStreamReader` + + public func streamWritter(_ delimiter: String = "\n", append: Bool = false) -> TextFileStreamWritter? { + return TextFileStreamWritter( + path: self.path, + delimiter: delimiter, + encoding: encoding, + append: append + ) + } + +} + + diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 6d84d9b..5214a37 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -491,7 +491,7 @@ class FileKitTests: XCTestCase { } // MARK: - TextFile - + let testFilePath: Path = .userTemporary + "filekit_test.txt" let textFile = TextFile(path: .userTemporary + "filekit_test.txt") func testFileName() { @@ -548,6 +548,9 @@ class FileKitTests: XCTestCase { try expectedLines.joined(separator: separator) |> textFile if let reader = textFile.streamReader() { + defer { + reader.close() + } var lines = [String]() for line in reader { lines.append(line) @@ -601,6 +604,40 @@ class FileKitTests: XCTestCase { XCTFail(String(describing: error)) } } + + func testTextFileStreamWritter() { + if testFilePath.exists { + try? testFilePath.deleteFile() + } + do { + let lines = [ + "Lorem ipsum dolor sit amet", + "consectetur adipiscing elit", + "Sed non risus" + ] + let separator = "\n" + + if let writter = textFile.streamWritter(separator) { + defer { + writter.close() + } + for line in lines { + let delim = line != lines.last + writter.write(line: line, delim: delim) + } + + let expected = try textFile.read() + let expectedLines = expected.components(separatedBy: separator) + XCTAssertEqual(expectedLines, lines) + + } else { + XCTFail("Failed to create writter") + } + + } catch { + XCTFail(String(describing: error)) + } + } // MARK: - FileType From b17670bc95ec5c847ea68fca44c155571d0d88e5 Mon Sep 17 00:00:00 2001 From: phimage Date: Tue, 22 Nov 2016 11:17:43 +0100 Subject: [PATCH 18/54] Fix misspelling on TextFileStreamWriter --- Sources/TextFile.swift | 18 +++++++++++------- Tests/FileKitTests.swift | 8 ++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 210fd6f..0adb15a 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -148,6 +148,10 @@ open class TextFileStream { return fileHandle?.offsetInFile ?? 0 } + open func seek(toFileOffset offset: UInt64) { + fileHandle?.seek(toFileOffset: offset) + } + /// Close the underlying file. No reading must be done after calling this method. open func close() -> Void { fileHandle?.closeFile() @@ -248,9 +252,9 @@ extension TextFileStreamReader : Sequence { } -// MARK: Line Writter -/// A class to read `TextFile` line by line. -open class TextFileStreamWritter: TextFileStream { +// MARK: Line Writer +/// A class to write a `TextFile` line by line. +open class TextFileStreamWriter: TextFileStream { // MARK: - Initialization @@ -303,15 +307,15 @@ open class TextFileStreamWritter: TextFileStream { extension TextFile { - /// Provide a writter to writte line by line. + /// Provide a writer to write line by line. /// /// - Parameter delimiter: the line delimiter (default: \n) /// - Parameter append: if true append at file end (default: false) /// - /// - Returns: the `TextFileStreamReader` + /// - Returns: the `TextFileStreamWriter` - public func streamWritter(_ delimiter: String = "\n", append: Bool = false) -> TextFileStreamWritter? { - return TextFileStreamWritter( + public func streamWriter(_ delimiter: String = "\n", append: Bool = false) -> TextFileStreamWriter? { + return TextFileStreamWriter( path: self.path, delimiter: delimiter, encoding: encoding, diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 5214a37..91c4a57 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -617,13 +617,13 @@ class FileKitTests: XCTestCase { ] let separator = "\n" - if let writter = textFile.streamWritter(separator) { + if let writer = textFile.streamWriter(separator) { defer { - writter.close() + writer.close() } for line in lines { let delim = line != lines.last - writter.write(line: line, delim: delim) + writer.write(line: line, delim: delim) } let expected = try textFile.read() @@ -631,7 +631,7 @@ class FileKitTests: XCTestCase { XCTAssertEqual(expectedLines, lines) } else { - XCTFail("Failed to create writter") + XCTFail("Failed to create writer") } } catch { From f5c3916021ab0f2a2a45b92dc4caa4a2f1e68837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Jim=C3=A9nez?= Date: Wed, 7 Dec 2016 18:40:06 +0100 Subject: [PATCH 19/54] Fix Swift Package Manager error When trying to add FileKit with SPM, it throws this error: Error: swift-package: error: the package has an unsupported layout, unexpected source file(s) found: /Packages/FileKit-4.0.0/Tests/FileKitTests.swift fix: move the file(s) inside a module Excluding the Tests dir fix the problem like swift-package suggests --- Package.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Package.swift b/Package.swift index d04231d..87c5d78 100644 --- a/Package.swift +++ b/Package.swift @@ -29,4 +29,7 @@ import PackageDescription let package = Package( name: "FileKit" + exclude: [ + "Tests" + ] ) From 99a4036e3be5e29544d4bffd9f77508ec9408675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Jim=C3=A9nez?= Date: Wed, 7 Dec 2016 18:44:10 +0100 Subject: [PATCH 20/54] Update Package.swift --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 87c5d78..0495e49 100644 --- a/Package.swift +++ b/Package.swift @@ -30,6 +30,6 @@ import PackageDescription let package = Package( name: "FileKit" exclude: [ - "Tests" - ] + "Tests" + ] ) From 33b34ba76317f52e996103f700f41b9e6271cfba Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 1 Jan 2017 00:28:21 -0500 Subject: [PATCH 21/54] Update copyright year to include 2017 --- FileKit.xcodeproj/project.pbxproj | 2 ++ Package.swift | 2 +- Sources/Array+File.swift | 4 ++-- Sources/ArrayFile.swift | 2 +- Sources/Bundle+FileKit.swift | 2 +- Sources/Data+FileKit.swift | 4 ++-- Sources/DataFile.swift | 2 +- Sources/DataType.swift | 2 +- Sources/Dictionary+File.swift | 4 ++-- Sources/DictionaryFile.swift | 2 +- Sources/DirectoryEnumerator.swift | 2 +- Sources/DispatchEvent.swift | 2 +- Sources/DispatchWatcher.swift | 2 +- Sources/File.swift | 2 +- Sources/FileKit.swift | 2 +- Sources/FileKitError.swift | 2 +- Sources/FilePermissions.swift | 2 +- Sources/FileProtection.swift | 2 +- Sources/FileSystemEvent.swift | 2 +- Sources/FileSystemEventStream.swift | 2 +- Sources/FileSystemWatcher.swift | 2 +- Sources/FileType.swift | 2 +- Sources/Image+FileKit.swift | 2 +- Sources/ImageFile.swift | 2 +- Sources/NSArray+FileKit.swift | 2 +- Sources/NSData+FileKit.swift | 2 +- Sources/NSDataFile.swift | 2 +- Sources/NSDictionary+FileKit.swift | 2 +- Sources/NSString+FileKit.swift | 2 +- Sources/Operators.swift | 2 +- Sources/Path.swift | 2 +- Sources/Process+FileKit.swift | 2 +- Sources/RelativePathType.swift | 2 +- Sources/String+FileKit.swift | 2 +- Sources/TextFile.swift | 2 +- Tests/FileKitTests.swift | 2 +- 36 files changed, 40 insertions(+), 38 deletions(-) diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 57f8d26..c87b1b2 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -168,6 +168,7 @@ 5263A9061B96BA3D00635A93 /* FileKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileKitTests.swift; sourceTree = ""; }; 5263A9081B96BA3D00635A93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 527612421BAEA3EE00503D0A /* FileKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 527848661E18CADD007E14F0 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 52A016C31C013F3D0045A9C8 /* DirectoryEnumerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DirectoryEnumerator.swift; sourceTree = ""; }; 52A016E81C01565C0045A9C8 /* FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileKit.swift; sourceTree = ""; }; 52A016F11C0184CA0045A9C8 /* FileProtection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileProtection.swift; sourceTree = ""; }; @@ -242,6 +243,7 @@ 521FC3FE1CDF0144006C9C3C /* Package.swift */, 52EF7A981DA58DE00093B983 /* .swift-version */, 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */, + 527848661E18CADD007E14F0 /* README.md */, ); sourceTree = ""; }; diff --git a/Package.swift b/Package.swift index 0495e49..cab217e 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2016 Nikolai Vazquez +// Copyright (c) 2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Array+File.swift b/Sources/Array+File.swift index 5ead43c..ea1a92d 100644 --- a/Sources/Array+File.swift +++ b/Sources/Array+File.swift @@ -4,8 +4,8 @@ // // The MIT License (MIT) // -// Copyright (c) 2016 Nikolai Vazquez -// Copyright (c) 2016 Marchand Eric +// Copyright (c) 2017 Nikolai Vazquez +// Copyright (c) 2017 Marchand Eric // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/ArrayFile.swift b/Sources/ArrayFile.swift index 81b1fd8..5d164d0 100644 --- a/Sources/ArrayFile.swift +++ b/Sources/ArrayFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Bundle+FileKit.swift b/Sources/Bundle+FileKit.swift index 18bf70b..46342cf 100644 --- a/Sources/Bundle+FileKit.swift +++ b/Sources/Bundle+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Data+FileKit.swift b/Sources/Data+FileKit.swift index 1a54a46..4a4f4be 100644 --- a/Sources/Data+FileKit.swift +++ b/Sources/Data+FileKit.swift @@ -4,8 +4,8 @@ // // The MIT License (MIT) // -// Copyright (c) 2016 Nikolai Vazquez -// Copyright (c) 2016 Marchand Eric +// Copyright (c) 2017 Nikolai Vazquez +// Copyright (c) 2017 Marchand Eric // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index 5df1c6f..9907d2e 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/DataType.swift b/Sources/DataType.swift index 9db0963..5941c02 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Dictionary+File.swift b/Sources/Dictionary+File.swift index 1dffccf..bad7a17 100644 --- a/Sources/Dictionary+File.swift +++ b/Sources/Dictionary+File.swift @@ -4,8 +4,8 @@ // // The MIT License (MIT) // -// Copyright (c) 2016 Nikolai Vazquez -// Copyright (c) 2016 Marchand Eric +// Copyright (c) 2017 Nikolai Vazquez +// Copyright (c) 2017 Marchand Eric // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/DictionaryFile.swift b/Sources/DictionaryFile.swift index ec3298e..b64bde6 100644 --- a/Sources/DictionaryFile.swift +++ b/Sources/DictionaryFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/DirectoryEnumerator.swift b/Sources/DirectoryEnumerator.swift index 3be8d78..12cec8d 100644 --- a/Sources/DirectoryEnumerator.swift +++ b/Sources/DirectoryEnumerator.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/DispatchEvent.swift b/Sources/DispatchEvent.swift index fe001ef..6a16008 100644 --- a/Sources/DispatchEvent.swift +++ b/Sources/DispatchEvent.swift @@ -3,7 +3,7 @@ // FileKit // // Created by ijump on 5/2/16. -// Copyright © 2016 Nikolai Vazquez. All rights reserved. +// Copyright © 2017 Nikolai Vazquez. All rights reserved. // import Foundation diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index 31fa1c3..b112d65 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -3,7 +3,7 @@ // FileKit // // Created by ijump on 5/2/16. -// Copyright © 2016 Nikolai Vazquez. All rights reserved. +// Copyright © 2017 Nikolai Vazquez. All rights reserved. // import Foundation diff --git a/Sources/File.swift b/Sources/File.swift index 3797e20..4b48886 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 371014f..7b72164 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileKitError.swift b/Sources/FileKitError.swift index 00be2f6..435936d 100644 --- a/Sources/FileKitError.swift +++ b/Sources/FileKitError.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index d5a7d7e..753a666 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index ac34160..6c1a10e 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileSystemEvent.swift b/Sources/FileSystemEvent.swift index 5ddbc57..0bd1f73 100644 --- a/Sources/FileSystemEvent.swift +++ b/Sources/FileSystemEvent.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileSystemEventStream.swift b/Sources/FileSystemEventStream.swift index 89f06ab..25b8cca 100644 --- a/Sources/FileSystemEventStream.swift +++ b/Sources/FileSystemEventStream.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index 9be2744..8337e44 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/FileType.swift b/Sources/FileType.swift index ea4e03b..0917e9b 100644 --- a/Sources/FileType.swift +++ b/Sources/FileType.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index c8bab94..c29687d 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/ImageFile.swift b/Sources/ImageFile.swift index dd09de7..a12f2b0 100644 --- a/Sources/ImageFile.swift +++ b/Sources/ImageFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/NSArray+FileKit.swift b/Sources/NSArray+FileKit.swift index 05c8977..620012f 100644 --- a/Sources/NSArray+FileKit.swift +++ b/Sources/NSArray+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/NSData+FileKit.swift b/Sources/NSData+FileKit.swift index 432c3d2..69c5ea4 100644 --- a/Sources/NSData+FileKit.swift +++ b/Sources/NSData+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/NSDataFile.swift b/Sources/NSDataFile.swift index 7fcf04e..a9a7cc3 100644 --- a/Sources/NSDataFile.swift +++ b/Sources/NSDataFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/NSDictionary+FileKit.swift b/Sources/NSDictionary+FileKit.swift index 56c1895..0dae95e 100644 --- a/Sources/NSDictionary+FileKit.swift +++ b/Sources/NSDictionary+FileKit.swift @@ -1,7 +1,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/NSString+FileKit.swift b/Sources/NSString+FileKit.swift index 25950e9..a5010d1 100644 --- a/Sources/NSString+FileKit.swift +++ b/Sources/NSString+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 89693a9..a0ece3b 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Path.swift b/Sources/Path.swift index c8daf68..ed9f0de 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Process+FileKit.swift b/Sources/Process+FileKit.swift index 2443000..aa3f011 100644 --- a/Sources/Process+FileKit.swift +++ b/Sources/Process+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/RelativePathType.swift b/Sources/RelativePathType.swift index c5f9a72..7adc778 100644 --- a/Sources/RelativePathType.swift +++ b/Sources/RelativePathType.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/String+FileKit.swift b/Sources/String+FileKit.swift index c75d9ea..dc74f8f 100644 --- a/Sources/String+FileKit.swift +++ b/Sources/String+FileKit.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 0adb15a..0d22907 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 91c4a57..cdf1f28 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -4,7 +4,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015-2016 Nikolai Vazquez +// Copyright (c) 2015-2017 Nikolai Vazquez // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal From 8ba3bae10f1cca7027191a533d9c3ff0fc1d86b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Jim=C3=A9nez?= Date: Thu, 8 Dec 2016 12:26:54 +0100 Subject: [PATCH 22/54] Update Package.swift Sorry, I missed a comma! --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index cab217e..c11c1b7 100644 --- a/Package.swift +++ b/Package.swift @@ -28,7 +28,7 @@ import PackageDescription let package = Package( - name: "FileKit" + name: "FileKit", exclude: [ "Tests" ] From 3bd3facb1744e1c3fdbb592110d0dca8cd70e55e Mon Sep 17 00:00:00 2001 From: phimage Date: Mon, 13 Feb 2017 21:27:23 +0100 Subject: [PATCH 23/54] Fix #41 swiftlint shorthand_operator is configured as warning instead of error Fix some other swiftlint warnings in code --- .swiftlint.yml | 2 + FileKit.xcodeproj/project.pbxproj | 14 ++++-- .../xcschemes/FileKit-OSX.xcscheme | 2 +- .../xcschemes/FileKit-iOS.xcscheme | 2 +- .../xcschemes/FileKit-tvOS.xcscheme | 2 +- .../xcschemes/FileKit-watchOS.xcscheme | 2 +- .../xcschemes/FileKitTests.xcscheme | 2 +- Sources/ArrayFile.swift | 2 +- Sources/Data+FileKit.swift | 7 +-- Sources/DataFile.swift | 3 +- Sources/DataType.swift | 5 -- Sources/DictionaryFile.swift | 2 +- Sources/DispatchWatcher.swift | 3 -- Sources/FilePermissions.swift | 2 +- Sources/FileProtection.swift | 2 +- Sources/FileSystemEvent.swift | 7 +-- Sources/NSString+FileKit.swift | 2 - Sources/Operators.swift | 9 +--- Sources/Path.swift | 47 ++++++++----------- Sources/RelativePathType.swift | 1 - Sources/TextFile.swift | 32 ++++++------- 21 files changed, 61 insertions(+), 89 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 69e4752..5e9ab88 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -9,6 +9,8 @@ disabled_rules: - variable_name - type_name +shorthand_operator: warning + # some rules are only opt-in opt_in_rules: - empty_count diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index c87b1b2..5a0724b 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -475,7 +475,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { @@ -799,8 +799,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; @@ -849,8 +851,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; @@ -920,7 +924,7 @@ 5204B85E1B96B85E00AA473F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -940,7 +944,7 @@ 5204B85F1B96B85E00AA473F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -987,6 +991,7 @@ 527612471BAEA3EE00503D0A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1006,6 +1011,7 @@ 527612481BAEA3EE00503D0A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1027,6 +1033,7 @@ 52B938B81BF3C3E5001B7AEB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1046,6 +1053,7 @@ 52B938B91BF3C3E5001B7AEB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index 3b1172b..ad871e9 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ /// A representation of a filesystem array file. /// /// The data type is Array. -public typealias ArrayFile = File> +public typealias ArrayFile = File<[T]> diff --git a/Sources/Data+FileKit.swift b/Sources/Data+FileKit.swift index 4a4f4be..377a67f 100644 --- a/Sources/Data+FileKit.swift +++ b/Sources/Data+FileKit.swift @@ -34,8 +34,7 @@ extension Data: ReadableWritable { public static func read(from path: Path) throws -> Data { do { return try self.init(contentsOf: path.url, options: []) - } - catch { + } catch { throw FileKitError.readFromFileFail(path: path) } } @@ -44,13 +43,11 @@ extension Data: ReadableWritable { public static func read(from path: Path, options: Data.ReadingOptions) throws -> Data { do { return try self.init(contentsOf: path.url, options: options) - } - catch { + } catch { throw FileKitError.readFromFileFail(path: path) } } - /// Writes `self` to a Path. public func write(to path: Path) throws { try write(to: path, atomically: true) diff --git a/Sources/DataFile.swift b/Sources/DataFile.swift index 9907d2e..33aafcb 100644 --- a/Sources/DataFile.swift +++ b/Sources/DataFile.swift @@ -27,7 +27,6 @@ import Foundation - /// A representation of a filesystem data file. /// /// The data type is Data. @@ -64,7 +63,7 @@ open class DataFile: File { open class DataFileWithOptions: DataFile { open var readingOptions: Data.ReadingOptions = [] - open var writingOptions: Data.WritingOptions? = nil + open var writingOptions: Data.WritingOptions? /// Initializes a file from a path with options. /// diff --git a/Sources/DataType.swift b/Sources/DataType.swift index 5941c02..c39c95c 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -30,8 +30,6 @@ import Foundation /// A type that can be used to read from and write to File instances. public typealias ReadableWritable = Readable & Writable - - /// A type that can be used to read from File instances. public protocol Readable { @@ -55,8 +53,6 @@ extension Readable { } - - /// A type that can be used to write to File instances. public protocol Writable { @@ -73,7 +69,6 @@ public protocol Writable { /// func write(to path: Path, atomically useAuxiliaryFile: Bool) throws - } extension Writable { diff --git a/Sources/DictionaryFile.swift b/Sources/DictionaryFile.swift index b64bde6..32ce05d 100644 --- a/Sources/DictionaryFile.swift +++ b/Sources/DictionaryFile.swift @@ -35,4 +35,4 @@ public typealias NSDictionaryFile = File /// A representation of a filesystem dictionary file. /// /// The data type is DictionaryFile. -public typealias DictionaryFile = File> +public typealias DictionaryFile = File<[K: V]> diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index b112d65..8a3af6a 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -8,8 +8,6 @@ import Foundation - - /// Delegate for `DispatchFileSystemWatcher` public protocol DispatchFileSystemWatcherDelegate: class { @@ -305,7 +303,6 @@ open class DispatchFileSystemWatcher { self.source = nil } - } extension Path { diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index 753a666..5937f9c 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -48,7 +48,7 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { /// A textual representation of `self`. public var description: String { var description = "" - for permission in FilePermissions.all { + for permission in FilePermissions.all { if self.contains(permission) { description += !description.isEmpty ? ", " : "" if permission == .read { diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index 6c1a10e..5afd968 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -121,7 +121,7 @@ extension Path { /// public func createFile(_ fileProtection: FileProtection) throws { let manager = FileManager() - let attributes = [FileAttributeKey.protectionKey.rawValue : fileProtection.rawValue] + let attributes = [FileAttributeKey.protectionKey.rawValue: fileProtection.rawValue] if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { throw FileKitError.createFileFail(path: self) } diff --git a/Sources/FileSystemEvent.swift b/Sources/FileSystemEvent.swift index 0bd1f73..cd51b38 100644 --- a/Sources/FileSystemEvent.swift +++ b/Sources/FileSystemEvent.swift @@ -52,7 +52,6 @@ public struct FileSystemEvent { public var flags: FileSystemEventFlags } - extension Path { // MARK: - Watching @@ -70,7 +69,6 @@ extension Path { } } - extension Sequence where Self.Iterator.Element == Path { // MARK: - Watching @@ -90,8 +88,6 @@ extension Sequence where Self.Iterator.Element == Path { } - - /// A set of fileystem event flags. public struct FileSystemEventFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { @@ -222,7 +218,7 @@ public struct FileSystemEventFlags: OptionSet, CustomStringConvertible, CustomDe "ItemRemoved", "ItemInodeMetaMod", "ItemRenamed", "ItemModified", "ItemFinderInfoMod", "ItemChangeOwner", "ItemXattrMod", "ItemIsFile", "ItemIsDir", - "ItemIsSymlink", "OwnEvent", + "ItemIsSymlink", "OwnEvent" ] // swiftlint:enable comma if #available(iOS 9, OSX 10.10, *) { array += ["ItemIsHardlink", "ItemIsLastHardlink"] @@ -268,7 +264,6 @@ public struct FileSystemEventFlags: OptionSet, CustomStringConvertible, CustomDe } - /// Flags for creating an event stream. public struct FileSystemEventStreamCreateFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Sources/NSString+FileKit.swift b/Sources/NSString+FileKit.swift index a5010d1..a710e5d 100644 --- a/Sources/NSString+FileKit.swift +++ b/Sources/NSString+FileKit.swift @@ -64,7 +64,6 @@ extension NSString: Writable { } } - } /* @@ -82,4 +81,3 @@ extension NSString: Writable { } } */ - diff --git a/Sources/Operators.swift b/Sources/Operators.swift index a0ece3b..93d4c7a 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -29,7 +29,7 @@ import Foundation -fileprivate func < (lhs: T?, rhs: T?) -> Bool { +fileprivate func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l < r @@ -64,8 +64,6 @@ public func |> (data: DataType, file: File try file.write(data) } - - // MARK: - TextFile /// Returns `true` if both text files have the same path and encoding. @@ -175,7 +173,6 @@ public func += (lhs: inout Path, rhs: String) { lhs = lhs + rhs } - /// Concatenates two `Path` instances and returns the result. public func / (lhs: Path, rhs: Path) -> Path { @@ -219,7 +216,7 @@ public func <^> (lhs: Path, rhs: Path) -> Path { infix operator /// Runs `closure` with the path as its current working directory. -public func (path: Path, closure: () throws -> ()) rethrows { +public func (path: Path, closure: () throws -> Void) rethrows { try path.changeDirectory(closure) } @@ -281,7 +278,6 @@ public func ->! (lhs: File, rhs: Path) thr try lhs ->> rhs } - infix operator +>> /// Copies the file at the left path to the right path. @@ -425,7 +421,6 @@ public postfix func * (path: Path) -> Path { return path.resolved } - postfix operator ^ /// Returns the path's parent path. diff --git a/Sources/Path.swift b/Sources/Path.swift index ed9f0de..34bd542 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -70,13 +70,11 @@ public struct Path { weak var delegate: FileManagerDelegate? /// Safe way to use fileManager var fileManager: FileManager { - get { -// if delegate == nil { -// print("\n\nDelegate is nil\n\n") -// } - unsafeFileManager.delegate = delegate - return unsafeFileManager - } + //if delegate == nil { + // print("\n\nDelegate is nil\n\n") + //} + unsafeFileManager.delegate = delegate + return unsafeFileManager } } @@ -108,20 +106,16 @@ public struct Path { /// The standardized path string value public var standardRawValue: String { - get { - return (self.rawValue as NSString).standardizingPath - } + return (self.rawValue as NSString).standardizingPath } /// The standardized path string value without expanding tilde public var standardRawValueWithTilde: String { - get { - let comps = components - if comps.isEmpty { - return "" - } else { - return self[comps.count - 1].rawValue - } + let comps = components + if comps.isEmpty { + return "" + } else { + return self[comps.count - 1].rawValue } } @@ -173,13 +167,11 @@ public struct Path { /// The standardized path string value without expanding tilde public var standardWithTilde: Path { - get { - let comps = components - if comps.isEmpty { - return Path("") - } else { - return self[comps.count - 1] - } + let comps = components + if comps.isEmpty { + return Path("") + } else { + return self[comps.count - 1] } } @@ -355,7 +347,7 @@ extension Path { /// /// - Parameter closure: The block to run while `Path.Current` is changed. /// - public func changeDirectory(_ closure: () throws -> ()) rethrows { + public func changeDirectory(_ closure: () throws -> Void) rethrows { let previous = Path.current defer { Path.current = previous } if _fmWraper.fileManager.changeCurrentDirectoryPath(_safeRawValue) { @@ -852,7 +844,7 @@ extension Path { /// Modify one attribute fileprivate func _setAttribute(_ key: FileAttributeKey, value: Any) throws { - try _setAttributes([key : value]) + try _setAttributes([key: value]) } /// The creation date of the file at the path. @@ -1124,7 +1116,6 @@ extension Path: Sequence { } - extension Path { // MARK: - Paths @@ -1275,7 +1266,7 @@ extension Path { } fileprivate static func _pathsInDomains(_ directory: FileManager.SearchPathDirectory, - _ domainMask: FileManager.SearchPathDomainMask) -> [Path] { + _ domainMask: FileManager.SearchPathDomainMask) -> [Path] { return NSSearchPathForDirectoriesInDomains(directory, domainMask, true) .map({ Path($0).standardized }) } diff --git a/Sources/RelativePathType.swift b/Sources/RelativePathType.swift index 7adc778..cd2305e 100644 --- a/Sources/RelativePathType.swift +++ b/Sources/RelativePathType.swift @@ -25,7 +25,6 @@ // THE SOFTWARE. // - import Foundation /// The type attribute for a relative path. diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 0d22907..5e97e92 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -84,7 +84,7 @@ extension TextFile { /// - Returns: the `TextFileStreamReader` public func streamReader(_ delimiter: String = "\n", - chunkSize: Int = 4096) -> TextFileStreamReader? { + chunkSize: Int = 4096) -> TextFileStreamReader? { return TextFileStreamReader( path: self.path, delimiter: delimiter, @@ -101,7 +101,7 @@ extension TextFile { /// /// - Returns: the lines public func grep(_ motif: String, include: Bool = true, - options: NSString.CompareOptions = []) -> [String] { + options: NSString.CompareOptions = []) -> [String] { guard let reader = streamReader() else { return [] } @@ -115,13 +115,13 @@ extension TextFile { /// A class to read or write `TextFile`. open class TextFileStream { - + /// The text encoding. open let encoding: String.Encoding let delimData: Data! var fileHandle: FileHandle? - + // MARK: - Initialization public init?( fileHandle: FileHandle, @@ -135,25 +135,25 @@ open class TextFileStream { } self.delimData = delimData } - + // MARK: - Deinitialization - + deinit { self.close() } - + // MARK: - public methods - + open var offset: UInt64 { return fileHandle?.offsetInFile ?? 0 } - + open func seek(toFileOffset offset: UInt64) { fileHandle?.seek(toFileOffset: offset) } /// Close the underlying file. No reading must be done after calling this method. - open func close() -> Void { + open func close() { fileHandle?.closeFile() fileHandle = nil } @@ -192,7 +192,6 @@ open class TextFileStreamReader: TextFileStream { super.init(fileHandle: fileHandle, delimiter: delimiter, encoding: encoding) } - // MARK: - public methods /// - Returns: The next line, or nil on EOF. @@ -233,7 +232,7 @@ open class TextFileStreamReader: TextFileStream { } /// Start reading from the beginning of file. - open func rewind() -> Void { + open func rewind() { fileHandle?.seek(toFileOffset: 0) buffer.length = 0 atEOF = false @@ -251,13 +250,12 @@ extension TextFileStreamReader : Sequence { } } - // MARK: Line Writer /// A class to write a `TextFile` line by line. open class TextFileStreamWriter: TextFileStream { // MARK: - Initialization - + /// - Parameter path: the file path /// - Parameter delimiter: the line delimiter (default: \n) /// - Parameter encoding: file encoding (default: .utf8) @@ -306,14 +304,14 @@ open class TextFileStreamWriter: TextFileStream { } extension TextFile { - + /// Provide a writer to write line by line. /// /// - Parameter delimiter: the line delimiter (default: \n) /// - Parameter append: if true append at file end (default: false) /// /// - Returns: the `TextFileStreamWriter` - + public func streamWriter(_ delimiter: String = "\n", append: Bool = false) -> TextFileStreamWriter? { return TextFileStreamWriter( path: self.path, @@ -324,5 +322,3 @@ extension TextFile { } } - - From 78d69010eba8037e7f6257855c13e01f2ecad2b2 Mon Sep 17 00:00:00 2001 From: Peter IJlst Date: Tue, 28 Mar 2017 16:15:14 +0200 Subject: [PATCH 24/54] Fix capturing watcher before it is declared for swift 3.1 --- Sources/FileSystemWatcher.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index 8337e44..6cc76f4 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -43,15 +43,16 @@ public class FileSystemWatcher { eventFlags: UnsafePointer?, eventIds: UnsafePointer?) in + FileSystemWatcher.log("Callback Fired") + + let watcher: FileSystemWatcher = unsafeBitCast(contextInfo, to: FileSystemWatcher.self) + defer { if let lastEventId = eventIds?[numEvents - 1] { watcher.lastEventId = lastEventId } } - FileSystemWatcher.log("Callback Fired") - - let watcher: FileSystemWatcher = unsafeBitCast(contextInfo, to: FileSystemWatcher.self) guard let paths = unsafeBitCast(eventPaths, to: NSArray.self) as? [String], let eventFlags = eventFlags, let eventIds = eventIds else { return } From d2427f3785c33059674d6f163e11ec15abee7511 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Wed, 5 Apr 2017 00:37:34 -0400 Subject: [PATCH 25/54] Prepare 4.0.1 release --- FileKit.podspec | 2 +- FileKit.xcodeproj/project.pbxproj | 8 ++++---- README.md | 2 +- Sources/FileKit.swift | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/FileKit.podspec b/FileKit.podspec index d05abce..094f3e7 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "4.0.0" + s.version = "4.0.1" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 5a0724b..b6827c5 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -807,8 +807,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; - CURRENT_RELEASE_NUMBER = 11; - CURRENT_RELEASE_VERSION = 4.0.0; + CURRENT_RELEASE_NUMBER = 12; + CURRENT_RELEASE_VERSION = 4.0.1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -859,8 +859,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; - CURRENT_RELEASE_NUMBER = 11; - CURRENT_RELEASE_VERSION = 4.0.0; + CURRENT_RELEASE_NUMBER = 12; + CURRENT_RELEASE_VERSION = 4.0.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/README.md b/README.md index bad4047..a27cd51 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ to learn more. ```ruby use_frameworks! - pod 'FileKit', '~> 4.0.0' + pod 'FileKit', '~> 4.0.1' ``` 2. Run `pod install` and open the `.xcworkspace` file to launch Xcode. diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 7b72164..9504271 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -33,7 +33,7 @@ /// /// - Copyright: [MIT License](https://opensource.org/licenses/MIT) /// -/// - Version: [v4.0.0](https://github.com/nvzqz/FileKit/releases/tag/v4.0.0) +/// - Version: [v4.0.1](https://github.com/nvzqz/FileKit/releases/tag/v4.0.1) /// /// - Requires: Xcode 8, Swift 3.0 /// @@ -42,10 +42,10 @@ public enum FileKitInfo { /// The current version. /// /// FileKit follows [Semantic Versioning v2.0.0](http://semver.org/). - public static let version = "v4.0.0" + public static let version = "v4.0.1" /// The current release. - public static let release = 11 + public static let release = 12 /// FileKit is licensed under the [MIT License](https://opensource.org/licenses/MIT). public static let license = "MIT" From b54fabf93b99cd81285f16dbca64b5e6edf96c83 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 23 Jun 2017 14:59:57 -0400 Subject: [PATCH 26/54] Add downloads badge to README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a27cd51..de1ac05 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ alt="Carthage">
+ downloads Trello Board From 85999177271043b127f8744259fc432b32e4f177 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Tue, 12 Sep 2017 11:47:16 +0200 Subject: [PATCH 27/54] Set warning for swiftlint shorthand_operator rule --- .swiftlint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index 5e9ab88..9c0c44d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -10,6 +10,7 @@ disabled_rules: - type_name shorthand_operator: warning +superfluous_disable_command: warning # some rules are only opt-in opt_in_rules: From 73b86c74d3d8a91de0fd68095cc8cfd5f2a3d24e Mon Sep 17 00:00:00 2001 From: phimage Date: Sat, 30 Sep 2017 22:24:41 +0200 Subject: [PATCH 28/54] Convert to swift 4 Add an underlying error cause to FileKitError if any --- .swift-version | 2 +- .travis.yml | 32 ++++ FileKit.podspec | 8 +- FileKit.xcodeproj/project.pbxproj | 38 +++-- .../xcschemes/FileKit-OSX.xcscheme | 4 +- .../xcschemes/FileKit-iOS.xcscheme | 4 +- .../xcschemes/FileKit-tvOS.xcscheme | 4 +- .../xcschemes/FileKit-watchOS.xcscheme | 4 +- .../xcschemes/FileKitTests.xcscheme | 4 +- README.md | 2 +- Sources/Array+File.swift | 4 +- Sources/Data+FileKit.swift | 6 +- Sources/DataType.swift | 2 +- Sources/Dictionary+File.swift | 4 +- Sources/DispatchWatcher.swift | 45 ++---- Sources/File.swift | 2 +- Sources/FileKit.swift | 2 - Sources/FileKitError.swift | 146 ++++++++++++------ Sources/FilePermissions.swift | 2 +- Sources/FileProtection.swift | 3 +- Sources/FileSystemEvent.swift | 4 +- Sources/FileSystemWatcher.swift | 12 +- Sources/Image+FileKit.swift | 2 +- Sources/NSArray+FileKit.swift | 2 +- Sources/NSData+FileKit.swift | 4 +- Sources/NSDataFile.swift | 2 +- Sources/NSDictionary+FileKit.swift | 2 +- Sources/NSString+FileKit.swift | 2 +- Sources/Operators.swift | 41 +++-- Sources/Path.swift | 83 +++++++--- Sources/String+FileKit.swift | 13 +- Sources/TextFile.swift | 120 ++++++++------ Tests/FileKitTests.swift | 78 +++++----- 33 files changed, 419 insertions(+), 264 deletions(-) create mode 100644 .travis.yml diff --git a/.swift-version b/.swift-version index 9f55b2c..5186d07 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -3.0 +4.0 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9faa79e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: objective-c +osx_image: xcode9 +env: + global: + - LC_CTYPE=en_US.UTF-8 + - LANG=en_US.UTF-8 + - PROJECT=FileKit.xcodeproj + - IOS_FRAMEWORK_SCHEME="FileKit-iOS" + - MACOS_FRAMEWORK_SCHEME="FileKit-OSX" + - IOS_SDK=iphonesimulator11.0 + - MACOS_SDK=macosx10.13 + matrix: + - DESTINATION="OS=11.0,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" + - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK=macosx10.13 RUN_TESTS="NO" +before_install: + - gem install xcpretty --no-rdoc --no-ri --no-document --quiet +script: + - set -o pipefail + - xcodebuild -version + - xcodebuild -showsdks + + - if [ $RUN_TESTS == "YES" ]; then + xcodebuild -project "$PROJECT" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO ENABLE_TESTABILITY=YES test | xcpretty; + else + xcodebuild -project "$PROJECT" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty; + fi +after_success: + - bash <(curl -s https://codecov.io/bash) + +branches: + only: + - master diff --git a/FileKit.podspec b/FileKit.podspec index 094f3e7..c9d4af8 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,14 +1,14 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "4.0.1" + s.version = "5.0.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } s.author = "Nikolai Vazquez" - s.ios.deployment_target = "8.0" - s.osx.deployment_target = "10.9" + s.ios.deployment_target = "9.0" + s.osx.deployment_target = "10.11" s.osx.exclude_files = "FileKit/*/FileProtection.swift" - s.watchos.deployment_target = '2.0' + s.watchos.deployment_target = '3.0' s.tvos.deployment_target = '9.0' s.source = { :git => "https://github.com/nvzqz/FileKit.git", :tag => "v#{s.version}" } s.source_files = "Sources/*.swift" diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index b6827c5..5385df9 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -475,12 +475,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0820; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; 5204B8571B96B85E00AA473F = { CreatedOnToolsVersion = 7.0; @@ -488,7 +488,7 @@ }; 5263A9031B96BA3D00635A93 = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; 527612411BAEA3EE00503D0A = { CreatedOnToolsVersion = 7.0; @@ -794,14 +794,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -846,14 +852,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -897,7 +909,8 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -917,7 +930,8 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -936,7 +950,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -957,7 +971,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -971,7 +985,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -984,7 +999,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -1003,6 +1019,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 4; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -1024,6 +1041,7 @@ SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1045,6 +1063,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1066,6 +1085,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index ad871e9..ccedd16 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme index 58fdacd..4ff729e 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme index d033db9..6edcf8c 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme index 093cd80..429d643 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme @@ -1,6 +1,6 @@ @@ -31,6 +32,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/README.md b/README.md index de1ac05..5d2fd79 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ to learn more. ```ruby use_frameworks! - pod 'FileKit', '~> 4.0.1' + pod 'FileKit', '~> 5.0.0' ``` 2. Run `pod install` and open the `.xcworkspace` file to launch Xcode. diff --git a/Sources/Array+File.swift b/Sources/Array+File.swift index ea1a92d..bf26aa0 100644 --- a/Sources/Array+File.swift +++ b/Sources/Array+File.swift @@ -37,10 +37,10 @@ extension Array: ReadableWritable, WritableConvertible { /// public static func read(from path: Path) throws -> Array { guard let contents = NSArray(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(NSArray.self)) } guard let dict = contents as? Array else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(Array.self)) } return dict } diff --git a/Sources/Data+FileKit.swift b/Sources/Data+FileKit.swift index 377a67f..7f72207 100644 --- a/Sources/Data+FileKit.swift +++ b/Sources/Data+FileKit.swift @@ -35,7 +35,7 @@ extension Data: ReadableWritable { do { return try self.init(contentsOf: path.url, options: []) } catch { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: error) } } @@ -44,7 +44,7 @@ extension Data: ReadableWritable { do { return try self.init(contentsOf: path.url, options: options) } catch { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: error) } } @@ -75,7 +75,7 @@ extension Data: ReadableWritable { do { try self.write(to: path.url, options: options) } catch { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path, error: error) } } diff --git a/Sources/DataType.swift b/Sources/DataType.swift index c39c95c..ea06023 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -115,7 +115,7 @@ extension WritableToFile { /// public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { guard write(toFile: path._safeRawValue, atomically: useAuxiliaryFile) else { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path, error: FileKitError.ReasonError.conversion(type(of: self))) } } diff --git a/Sources/Dictionary+File.swift b/Sources/Dictionary+File.swift index bad7a17..8f6ed83 100644 --- a/Sources/Dictionary+File.swift +++ b/Sources/Dictionary+File.swift @@ -37,10 +37,10 @@ extension Dictionary: ReadableWritable, WritableConvertible { /// public static func read(from path: Path) throws -> Dictionary { guard let contents = NSDictionary(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(NSDictionary.self)) } guard let dict = contents as? Dictionary else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(Dictionary.self)) } return dict } diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index 8a3af6a..f99988a 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -50,44 +50,28 @@ public extension DispatchFileSystemWatcherDelegate { // MARK: - Extension /// Call when the file-system object was deleted from the namespace. - public func fsWatcherDidObserveDelete(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveDelete(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object data changed. - public func fsWatcherDidObserveWrite(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveWrite(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object changed in size. - public func fsWatcherDidObserveExtend(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveExtend(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object metadata changed. - public func fsWatcherDidObserveAttrib(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveAttrib(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object link count changed. - public func fsWatcherDidObserveLink(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveLink(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object was renamed in the namespace. - public func fsWatcherDidObserveRename(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveRename(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object was revoked. - public func fsWatcherDidObserveRevoke(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveRevoke(_ watch: DispatchFileSystemWatcher) {} /// Call when the file-system object was created. - public func fsWatcherDidObserveCreate(_ watch: DispatchFileSystemWatcher) { - - } + public func fsWatcherDidObserveCreate(_ watch: DispatchFileSystemWatcher) {} /// Call when the directory changed (additions, deletions, and renamings). /// @@ -242,7 +226,6 @@ open class DispatchFileSystemWatcher { return true } } - return false } // Only watching for regular file and directory @@ -279,11 +262,9 @@ open class DispatchFileSystemWatcher { return true } } - return false - } else { - return false } + return false } /// Stop watching. @@ -321,13 +302,13 @@ extension Path { delegate: DispatchFileSystemWatcherDelegate? = nil, callback: ((DispatchFileSystemWatcher) -> Void)? = nil ) -> DispatchFileSystemWatcher { - let dispathQueue: DispatchQueue + let dispatchQueue: DispatchQueue if #available(OSX 10.10, *) { - dispathQueue = queue ?? DispatchQueue.global(qos: .default) + dispatchQueue = queue ?? DispatchQueue.global(qos: .default) } else { - dispathQueue = queue ?? DispatchQueue.global(priority: .default) + dispatchQueue = queue ?? DispatchQueue.global(priority: .default) } - let watcher = DispatchFileSystemWatcher(path: self, events: events, queue: dispathQueue, callback: callback) + let watcher = DispatchFileSystemWatcher(path: self, events: events, queue: dispatchQueue, callback: callback) watcher.delegate = delegate watcher.startWatching() return watcher diff --git a/Sources/File.swift b/Sources/File.swift index 4b48886..3f51554 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -255,7 +255,7 @@ extension File: CustomStringConvertible { /// A textual representation of `self`. public var description: String { - return String(describing: type(of: self)) + "('" + path.description + "')" + return String(describing: Swift.type(of: self)) + "('" + path.description + "')" } } diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 9504271..04e5fb6 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -24,8 +24,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // -// swiftlint:disable line_length -// /// Information regarding [FileKit](https://github.com/nvzqz/FileKit). /// diff --git a/Sources/FileKitError.swift b/Sources/FileKitError.swift index 435936d..6eda81d 100644 --- a/Sources/FileKitError.swift +++ b/Sources/FileKitError.swift @@ -27,83 +27,143 @@ import Foundation +// MARK: FileKitError + /// An error that can be thrown by FileKit. public enum FileKitError: Error { - // MARK: FileKitError - - /// The reason for why the error occured. - public var message: String { - switch self { - case let .fileDoesNotExist(path): - return "File does not exist at \"\(path)\"" - case let .changeDirectoryFail(fromPath, toPath): - return "Could not change the directory from \"\(fromPath)\" to \"\(toPath)\"" - case let .createSymlinkFail(fromPath, toPath): - return "Could not create symlink from \"\(fromPath)\" to \"\(toPath)\"" - case let .createHardlinkFail(fromPath, toPath): - return "Could not create a hard link from \"\(fromPath)\" to \"\(toPath)\"" - case let .createFileFail(path): - return "Could not create file at \"\(path)\"" - case let .createDirectoryFail(path): - return "Could not create a directory at \"\(path)\"" - case let .deleteFileFail(path): - return "Could not delete file at \"\(path)\"" - case let .readFromFileFail(path): - return "Could not read from file at \"\(path)\"" - case let .writeToFileFail(path): - return "Could not write to file at \"\(path)\"" - case let .moveFileFail(fromPath, toPath): - return "Could not move file at \"\(fromPath)\" to \"\(toPath)\"" - case let .copyFileFail(fromPath, toPath): - return "Could not copy file from \"\(fromPath)\" to \"\(toPath)\"" - case let .attributesChangeFail(path): - return "Could not change file attrubutes at \"\(path)\"" - } - } - /// A file does not exist. case fileDoesNotExist(path: Path) + /// A file already exists at operation destination. + case fileAlreadyExists(path: Path) + /// Could not change the current directory. - case changeDirectoryFail(from: Path, to: Path) + case changeDirectoryFail(from: Path, to: Path, error: Error) /// A symbolic link could not be created. - case createSymlinkFail(from: Path, to: Path) + case createSymlinkFail(from: Path, to: Path, error: Error) /// A hard link could not be created. - case createHardlinkFail(from: Path, to: Path) + case createHardlinkFail(from: Path, to: Path, error: Error) /// A file could not be created. case createFileFail(path: Path) /// A directory could not be created. - case createDirectoryFail(path: Path) + case createDirectoryFail(path: Path, error: Error) /// A file could not be deleted. - case deleteFileFail(path: Path) + case deleteFileFail(path: Path, error: Error) /// A file could not be read from. - case readFromFileFail(path: Path) + case readFromFileFail(path: Path, error: Error) /// A file could not be written to. - case writeToFileFail(path: Path) + case writeToFileFail(path: Path, error: Error) /// A file could not be moved. - case moveFileFail(from: Path, to: Path) + case moveFileFail(from: Path, to: Path, error: Error) /// A file could not be copied. - case copyFileFail(from: Path, to: Path) + case copyFileFail(from: Path, to: Path, error: Error) /// One or many attributes could not be changed. - case attributesChangeFail(path: Path) + case attributesChangeFail(path: Path, error: Error) + + // MARK: - Reason + + /// An error that could be cause of `FileKitError` + enum ReasonError: Error { + /// Failed to read or convert to specific type. + case conversion(Any) + /// A file stream/handle is alread closed. + case closed + /// Failed to encode string using specific encoding. + case encoding(String.Encoding, data: String) + } } +// MARK: - Message +extension FileKitError { + + /// The reason for why the error occured. + public var message: String { + switch self { + case let .fileDoesNotExist(path): + return "File does not exist at \"\(path)\"" + case let .fileAlreadyExists(path): + return "File already exists at \"\(path)\"" + case let .changeDirectoryFail(fromPath, toPath, _): + return "Could not change the directory from \"\(fromPath)\" to \"\(toPath)\"" + case let .createSymlinkFail(fromPath, toPath, _): + return "Could not create symlink from \"\(fromPath)\" to \"\(toPath)\"" + case let .createHardlinkFail(fromPath, toPath, _): + return "Could not create a hard link from \"\(fromPath)\" to \"\(toPath)\"" + case let .createFileFail(path): + return "Could not create file at \"\(path)\"" + case let .createDirectoryFail(path, _): + return "Could not create a directory at \"\(path)\"" + case let .deleteFileFail(path, _): + return "Could not delete file at \"\(path)\"" + case let .readFromFileFail(path, _): + return "Could not read from file at \"\(path)\"" + case let .writeToFileFail(path, _): + return "Could not write to file at \"\(path)\"" + case let .moveFileFail(fromPath, toPath, _): + return "Could not move file at \"\(fromPath)\" to \"\(toPath)\"" + case let .copyFileFail(fromPath, toPath, _): + return "Could not copy file from \"\(fromPath)\" to \"\(toPath)\"" + case let .attributesChangeFail(path): + return "Could not change file attrubutes at \"\(path)\"" + } + } +} + +// MARK: - CustomStringConvertible extension FileKitError: CustomStringConvertible { - // MARK: - CustomStringConvertible + /// A textual representation of `self`. public var description: String { return String(describing: type(of: self)) + "(" + message + ")" } } + +// MARK: - CustomDebugStringConvertible +extension FileKitError: CustomDebugStringConvertible { + + /// A textual representation of this instance, suitable for debugging. + public var debugDescription: String { + if let error = error { + return "\(self.description) \(error)" + } + return self.description + } + +} + +// MARK: - underlying error +extension FileKitError { + + /// Return the underlying error if any + public var error: Error? { + switch self { + case .changeDirectoryFail(_, _, let error), + .createSymlinkFail(_, _, let error), + .createHardlinkFail(_, _, let error), + .createDirectoryFail(_, let error), + .deleteFileFail(_, let error), + .readFromFileFail(_, let error), + .writeToFileFail(_, let error), + .moveFileFail(_, _, let error), + .copyFileFail(_, _, let error): + return error + case .fileDoesNotExist, + .fileAlreadyExists, + .createFileFail, + .attributesChangeFail: + return nil + } + } +} diff --git a/Sources/FilePermissions.swift b/Sources/FilePermissions.swift index 5937f9c..09e02dc 100644 --- a/Sources/FilePermissions.swift +++ b/Sources/FilePermissions.swift @@ -86,7 +86,7 @@ public struct FilePermissions: OptionSet, CustomStringConvertible { /// Creates a set of permissions for `file`. /// /// - Parameter file: The file to create a set of persmissions for. - public init(forFile file: File) { + public init(forFile file: File) { self.init(forPath: file.path) } diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index 5afd968..b497074 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -121,7 +121,8 @@ extension Path { /// public func createFile(_ fileProtection: FileProtection) throws { let manager = FileManager() - let attributes = [FileAttributeKey.protectionKey.rawValue: fileProtection.rawValue] + let attributes: [FileAttributeKey : Any] = [.protectionKey: fileProtection] // todo test + if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { throw FileKitError.createFileFail(path: self) } diff --git a/Sources/FileSystemEvent.swift b/Sources/FileSystemEvent.swift index cd51b38..de424a9 100644 --- a/Sources/FileSystemEvent.swift +++ b/Sources/FileSystemEvent.swift @@ -35,10 +35,10 @@ public struct FileSystemEvent { // MARK: - Static Properties /// All of the event IDs. - static let AllEventId = 0 + public static let allEventId = 0 /// The last event ID since now. - static let NowEventId = FSEventStreamEventId(kFSEventStreamEventIdSinceNow) + public static let nowEventId = FSEventStreamEventId(kFSEventStreamEventIdSinceNow) // MARK: - Properties diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index 6cc76f4..a07b125 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -40,20 +40,18 @@ public class FileSystemWatcher { contextInfo: UnsafeMutableRawPointer?, numEvents: Int, eventPaths: UnsafeMutableRawPointer, - eventFlags: UnsafePointer?, - eventIds: UnsafePointer?) in + eventFlags: UnsafePointer, + eventIds: UnsafePointer) in FileSystemWatcher.log("Callback Fired") let watcher: FileSystemWatcher = unsafeBitCast(contextInfo, to: FileSystemWatcher.self) defer { - if let lastEventId = eventIds?[numEvents - 1] { - watcher.lastEventId = lastEventId - } + watcher.lastEventId = eventIds[numEvents - 1] } - guard let paths = unsafeBitCast(eventPaths, to: NSArray.self) as? [String], let eventFlags = eventFlags, let eventIds = eventIds else { + guard let paths = unsafeBitCast(eventPaths, to: NSArray.self) as? [String] else { return } @@ -113,7 +111,7 @@ public class FileSystemWatcher { /// - Parameter queue: The queue to be run within. /// - Parameter callback: The callback to be called on changes. public init(paths: [Path], - sinceWhen: FSEventStreamEventId = FileSystemEvent.NowEventId, + sinceWhen: FSEventStreamEventId = FileSystemEvent.nowEventId, flags: FileSystemEventStreamCreateFlags = [.UseCFTypes, .FileEvents], latency: CFTimeInterval = 0, queue: DispatchQueue? = nil, diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index c29687d..b3ea3ab 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -52,7 +52,7 @@ extension Image: ReadableWritable, WritableConvertible { /// public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(Image.self)) } return contents } diff --git a/Sources/NSArray+FileKit.swift b/Sources/NSArray+FileKit.swift index 620012f..bcb5d9c 100644 --- a/Sources/NSArray+FileKit.swift +++ b/Sources/NSArray+FileKit.swift @@ -34,7 +34,7 @@ extension NSArray: ReadableWritable, WritableToFile { /// - Parameter path: The path an array to be read from. public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(NSArray.self)) } return contents } diff --git a/Sources/NSData+FileKit.swift b/Sources/NSData+FileKit.swift index 69c5ea4..62add8e 100644 --- a/Sources/NSData+FileKit.swift +++ b/Sources/NSData+FileKit.swift @@ -32,7 +32,7 @@ extension NSData: ReadableWritable, WritableToFile { /// Returns data read from the given path. public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(NSData.self)) } return contents } @@ -42,7 +42,7 @@ extension NSData: ReadableWritable, WritableToFile { do { return try self.init(contentsOfFile: path._safeRawValue, options: options) } catch { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: error) } } diff --git a/Sources/NSDataFile.swift b/Sources/NSDataFile.swift index a9a7cc3..9807c9e 100644 --- a/Sources/NSDataFile.swift +++ b/Sources/NSDataFile.swift @@ -56,7 +56,7 @@ extension File where DataType: NSData { do { try data.write(toFile: self.path._safeRawValue, options: options) } catch { - throw FileKitError.writeToFileFail(path: self.path) + throw FileKitError.writeToFileFail(path: self.path, error: error) } } diff --git a/Sources/NSDictionary+FileKit.swift b/Sources/NSDictionary+FileKit.swift index 0dae95e..2e1c9fa 100644 --- a/Sources/NSDictionary+FileKit.swift +++ b/Sources/NSDictionary+FileKit.swift @@ -29,7 +29,7 @@ extension NSDictionary: ReadableWritable, WritableToFile { /// Returns a dictionary read from the given path. public class func read(from path: Path) throws -> Self { guard let contents = self.init(contentsOfFile: path._safeRawValue) else { - throw FileKitError.readFromFileFail(path: path) + throw FileKitError.readFromFileFail(path: path, error: FileKitError.ReasonError.conversion(NSDictionary.self)) } return contents } diff --git a/Sources/NSString+FileKit.swift b/Sources/NSString+FileKit.swift index a710e5d..b27cf60 100644 --- a/Sources/NSString+FileKit.swift +++ b/Sources/NSString+FileKit.swift @@ -60,7 +60,7 @@ extension NSString: Writable { atomically: useAuxiliaryFile, encoding: String.Encoding.utf8.rawValue) } catch { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path, error: error) } } diff --git a/Sources/Operators.swift b/Sources/Operators.swift index 93d4c7a..6ef9cfb 100644 --- a/Sources/Operators.swift +++ b/Sources/Operators.swift @@ -29,7 +29,7 @@ import Foundation -fileprivate func < (lhs: T?, rhs: T?) -> Bool { +private func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l < r @@ -44,13 +44,13 @@ fileprivate func < (lhs: T?, rhs: T?) -> Bool { /// Returns `true` if both files' paths are the same. -public func ==(lhs: File, rhs: File) -> Bool { +public func ==(lhs: File, rhs: File) -> Bool { return lhs.path == rhs.path } /// Returns `true` if `lhs` is smaller than `rhs` in size. -public func < (lhs: File, rhs: File) -> Bool { +public func < (lhs: File, rhs: File) -> Bool { return lhs.size < rhs.size } @@ -60,7 +60,7 @@ infix operator |> /// /// - Throws: `FileKitError.WriteToFileFail` /// -public func |> (data: DataType, file: File) throws { +public func |> (data: DataType, file: File) throws { try file.write(data) } @@ -82,12 +82,17 @@ infix operator |>> /// - Throws: `FileKitError.WriteToFileFail` /// public func |>> (data: String, file: TextFile) throws { - // TODO use TextFileStreamWritter - var data = data - if let contents = try? file.read() { - data = contents + "\n" + data + let textStreamWriter = try file.streamWriter(append: true) + + guard textStreamWriter.writeDelimiter(), textStreamWriter.write(line: data, delim: false) else { + let reason: FileKitError.ReasonError + if textStreamWriter.isClosed { + reason = .closed + } else { + reason = .encoding(textStreamWriter.encoding, data: data) + } + throw FileKitError.writeToFileFail(path: file.path, error: reason) } - try data |> file } /// Return lines of file that match the motif. @@ -107,7 +112,7 @@ infix operator |~ /// Return lines of file that match the regex motif. public func |~ (file: TextFile, motif: String) -> [String] { - return file.grep(motif, options: NSString.CompareOptions.regularExpression) + return file.grep(motif, options: .regularExpression) } // MARK: - Path @@ -142,7 +147,7 @@ public func + (lhs: Path, rhs: Path) -> Path { if rhs.rawValue.isEmpty || rhs.rawValue == "." { return lhs } switch (lhs.rawValue.hasSuffix(Path.separator), rhs.rawValue.hasPrefix(Path.separator)) { case (true, true): - let rhsRawValue = rhs.rawValue.substring(from: rhs.rawValue.characters.index(after: rhs.rawValue.startIndex)) + let rhsRawValue = rhs.dropFirst() return Path("\(lhs.rawValue)\(rhsRawValue)") case (false, false): return Path("\(lhs.rawValue)\(Path.separator)\(rhs.rawValue)") @@ -165,11 +170,13 @@ public func + (lhs: Path, rhs: String) -> Path { /// Appends the right path to the left path. public func += (lhs: inout Path, rhs: Path) { + // swiftlint:disable:next shorthand_operator lhs = lhs + rhs } /// Appends the path value of the String to the left path. public func += (lhs: inout Path, rhs: String) { + // swiftlint:disable:next shorthand_operator lhs = lhs + rhs } @@ -240,7 +247,7 @@ public func ->> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.MoveFileFail` /// -public func ->> (lhs: File, rhs: Path) throws { +public func ->> (lhs: File, rhs: Path) throws { try lhs.move(to: rhs) } @@ -271,7 +278,7 @@ public func ->! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func ->! (lhs: File, rhs: Path) throws { +public func ->! (lhs: File, rhs: Path) throws { if rhs.isAny { try rhs.deleteFile() } @@ -298,7 +305,7 @@ public func +>> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CopyFileFail` /// -public func +>> (lhs: File, rhs: Path) throws { +public func +>> (lhs: File, rhs: Path) throws { try lhs.copy(to: rhs) } @@ -329,7 +336,7 @@ public func +>! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func +>! (lhs: File, rhs: Path) throws { +public func +>! (lhs: File, rhs: Path) throws { if rhs.isAny { try rhs.deleteFile() } @@ -364,7 +371,7 @@ public func =>> (lhs: Path, rhs: Path) throws { /// /// - Throws: `FileKitError.FileDoesNotExist`, `FileKitError.CreateSymlinkFail` /// -public func =>> (lhs: File, rhs: Path) throws { +public func =>> (lhs: File, rhs: Path) throws { try lhs.symlink(to: rhs) } @@ -401,7 +408,7 @@ public func =>! (lhs: Path, rhs: Path) throws { /// `FileKitError.FileDoesNotExist`, /// `FileKitError.CreateSymlinkFail` /// -public func =>! (lhs: File, rhs: Path) throws { +public func =>! (lhs: File, rhs: Path) throws { try lhs.path =>! rhs } diff --git a/Sources/Path.swift b/Sources/Path.swift index 34bd542..263eacd 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -418,11 +418,10 @@ extension Path { let minCount = Swift.min(selfComponents.count, pathComponents.count) var total = minCount - for index in 0 ..< total { - if selfComponents[index].rawValue != pathComponents[index].rawValue { + for index in 0 ..< total + where selfComponents[index].rawValue != pathComponents[index].rawValue { total = index break - } } let ancestorComponents = selfComponents[0.. FileHandle { + switch mode { + case .read: + do { + return try FileHandle(forReadingFrom: absolute.url) + } catch { + throw FileKitError.readFromFileFail(path: self, error: error) + } + case .write: + do { + return try FileHandle(forWritingTo: absolute.url) + } catch { + throw FileKitError.writeToFileFail(path: self, error: error) + } + case .update: + do { + return try FileHandle(forUpdating: absolute.url) + } catch { + throw FileKitError.writeToFileFail(path: self, error: error) + } + } + } + +} + extension Path { // MARK: - NSStream diff --git a/Sources/String+FileKit.swift b/Sources/String+FileKit.swift index dc74f8f..280b483 100644 --- a/Sources/String+FileKit.swift +++ b/Sources/String+FileKit.swift @@ -34,13 +34,12 @@ extension String: ReadableWritable { /// Creates a string from a path. public static func read(from path: Path) throws -> String { - let possibleContents = try? String( - contentsOfFile: path._safeRawValue, - encoding: ReadableWritableStringEncoding) - guard let contents = possibleContents else { - throw FileKitError.readFromFileFail(path: path) + do { + return try String(contentsOfFile: path._safeRawValue, + encoding: ReadableWritableStringEncoding) + } catch { + throw FileKitError.readFromFileFail(path: path, error: error) } - return contents } /// Writes the string to a path atomically. @@ -65,7 +64,7 @@ extension String: ReadableWritable { atomically: useAuxiliaryFile, encoding: ReadableWritableStringEncoding) } catch { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path, error: error) } } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 5e97e92..2cd9311 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -66,7 +66,7 @@ open class TextFile: File { do { try data.write(toFile: path._safeRawValue, atomically: useAuxiliaryFile, encoding: encoding) } catch { - throw FileKitError.writeToFileFail(path: path) + throw FileKitError.writeToFileFail(path: path, error: error) } } @@ -82,10 +82,12 @@ extension TextFile { /// - Parameter chunkSize: size of buffer (default: 4096) /// /// - Returns: the `TextFileStreamReader` - + /// + /// - Throws: + /// `FileKitError.readFromFileFail` public func streamReader(_ delimiter: String = "\n", - chunkSize: Int = 4096) -> TextFileStreamReader? { - return TextFileStreamReader( + chunkSize: Int = 4096) throws -> TextFileStreamReader { + return try TextFileStreamReader( path: self.path, delimiter: delimiter, encoding: encoding, @@ -101,8 +103,8 @@ extension TextFile { /// /// - Returns: the lines public func grep(_ motif: String, include: Bool = true, - options: NSString.CompareOptions = []) -> [String] { - guard let reader = streamReader() else { + options: String.CompareOptions = []) -> [String] { + guard let reader = try? streamReader() else { return [] } defer { @@ -119,21 +121,18 @@ open class TextFileStream { /// The text encoding. open let encoding: String.Encoding - let delimData: Data! + let delimData: Data var fileHandle: FileHandle? // MARK: - Initialization - public init?( + public init( fileHandle: FileHandle, - delimiter: String, + delimiter: Data, encoding: String.Encoding = .utf8 - ) { + ) throws { self.encoding = encoding self.fileHandle = fileHandle - guard let delimData = delimiter.data(using: encoding) else { - return nil - } - self.delimData = delimData + self.delimData = delimiter } // MARK: - Deinitialization @@ -157,6 +156,11 @@ open class TextFileStream { fileHandle?.closeFile() fileHandle = nil } + + /// Return true if file handle closed. + open var isClosed: Bool { + return fileHandle == nil + } } /// A class to read `TextFile` line by line. @@ -168,7 +172,7 @@ open class TextFileStreamReader: TextFileStream { /// Tells if the position is at the end of file. open var atEOF: Bool = false - let buffer: NSMutableData! + var buffer: Data! // MARK: - Initialization @@ -176,20 +180,20 @@ open class TextFileStreamReader: TextFileStream { /// - Parameter delimiter: the line delimiter (default: \n) /// - Parameter encoding: file encoding (default: .utf8) /// - Parameter chunkSize: size of buffer (default: 4096) - public init?( + public init( path: Path, delimiter: String = "\n", encoding: String.Encoding = .utf8, chunkSize: Int = 4096 - ) { + ) throws { self.chunkSize = chunkSize - guard let fileHandle = path.fileHandleForReading, - let buffer = NSMutableData(capacity: chunkSize) else { - self.buffer = nil - return nil + let fileHandle = try path.fileHandle(for: .read) + self.buffer = Data(capacity: chunkSize) + + guard let delimData = delimiter.data(using: encoding) else { + throw FileKitError.ReasonError.encoding(encoding, data: delimiter) } - self.buffer = buffer - super.init(fileHandle: fileHandle, delimiter: delimiter, encoding: encoding) + try super.init(fileHandle: fileHandle, delimiter: delimData, encoding: encoding) } // MARK: - public methods @@ -201,40 +205,39 @@ open class TextFileStreamReader: TextFileStream { } // Read data chunks from file until a line delimiter is found. - var range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) - while range.location == NSNotFound { - let tmpData = fileHandle?.readData(ofLength: chunkSize) - if tmpData == nil || tmpData!.isEmpty { + var range = buffer.range(of: delimData, options: [], in: 0.. 0 { + if !buffer.isEmpty { // Buffer contains last line in file (not terminated by delimiter). - let line = NSString(data: buffer as Data, encoding: encoding.rawValue) + let line = String(data: buffer, encoding: encoding) - buffer.length = 0 - return line as String? + buffer.count = 0 + return line } // No more lines. return nil } - buffer.append(tmpData!) - range = buffer.range(of: delimData, options: [], in: NSRange(location: 0, length: buffer.length)) + buffer.append(tmpData) + range = buffer.range(of: delimData, options: [], in: 0.. = 0.. Bool { + if let handle = fileHandle { + handle.write(delimData) + return true + } + return false + } + /// Causes all in-memory data and attributes of the file represented by the receiver to be written to permanent storage. open func synchronize() { fileHandle?.synchronizeFile() @@ -311,9 +330,12 @@ extension TextFile { /// - Parameter append: if true append at file end (default: false) /// /// - Returns: the `TextFileStreamWriter` - - public func streamWriter(_ delimiter: String = "\n", append: Bool = false) -> TextFileStreamWriter? { - return TextFileStreamWriter( + /// + /// - Throws: + /// `FileKitError.CreateFileFail`, + /// `FileKitError.writeToFileFail` + public func streamWriter(_ delimiter: String = "\n", append: Bool = false) throws -> TextFileStreamWriter { + return try TextFileStreamWriter( path: self.path, delimiter: delimiter, encoding: encoding, diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index cdf1f28..9b9de4a 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -186,7 +186,7 @@ class FileKitTests: XCTestCase { let p: Path = Path.userTemporary let children = p.children() - guard let child = children.first else { + guard let child = children.first else { XCTFail("No child into \(p)") return } @@ -226,18 +226,18 @@ class FileKitTests: XCTestCase { } for p in [a, b] { - print(p.creationDate) - print(p.modificationDate) - print(p.ownerName) - print(p.ownerID) - print(p.groupName) - print(p.groupID) - print(p.extensionIsHidden) - print(p.posixPermissions) - print(p.fileReferenceCount) - print(p.fileSize) - print(p.filesystemFileNumber) - print(p.fileType) + print(String(describing: p.creationDate)) + print(String(describing: p.modificationDate)) + print(String(describing: p.ownerName)) + print(String(describing: p.ownerID)) + print(String(describing: p.groupName)) + print(String(describing: p.groupID)) + print(String(describing: p.extensionIsHidden)) + print(String(describing: p.posixPermissions)) + print(String(describing: p.fileReferenceCount)) + print(String(describing: p.fileSize)) + print(String(describing: p.filesystemFileNumber)) + print(String(describing: p.fileType)) print("") } } @@ -530,7 +530,7 @@ class FileKitTests: XCTestCase { try text |>> textFile contents = try textFile.read() - XCTAssertTrue(contents.hasSuffix(text + "\n" + text)) + XCTAssertTrue(contents.hasSuffix("\(text)\n\(text)")) } catch { XCTFail(String(describing: error)) @@ -546,21 +546,17 @@ class FileKitTests: XCTestCase { ] let separator = "\n" try expectedLines.joined(separator: separator) |> textFile - - if let reader = textFile.streamReader() { - defer { - reader.close() - } - var lines = [String]() - for line in reader { - lines.append(line) - } - XCTAssertEqual(expectedLines, lines) - - } else { - XCTFail("Failed to create reader") + + let reader = try textFile.streamReader() + defer { + reader.close() } - + var lines = [String]() + for line in reader { + lines.append(line) + } + XCTAssertEqual(expectedLines, lines) + } catch { XCTFail(String(describing: error)) } @@ -617,23 +613,19 @@ class FileKitTests: XCTestCase { ] let separator = "\n" - if let writer = textFile.streamWriter(separator) { - defer { - writer.close() - } - for line in lines { - let delim = line != lines.last - writer.write(line: line, delim: delim) - } - - let expected = try textFile.read() - let expectedLines = expected.components(separatedBy: separator) - XCTAssertEqual(expectedLines, lines) - - } else { - XCTFail("Failed to create writer") + let writer = try textFile.streamWriter(separator) + defer { + writer.close() + } + for line in lines { + let delim = line != lines.last + writer.write(line: line, delim: delim) } + let expected = try textFile.read() + let expectedLines = expected.components(separatedBy: separator) + XCTAssertEqual(expectedLines, lines) + } catch { XCTFail(String(describing: error)) } From 399ace45affcc5a771285ea3a58e43e92dccf6ca Mon Sep 17 00:00:00 2001 From: phimage Date: Sun, 1 Oct 2017 00:09:30 +0200 Subject: [PATCH 29/54] Allow to write and read Codable objects for Path/File #50 --- FileKit.xcodeproj/project.pbxproj | 30 ++++++++++- Sources/FileKit.swift | 52 ++++++++++++++++++- Sources/ImageFile.swift | 3 ++ Sources/JSONType.swift | 64 ++++++++++++++++++++++++ Sources/PropertyListType.swift | 64 ++++++++++++++++++++++++ Tests/FileKitTests.swift | 83 +++++++++++++++++++++++++++++++ 6 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 Sources/JSONType.swift create mode 100644 Sources/PropertyListType.swift diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 5385df9..31c607e 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -114,6 +114,14 @@ 52BF6BB21B99322000F07E13 /* FileKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BF6BB01B99322000F07E13 /* FileKitError.swift */; }; 82F4F2BD1CA95480002C8393 /* FileSystemWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */; }; 82F4F2C01CA956F2002C8393 /* FileSystemEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */; }; + C411910C1F804C8300978BA4 /* JSONType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41191091F804A6000978BA4 /* JSONType.swift */; }; + C411910D1F804C8300978BA4 /* JSONType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41191091F804A6000978BA4 /* JSONType.swift */; }; + C411910E1F804C8300978BA4 /* JSONType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41191091F804A6000978BA4 /* JSONType.swift */; }; + C411910F1F804C8400978BA4 /* JSONType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41191091F804A6000978BA4 /* JSONType.swift */; }; + C41191101F804C8600978BA4 /* PropertyListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C411910A1F804A6000978BA4 /* PropertyListType.swift */; }; + C41191111F804C8600978BA4 /* PropertyListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C411910A1F804A6000978BA4 /* PropertyListType.swift */; }; + C41191131F804C8700978BA4 /* PropertyListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C411910A1F804A6000978BA4 /* PropertyListType.swift */; }; + C41191141F804C8800978BA4 /* PropertyListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C411910A1F804A6000978BA4 /* PropertyListType.swift */; }; C41FC73A1D9BDCB400C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; C41FC73B1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; C41FC73C1D9BDCD100C3A0F1 /* Data+FileKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */; }; @@ -185,6 +193,8 @@ 82F4F2BB1CA94DEC002C8393 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 82F4F2BC1CA95480002C8393 /* FileSystemWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemWatcher.swift; sourceTree = ""; }; 82F4F2BF1CA956F2002C8393 /* FileSystemEventStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSystemEventStream.swift; sourceTree = ""; }; + C41191091F804A6000978BA4 /* JSONType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONType.swift; sourceTree = ""; }; + C411910A1F804A6000978BA4 /* PropertyListType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyListType.swift; sourceTree = ""; }; C41FC7391D9BDCB400C3A0F1 /* Data+FileKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+FileKit.swift"; sourceTree = ""; }; C41FC73E1D9BE44A00C3A0F1 /* Dictionary+File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+File.swift"; sourceTree = ""; }; C41FC7401D9BE4DB00C3A0F1 /* DataFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataFile.swift; sourceTree = ""; }; @@ -270,9 +280,10 @@ 52255DCA1C042D6E00AC1DA5 /* FilePermissions.swift */, 52A016C31C013F3D0045A9C8 /* DirectoryEnumerator.swift */, 523C33981B9B764600AB70E4 /* DataType.swift */, + C411910B1F804A9000978BA4 /* Codable Types */, + 52F3AFA71CDFB48600C2BBBD /* File Types */, 52BF6BB01B99322000F07E13 /* FileKitError.swift */, 523C33A61B9B894A00AB70E4 /* Operators.swift */, - 52F3AFA71CDFB48600C2BBBD /* File Types */, 52F3AFA61CDFB46300C2BBBD /* Watching */, 52F3AFA51CDFB45100C2BBBD /* Extensions */, ); @@ -340,6 +351,15 @@ name = "File Types"; sourceTree = ""; }; + C411910B1F804A9000978BA4 /* Codable Types */ = { + isa = PBXGroup; + children = ( + C41191091F804A6000978BA4 /* JSONType.swift */, + C411910A1F804A6000978BA4 /* PropertyListType.swift */, + ); + name = "Codable Types"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -634,6 +654,7 @@ 82F4F2C01CA956F2002C8393 /* FileSystemEventStream.swift in Sources */, 52A016C41C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, 524D315F1BC7A02A008B93D0 /* Image+FileKit.swift in Sources */, + C411910C1F804C8300978BA4 /* JSONType.swift in Sources */, C41FC73F1D9BE44A00C3A0F1 /* Dictionary+File.swift in Sources */, 524D315B1BC79331008B93D0 /* NSDataFile.swift in Sources */, 520E0E301C110CA900BAEA99 /* Process+FileKit.swift in Sources */, @@ -642,6 +663,7 @@ C41FC7411D9BE4DB00C3A0F1 /* DataFile.swift in Sources */, 52A017001C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, 52A016F61C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, + C41191131F804C8700978BA4 /* PropertyListType.swift in Sources */, C41FC7461D9BEEC000C3A0F1 /* Array+File.swift in Sources */, 52B938C91BF402ED001B7AEB /* ImageFile.swift in Sources */, 17217D5E1CDCD74000723D11 /* DispatchEvent.swift in Sources */, @@ -673,12 +695,14 @@ 524D315C1BC79331008B93D0 /* NSDataFile.swift in Sources */, 52A0170B1C01D5400045A9C8 /* FileType.swift in Sources */, 523C33A81B9B894A00AB70E4 /* Operators.swift in Sources */, + C411910D1F804C8300978BA4 /* JSONType.swift in Sources */, C41FC74D1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, C41FC7471D9BEEF300C3A0F1 /* Array+File.swift in Sources */, 52A017111C024D840045A9C8 /* NSString+FileKit.swift in Sources */, 520E0E311C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 523C33791B9A7EFC00AB70E4 /* TextFile.swift in Sources */, 52A017011C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, + C41191141F804C8800978BA4 /* PropertyListType.swift in Sources */, 5263A8FD1B96B94D00635A93 /* Path.swift in Sources */, 52A016C51C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, 524D31601BC7A02A008B93D0 /* Image+FileKit.swift in Sources */, @@ -718,12 +742,14 @@ 524D315D1BC79331008B93D0 /* NSDataFile.swift in Sources */, 52A0170C1C01D5400045A9C8 /* FileType.swift in Sources */, 5276124D1BAEA43600503D0A /* DictionaryFile.swift in Sources */, + C411910E1F804C8300978BA4 /* JSONType.swift in Sources */, C41FC74C1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, C41FC74A1D9BEEF400C3A0F1 /* Array+File.swift in Sources */, 52A017121C024D840045A9C8 /* NSString+FileKit.swift in Sources */, 520E0E321C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 5276124B1BAEA43600503D0A /* File.swift in Sources */, 52A017021C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, + C41191111F804C8600978BA4 /* PropertyListType.swift in Sources */, 5276124C1BAEA43600503D0A /* TextFile.swift in Sources */, 52A016C61C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, 524D31611BC7A02A008B93D0 /* Image+FileKit.swift in Sources */, @@ -755,12 +781,14 @@ 52B938C41BF3C42A001B7AEB /* Operators.swift in Sources */, 52A016F41C0184CA0045A9C8 /* FileProtection.swift in Sources */, 52B938BD1BF3C42A001B7AEB /* TextFile.swift in Sources */, + C411910F1F804C8400978BA4 /* JSONType.swift in Sources */, C41FC74B1D9BF05A00C3A0F1 /* Dictionary+File.swift in Sources */, C41FC7491D9BEEF400C3A0F1 /* Array+File.swift in Sources */, 52B938C11BF3C42A001B7AEB /* Path.swift in Sources */, 52A016F91C01ACE50045A9C8 /* NSDictionary+FileKit.swift in Sources */, 52A0170D1C01D5400045A9C8 /* FileType.swift in Sources */, 52B938BE1BF3C42A001B7AEB /* DictionaryFile.swift in Sources */, + C41191101F804C8600978BA4 /* PropertyListType.swift in Sources */, 520E0E331C110CA900BAEA99 /* Process+FileKit.swift in Sources */, 52A017031C01AD4A0045A9C8 /* NSData+FileKit.swift in Sources */, 52A016C71C013F3D0045A9C8 /* DirectoryEnumerator.swift in Sources */, diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 04e5fb6..5fde029 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -40,7 +40,7 @@ public enum FileKitInfo { /// The current version. /// /// FileKit follows [Semantic Versioning v2.0.0](http://semver.org/). - public static let version = "v4.0.1" + public static let version = "v5.0.0" /// The current release. public static let release = 12 @@ -55,3 +55,53 @@ public enum FileKitInfo { public static let projectURL = "https://github.com/nvzqz/FileKit" } + +import Foundation + +public struct FileKit { + + /// Shared json decoder instance + public static var jsonDecoder = JSONDecoder() + /// Shared json encoder instance + public static var jsonEncoder = JSONEncoder() + /// Shared property list decoder instance + public static var propertyListDecoder = PropertyListDecoder() + /// Shared property list encoder instance + public static var propertyListEncoder = PropertyListEncoder() + +} + +extension FileKit { + + /// Write an `Encodable` object to path + /// + /// - Parameter codable: The codable object to write. + /// - Parameter path: The destination path for write operation. + /// - Parameter encoder: A specific JSON encoder (default: FileKit.jsonEncoder). + /// + public static func write(_ codable: T, to path: Path, with encoder: JSONEncoder = FileKit.jsonEncoder) throws { + do { + let data = try encoder.encode(codable) + try DataFile(path: path).write(data) + } catch let error as FileKitError { + throw error + } catch { + throw FileKitError.writeToFileFail(path: path, error: error) + } + } + + /// Read an `Encodable` object from path + /// + /// - Parameter path: The destination path for write operation. + /// - Parameter decoder: A specific JSON decoder (default: FileKit.jsonDecoder). + /// + public static func read(from path: Path, with decoder: JSONDecoder = FileKit.jsonDecoder) throws -> T { + let data = try DataFile(path: path).read() + do { + return try decoder.decode(T.self, from: data) + } catch { + throw FileKitError.readFromFileFail(path: path, error: error) + } + } + +} diff --git a/Sources/ImageFile.swift b/Sources/ImageFile.swift index a12f2b0..68a9701 100644 --- a/Sources/ImageFile.swift +++ b/Sources/ImageFile.swift @@ -27,7 +27,10 @@ import Foundation +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) /// A representation of a filesystem image file. /// /// The data type is Image. public typealias ImageFile = File + +#endif diff --git a/Sources/JSONType.swift b/Sources/JSONType.swift new file mode 100644 index 0000000..4cdb738 --- /dev/null +++ b/Sources/JSONType.swift @@ -0,0 +1,64 @@ +// +// JSONFile.swift +// FileKit +// +// Created by phimage on 30/09/2017. +// Copyright © 2017 Nikolai Vazquez. All rights reserved. +// + +import Foundation + +// MARK: JSONReadable + +/// A JSON readable object is `Decodable`and provide it`s own decoder +public protocol JSONReadable: Readable, Decodable { + static var jsonDecoder: JSONDecoder { get } +} +extension JSONReadable { + // default implementation return the shared one + public static var jsonDecoder: JSONDecoder { + return FileKit.jsonDecoder + } +} +// Implement Readable +extension JSONReadable { + + /// Read a Decodable object + public static func read(from path: Path) throws -> Self { + let data = try DataFile(path: path).read() + do { + return try jsonDecoder.decode(self, from: data) + } catch { + throw FileKitError.readFromFileFail(path: path, error: error) + } + } + +} + +// MARK: JSONWritable + +/// A JSON readable object is `Decodable`and provide it`s own decoder +public protocol JSONWritable: Writable, Encodable { + var jsonEncoder: JSONEncoder { get } +} +extension JSONWritable { + // default implementation return the shared one + public var jsonEncoder: JSONEncoder { + return FileKit.jsonEncoder + } +} +// Implement Writable +extension JSONWritable { + + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + do { + let data = try jsonEncoder.encode(self) + try DataFile(path: path).write(data, atomically: useAuxiliaryFile) + } catch let error as FileKitError { + throw error + } catch { + throw FileKitError.writeToFileFail(path: path, error: error) + } + } + +} diff --git a/Sources/PropertyListType.swift b/Sources/PropertyListType.swift new file mode 100644 index 0000000..8950130 --- /dev/null +++ b/Sources/PropertyListType.swift @@ -0,0 +1,64 @@ +// +// PropertyListFile.swift +// FileKit +// +// Created by phimage on 30/09/2017. +// Copyright © 2017 Nikolai Vazquez. All rights reserved. +// + +import Foundation + +// MARK: PropertyListReadable + +/// A PropertyList readable object is `Decodable`and provide it`s own decoder +public protocol PropertyListReadable: Readable, Decodable { + static var propertyListDecoder: PropertyListDecoder { get } +} +extension PropertyListReadable { + // default implementation return the shared one + public static var propertyListDecoder: PropertyListDecoder { + return FileKit.propertyListDecoder + } +} +// Implement Readable +extension PropertyListReadable { + + /// Read a Decodable object + public static func read(from path: Path) throws -> Self { + let data = try DataFile(path: path).read() + do { + return try propertyListDecoder.decode(self, from: data) + } catch { + throw FileKitError.readFromFileFail(path: path, error: error) + } + } + +} + +// MARK: PropertyListWritable + +/// A PropertyList readable object is `Decodable`and provide it`s own decoder +public protocol PropertyListWritable: Writable, Encodable { + var propertyListEncoder: PropertyListEncoder { get } +} +extension PropertyListWritable { + // default implementation return the shared one + public var propertyListEncoder: PropertyListEncoder { + return FileKit.propertyListEncoder + } +} +// Implement Writable +extension PropertyListWritable { + + public func write(to path: Path, atomically useAuxiliaryFile: Bool) throws { + do { + let data = try propertyListEncoder.encode(self) + try DataFile(path: path).write(data, atomically: useAuxiliaryFile) + } catch let error as FileKitError { + throw error + } catch { + throw FileKitError.writeToFileFail(path: path, error: error) + } + } + +} diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 9b9de4a..49d2dab 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -847,4 +847,87 @@ class FileKitTests: XCTestCase { operation() self.waitForExpectations(timeout: 10, handler: nil) } + + // MARK: - Codable + + func testJSONCodable() { + let encodable = TestJSONCodable(string: "test", integer: 9) + let path: Path = .userTemporary + "testcodable.json" + let codableFile = File(path: path) + + do { + try codableFile.write(encodable) + let decodable: TestJSONCodable = try codableFile.read() + XCTAssertEqual(decodable, encodable) + } catch { + XCTFail(String(describing: error)) + } + } + + func testCodable() { + let encodable = TestCodable(string: "test", integer: 9) + let path: Path = .userTemporary + "testcodable.plist" + + do { + try FileKit.write(encodable, to: path) + let decodable: TestCodable = try FileKit.read(from: path) + XCTAssertEqual(decodable, encodable) + } catch { + XCTFail(String(describing: error)) + } + } + + func testCodableArray() { + let encodable = [TestCodable(string: "test", integer: 9), TestCodable(string: "test3", integer: 8)] + let path: Path = .userTemporary + "testcodablearray.plist" + + do { + try FileKit.write(encodable, to: path) + let decodable: [TestCodable] = try FileKit.read(from: path) + XCTAssertEqual(decodable, encodable) + } catch { + XCTFail(String(describing: error)) + } + } + +} + +// MARK: Test objects + +struct TestCodable: Codable { + let string: String + let integer: Int } + +extension TestCodable: Equatable { + static func == (l: TestCodable, r: TestCodable) -> Bool { + return l.string == r.string && l.integer == r.integer + } +} + +struct TestJSONCodable: Codable { + let string: String + let integer: Int +} + +extension TestJSONCodable: JSONWritable, JSONReadable {} + +extension TestJSONCodable: Equatable { + static func == (l: TestJSONCodable, r: TestJSONCodable) -> Bool { + return l.string == r.string && l.integer == r.integer + } +} + +struct TestPropertyListCodable: Codable { + let string: String + let integer: Int +} + +extension TestPropertyListCodable: PropertyListWritable, PropertyListReadable {} + +extension TestPropertyListCodable: Equatable { + static func == (l: TestPropertyListCodable, r: TestPropertyListCodable) -> Bool { + return l.string == r.string && l.integer == r.integer + } +} + From 93505a1ad04b4a2de01abd751ace4f05c6db16a5 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sat, 30 Sep 2017 21:37:20 -0400 Subject: [PATCH 30/54] Update Xcode version requirement in FileKitInfo Also updated link to latest FileKit version. --- Sources/FileKit.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/FileKit.swift b/Sources/FileKit.swift index 5fde029..e846666 100644 --- a/Sources/FileKit.swift +++ b/Sources/FileKit.swift @@ -31,9 +31,9 @@ /// /// - Copyright: [MIT License](https://opensource.org/licenses/MIT) /// -/// - Version: [v4.0.1](https://github.com/nvzqz/FileKit/releases/tag/v4.0.1) +/// - Version: [v5.0.0](https://github.com/nvzqz/FileKit/releases/tag/v4.0.0) /// -/// - Requires: Xcode 8, Swift 3.0 +/// - Requires: Xcode 9, Swift 4.0 /// public enum FileKitInfo { From ed5b84cad633d2d45b241bab02622ac55dddaa93 Mon Sep 17 00:00:00 2001 From: phimage Date: Sat, 18 Nov 2017 20:18:45 +0100 Subject: [PATCH 31/54] Update README for Encodable/Decodable methods --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 5d2fd79..046b280 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,23 @@ The `DataFile` class allows for reading and writing `Data` to a file. Although it is a subclass of `File`, `DataFile` offers some functionality that `File` doesn't. You could specify `Data.ReadingOptions` and `Data.WritingOptions` +#### Encodable/Decodable + +You can use any `Codable` object with `File`. + +```swift +let codableFile = File(path: path) +try codableFile.write(toEncode) +let decoded: AnyCodableClass = try codableFile.read() +``` + +Alternatively you can use utility methods + +```swift +try FileKit.write(toEncode, to: path) +let decoded: AnyCodableClass = try FileKit.read(from: path) +``` + ### File Permissions The `FilePermissions` struct allows for seeing the permissions of the current From 268c6e27277dcf67c8f5c10b75b1f85460ef87d1 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Wed, 17 Jan 2018 09:11:31 +0100 Subject: [PATCH 32/54] swiftlint: fix colon violation --- Sources/FileProtection.swift | 2 +- Sources/Path.swift | 4 ++-- Sources/TextFile.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/FileProtection.swift b/Sources/FileProtection.swift index b497074..e7aac84 100644 --- a/Sources/FileProtection.swift +++ b/Sources/FileProtection.swift @@ -121,7 +121,7 @@ extension Path { /// public func createFile(_ fileProtection: FileProtection) throws { let manager = FileManager() - let attributes: [FileAttributeKey : Any] = [.protectionKey: fileProtection] // todo test + let attributes: [FileAttributeKey: Any] = [.protectionKey: fileProtection] // todo test if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { throw FileKitError.createFileFail(path: self) diff --git a/Sources/Path.swift b/Sources/Path.swift index 263eacd..61de950 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -822,14 +822,14 @@ extension Path { /// Returns the path's attributes. /// /// this method does not follow links. - public var attributes: [FileAttributeKey : Any] { + public var attributes: [FileAttributeKey: Any] { return (try? _fmWraper.fileManager.attributesOfItem(atPath: _safeRawValue)) ?? [:] } /// Modify attributes /// /// this method does not follow links. - fileprivate func _setAttributes(_ attributes: [FileAttributeKey : Any]) throws { + fileprivate func _setAttributes(_ attributes: [FileAttributeKey: Any]) throws { do { try _fmWraper.fileManager.setAttributes(attributes, ofItemAtPath: self._safeRawValue) } catch { diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index 2cd9311..b9b00f9 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -244,7 +244,7 @@ open class TextFileStreamReader: TextFileStream { } // Implement `SequenceType` for `TextFileStreamReader` -extension TextFileStreamReader : Sequence { +extension TextFileStreamReader: Sequence { /// - Returns: An iterator to be used for iterating over a `TextFileStreamReader` object. public func makeIterator() -> AnyIterator { return AnyIterator { From 7521741d10b9e4c9b3eb1501191652f821eb3142 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Tue, 22 May 2018 13:18:17 +0200 Subject: [PATCH 33/54] Update to Xcode 9.3 and swift 4.1 --- .swift-version | 2 +- FileKit.podspec | 2 +- FileKit.xcodeproj/project.pbxproj | 6 +++++- .../xcshareddata/xcschemes/FileKit-OSX.xcscheme | 4 +--- .../xcshareddata/xcschemes/FileKit-iOS.xcscheme | 4 +--- .../xcshareddata/xcschemes/FileKit-tvOS.xcscheme | 4 +--- .../xcshareddata/xcschemes/FileKit-watchOS.xcscheme | 4 +--- .../xcshareddata/xcschemes/FileKitTests.xcscheme | 8 +++----- Sources/Path.swift | 8 ++++---- 9 files changed, 18 insertions(+), 24 deletions(-) diff --git a/.swift-version b/.swift-version index 5186d07..7d5c902 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.0 +4.1 diff --git a/FileKit.podspec b/FileKit.podspec index c9d4af8..3472a3f 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "5.0.0" + s.version = "5.1.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 31c607e..0f8c20c 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -495,7 +495,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0930; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { @@ -826,12 +826,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -884,12 +886,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index ccedd16..44b344c 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ @@ -37,7 +36,6 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme index 4ff729e..3b0d38c 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-tvOS.xcscheme @@ -1,6 +1,6 @@ @@ -37,7 +36,6 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme index 6edcf8c..2ecaabb 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-watchOS.xcscheme @@ -1,6 +1,6 @@ @@ -37,7 +36,6 @@ buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme index 429d643..2e9daa9 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKitTests.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -32,7 +31,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/Sources/Path.swift b/Sources/Path.swift index 61de950..fa15e9e 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -58,7 +58,7 @@ public struct Path { public static func volumes(_ options: FileManager.VolumeEnumerationOptions = []) -> [Path] { let volumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil, options: options) - return (volumes ?? []).flatMap { Path(url: $0) } + return (volumes ?? []).compactMap { Path(url: $0) } } // MARK: - Properties @@ -127,13 +127,13 @@ public struct Path { return [] } if isAbsolute { - return (absolute.rawValue as NSString).pathComponents.enumerated().flatMap { + return (absolute.rawValue as NSString).pathComponents.enumerated().compactMap { (($0 == 0 || $1 != "/") && $1 != ".") ? Path($1) : nil } } else { let comps = (self.rawValue as NSString).pathComponents.enumerated() // remove extraneous `/` and `.` - let cleanComps = comps.flatMap { + let cleanComps = comps.compactMap { (($0 == 0 || $1 != "/") && $1 != ".") ? Path($1) : nil } return _cleanComponents(cleanComps) @@ -144,7 +144,7 @@ public struct Path { fileprivate func _cleanComponents(_ comps: [Path]) -> [Path] { var isContinue = false let count = comps.count - let cleanComps: [Path] = comps.enumerated().flatMap { + let cleanComps: [Path] = comps.enumerated().compactMap { if ($1.rawValue != ".." && $0 < count - 1 && comps[$0 + 1].rawValue == "..") || ($1.rawValue == ".." && $0 > 0 && comps[$0 - 1].rawValue != "..") { isContinue = true return nil From a53661a322cf9d6decb6df2ba206afa6648a2d3e Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Fri, 31 Aug 2018 11:09:52 +0200 Subject: [PATCH 34/54] Add alias for `Codable` implementations #61 --- Sources/JSONType.swift | 2 ++ Sources/PropertyListType.swift | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Sources/JSONType.swift b/Sources/JSONType.swift index 4cdb738..d2d003e 100644 --- a/Sources/JSONType.swift +++ b/Sources/JSONType.swift @@ -8,6 +8,8 @@ import Foundation +public typealias JSONReadableWritable = JSONReadable & JSONWritable + // MARK: JSONReadable /// A JSON readable object is `Decodable`and provide it`s own decoder diff --git a/Sources/PropertyListType.swift b/Sources/PropertyListType.swift index 8950130..a147664 100644 --- a/Sources/PropertyListType.swift +++ b/Sources/PropertyListType.swift @@ -8,6 +8,8 @@ import Foundation +public typealias PropertyListReadableWritable = PropertyListReadable & PropertyListWritable + // MARK: PropertyListReadable /// A PropertyList readable object is `Decodable`and provide it`s own decoder From cd8f49798ce492867699f8b6ccc74e99dc344cf1 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Fri, 31 Aug 2018 11:29:54 +0200 Subject: [PATCH 35/54] Update README.md for `Codable` and JSON --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 046b280..7174fd9 100644 --- a/README.md +++ b/README.md @@ -372,6 +372,8 @@ that `File` doesn't. You could specify `Data.ReadingOptions` and `Data.Wri You can use any `Codable` object with `File`. ```swift +extension AnyCodableClass: JSONReadableWritable {} // if you want json encoding/decoding + let codableFile = File(path: path) try codableFile.write(toEncode) let decoded: AnyCodableClass = try codableFile.read() From e2f4578172c69ebb413db01f043d6e31812a3585 Mon Sep 17 00:00:00 2001 From: Phimage Date: Mon, 17 Sep 2018 22:45:30 +0200 Subject: [PATCH 36/54] Update podspec to 5.1.1 --- FileKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FileKit.podspec b/FileKit.podspec index 3472a3f..7757d8c 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "5.1.0" + s.version = "5.1.1" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } From 71188fb2ef0e9b305357add4e3cf61616267ae5a Mon Sep 17 00:00:00 2001 From: Igor Muzyka Date: Tue, 26 Jun 2018 23:54:28 +0300 Subject: [PATCH 37/54] Updated to Swift 4.2 --- FileKit.xcodeproj/project.pbxproj | 22 +++++++++---------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++++++ Sources/DispatchWatcher.swift | 4 ++-- Sources/Image+FileKit.swift | 2 +- Sources/TextFile.swift | 4 ++-- 5 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 FileKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 0f8c20c..46bffa0 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -504,7 +504,7 @@ }; 5204B8571B96B85E00AA473F = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 1000; }; 5263A9031B96BA3D00635A93 = { CreatedOnToolsVersion = 7.0; @@ -942,7 +942,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -963,7 +963,7 @@ SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -982,7 +982,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -1003,7 +1003,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1018,7 +1018,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1032,7 +1032,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1051,7 +1051,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 4; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -1073,7 +1073,7 @@ SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1095,7 +1095,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1117,7 +1117,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; diff --git a/FileKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/FileKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/FileKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index f99988a..814d6fd 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -87,10 +87,10 @@ open class DispatchFileSystemWatcher { // MARK: - Properties /// The paths being watched. - open let path: Path + public let path: Path /// The events used to create the watcher. - open let events: DispatchFileSystemEvents + public let events: DispatchFileSystemEvents /// The delegate to call when events happen weak var delegate: DispatchFileSystemWatcherDelegate? diff --git a/Sources/Image+FileKit.swift b/Sources/Image+FileKit.swift index b3ea3ab..f0dbc0e 100644 --- a/Sources/Image+FileKit.swift +++ b/Sources/Image+FileKit.swift @@ -63,7 +63,7 @@ extension Image: ReadableWritable, WritableConvertible { #if os(OSX) return self.tiffRepresentation ?? Data() #else - return UIImagePNGRepresentation(self) ?? Data() + return self.pngData() ?? Data() #endif } diff --git a/Sources/TextFile.swift b/Sources/TextFile.swift index b9b00f9..05c9235 100644 --- a/Sources/TextFile.swift +++ b/Sources/TextFile.swift @@ -119,7 +119,7 @@ extension TextFile { open class TextFileStream { /// The text encoding. - open let encoding: String.Encoding + public let encoding: String.Encoding let delimData: Data var fileHandle: FileHandle? @@ -167,7 +167,7 @@ open class TextFileStream { open class TextFileStreamReader: TextFileStream { /// The chunk size when reading. - open let chunkSize: Int + public let chunkSize: Int /// Tells if the position is at the end of file. open var atEOF: Bool = false From 1bebe4b00efa5e9de53b9cb4b14e023a94361b1e Mon Sep 17 00:00:00 2001 From: Igor Muzyka Date: Wed, 27 Jun 2018 00:01:44 +0300 Subject: [PATCH 38/54] Changed .swift-version to 4.2 --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index 7d5c902..bf77d54 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.1 +4.2 From cb1a5285ca780d66264a3e70862f9845ff1cfb18 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Tue, 18 Sep 2018 09:12:51 +0200 Subject: [PATCH 39/54] Update travis to Xcode 10, podspec to 5.2.0 --- .travis.yml | 8 ++++---- FileKit.podspec | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9faa79e..a247a79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode9 +osx_image: xcode10 env: global: - LC_CTYPE=en_US.UTF-8 @@ -7,11 +7,11 @@ env: - PROJECT=FileKit.xcodeproj - IOS_FRAMEWORK_SCHEME="FileKit-iOS" - MACOS_FRAMEWORK_SCHEME="FileKit-OSX" - - IOS_SDK=iphonesimulator11.0 + - IOS_SDK=iphonesimulator12.0 - MACOS_SDK=macosx10.13 matrix: - - DESTINATION="OS=11.0,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" - - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK=macosx10.13 RUN_TESTS="NO" + - DESTINATION="OS=12.0,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="NO" + - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" RUN_TESTS="YES" before_install: - gem install xcpretty --no-rdoc --no-ri --no-document --quiet script: diff --git a/FileKit.podspec b/FileKit.podspec index 7757d8c..a4412fc 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "5.1.1" + s.version = "5.2.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } From ea3451ae941336b133d46be6b0dc99590ba3fba0 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Tue, 25 Sep 2018 14:09:50 +0200 Subject: [PATCH 40/54] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a247a79..9d97aee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: - IOS_FRAMEWORK_SCHEME="FileKit-iOS" - MACOS_FRAMEWORK_SCHEME="FileKit-OSX" - IOS_SDK=iphonesimulator12.0 - - MACOS_SDK=macosx10.13 + - MACOS_SDK=macosx10.14 matrix: - DESTINATION="OS=12.0,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="NO" - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" RUN_TESTS="YES" From cc67e70c68aede067986b1e2197346d425b8c238 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Tue, 6 Nov 2018 16:08:05 -0500 Subject: [PATCH 41/54] Add patreon and paypal donation links --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7174fd9..29231de 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -

+

-

+
-

+

-

+

Installation • Usage • License • Documentation -

+
FileKit is a Swift framework that allows for simple and expressive file management. From 67fc84c207879ca4580e8935f8b11a41fe19ad20 Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Mon, 8 Apr 2019 15:29:02 +0200 Subject: [PATCH 42/54] Fix Xcode 10.2 warnings --- FileKit.xcodeproj/project.pbxproj | 5 +++-- .../xcschemes/FileKit-OSX.xcscheme | 2 +- .../xcschemes/FileKit-iOS.xcscheme | 2 +- .../xcschemes/FileKit-tvOS.xcscheme | 2 +- .../xcschemes/FileKit-watchOS.xcscheme | 2 +- .../xcschemes/FileKitTests.xcscheme | 2 +- Sources/DispatchWatcher.swift | 18 +++++++++--------- Sources/Path.swift | 6 +++--- 8 files changed, 20 insertions(+), 19 deletions(-) diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 46bffa0..dec18aa 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -495,7 +495,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { @@ -520,10 +520,11 @@ }; buildConfigurationList = 5204B7B01B968B8600AA473F /* Build configuration list for PBXProject "FileKit" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 5204B7AC1B968B8600AA473F; productRefGroup = 5204B7B71B968B8600AA473F /* Products */; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index 44b344c..3e7bb33 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 8 Apr 2019 15:29:02 +0200 Subject: [PATCH 43/54] Fix Xcode 10.2 warnings --- FileKit.xcodeproj/project.pbxproj | 5 +++-- .../xcschemes/FileKit-OSX.xcscheme | 2 +- .../xcschemes/FileKit-iOS.xcscheme | 2 +- .../xcschemes/FileKit-tvOS.xcscheme | 2 +- .../xcschemes/FileKit-watchOS.xcscheme | 2 +- .../xcschemes/FileKitTests.xcscheme | 2 +- Sources/DispatchWatcher.swift | 18 +++++++++--------- Sources/Path.swift | 6 +++--- 8 files changed, 20 insertions(+), 19 deletions(-) diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 46bffa0..dec18aa 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -495,7 +495,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { @@ -520,10 +520,11 @@ }; buildConfigurationList = 5204B7B01B968B8600AA473F /* Build configuration list for PBXProject "FileKit" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 5204B7AC1B968B8600AA473F; productRefGroup = 5204B7B71B968B8600AA473F /* Products */; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index 44b344c..3e7bb33 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 8 Apr 2019 16:03:46 +0200 Subject: [PATCH 44/54] Update travis file for xcode 10.2 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d97aee..ce42220 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode10 +osx_image: xcode10.2 env: global: - LC_CTYPE=en_US.UTF-8 @@ -7,10 +7,10 @@ env: - PROJECT=FileKit.xcodeproj - IOS_FRAMEWORK_SCHEME="FileKit-iOS" - MACOS_FRAMEWORK_SCHEME="FileKit-OSX" - - IOS_SDK=iphonesimulator12.0 + - IOS_SDK=iphonesimulator12.2 - MACOS_SDK=macosx10.14 matrix: - - DESTINATION="OS=12.0,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="NO" + - DESTINATION="OS=12.2,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="NO" - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" RUN_TESTS="YES" before_install: - gem install xcpretty --no-rdoc --no-ri --no-document --quiet From 48b5ddb287f131a5c628badc819b880453f94449 Mon Sep 17 00:00:00 2001 From: Davide Mazzoni Date: Wed, 20 Mar 2019 12:14:46 +0100 Subject: [PATCH 45/54] Update Package.swift to API v4.2 --- Package.swift | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index c11c1b7..845b0bf 100644 --- a/Package.swift +++ b/Package.swift @@ -1,3 +1,4 @@ +// swift-tools-version:4.2 // // Package.swift // FileKit @@ -29,7 +30,23 @@ import PackageDescription let package = Package( name: "FileKit", - exclude: [ - "Tests" + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "FileKit", + targets: ["FileKit"]), + ], + dependencies: [], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "FileKit", + dependencies: [], + path: "Sources"), + .testTarget( + name: "FileKitTests", + dependencies: ["FileKit"], + path: "Tests") ] ) From 886dc4808fb6419fd62f49c2a49b4a05a02f1c01 Mon Sep 17 00:00:00 2001 From: phimage Date: Sun, 1 Sep 2019 21:15:52 +0200 Subject: [PATCH 46/54] Fix swiftlint useless warning. Fix test --- Sources/DataType.swift | 4 ++-- Tests/FileKitTests.swift | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Sources/DataType.swift b/Sources/DataType.swift index ea06023..a1a4758 100644 --- a/Sources/DataType.swift +++ b/Sources/DataType.swift @@ -47,7 +47,7 @@ extension Readable { /// /// - Parameter path: The path being read from. /// - public init(contentsOfPath path: Path) throws { // swiftlint:disable:this valid_docs + public init(contentsOfPath path: Path) throws { self = try Self.read(from: path) } @@ -77,7 +77,7 @@ extension Writable { /// /// - Parameter path: The path being written to. /// - public func write(to path: Path) throws { // swiftlint:disable:this valid_docs + public func write(to path: Path) throws { try write(to: path, atomically: true) } diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index 49d2dab..bd3ac14 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -199,7 +199,11 @@ class FileKitTests: XCTestCase { let directories = children.filter { $0.isDirectory } - guard let directory = directories.first, let childOfChild = directory.children().first else { + if let directory = directories.first, directory.children().isEmpty { + try? (directory + "childOfChild").createDirectory() + } + + guard let directory = directories.first, let childOfChild = directory.children().first else { XCTFail("No child of child into \(p)") return } From 7133459387efb97d2e49d35ffa69274d30d86c46 Mon Sep 17 00:00:00 2001 From: phimage Date: Sun, 1 Sep 2019 21:17:22 +0200 Subject: [PATCH 47/54] Update podspec to 5.3 --- FileKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FileKit.podspec b/FileKit.podspec index a4412fc..6eff8c2 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "5.2.0" + s.version = "5.3.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } From 826d9161b184509f80d85c28cd612d630646de98 Mon Sep 17 00:00:00 2001 From: phimage Date: Sun, 1 Sep 2019 21:32:59 +0200 Subject: [PATCH 48/54] Update project to swift 5 --- .swift-version | 2 +- .swiftlint.yml | 2 -- FileKit.podspec | 2 +- FileKit.xcodeproj/project.pbxproj | 32 ++++++++++++++----------------- Package.swift | 2 +- 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/.swift-version b/.swift-version index bf77d54..6e63660 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.2 +5.0 \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml index 9c0c44d..b09e5df 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,8 +3,6 @@ included: # rule identifiers to exclude from running disabled_rules: - - valid_docs - - function_body_length - cyclomatic_complexity - variable_name - type_name diff --git a/FileKit.podspec b/FileKit.podspec index 6eff8c2..3cb9041 100644 --- a/FileKit.podspec +++ b/FileKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "FileKit" - s.version = "5.3.0" + s.version = "6.0.0" s.summary = "Simple and expressive file management in Swift." s.homepage = "https://github.com/nvzqz/FileKit" s.license = { :type => "MIT", :file => "LICENSE.md" } diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index dec18aa..4bd98c6 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -500,7 +500,7 @@ TargetAttributes = { 5204B84A1B96B83800AA473F = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0900; + LastSwiftMigration = 1020; }; 5204B8571B96B85E00AA473F = { CreatedOnToolsVersion = 7.0; @@ -508,7 +508,7 @@ }; 5263A9031B96BA3D00635A93 = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0900; + LastSwiftMigration = 1020; }; 527612411BAEA3EE00503D0A = { CreatedOnToolsVersion = 7.0; @@ -869,7 +869,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -921,7 +921,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -942,8 +942,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -963,8 +962,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -983,7 +981,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -1004,7 +1002,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1018,8 +1016,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -1032,8 +1029,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -1052,7 +1048,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -1074,7 +1070,7 @@ SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1096,7 +1092,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1118,7 +1114,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; diff --git a/Package.swift b/Package.swift index 845b0bf..84bae78 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.2 +// swift-tools-version:5.0 // // Package.swift // FileKit From 38fb74327387b1c8accd257177ef4c4cc00c1fbb Mon Sep 17 00:00:00 2001 From: Eric Marchand Date: Mon, 9 Sep 2019 11:30:32 +0200 Subject: [PATCH 49/54] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ce42220..05f6b40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ env: - DESTINATION="OS=12.2,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="NO" - DESTINATION="arch=x86_64" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" RUN_TESTS="YES" before_install: - - gem install xcpretty --no-rdoc --no-ri --no-document --quiet + - gem install xcpretty --no-document --quiet script: - set -o pipefail - xcodebuild -version From d534ffe5a681b156df9036708c49529a3b08682d Mon Sep 17 00:00:00 2001 From: "eric.marchand" Date: Sun, 14 Feb 2021 07:53:25 +0100 Subject: [PATCH 50/54] Add method to get file name without extension Fix #69 --- Sources/File.swift | 5 +++++ Sources/Path.swift | 8 ++++++++ Tests/FileKitTests.swift | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/Sources/File.swift b/Sources/File.swift index 3f51554..295c34d 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -44,6 +44,11 @@ open class File: Comparable { return path.fileName } + /// The file's name without extension. + open var nameWithoutExtension: String { + return path.fileNameWithoutExtension + } + /// The file's filesystem path extension. public final var pathExtension: String { get { diff --git a/Sources/Path.swift b/Sources/Path.swift index 1c3f0fd..fc8f326 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -160,6 +160,11 @@ public struct Path { return self.absolute.components.last?.rawValue ?? "" } + /// The name of the file without extension. + public var fileNameWithoutExtension: String { + return ((rawValue as NSString).lastPathComponent as NSString).deletingPathExtension + } + /// A new path created by removing extraneous components from the path. public var standardized: Path { return Path((self.rawValue as NSString).standardizingPath) @@ -301,6 +306,9 @@ public struct Path { rawValue = path + ".\(newValue)" } } + mutating func appendToExtension(_ toAppend: String) { + self.pathExtension = pathExtension + toAppend + } /// The path's parent path. public var parent: Path { diff --git a/Tests/FileKitTests.swift b/Tests/FileKitTests.swift index bd3ac14..0efbdc6 100644 --- a/Tests/FileKitTests.swift +++ b/Tests/FileKitTests.swift @@ -497,6 +497,7 @@ class FileKitTests: XCTestCase { // MARK: - TextFile let testFilePath: Path = .userTemporary + "filekit_test.txt" let textFile = TextFile(path: .userTemporary + "filekit_test.txt") + let textFileWithoutExt = TextFile(path: .userTemporary + "filekit_test") func testFileName() { XCTAssertEqual(TextFile(path: "/Users/").name, "Users") @@ -506,6 +507,11 @@ class FileKitTests: XCTestCase { XCTAssertEqual(textFile.pathExtension, "txt") } + func testTextFileWihoutExtension() { + XCTAssertEqual(textFile.nameWithoutExtension, "filekit_test") + XCTAssertEqual(textFileWithoutExt.nameWithoutExtension, "filekit_test") + } + func testTextFileExists() { do { try textFile.create() From c762eb37b7152e81f96b7fa90a5c1314aa0700d7 Mon Sep 17 00:00:00 2001 From: "eric.marchand" Date: Sun, 14 Feb 2021 09:27:07 +0100 Subject: [PATCH 51/54] Add some functions for iCloud #63 --- Sources/Path.swift | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Sources/Path.swift b/Sources/Path.swift index fc8f326..9f1bf8f 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -1003,6 +1003,70 @@ extension Path { } +extension Path { + + // MARK: - Ubiquity Container + + /// Create a path for the iCloud container associated with the specified identifier and establishes access to that container. + public init?(ubiquityContainerIdentifier containerIdentifier: String) { + guard let url = FileManager.default.url(forUbiquityContainerIdentifier: containerIdentifier) else { + return nil + } + self.init(url: url) + } + + /// - Returns: a Boolean indicating whether the item is targeted for storage in iCloud. + public var isUbiquitousItem: Bool { + return _fmWraper.fileManager.isUbiquitousItem(at: self.url) + } + + /// Removes the local copy of the specified item that’s stored in iCloud. + public func evictUbiquitousItem() throws { + do { + return try _fmWraper.fileManager.evictUbiquitousItem(at: self.url) + } catch { + throw FileKitError.deleteFileFail(path: self, error: error) + } + } + + /// Returns a URL that can be emailed to users to allow them to download a copy of a flat file item from iCloud. + /// It return also the expiration date. + func publicUbiquitousURL() throws -> (URL, Date?) { + var expiration: NSDate? + let url = try _fmWraper.fileManager.url(forPublishingUbiquitousItemAt: self.url, expiration: &expiration) + guard let date = expiration else { + return (url, nil) + } + // TODO need to encapsulate error before exposing it + return (url, date as Date) + } + + /// Indicates whether the current file should be stored in iCloud. + public func setUbiquitous(destination: Path) throws { + do { + try _fmWraper.fileManager.setUbiquitous(true, itemAt: self.url, destinationURL: destination.url) + } catch { + throw FileKitError.attributesChangeFail(path: self, error: error) + } + } + + /// Indicates whether the current file should no more be stored in iCloud. + public func unsetUbiquitous() throws { + do { + try _fmWraper.fileManager.setUbiquitous(false, itemAt: self.url, destinationURL: self.url) + } catch { + throw FileKitError.attributesChangeFail(path: self, error: error) + } + } + + /// Starts downloading (if necessary) the specified item to the local system. + func startDownloadingUbiquitous() throws { + try _fmWraper.fileManager.startDownloadingUbiquitousItem(at: self.url) + // TODO need to encapsulate error before exposing it + } + +} + extension Path { // MARK: - SecurityApplicationGroupIdentifier From 5c1b827c532a8bccae117999c91f09ca743cadde Mon Sep 17 00:00:00 2001 From: "eric.marchand" Date: Sun, 14 Feb 2021 09:27:34 +0100 Subject: [PATCH 52/54] Fix message of `attributesChangeFail` --- Sources/FileKitError.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FileKitError.swift b/Sources/FileKitError.swift index 6eda81d..4bb6865 100644 --- a/Sources/FileKitError.swift +++ b/Sources/FileKitError.swift @@ -114,7 +114,7 @@ extension FileKitError { return "Could not move file at \"\(fromPath)\" to \"\(toPath)\"" case let .copyFileFail(fromPath, toPath, _): return "Could not copy file from \"\(fromPath)\" to \"\(toPath)\"" - case let .attributesChangeFail(path): + case let .attributesChangeFail(path, _): return "Could not change file attrubutes at \"\(path)\"" } } From 6937ec38b0c383b0505caeea6603e62086bf5431 Mon Sep 17 00:00:00 2001 From: "eric.marchand" Date: Sun, 14 Feb 2021 09:34:20 +0100 Subject: [PATCH 53/54] Fix SwiftLint warnings --- .swiftlint.yml | 1 + Sources/DispatchWatcher.swift | 8 ++++---- Sources/FileSystemWatcher.swift | 12 ++++++------ Sources/Path.swift | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index b09e5df..fa9b18a 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -6,6 +6,7 @@ disabled_rules: - cyclomatic_complexity - variable_name - type_name + - todo shorthand_operator: warning superfluous_disable_command: warning diff --git a/Sources/DispatchWatcher.swift b/Sources/DispatchWatcher.swift index 9169f25..985ee06 100644 --- a/Sources/DispatchWatcher.swift +++ b/Sources/DispatchWatcher.swift @@ -145,7 +145,7 @@ open class DispatchFileSystemWatcher { // MARK: - Deinitialization deinit { - //print("\(path): Deinit") + // print("\(path): Deinit") close() } @@ -217,7 +217,7 @@ open class DispatchFileSystemWatcher { // stop watching when path created if self?.path.isRegular == true || self?.path.isDirectoryFile == true { self?.dispatchDelegate(.Create) - //self.delegate?.fsWatcherDidObserveCreate(self) + // self.delegate?.fsWatcherDidObserveCreate(self) self?.createWatcher = nil self?.startWatching() watch.stopWatching() @@ -245,13 +245,13 @@ open class DispatchFileSystemWatcher { } // Define the block to call when a file change is detected. - source!.setEventHandler { //[unowned self] () in + source!.setEventHandler { // [unowned self] () in let eventType = DispatchFileSystemEvents(rawValue: self.source!.data) self.dispatchDelegate(eventType) } // Define a cancel handler to ensure the path is closed when the source is cancelled. - source!.setCancelHandler { //[unowned self] () in + source!.setCancelHandler { // [unowned self] () in _ = Darwin.close(self.fileDescriptor) self.fileDescriptor = -1 self.source = nil diff --git a/Sources/FileSystemWatcher.swift b/Sources/FileSystemWatcher.swift index a07b125..5ca5005 100644 --- a/Sources/FileSystemWatcher.swift +++ b/Sources/FileSystemWatcher.swift @@ -35,13 +35,13 @@ public class FileSystemWatcher { // MARK: - Private Static Properties /// The event stream callback for when events occur. - private static let _eventCallback: FSEventStreamCallback = { + private static let _eventCallback: FSEventStreamCallback = { // swiftlint:disable all (stream: ConstFSEventStreamRef, - contextInfo: UnsafeMutableRawPointer?, - numEvents: Int, - eventPaths: UnsafeMutableRawPointer, - eventFlags: UnsafePointer, - eventIds: UnsafePointer) in + contextInfo: UnsafeMutableRawPointer?, + numEvents: Int, + eventPaths: UnsafeMutableRawPointer, + eventFlags: UnsafePointer, + eventIds: UnsafePointer) in // swiftlint:enable all FileSystemWatcher.log("Callback Fired") diff --git a/Sources/Path.swift b/Sources/Path.swift index 9f1bf8f..9bfa44e 100644 --- a/Sources/Path.swift +++ b/Sources/Path.swift @@ -70,9 +70,9 @@ public struct Path { weak var delegate: FileManagerDelegate? /// Safe way to use fileManager var fileManager: FileManager { - //if delegate == nil { + // if delegate == nil { // print("\n\nDelegate is nil\n\n") - //} + // } unsafeFileManager.delegate = delegate return unsafeFileManager } From 9006d2888025fbe893c3c396327b2fe45a8c177b Mon Sep 17 00:00:00 2001 From: phimage Date: Mon, 20 Feb 2023 09:48:56 +0100 Subject: [PATCH 54/54] Fix warning and update project with Xcode 14.2 --- .swiftlint.yml | 2 +- FileKit.xcodeproj/project.pbxproj | 123 ++++++++++++++---- .../xcschemes/FileKit-OSX.xcscheme | 24 ++-- .../xcschemes/FileKit-iOS.xcscheme | 6 +- .../xcschemes/FileKit-tvOS.xcscheme | 6 +- .../xcschemes/FileKit-watchOS.xcscheme | 6 +- .../xcschemes/FileKitTests.xcscheme | 10 +- Sources/DispatchEvent.swift | 16 +-- Sources/DispatchWatcher.swift | 2 +- Sources/FilePermissions.swift | 18 ++- Sources/FileSystemEvent.swift | 34 ++--- 11 files changed, 141 insertions(+), 106 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index fa9b18a..47e1f1b 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -4,7 +4,7 @@ included: # rule identifiers to exclude from running disabled_rules: - cyclomatic_complexity - - variable_name + - identifier_name - type_name - todo diff --git a/FileKit.xcodeproj/project.pbxproj b/FileKit.xcodeproj/project.pbxproj index 4bd98c6..eedb650 100644 --- a/FileKit.xcodeproj/project.pbxproj +++ b/FileKit.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -495,7 +495,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1420; ORGANIZATIONNAME = "Nikolai Vazquez"; TargetAttributes = { 5204B84A1B96B83800AA473F = { @@ -581,6 +581,7 @@ /* Begin PBXShellScriptBuildPhase section */ 52995ACA1C0D967100A1AD23 /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -591,10 +592,11 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; 52995ACB1C0D967700A1AD23 /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -605,10 +607,11 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; 52995ACC1C0D967D00A1AD23 /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -619,10 +622,11 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; 52995ACD1C0D968400A1AD23 /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -633,7 +637,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -837,6 +841,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -846,6 +851,7 @@ CURRENT_PROJECT_VERSION = 1; CURRENT_RELEASE_NUMBER = 12; CURRENT_RELEASE_VERSION = 4.0.1; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -863,7 +869,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -897,6 +903,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -906,6 +913,7 @@ CURRENT_PROJECT_VERSION = 1; CURRENT_RELEASE_NUMBER = 12; CURRENT_RELEASE_VERSION = 4.0.1; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -917,7 +925,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; @@ -931,6 +939,7 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -938,7 +947,12 @@ FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; @@ -950,6 +964,7 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -957,11 +972,17 @@ FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; }; name = Release; @@ -976,7 +997,13 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; @@ -996,12 +1023,19 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -1012,8 +1046,14 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -1024,11 +1064,18 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = com.nikolaivazquez.FileKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; }; name = Release; @@ -1043,14 +1090,19 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.0; + WATCHOS_DEPLOYMENT_TARGET = 4.0; }; name = Debug; }; @@ -1064,16 +1116,22 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; - WATCHOS_DEPLOYMENT_TARGET = 2.0; + WATCHOS_DEPLOYMENT_TARGET = 4.0; }; name = Release; }; @@ -1087,14 +1145,19 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; }; @@ -1108,15 +1171,21 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Support/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.nikolaivazquez.$(PROJECT_NAME)"; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 12.0; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme index 3e7bb33..086778c 100644 --- a/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme +++ b/FileKit.xcodeproj/xcshareddata/xcschemes/FileKit-OSX.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -39,17 +48,6 @@ - - - - - - - - - - - - - - - - - - - - + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> @@ -24,8 +24,6 @@ - - - -