diff --git a/README.md b/README.md index 3bb177e..15b4181 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ further [reference](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). curl -o install.sh -L https://raw.githubusercontent.com/rockstaedt/commit-message-check/main/install.sh && chmod +x ./install.sh && ./install.sh ``` -## Usage +## Usage (Deprecated) Every time a git commit is made, the corresponding hook is fired. For a commit message that is too long (>50 characters), the commit process is diff --git a/cmd/handler.go b/cmd/handler.go index baa7ca3..8ad93f3 100644 --- a/cmd/handler.go +++ b/cmd/handler.go @@ -10,6 +10,7 @@ import ( type Handler struct { Config model.Config Writer io.Writer + Reader io.Reader } func NewHandler(config model.Config) *Handler { diff --git a/cmd/validate.go b/cmd/validate.go index 7934e38..e147d1e 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -27,8 +27,19 @@ func (h *Handler) validate() int { } if numOfExceedingChars > (hardLimit - softLimit) { - h.notify("Abort commit. Subject line too long. Please fix.", "red") - return 1 + h.notify("Subject line too long. Do you want to abort? (y/n)", "red") + + var decision string + if _, err := fmt.Fscanln(h.Reader, &decision); err != nil { + h.notify("Could not read user input.", "red") + return 1 + } + + if decision == "y" { + return 1 + } + + return 0 } message := fmt.Sprintf("Your subject exceeds the soft limit of 50 chars by %d chars.", numOfExceedingChars) diff --git a/cmd/validate_test.go b/cmd/validate_test.go index 16458b9..813db66 100644 --- a/cmd/validate_test.go +++ b/cmd/validate_test.go @@ -40,8 +40,7 @@ func TestValidate(t *testing.T) { assert.Contains(t, buffer.String(), "i am two characters more thäaaaaaaaaaaaaaaaaaaaan "+color.Yellow+"50") }) - t.Run("returns 1 when commit message too long", func(t *testing.T) { - buffer.Reset() + t.Run("asks user for abort when commit message too long", func(t *testing.T) { testFile := t.TempDir() + "/text.txt" content := "waaaaaaaaaaaaaaaaaaaaaaaaaay tooooooooooooooooooo" + "looooooooooooooooooooooong" @@ -50,10 +49,34 @@ func TestValidate(t *testing.T) { handler := NewHandler(model.Config{CommitMsgFile: testFile}) handler.Writer = buffer - status := handler.Run("validate") + t.Run("user confirms abort returns 1", func(t *testing.T) { + buffer.Reset() + handler.Reader = bytes.NewReader([]byte("y")) - assert.Contains(t, buffer.String(), color.Red+"Abort commit") - assert.Equal(t, 1, status) + status := handler.Run("validate") + + assert.Contains(t, buffer.String(), color.Red+"Subject line too long. Do you want to abort? (y/n)") + assert.Equal(t, 1, status) + }) + + t.Run("user declines abort returns 0", func(t *testing.T) { + buffer.Reset() + handler.Reader = bytes.NewReader([]byte("n")) + + status := handler.Run("validate") + + assert.Equal(t, 0, status) + }) + + t.Run("error at reading user input returns 1", func(t *testing.T) { + buffer.Reset() + handler.Reader = bytes.NewReader([]byte("")) + + status := handler.Run("validate") + + assert.Equal(t, 1, status) + assert.Contains(t, buffer.String(), color.Red+"Could not read user input.") + }) }) t.Run("returns 1 when error at reading file", func(t *testing.T) { diff --git a/main.go b/main.go index dbc743d..bdc55f9 100644 --- a/main.go +++ b/main.go @@ -61,6 +61,7 @@ func main() { handler := cmd.NewHandler(config) handler.Writer = os.Stdout + handler.Reader = os.Stdin os.Exit(handler.Run(os.Args[1])) } diff --git a/util/hook.go b/util/hook.go index 9e4a914..17b44f1 100644 --- a/util/hook.go +++ b/util/hook.go @@ -52,6 +52,7 @@ func DeleteHook(path, _ string) error { func writeContent(writer io.Writer, exePath string) { _, err := fmt.Fprint(writer, "#!/bin/sh\n\n") + _, err = fmt.Fprint(writer, "exec < /dev/tty\n\n") _, err = fmt.Fprintf(writer, `"%s/commit-message-check" validate $1`, exePath) _, err = fmt.Fprint(writer, "\n") diff --git a/util/hook_test.go b/util/hook_test.go index df994dd..f6d063b 100644 --- a/util/hook_test.go +++ b/util/hook_test.go @@ -136,6 +136,7 @@ func TestWriteContent(t *testing.T) { writeContent(buffer, "usr/tmp") assert.Contains(t, buffer.String(), "#!/bin/sh\n\n") + assert.Contains(t, buffer.String(), "exec < /dev/tty\n\n") }) t.Run("executes commit-message-check with root path and quotes path to handle spaces", func(t *testing.T) {