Skip to content

Instantly share code, notes, and snippets.

Created December 20, 2009 09:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save anonymous/260411 to your computer and use it in GitHub Desktop.
Save anonymous/260411 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""A Python git pre-commit script for Go programming language projects.
Install the script by putting it in .git/hooks/ directory in your project
directory. The script file must be called "pre-commit". Make sure the
executable flag in the script file is set. The script assumes you are building
your project with make.
The script makes sure that all go source files in the project have valid
formatting and that the project unit tests pass before allowing the commit to
proceed. The script checks out the git index of the project into a temporary
directory. It checks gofmt validity by running gofmt on each *.go file and
checking that the output is identical to the original file with diff. It runs
unit tests by doing "make test" at the project root and checking the return
value. Gofmt check is done before "make test" so that generated .go files
won't be involved in the format check.
You can bypass the check with the "--no-verify" flag to git commit."""
import os
import os.path
import tempfile
import shutil
import sys
from subprocess import *
def git_checkout_index(path):
call("git checkout-index --prefix=%s/ -a" % path, shell=True)
def file_needs_gofmt(filepath):
p1 = Popen(["gofmt", filepath], stdout=PIPE)
p2 = Popen(["diff", "-", filepath], stdin=p1.stdout, stdout=open(os.devnull, 'w'))
return os.waitpid(p2.pid, 0)[1]
def files_needing_gofmt(path):
need_gofmt = []
for root, dirs, files in os.walk(path):
for gofile in [x for x in files if x.endswith('.go')]:
if file_needs_gofmt(os.path.join(root, gofile)):
need_gofmt.append(gofile)
return need_gofmt
def gofmt_check(path):
need_gofmt = files_needing_gofmt(path)
if need_gofmt:
for gofile in need_gofmt:
print gofile, "needs gofmt."
sys.exit(1)
def unittest_check(path):
status = call("make test", shell=True, cwd=path)
if status:
print "Unit test(s) failed."
sys.exit(1)
def main():
tmpdir = tempfile.mkdtemp()
try:
git_checkout_index(tmpdir)
gofmt_check(tmpdir)
unittest_check(tmpdir)
finally:
shutil.rmtree(tmpdir)
if __name__=='__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment