diff --git a/bin/lint b/bin/lint new file mode 100755 index 00000000..9f5d3c89 --- /dev/null +++ b/bin/lint @@ -0,0 +1,81 @@ +#!/bin/bash +# This scipt lints go files for common errors. +# +# Its runs gofmt and go vet, and optionally golint and +# gocyclo, if they are installed. +# +# With no arguments, it lints the current files staged +# for git commit. Or you can pass it explicit filenames +# (or directories) and it will lint them. +# +# To use this script automatically, run: +# ln -s ../../bin/lint .git/hooks/pre-commit + +set -eu + +function lint_go { + filename="$1" + result=0 + + if [ -n "$(gofmt -l "${filename}")" ]; then + result=1 + echo "${filename}: run gofmt -w ${filename}!" + fi + + go tool vet "${filename}" || result=$? + + # golint is completely optional. If you don't like it + # don't have it installed. + if type golint >/dev/null 2>&1; then + # golint doesn't set an exit code it seems + lintoutput=$(golint "${filename}") + if [ "$lintoutput" != "" ]; then + result=1 + echo "$lintoutput" + fi + fi + + # gocyclo is completely optional. If you don't like it + # don't have it installed. Also never blocks a commit, + # it just warns. + if type gocyclo >/dev/null 2>&1; then + gocyclo -over 25 "${filename}" | while read line; do + echo "${filename}": higher than 25 cyclomatic complexity - "${line}" + done + fi + + return $result +} + +function lint { + filename="$1" + ext="${filename##*\.}" + + # Don't lint this script + if [ "${filename}" = "bin/lint" ]; then + return + fi + + case "$ext" in + go) lint_go "${filename}" + ;; + esac +} + +function lint_files { + result=0 + while read filename; do + lint "${filename}" || result=1 + done + exit $result +} + +function list_files { + if [ $# -gt 0 ]; then + find "$@" -type f + else + git diff --cached --name-only + fi +} + +list_files "$@" | lint_files