diff --git a/git/commits.go b/git/commits.go index 2d2f5d2..8ae5790 100644 --- a/git/commits.go +++ b/git/commits.go @@ -57,6 +57,19 @@ var FieldNames = map[string]string{ "%G?": "verification_flag", } +// Show returns the diff of a commit. +// +// NOTE: This could be expensive for very large commits. +func Show(commit string) ([]byte, error) { + cmd := exec.Command("git", "show", commit) + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + return nil, err + } + return out, nil +} + // CommitEntry represents a single commit's information from `git`. // See also FieldNames type CommitEntry map[string]string diff --git a/main.go b/main.go index 9ff0322..7d90296 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "os" "strings" + _ "github.com/vbatts/git-validation/rules/danglingwhitespace" _ "github.com/vbatts/git-validation/rules/dco" _ "github.com/vbatts/git-validation/rules/shortsubject" "github.com/vbatts/git-validation/validate" diff --git a/rules/danglingwhitespace/rule.go b/rules/danglingwhitespace/rule.go new file mode 100644 index 0000000..d55ddb5 --- /dev/null +++ b/rules/danglingwhitespace/rule.go @@ -0,0 +1,49 @@ +package danglingwhitespace + +import ( + "bytes" + "fmt" + + "github.com/vbatts/git-validation/git" + "github.com/vbatts/git-validation/validate" +) + +var ( + // DanglingWhitespace is the rule for checking the presence of dangling + // whitespaces on line endings. + DanglingWhitespace = validate.Rule{ + Name: "dangling-whitespace", + Description: "checking the presence of dangling whitespaces on line endings", + Run: ValidateDanglingWhitespace, + } +) + +func init() { + validate.RegisterRule(DanglingWhitespace) +} + +func ValidateDanglingWhitespace(c git.CommitEntry) (vr validate.Result) { + diff, err := git.Show(c["commit"]) + if err != nil { + return validate.Result{Pass: false, Msg: err.Error(), CommitEntry: c} + } + + vr.CommitEntry = c + vr.Pass = true + for _, line := range bytes.Split(diff, newLine) { + if !bytes.HasPrefix(line, diffAddLine) || bytes.Equal(line, diffAddLine) { + continue + } + if len(bytes.TrimSpace(line)) != len(line) { + vr.Pass = false + vr.Msg = fmt.Sprintf("line %q has trailiing spaces", string(line)) + } + } + vr.Msg = "all added diff lines do not have trailing spaces" + return +} + +var ( + newLine = []byte("\n") + diffAddLine = []byte("+ ") +)