Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions Sources/CommitPrefix/CPInterface.swift
Original file line number Diff line number Diff line change
@@ -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

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CPFileHandler.swift
// CPInterfaceImpl.swift
// commitPrefix
//
// MIT License
Expand All @@ -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:
Expand All @@ -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()
}

}
2 changes: 1 addition & 1 deletion Sources/CommitPrefix/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Foundation

struct CPInfo {

static let version = "1.4.0"
static let version = "1.4.2"

}

Expand Down
17 changes: 11 additions & 6 deletions Sources/CommitPrefix/Error+Debug/CPDebugPrint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
153 changes: 79 additions & 74 deletions Sources/CommitPrefix/Hook/CommitMessageHookContents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ struct CommitMessageHookContents {

let fileIdentifier = "Created by CommitPrefix \(CPInfo.version)"

private let tab = "<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
Expand All @@ -45,36 +48,38 @@ struct CommitMessageHookContents {
//

import Foundation

\(renderEnumIOError())

\(renderStructIOCommitPrefix())

\(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)}

}
"""
Expand All @@ -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)

}
"""
Expand Down
Loading