Skip to content

Instantly share code, notes, and snippets.

@pfctgeorge
Last active November 23, 2015 12:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pfctgeorge/775c8b0b7ca7ba812e87 to your computer and use it in GitHub Desktop.
Save pfctgeorge/775c8b0b7ca7ba812e87 to your computer and use it in GitHub Desktop.
Git hooks
#!/env/python
# coding: utf-8
from subprocess import check_output, PIPE, Popen
import sys
import re
BADREV = "0000000000000000000000000000000000000000"
def is_binary_file(filename):
regex = ('\.(pdb|dll|exe|png|gif|jpg|mwb|zip|tgz|gz|bz2|7z'
'|rar|swf|fla|jar|mo|ttf|foo|mp3|icc|pdf|bmp|wmf|otf)$')
return re.search(regex, filename) is not None
def is_merging_commit(rev):
s = check_output(["git", "rev-list", "--parents", "-n", "1", rev])
return len(s.split()) - 1 >= 2
def is_fixed_issue(rev):
commit_message = check_output(["git", "show", "-s",
"--format=format:%s", rev]).strip()
return re.match("Fixes \#\d+: ", commit_message) is not None
def check_crlf(rev):
diff_tree = check_output(["git", "diff-tree", "-r", rev]).strip()
for line in diff_tree.split("\n")[1:]:
(old_mode, new_mode, old_sha1, new_sha1, _, name) = line.split()
# skip checking for deleted file and binary file
if new_sha1 == BADREV or is_binary_file(name):
continue
p1 = Popen(["git", "cat-file", "blob", new_sha1], stdout=PIPE)
p2 = Popen(["grep -c $'\x0D'"], stdin=p1.stdout, stdout=PIPE,
shell=True)
p1.stdout.close()
if (int(p2.communicate()[0]) > 0):
return False
return True
def print_error_message_for_not_fixing_issue_commit(rev):
print "###########################################################"
print "# The message of commit [%s] should be" % rev[0:7]
print "# started with `Fixes #:issue-id` format."
print "# please run `git rebase -i` to deal with."
print "############################################################"
def print_error_message_for_crlf_commit(rev):
print "############################################################"
print "# One or more files in commit [%s] contained CRLF" % rev[0:7]
print "# line endings which are not allowed. Please visit"
print "# https://help.github.com/articles/dealing-with-line-endings"
print "# for correct configuration and re-commit the change."
print "############################################################"
def check_rev(rev):
# skip checking for merging commit
if is_merging_commit(rev):
return True
if not is_fixed_issue(rev):
print_error_message_for_not_fixing_issue_commit(rev)
return False
if not check_crlf(rev):
print_error_message_for_crlf_commit(rev)
return False
return True
if __name__ == "__main__":
for line in sys.stdin:
old, new, ref = line.strip().split()
if new == BADREV:
continue
if old == BADREV:
# try to push a new branch
refs = check_output(["git", "for-each-ref", "--format=%(refname)",
"refs/heads/*"]).strip().split("\n")
for ref in refs:
for rev in check_output(["git", "rev-list", "--topo-order",
"--reverse", "%s...%s" % (new, ref)
]).strip().split("\n"):
if not check_rev(rev):
exit(1)
exit(0)
for rev in check_output(["git", "rev-list",
"--topo-order", "--reverse",
"%s...%s" % (new, old)]).strip().split("\n"):
if not check_rev(rev):
exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment