diff --git a/.travis.yml b/.travis.yml index 49b3767..13922bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7.1 +osx_image: xcode9.1 script: - bundle exec rake default diff --git a/SwiftFilePath.xcodeproj/project.pbxproj b/SwiftFilePath.xcodeproj/project.pbxproj index fa1a1a8..048df7c 100644 --- a/SwiftFilePath.xcodeproj/project.pbxproj +++ b/SwiftFilePath.xcodeproj/project.pbxproj @@ -366,7 +366,7 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0910; ORGANIZATIONNAME = "Norihiro Sakamoto"; TargetAttributes = { CC7832EB1A610124005E77C3 = { @@ -598,6 +598,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -636,6 +637,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -941,6 +943,7 @@ D63BC3AC1C172BCD0071D0E2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D63BC3AD1C172BCD0071D0E2 /* Build configuration list for PBXNativeTarget "SwiftFilePath-tvOS Tests" */ = { isa = XCConfigurationList; @@ -949,6 +952,7 @@ D63BC3AF1C172BCD0071D0E2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D63BC3BA1C172C540071D0E2 /* Build configuration list for PBXNativeTarget "SwiftFilePath-watchOS" */ = { isa = XCConfigurationList; @@ -957,6 +961,7 @@ D63BC3BC1C172C540071D0E2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D63BC3D31C172C740071D0E2 /* Build configuration list for PBXNativeTarget "SwiftFilePath-Mac" */ = { isa = XCConfigurationList; @@ -965,6 +970,7 @@ D63BC3D51C172C740071D0E2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D63BC3D61C172C740071D0E2 /* Build configuration list for PBXNativeTarget "SwiftFilePath-Mac Tests" */ = { isa = XCConfigurationList; @@ -973,6 +979,7 @@ D63BC3D81C172C740071D0E2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/SwiftFilePath.xcodeproj/xcshareddata/xcschemes/SwiftFilePath-Mac.xcscheme b/SwiftFilePath.xcodeproj/xcshareddata/xcschemes/SwiftFilePath-Mac.xcscheme index eaa5516..cd8f371 100644 --- a/SwiftFilePath.xcodeproj/xcshareddata/xcschemes/SwiftFilePath-Mac.xcscheme +++ b/SwiftFilePath.xcodeproj/xcshareddata/xcschemes/SwiftFilePath-Mac.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/SwiftFilePath/Path.swift b/SwiftFilePath/Path.swift index 5dea3ca..0c646d6 100644 --- a/SwiftFilePath/Path.swift +++ b/SwiftFilePath/Path.swift @@ -10,120 +10,102 @@ public class Path { // MARK: - Class methods - public class func isDir(path:NSString) -> Bool { + public class func isDir(_ path: String) -> Bool { var isDirectory: ObjCBool = false - NSFileManager.defaultManager().fileExistsAtPath(path as String, isDirectory:&isDirectory) - return isDirectory ? true : false + FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) + return isDirectory.boolValue } // MARK: - Instance properties and initializer - lazy var fileManager = NSFileManager.defaultManager() - public let path_string:String + var fileManager: FileManager { + return FileManager.default + } + + public let url: URL + public init(_ url: URL) { + assert(url.isFileURL, "Must be file URL") + self.url = url + } - public init(_ p: String) { - self.path_string = p + public convenience init(_ path: String) { + self.init(URL(fileURLWithPath: path)) } // MARK: - Instance val - public var attributes:NSDictionary?{ + public var attributes: [FileAttributeKey: Any]?{ get { return self.loadAttributes() } } public var asString: String { - return path_string + return url.path } public var exists: Bool { - return fileManager.fileExistsAtPath(path_string) + return fileManager.fileExists(atPath: url.path) } public var isDir: Bool { - return Path.isDir(path_string); + return Path.isDir(url.path) } - public var basename:NSString { - return ( path_string as NSString ).lastPathComponent + public var basename: String { + return url.lastPathComponent } - public var parent: Path{ - return Path( (path_string as NSString ).stringByDeletingLastPathComponent ) + public var parent: Path { + return Path(url.deletingLastPathComponent()) } // MARK: - Instance methods public func toString() -> String { - return path_string + return url.path } - public func remove() -> Result { + @discardableResult + public func remove() -> Result { assert(self.exists,"To remove file, file MUST be exists") - var error: NSError? - let result: Bool do { - try fileManager.removeItemAtPath(path_string) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try fileManager.removeItem(at: url) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!); } - public func copyTo(toPath:Path) -> Result { + @discardableResult + public func copyTo(_ toPath: Path) -> Result { assert(self.exists,"To copy file, file MUST be exists") - var error: NSError? - let result: Bool do { - try fileManager.copyItemAtPath(path_string, - toPath: toPath.toString()) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try fileManager.copyItem(at: url, to: toPath.url) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) } - public func moveTo(toPath:Path) -> Result { + @discardableResult + public func moveTo(_ toPath: Path) -> Result { assert(self.exists,"To move file, file MUST be exists") - var error: NSError? - let result: Bool do { - try fileManager.moveItemAtPath(path_string, - toPath: toPath.toString()) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try fileManager.moveItem(at: url, to: toPath.url) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) } - private func loadAttributes() -> NSDictionary? { - assert(self.exists,"File must be exists to load file.< \(path_string) >") - var loadError: NSError? - let result: [NSObject: AnyObject]? + private func loadAttributes() -> [FileAttributeKey: Any]? { + assert(self.exists,"File must be exists to load file.< \(url.path) >") do { - result = try self.fileManager.attributesOfItemAtPath(path_string) - } catch let error as NSError { - loadError = error - result = nil - } - - if let error = loadError { + return try fileManager.attributesOfItem(atPath: url.path) + } catch let error { print("Error< \(error.localizedDescription) >") } - - return result + return nil } } @@ -132,7 +114,7 @@ public class Path { extension Path: CustomStringConvertible { public var description: String { - return "\(NSStringFromClass(self.dynamicType))" + return "\(String(describing: Path.self))" } } diff --git a/SwiftFilePath/PathExtensionDir.swift b/SwiftFilePath/PathExtensionDir.swift index 52dfb2e..a6d9909 100644 --- a/SwiftFilePath/PathExtensionDir.swift +++ b/SwiftFilePath/PathExtensionDir.swift @@ -21,95 +21,72 @@ extension Path { } public class var documentsDir:Path { - return Path.userDomainOf(.DocumentDirectory) + return Path.userDomainOf(.documentDirectory) } public class var cacheDir:Path { - return Path.userDomainOf(.CachesDirectory) + return Path.userDomainOf(.cachesDirectory) } - private class func userDomainOf(pathEnum:NSSearchPathDirectory)->Path{ - let pathString = NSSearchPathForDirectoriesInDomains(pathEnum, .UserDomainMask, true)[0] - return Path( pathString ) + private class func userDomainOf(_ pathEnum: FileManager.SearchPathDirectory) -> Path { + let pathString = NSSearchPathForDirectoriesInDomains(pathEnum, .userDomainMask, true)[0] + return Path(pathString) } } #endif // Add Dir Behavior to Path by extension -extension Path: SequenceType { +extension Path: Sequence { - public subscript(filename: String) -> Path{ - get { return self.content(filename) } + public subscript(filename: String) -> Path { + return content(filename) } - public var children:Array? { - assert(self.isDir,"To get children, path must be dir< \(path_string) >") - assert(self.exists,"Dir must be exists to get children.< \(path_string) >") - var loadError: NSError? - let contents: [AnyObject]? + public var children: [Path]? { + assert(self.isDir,"To get children, path must be dir< \(url.path) >") + assert(self.exists,"Dir must be exists to get children.< \(url.path) >") do { - contents = try self.fileManager.contentsOfDirectoryAtPath(path_string - ) - } catch let error as NSError { - loadError = error - contents = nil - } - if let error = loadError { + let contents = try fileManager.contentsOfDirectory(atPath: url.path) + return contents.map({ + content($0) + }) + } catch let error { print("Error< \(error.localizedDescription) >") } - - return contents!.map({ [unowned self] content in - return self.content(content as! String) - }) - + return nil } - public var contents:Array? { - return self.children + public var contents: [Path]? { + return children } - public func content(path_string:NSString) -> Path { - return Path( - NSURL(fileURLWithPath: self.path_string) - .URLByAppendingPathComponent( path_string as String ) - .path! - ) + public func content(_ path: String) -> Path { + return Path(url.appendingPathComponent(path)) } - public func child(path:NSString) -> Path { - return self.content(path) + public func child(_ path: String) -> Path { + return content(path) } - public func mkdir() -> Result { - var error: NSError? - let result: Bool + @discardableResult + public func mkdir() -> Result { do { - try fileManager.createDirectoryAtPath(path_string, - withIntermediateDirectories:true, - attributes:nil) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) - } - public func generate() -> AnyGenerator { - assert(self.isDir,"To get iterator, path must be dir< \(path_string) >") - let iterator = fileManager.enumeratorAtPath(path_string) - return anyGenerator() { - let optionalContent = iterator?.nextObject() as! String? - if let content = optionalContent { + public func makeIterator() -> AnyIterator { + assert(self.isDir,"To get iterator, path must be dir< \(url.path) >") + let iterator = fileManager.enumerator(atPath: url.path) + return AnyIterator() { + if let content = iterator?.nextObject() as? String { return self.content(content) - } else { - return .None } + return .none } } - } diff --git a/SwiftFilePath/PathExtensionFile.swift b/SwiftFilePath/PathExtensionFile.swift index 4442b04..b68f67c 100644 --- a/SwiftFilePath/PathExtensionFile.swift +++ b/SwiftFilePath/PathExtensionFile.swift @@ -9,98 +9,71 @@ // Add File Behavior to Path by extension extension Path { - public var ext:NSString { - return NSURL(fileURLWithPath:path_string).pathExtension! + public var ext: String { + return url.pathExtension } - public func touch() -> Result { + @discardableResult + public func touch() -> Result { assert(!self.isDir,"Can NOT touch to dir") return self.exists ? self.updateModificationDate() : self.createEmptyFile() } - public func updateModificationDate(date: NSDate = NSDate() ) -> Result{ - var error: NSError? - let result: Bool + public func updateModificationDate(_ date: Date = Date() ) -> Result { do { - try fileManager.setAttributes( - [NSFileModificationDate :date], - ofItemAtPath:path_string) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try fileManager.setAttributes([.modificationDate: date], ofItemAtPath: url.path) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) } - private func createEmptyFile() -> Result{ + @discardableResult + private func createEmptyFile() -> Result { return self.writeString("") } // MARK: - read/write String - public func readString() -> String? { assert(!self.isDir,"Can NOT read data from dir") - var readError:NSError? - let read: String? - do { - read = try String(contentsOfFile: path_string, - encoding: NSUTF8StringEncoding) - } catch let error as NSError { - readError = error - read = nil - } - if let error = readError { + do { + return try String(contentsOf: url, encoding: .utf8) + } catch let error { print("readError< \(error.localizedDescription) >") } - - return read + return nil } - public func writeString(string:String) -> Result { + @discardableResult + public func writeString(_ string: String) -> Result { assert(!self.isDir,"Can NOT write data from dir") - var error: NSError? - let result: Bool do { - try string.writeToFile(path_string, - atomically:true, - encoding: NSUTF8StringEncoding) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try string.write(to: url, atomically: true, encoding: .utf8) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) } // MARK: - read/write NSData - public func readData() -> NSData? { + public func readData() -> Data? { assert(!self.isDir,"Can NOT read data from dir") - return NSData(contentsOfFile: path_string) + return try? Data(contentsOf: url) } - public func writeData(data:NSData) -> Result { + @discardableResult + public func writeData(_ data: Data) -> Result { assert(!self.isDir,"Can NOT write data from dir") - var error: NSError? - let result: Bool do { - try data.writeToFile(path_string, options:.DataWritingAtomic) - result = true - } catch let error1 as NSError { - error = error1 - result = false + try data.write(to: url) + return Result(success: self) + } catch let error { + return Result(failure: error) } - return result - ? Result(success: self) - : Result(failure: error!) } } diff --git a/SwiftFilePath/Result.swift b/SwiftFilePath/Result.swift index fc0715a..38240dc 100644 --- a/SwiftFilePath/Result.swift +++ b/SwiftFilePath/Result.swift @@ -8,68 +8,68 @@ public enum Result { - case Success(S) - case Failure(F) + case success(S) + case failure(F) public init(success:S){ - self = .Success(success) + self = .success(success) } public init(failure:F){ - self = .Failure(failure) + self = .failure(failure) } public var isSuccess:Bool { switch self { - case .Success: return true - case .Failure: return false + case .success: return true + case .failure: return false } } public var isFailure:Bool { switch self { - case .Success: return false - case .Failure: return true + case .success: return false + case .failure: return true } } public var value:S? { switch self { - case .Success(let success): + case .success(let success): return success - case .Failure(_): - return .None + case .failure(_): + return .none } } public var error:F? { switch self { - case .Success(_): - return .None - case .Failure(let error): + case .success(_): + return .none + case .failure(let error): return error } } - public func onFailure(handler:(F) -> Void ) -> Result { + public func onFailure(_ handler:(F) -> Void ) -> Result { switch self { - case .Success(_): + case .success(_): return self - case .Failure(let error): + case .failure(let error): handler( error ) return self } } - public func onSuccess(handler:(S) -> Void ) -> Result { + public func onSuccess(_ handler:(S) -> Void ) -> Result { switch self { - case .Success(let success): + case .success(let success): handler(success ) return self - case .Failure(_): + case .failure(_): return self } } -} \ No newline at end of file +} diff --git a/SwiftFilePathTests/SwiftFilePathTests.swift b/SwiftFilePathTests/SwiftFilePathTests.swift index d2bdfbf..ea21a7b 100644 --- a/SwiftFilePathTests/SwiftFilePathTests.swift +++ b/SwiftFilePathTests/SwiftFilePathTests.swift @@ -13,14 +13,10 @@ import SwiftFilePath extension String { - func match(pattern: String) -> Bool { - let matcher: NSRegularExpression? - do { - matcher = try NSRegularExpression(pattern: pattern, options: []) - } catch _ as NSError { - matcher = nil - } - return matcher?.numberOfMatchesInString(self, options: [], range: NSMakeRange(0, self.utf16.count)) != 0 + func match(_ pattern: String) -> Bool { + let matcher = try? NSRegularExpression(pattern: NSRegularExpression.escapedPattern(for: pattern), + options: []) + return matcher?.numberOfMatches(in: self, options: [], range: NSMakeRange(0, count)) != 0 } } @@ -62,7 +58,7 @@ class SwiftFilePathTests: XCTestCase { let temporaryDir = Path.temporaryDir XCTAssertTrue( - temporaryDir.toString().match("/data/tmp/") + temporaryDir.toString().match("/data/tmp") ) let documentsDir = Path.documentsDir @@ -104,7 +100,7 @@ class SwiftFilePathTests: XCTestCase { let file = sandboxDir.content("foo.txt") file.touch() - let permission:Int? = file.attributes!.filePosixPermissions() + let permission: Int? = file.attributes?[.posixPermissions] as? Int XCTAssertEqual( permission!,420); } @@ -229,8 +225,8 @@ class SwiftFilePathTests: XCTestCase { subdir.mkdir() let boxContents = sandboxDir.contents - XCTAssertEqual( boxContents!.count, 3) - XCTAssertEqual( subdir.contents!.count, 0) + XCTAssertEqual(boxContents!.count, 3) + XCTAssertEqual(subdir.contents!.count, 0) for content in boxContents! { XCTAssertTrue(content.exists) @@ -239,8 +235,8 @@ class SwiftFilePathTests: XCTestCase { let dirsInContents = boxContents!.filter({content in return content.isDir }) - XCTAssertEqual( dirsInContents.count, 1) - XCTAssertEqual( dirsInContents.first!.toString(), subdir.toString()) + XCTAssertEqual(dirsInContents.count, 1) + XCTAssertEqual(dirsInContents.first!.toString(), subdir.toString()) } @@ -257,8 +253,8 @@ class SwiftFilePathTests: XCTestCase { for content in sandboxDir { XCTAssertTrue(content.exists) - contentCount++ - if( content.isDir ){ dirCount++ } + contentCount += 1 + if( content.isDir ){ dirCount += 1 } } XCTAssertEqual( contentCount, 3) XCTAssertEqual( dirCount, 1) @@ -300,31 +296,31 @@ class SwiftFilePathTests: XCTestCase { locally { let string = "HelloData" - let data = string.dataUsingEncoding(NSUTF8StringEncoding) - let result = binFile.writeData( data! ) - XCTAssertTrue( result.isSuccess ) + let data = string.data(using: .utf8) + let result = binFile.writeData(data!) + XCTAssertTrue(result.isSuccess) let readData = binFile.readData() - let readString = NSString(data: readData!, encoding: NSUTF8StringEncoding)! - XCTAssertEqual( readString, "HelloData") + let readString = String(data: readData!, encoding: .utf8) + XCTAssertEqual(readString, string) } locally { let string = "HelloData Again" - let data = string.dataUsingEncoding(NSUTF8StringEncoding) - let result = binFile.writeData( data! ) - XCTAssertTrue( result.isSuccess ) + let data = string.data(using: .utf8) + let result = binFile.writeData(data!) + XCTAssertTrue(result.isSuccess) let readData = binFile.readData() - let readString = NSString(data: readData!, encoding: NSUTF8StringEncoding)! - XCTAssertEqual( readString, "HelloData Again") + let readString = String(data: readData!, encoding: .utf8) + XCTAssertEqual(readString, string) } locally { binFile.remove() - let empty = NSData() + let empty = Data() let readData = binFile.readData() ?? empty - XCTAssertEqual( readData, empty ) + XCTAssertEqual(readData, empty) } } @@ -431,10 +427,10 @@ class SwiftFilePathTests: XCTestCase { let result = Result(success:200); switch result { - case .Success(let value): + case .success(let value): callOnSuccess = true print(value) - case .Failure(let error): + case .failure(let error): callOnFailure = true print(error) } @@ -448,10 +444,10 @@ class SwiftFilePathTests: XCTestCase { let result = Result(failure: "ERROR!!!"); switch result { - case .Success(let value): + case .success(let value): callOnSuccess = true print(value) - case .Failure(let error): + case .failure(let error): callOnFailure = true print(error) } @@ -460,4 +456,4 @@ class SwiftFilePathTests: XCTestCase { } } -} \ No newline at end of file +}