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..4fac37b --- /dev/null +++ b/Sources/CommitPrefix/CPInterface.swift @@ -0,0 +1,46 @@ +// +// 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 + +protocol CPInterface { + + func outputVersion() -> ConslerOutput + + 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 70% rename from Sources/CommitPrefix/CPFileHandler.swift rename to Sources/CommitPrefix/CPInterfaceImpl.swift index ad332ac..09567be 100644 --- a/Sources/CommitPrefix/CPFileHandler.swift +++ b/Sources/CommitPrefix/CPInterfaceImpl.swift @@ -1,5 +1,5 @@ // -// CPFileHandler.swift +// CPInterfaceImpl.swift // commitPrefix // // MIT License @@ -25,27 +25,43 @@ // SOFTWARE. import Consler -import Foundation import Files +import Foundation -struct CPFileHandler { +struct CommitPrefix { - private let cpInteractor: CPInteractor + private init() {} - init() throws { + 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) } 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 } +} + +// MARK: - CPInterface Conformances +extension CommitPrefix: CPInterface { + func outputPrefixes() throws -> ConslerOutput { - try cpInteractor.outputPrefixes() + 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() switch cpState.mode { case .normal: @@ -63,19 +79,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/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" } 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) } 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) } """ 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) }