From 67efb917b944608a98655cb11696ad03fa3252a1 Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:42:37 -0800 Subject: [PATCH 1/6] [CPFeature-008] Fixed Hook Script formatting issue with multi line string literals --- .../ArgumentBuilder.swift | 0 .../CLIArguments.swift | 0 Sources/CommitPrefix/CPInterface.swift | 44 +++++ ...ileHandler.swift => CPInterfaceImpl.swift} | 27 ++-- .../Hook/CommitMessageHookContents.swift | 153 +++++++++--------- 5 files changed, 141 insertions(+), 83 deletions(-) rename Sources/CommitPrefix/{Interface => CLInterface}/ArgumentBuilder.swift (100%) rename Sources/CommitPrefix/{Interface => CLInterface}/CLIArguments.swift (100%) create mode 100644 Sources/CommitPrefix/CPInterface.swift rename Sources/CommitPrefix/{CPFileHandler.swift => CPInterfaceImpl.swift} (75%) diff --git a/Sources/CommitPrefix/Interface/ArgumentBuilder.swift b/Sources/CommitPrefix/CLInterface/ArgumentBuilder.swift similarity index 100% rename from Sources/CommitPrefix/Interface/ArgumentBuilder.swift rename to Sources/CommitPrefix/CLInterface/ArgumentBuilder.swift diff --git a/Sources/CommitPrefix/Interface/CLIArguments.swift b/Sources/CommitPrefix/CLInterface/CLIArguments.swift similarity index 100% rename from Sources/CommitPrefix/Interface/CLIArguments.swift rename to Sources/CommitPrefix/CLInterface/CLIArguments.swift diff --git a/Sources/CommitPrefix/CPInterface.swift b/Sources/CommitPrefix/CPInterface.swift new file mode 100644 index 0000000..2ffab05 --- /dev/null +++ b/Sources/CommitPrefix/CPInterface.swift @@ -0,0 +1,44 @@ +// +// CPInterface.swift +// commitPrefix +// +// MIT License +// +// Copyright (c) 2020 STEPHEN L. MARTINEZ +// +// 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 Consler +import Foundation + +public protocol CPInterface { + + func outputPrefixes() throws -> ConslerOutput + + func viewState() throws -> ConslerOutput + + func deletePrefixes() throws -> ConslerOutput + + func writeNew(prefixes rawValue: String) throws -> ConslerOutput + + func activateBranchMode(with validator: String) throws -> ConslerOutput + + func activateNormalMode() throws -> ConslerOutput + +} diff --git a/Sources/CommitPrefix/CPFileHandler.swift b/Sources/CommitPrefix/CPInterfaceImpl.swift similarity index 75% rename from Sources/CommitPrefix/CPFileHandler.swift rename to Sources/CommitPrefix/CPInterfaceImpl.swift index ad332ac..6b422ac 100644 --- a/Sources/CommitPrefix/CPFileHandler.swift +++ b/Sources/CommitPrefix/CPInterfaceImpl.swift @@ -28,24 +28,29 @@ import Consler import Foundation import Files -struct CPFileHandler { +struct CommitPrefix: CPInterface { - private let cpInteractor: CPInteractor + private init() {} - init() throws { + private func getInteractor() throws -> CPInteractor { guard Folder.current.containsSubfolder(named: FolderName.git) else { throw CPError.notAGitRepo(currentLocation: Folder.current.path) } let gitDirectory = try Folder.current.subfolder(named: FolderName.git) - self.cpInteractor = try CPInteractor(gitDirectory: gitDirectory) try CommitMessageHook.findOrCreate(with: gitDirectory) + let cpInteractor = try CPInteractor(gitDirectory: gitDirectory) + return cpInteractor } + public static func interface() -> CPInterface { CommitPrefix() } + func outputPrefixes() throws -> ConslerOutput { - try cpInteractor.outputPrefixes() + let cpInteractor = try getInteractor() + return try cpInteractor.outputPrefixes() } func viewState() throws -> ConslerOutput { + let cpInteractor = try getInteractor() let cpState = try cpInteractor.getCommitPrefixState() switch cpState.mode { case .normal: @@ -63,19 +68,23 @@ struct CPFileHandler { } func deletePrefixes() throws -> ConslerOutput { - try cpInteractor.deletePrefixes() + let cpInteractor = try getInteractor() + return try cpInteractor.deletePrefixes() } func writeNew(prefixes rawValue: String) throws -> ConslerOutput { - try cpInteractor.writeNew(prefixes: rawValue) + let cpInteractor = try getInteractor() + return try cpInteractor.writeNew(prefixes: rawValue) } func activateBranchMode(with validator: String) throws -> ConslerOutput { - try cpInteractor.activateBranchMode(with: validator) + let cpInteractor = try getInteractor() + return try cpInteractor.activateBranchMode(with: validator) } func activateNormalMode() throws -> ConslerOutput { - try cpInteractor.activateNormalMode() + let cpInteractor = try getInteractor() + return try cpInteractor.activateNormalMode() } } diff --git a/Sources/CommitPrefix/Hook/CommitMessageHookContents.swift b/Sources/CommitPrefix/Hook/CommitMessageHookContents.swift index 753a42b..8b6ec65 100644 --- a/Sources/CommitPrefix/Hook/CommitMessageHookContents.swift +++ b/Sources/CommitPrefix/Hook/CommitMessageHookContents.swift @@ -30,13 +30,16 @@ struct CommitMessageHookContents { let fileIdentifier = "Created by CommitPrefix \(CPInfo.version)" + private let tab = "" + private var currentDate: String { let formatter = DateFormatter() formatter.dateFormat = "MM/dd/yyyy" return formatter.string(from: Date()) } - func renderScript() -> String { """ + func renderScript() -> String { + let script = """ #!/usr/bin/env swift // // Commit-msg @@ -45,7 +48,7 @@ struct CommitMessageHookContents { // import Foundation - + \(renderEnumIOError()) \(renderStructIOCommitPrefix()) @@ -53,28 +56,30 @@ struct CommitMessageHookContents { \(renderMainDoTryCatch()) """ + + return script.replacingOccurrences(of: tab, with: " ") } private func renderEnumIOError() -> String { """ enum IOError: Error { - case invalidArgument - case overwriteError - case commitPrefixError - - var message: String { - switch self { - case .invalidArgument: - return "Intended to recieve .git/COMMIT_EDITMSG arg" - case .overwriteError: - return "There was an error writting to the commit message" - case .commitPrefixError: - return \"\"\" + \(tab)case invalidArgument + \(tab)case overwriteError + \(tab)case commitPrefixError + + \(tab)var message: String { + \(tab + tab)switch self { + \(tab + tab)case .invalidArgument: + \(tab + tab + tab)return "Intended to recieve .git/COMMIT_EDITMSG arg" + \(tab + tab)case .overwriteError: + \(tab + tab + tab)return "There was an error writting to the commit message" + \(tab + tab)case .commitPrefixError: + \(tab + tab + tab)return \"\"\" - - CommitPrefix Error - \"\"\" - } - } + \(tab + tab + tab)- CommitPrefix Error + \(tab + tab + tab)\"\"\" + \(tab + tab)} + \(tab)} } """ @@ -83,102 +88,102 @@ struct CommitMessageHookContents { private func renderStructIOCommitPrefix() -> String { """ struct IOCommitPrefix { - let commitMsgPath: String + \(tab)let commitMsgPath: String - init(filePath: [String] = Array(CommandLine.arguments.dropFirst())) throws { - guard let firstArg = filePath.first else { throw IOError.invalidArgument } - self.commitMsgPath = firstArg - } + \(tab)init(filePath: [String] = Array(CommandLine.arguments.dropFirst())) throws { + \(tab + tab)guard let firstArg = filePath.first else { throw IOError.invalidArgument } + \(tab + tab)self.commitMsgPath = firstArg + \(tab)} - \(renderIOCPMethodGetPrefixes()) + \(renderIOCPMethodGetPrefixes()) - \(renderIOCPMethodGetCommitMessage()) + \(renderIOCPMethodGetCommitMessage()) + + \(renderIOCPMethodOverwriteContents()) - \(renderIOCPMethodOverwriteContents()) - } """ } private func renderIOCPMethodGetPrefixes() -> String { """ - func getPrefixes() throws -> String { - let readProcess = Process() - readProcess.launchPath = "/usr/bin/env" + \(tab)func getPrefixes() throws -> String { + \(tab + tab)let readProcess = Process() + \(tab + tab)readProcess.launchPath = "/usr/bin/env" - var readProcessEnv = ProcessInfo.processInfo.environment - let paths = readProcessEnv["PATH"] - paths.map { readProcessEnv["PATH"] = "/usr/local/bin:\\($0)" } + \(tab + tab)var readProcessEnv = ProcessInfo.processInfo.environment + \(tab + tab)let paths = readProcessEnv["PATH"] + \(tab + tab)paths.map { readProcessEnv["PATH"] = "/usr/local/bin:\\($0)" } - readProcess.environment = readProcessEnv - readProcess.arguments = ["commitPrefix", "-o"] + \(tab + tab)readProcess.environment = readProcessEnv + \(tab + tab)readProcess.arguments = ["commitPrefix", "-o"] - let pipe = Pipe() - readProcess.standardOutput = pipe - readProcess.launch() + \(tab + tab)let pipe = Pipe() + \(tab + tab)readProcess.standardOutput = pipe + \(tab + tab)readProcess.launch() - readProcess.waitUntilExit() + \(tab + tab)readProcess.waitUntilExit() - if readProcess.terminationStatus != 0 { - throw IOError.commitPrefixError - } + \(tab + tab)if readProcess.terminationStatus != 0 { + \(tab + tab + tab)throw IOError.commitPrefixError + \(tab + tab)} - let data = pipe.fileHandleForReading.readDataToEndOfFile() - let contents = String(data: data, encoding: .utf8) + \(tab + tab)let data = pipe.fileHandleForReading.readDataToEndOfFile() + \(tab + tab)let contents = String(data: data, encoding: .utf8) - return contents ?? "" - } + \(tab + tab)return contents ?? "" + \(tab)} """ } private func renderIOCPMethodGetCommitMessage() -> String { """ - func getCommitMessage() -> String { - let readProcess = Process() - readProcess.launchPath = "/usr/bin/env" - readProcess.arguments = ["cat", commitMsgPath] + \(tab)func getCommitMessage() -> String { + \(tab + tab)let readProcess = Process() + \(tab + tab)readProcess.launchPath = "/usr/bin/env" + \(tab + tab)readProcess.arguments = ["cat", commitMsgPath] - let pipe = Pipe() - readProcess.standardOutput = pipe - readProcess.launch() + \(tab + tab)let pipe = Pipe() + \(tab + tab)readProcess.standardOutput = pipe + \(tab + tab)readProcess.launch() - readProcess.waitUntilExit() + \(tab + tab)readProcess.waitUntilExit() - let data = pipe.fileHandleForReading.readDataToEndOfFile() - let contents = String(data: data, encoding: .utf8) + \(tab + tab)let data = pipe.fileHandleForReading.readDataToEndOfFile() + \(tab + tab)let contents = String(data: data, encoding: .utf8) - return contents ?? "" - } + \(tab + tab)return contents ?? "" + \(tab)} """ } private func renderIOCPMethodOverwriteContents() -> String { """ - func overwriteContents(with contents: String) throws { - do { - try contents.write(toFile: commitMsgPath, atomically: true, encoding: .utf8) - } catch { - throw IOError.overwriteError - } - } + \(tab)func overwriteContents(with contents: String) throws { + \(tab + tab)do { + \(tab + tab + tab)try contents.write(toFile: commitMsgPath, atomically: true, encoding: .utf8) + \(tab + tab)} catch { + \(tab + tab + tab)throw IOError.overwriteError + \(tab + tab)} + \(tab)} """ } private func renderMainDoTryCatch() -> String { """ do { - let ioCommitPrefix = try IOCommitPrefix() + \(tab)let ioCommitPrefix = try IOCommitPrefix() - let prefixes = try ioCommitPrefix.getPrefixes() - .trimmingCharacters(in: .newlines) + \(tab)let prefixes = try ioCommitPrefix.getPrefixes() + \(tab + tab).trimmingCharacters(in: .newlines) - let commitMessage = ioCommitPrefix.getCommitMessage() - .trimmingCharacters(in: .newlines) + \(tab)let commitMessage = ioCommitPrefix.getCommitMessage() + \(tab + tab).trimmingCharacters(in: .newlines) - let newCommitMessage = [prefixes, commitMessage].joined(separator: " ") - try ioCommitPrefix.overwriteContents(with: newCommitMessage) + \(tab)let newCommitMessage = [prefixes, commitMessage].joined(separator: " ") + \(tab)try ioCommitPrefix.overwriteContents(with: newCommitMessage) } catch let ioError as IOError { - print(ioError.message) - exit(1) + \(tab)print(ioError.message) + \(tab)exit(1) } """ From 6ab6174d5e44de3df1d2d11d101fa0116e25dba2 Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:44:35 -0800 Subject: [PATCH 2/6] [CPFeature-008] Changed the debug print to use a multiline string literal --- .../CommitPrefix/Error+Debug/CPDebugPrint.swift | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/CommitPrefix/Error+Debug/CPDebugPrint.swift b/Sources/CommitPrefix/Error+Debug/CPDebugPrint.swift index 393abcd..4b8701e 100644 --- a/Sources/CommitPrefix/Error+Debug/CPDebugPrint.swift +++ b/Sources/CommitPrefix/Error+Debug/CPDebugPrint.swift @@ -35,10 +35,15 @@ private let isDebugMode = false /// A Debug Printer that only prints in debug mode func cpDebugPrint(_ value: Any, file: String = #file, line: Int = #line, function: String = #function) { guard isDebugMode else { return } - print("********** Commit Prefix Debug **********") - print("File: \(file)") - print("Line: \(line)") - print("Function: \(function)") - print("value: ", value) - print("*****************************************") + let debugOutput = """ + + ********** Commit Prefix Debug ********** + File: \(file) + Line: \(line) + Function: \(function) + value: \(value) + ***************************************** + + """ + print(debugOutput) } From a0d4a1632c8d04a47737d7a385524571f73b68bf Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:44:50 -0800 Subject: [PATCH 3/6] [CPFeature-008] Updated the patch number --- Sources/CommitPrefix/Constants.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CommitPrefix/Constants.swift b/Sources/CommitPrefix/Constants.swift index dc864cb..d207427 100644 --- a/Sources/CommitPrefix/Constants.swift +++ b/Sources/CommitPrefix/Constants.swift @@ -28,7 +28,7 @@ import Foundation struct CPInfo { - static let version = "1.4.0" + static let version = "1.4.2" } From 2f3cee167bbd8bc1d6f149795b806b7e6ce97f48 Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:45:44 -0800 Subject: [PATCH 4/6] [CPFeature-008] Added the CPInterface protocol --- Sources/CommitPrefix/CPInterface.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/CommitPrefix/CPInterface.swift b/Sources/CommitPrefix/CPInterface.swift index 2ffab05..4fac37b 100644 --- a/Sources/CommitPrefix/CPInterface.swift +++ b/Sources/CommitPrefix/CPInterface.swift @@ -27,7 +27,9 @@ import Consler import Foundation -public protocol CPInterface { +protocol CPInterface { + + func outputVersion() -> ConslerOutput func outputPrefixes() throws -> ConslerOutput From cecac8587eb65882ab7b89fc5eab11009cc614d8 Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:46:45 -0800 Subject: [PATCH 5/6] [CPFeature-008] Changed the CPFileHandler to be the CPInterface Implementation . Renamed it to CommitPrefix --- Sources/CommitPrefix/CPInterfaceImpl.swift | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Sources/CommitPrefix/CPInterfaceImpl.swift b/Sources/CommitPrefix/CPInterfaceImpl.swift index 6b422ac..09567be 100644 --- a/Sources/CommitPrefix/CPInterfaceImpl.swift +++ b/Sources/CommitPrefix/CPInterfaceImpl.swift @@ -1,5 +1,5 @@ // -// CPFileHandler.swift +// CPInterfaceImpl.swift // commitPrefix // // MIT License @@ -25,13 +25,15 @@ // SOFTWARE. import Consler -import Foundation import Files +import Foundation -struct CommitPrefix: CPInterface { +struct CommitPrefix { private init() {} + static func interface() -> CPInterface { CommitPrefix() } + private func getInteractor() throws -> CPInteractor { guard Folder.current.containsSubfolder(named: FolderName.git) else { throw CPError.notAGitRepo(currentLocation: Folder.current.path) @@ -42,13 +44,22 @@ struct CommitPrefix: CPInterface { return cpInteractor } - public static func interface() -> CPInterface { CommitPrefix() } +} + +// MARK: - CPInterface Conformances +extension CommitPrefix: CPInterface { func outputPrefixes() throws -> ConslerOutput { let cpInteractor = try getInteractor() return try cpInteractor.outputPrefixes() } + func outputVersion() -> ConslerOutput { + return ConslerOutput( + "CommitPrefix ", "version ", CPInfo.version) + .describedBy(.normal, .cyan, .cyan) + } + func viewState() throws -> ConslerOutput { let cpInteractor = try getInteractor() let cpState = try cpInteractor.getCommitPrefixState() From 1ee545315cc2314d6ed72dd37c767ff0f53c5232 Mon Sep 17 00:00:00 2001 From: Stephen Martinez Date: Thu, 2 Jan 2020 19:48:07 -0800 Subject: [PATCH 6/6] [CPFeature-008] Updated main with the new interface and changed version output to be more consistent with the other outputs --- Sources/CommitPrefix/main.swift | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/Sources/CommitPrefix/main.swift b/Sources/CommitPrefix/main.swift index b76fd93..c18c15d 100644 --- a/Sources/CommitPrefix/main.swift +++ b/Sources/CommitPrefix/main.swift @@ -27,45 +27,39 @@ import Consler import Foundation -let cpCommandLineInterface = CLIArguments() +let commandLineInterface = CLIArguments() +let cpInterface = CommitPrefix.interface() do { - switch try cpCommandLineInterface.getCommand() { + switch try commandLineInterface.getCommand() { case .outputVersion: - Consler.output( - "CommitPrefix ", "version ", CPInfo.version, - descriptors: [.normal, .cyan, .cyan]) + let versionOutput = cpInterface.outputVersion() + Consler.output(versionOutput) case .viewState: - let fileHandler = try CPFileHandler() - let viewStateOutput = try fileHandler.viewState() + let viewStateOutput = try cpInterface.viewState() Consler.output(viewStateOutput) case .outputPrefixes: - let fileHandler = try CPFileHandler() - let prefixesOutput = try fileHandler.outputPrefixes() + let prefixesOutput = try cpInterface.outputPrefixes() Consler.output(prefixesOutput) case .deletePrefixes: - let fileHandler = try CPFileHandler() - let deletionOutput = try fileHandler.deletePrefixes() + let deletionOutput = try cpInterface.deletePrefixes() Consler.output(deletionOutput) case .modeNormal: - let fileHandler = try CPFileHandler() - let normalModeOutput = try fileHandler.activateNormalMode() + let normalModeOutput = try cpInterface.activateNormalMode() Consler.output(normalModeOutput) case .modeBranchParse(validator: let rawValidatorValue): - let fileHandler = try CPFileHandler() - let branchModeOutput = try fileHandler.activateBranchMode(with: rawValidatorValue) + let branchModeOutput = try cpInterface.activateBranchMode(with: rawValidatorValue) Consler.output(branchModeOutput) case .newPrefixes(value: let rawPrefixValue): - let fileHandler = try CPFileHandler() - let newPrefixesOutput = try fileHandler.writeNew(prefixes: rawPrefixValue) + let newPrefixesOutput = try cpInterface.writeNew(prefixes: rawPrefixValue) Consler.output(newPrefixesOutput) }