From 72fd7f4a08f648273fac0ab49c7a11acbdafc8c8 Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 11:50:59 -0600 Subject: [PATCH 1/6] Improve rename API by making rename operation more explicit with ExtensionActions --- Sources/Files.swift | 87 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/Sources/Files.swift b/Sources/Files.swift index d01aa33..f85ae04 100644 --- a/Sources/Files.swift +++ b/Sources/Files.swift @@ -237,47 +237,112 @@ public class FileSystem { self.name = pathComponents[pathComponents.count - 2] } } - + + /// Actions that can be taken on an extension while renaming an item + public enum ExtensionAction { + /// Keep the item's current extension + case keep + /// Remove the item's current extenion + case remove + /// Change the item's extension to the contained String + case change(to: String) + } + /** * Rename the item * * - parameter newName: The new name that the item should have - * - parameter keepExtension: Whether the file should keep the same extension as it had before (defaults to `true`) + * - parameter extension: The action to take on the item's extension (defaults to .keep) * * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed */ - public func rename(to newName: String, keepExtension: Bool = true) throws { + public func rename(to newName: String, extension extensionAction: ExtensionAction = .keep) throws { guard let parent = parent else { throw OperationError.renameFailed(self) } - + var newName = newName - - if keepExtension { + + switch extensionAction { + case .keep: if let `extension` = `extension` { let extensionString = ".\(`extension`)" - + if !newName.hasSuffix(extensionString) { newName += extensionString } } + + case .remove: + if let `extension` = `extension` { + let extensionString = ".\(`extension`)" + + if newName.hasSuffix(extensionString) { + newName = String(newName.dropLast(extensionString.count)) + } + } + + case .change(var newExtension): + if !newExtension.hasPrefix(".") { + newExtension = "." + newExtension + } + + if !newName.hasSuffix(newExtension) { + newName += newExtension + } } - + var newPath = parent.path + newName - + if kind == .folder && !newPath.hasSuffix("/") { newPath += "/" } - + do { try fileManager.moveItem(atPath: path, toPath: newPath) - + name = newName path = newPath } catch { throw OperationError.renameFailed(self) } } + + /** + * Rename the item + * + * - parameter newName: The new name that the item should have + * - parameter newExtension: The new extension that the item should have + * + * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed + */ + public func rename(to newName: String, extension newExtension: String) throws { + try rename(to: newName, extension: .change(to: newExtension)) + } + + /** + * Rename the item + * + * - parameter newName: The new name that the item should have + * - parameter keepExtension: Whether the file should keep the same extension as it had before (defaults to `true`) + * + * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed + */ + public func rename(to newName: String, keepExtension: Bool) throws { + if keepExtension { + try rename(to: newName, extension: .keep) + } else { + let nameComponents = newName.components(separatedBy: ".") + let nameComponent = nameComponents[0] + let action: ExtensionAction + if nameComponents.count > 1 { + action = .change(to: nameComponents[1]) + } else { + action = .remove + } + try rename(to: nameComponent, extension: action) + } + } /** * Move this item to a new folder From 269b422a57881e2f06bfcf665f717f7cc0031834 Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 11:57:15 -0600 Subject: [PATCH 2/6] Add more tests for the new extension actions --- Tests/FilesTests/FilesTests.swift | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tests/FilesTests/FilesTests.swift b/Tests/FilesTests/FilesTests.swift index 4bd4e2c..2ebeee9 100644 --- a/Tests/FilesTests/FilesTests.swift +++ b/Tests/FilesTests/FilesTests.swift @@ -129,6 +129,27 @@ class FilesTests: XCTestCase { XCTAssertEqual(file.name, "other.txt") XCTAssertEqual(file.path, folder.path + "other.txt") XCTAssertEqual(file.extension, "txt") + + // Now try renaming the file using the extension actions + try file.rename(to: "some", extension: .keep) + XCTAssertEqual(file.name, "some.txt") + XCTAssertEqual(file.path, folder.path + "some.txt") + XCTAssertEqual(file.extension, "txt") + + try file.rename(to: "different", extension: .change(to: "pdf")) + XCTAssertEqual(file.name, "different.pdf") + XCTAssertEqual(file.path, folder.path + "different.pdf") + XCTAssertEqual(file.extension, "pdf") + + try file.rename(to: "another", extension: .remove) + XCTAssertEqual(file.name, "another") + XCTAssertEqual(file.path, folder.path + "another") + XCTAssertNil(file.extension) + + try file.rename(to: "lastOne", extension: ".png") + XCTAssertEqual(file.name, "lastOne.png") + XCTAssertEqual(file.path, folder.path + "lastOne.png") + XCTAssertEqual(file.extension, "png") } } From 2568e8151fb884ec40b84bef3b09c608fe0d115b Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 11:59:18 -0600 Subject: [PATCH 3/6] Reorder the methods to clean up diff --- Sources/Files.swift | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Sources/Files.swift b/Sources/Files.swift index f85ae04..6df2ee6 100644 --- a/Sources/Files.swift +++ b/Sources/Files.swift @@ -238,6 +238,30 @@ public class FileSystem { } } + /** + * Rename the item + * + * - parameter newName: The new name that the item should have + * - parameter keepExtension: Whether the file should keep the same extension as it had before (defaults to `true`) + * + * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed + */ + public func rename(to newName: String, keepExtension: Bool) throws { + if keepExtension { + try rename(to: newName, extension: .keep) + } else { + let nameComponents = newName.components(separatedBy: ".") + let nameComponent = nameComponents[0] + let action: ExtensionAction + if nameComponents.count > 1 { + action = .change(to: nameComponents[1]) + } else { + action = .remove + } + try rename(to: nameComponent, extension: action) + } + } + /// Actions that can be taken on an extension while renaming an item public enum ExtensionAction { /// Keep the item's current extension @@ -319,30 +343,6 @@ public class FileSystem { public func rename(to newName: String, extension newExtension: String) throws { try rename(to: newName, extension: .change(to: newExtension)) } - - /** - * Rename the item - * - * - parameter newName: The new name that the item should have - * - parameter keepExtension: Whether the file should keep the same extension as it had before (defaults to `true`) - * - * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed - */ - public func rename(to newName: String, keepExtension: Bool) throws { - if keepExtension { - try rename(to: newName, extension: .keep) - } else { - let nameComponents = newName.components(separatedBy: ".") - let nameComponent = nameComponents[0] - let action: ExtensionAction - if nameComponents.count > 1 { - action = .change(to: nameComponents[1]) - } else { - action = .remove - } - try rename(to: nameComponent, extension: action) - } - } /** * Move this item to a new folder From df6d7b39fd3d79877b60d36e59012aca365b859f Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 12:00:38 -0600 Subject: [PATCH 4/6] Remove documentation comment about defaulting to true --- Sources/Files.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Files.swift b/Sources/Files.swift index 6df2ee6..29d9e42 100644 --- a/Sources/Files.swift +++ b/Sources/Files.swift @@ -242,7 +242,7 @@ public class FileSystem { * Rename the item * * - parameter newName: The new name that the item should have - * - parameter keepExtension: Whether the file should keep the same extension as it had before (defaults to `true`) + * - parameter keepExtension: Whether the file should keep the same extension as it had before * * - throws: `FileSystem.Item.OperationError.renameFailed` if the item couldn't be renamed */ @@ -261,7 +261,7 @@ public class FileSystem { try rename(to: nameComponent, extension: action) } } - + /// Actions that can be taken on an extension while renaming an item public enum ExtensionAction { /// Keep the item's current extension From dd681733ace59a772decfeecab1a42fe1a1f9262 Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 14:59:57 -0600 Subject: [PATCH 5/6] Take last name component --- Sources/Files.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Files.swift b/Sources/Files.swift index 29d9e42..4abd37f 100644 --- a/Sources/Files.swift +++ b/Sources/Files.swift @@ -254,7 +254,7 @@ public class FileSystem { let nameComponent = nameComponents[0] let action: ExtensionAction if nameComponents.count > 1 { - action = .change(to: nameComponents[1]) + action = .change(to: nameComponents.last!) } else { action = .remove } From 2ae3511458795109811e892600a6c0eb24304c65 Mon Sep 17 00:00:00 2001 From: Clay Ellis Date: Fri, 1 Jun 2018 15:07:11 -0600 Subject: [PATCH 6/6] Add test to rename file with extension included in name --- Tests/FilesTests/FilesTests.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/FilesTests/FilesTests.swift b/Tests/FilesTests/FilesTests.swift index 2ebeee9..5e92e41 100644 --- a/Tests/FilesTests/FilesTests.swift +++ b/Tests/FilesTests/FilesTests.swift @@ -141,6 +141,11 @@ class FilesTests: XCTestCase { XCTAssertEqual(file.path, folder.path + "different.pdf") XCTAssertEqual(file.extension, "pdf") + try file.rename(to: "oneMore.txt", extension: .change(to: "txt")) + XCTAssertEqual(file.name, "oneMore.txt") + XCTAssertEqual(file.path, folder.path + "oneMore.txt") + XCTAssertEqual(file.extension, "txt") + try file.rename(to: "another", extension: .remove) XCTAssertEqual(file.name, "another") XCTAssertEqual(file.path, folder.path + "another")