github.com/twelho/conform@v0.0.0-20231016230407-c25e9238598a/internal/policy/commit/check_imperative_verb.go (about)

     1  // This Source Code Form is subject to the terms of the Mozilla Public
     2  // License, v. 2.0. If a copy of the MPL was not distributed with this
     3  // file, You can obtain one at http://mozilla.org/MPL/2.0/.
     4  
     5  package commit
     6  
     7  import (
     8  	"strings"
     9  
    10  	"github.com/pkg/errors"
    11  	"gopkg.in/jdkato/prose.v2"
    12  
    13  	"github.com/twelho/conform/internal/policy"
    14  )
    15  
    16  // ImperativeCheck enforces that the first word of a commit message header is
    17  // and imperative verb.
    18  type ImperativeCheck struct {
    19  	errors []error
    20  }
    21  
    22  // Name returns the name of the check.
    23  func (i ImperativeCheck) Name() string {
    24  	return "Imperative Mood"
    25  }
    26  
    27  // Message returns to check message.
    28  func (i ImperativeCheck) Message() string {
    29  	if len(i.errors) != 0 {
    30  		return i.errors[0].Error()
    31  	}
    32  
    33  	return "Commit begins with imperative verb"
    34  }
    35  
    36  // Errors returns any violations of the check.
    37  func (i ImperativeCheck) Errors() []error {
    38  	return i.errors
    39  }
    40  
    41  // ValidateImperative checks the commit message for a GPG signature.
    42  func (c Commit) ValidateImperative() policy.Check { //nolint:ireturn
    43  	check := &ImperativeCheck{}
    44  
    45  	var (
    46  		word string
    47  		err  error
    48  	)
    49  
    50  	if word, err = c.firstWord(); err != nil {
    51  		check.errors = append(check.errors, err)
    52  
    53  		return check
    54  	}
    55  
    56  	doc, err := prose.NewDocument("I " + strings.ToLower(word))
    57  	if err != nil {
    58  		check.errors = append(check.errors, errors.Errorf("Failed to create document: %v", err))
    59  
    60  		return check
    61  	}
    62  
    63  	if len(doc.Tokens()) != 2 {
    64  		check.errors = append(check.errors, errors.Errorf("Expected 2 tokens, got %d", len(doc.Tokens())))
    65  
    66  		return check
    67  	}
    68  
    69  	tokens := doc.Tokens()
    70  	tok := tokens[1]
    71  
    72  	for _, tag := range []string{"VBD", "VBG", "VBZ"} {
    73  		if tok.Tag == tag {
    74  			check.errors = append(check.errors, errors.Errorf("First word of commit must be an imperative verb: %q is invalid", word))
    75  		}
    76  	}
    77  
    78  	return check
    79  }