From: Gary Benson <gbenson@redhat.com>
To: Joel Brobecker <brobecker@adacore.com>
Cc: Mike Frysinger <vapier@gentoo.org>,
gdb@sourceware.org,
Andreas Arnez <arnez@linux.vnet.ibm.com>
Subject: Re: ChangeLogs in commit messages
Date: Fri, 15 Aug 2014 15:02:00 -0000 [thread overview]
Message-ID: <20140815150202.GA5674@blade.nx> (raw)
In-Reply-To: <20140815132816.GC6019@adacore.com>
Joel Brobecker wrote:
> > Does anybody have any experience writing such checks? Or, does
> > anybody know of any project that already uses such checks? I can
> > look into doing it myself (it's a pre-receive hook, right?)
>
> I have loads of experience writing git hooks, but none with
> this repository's implementation.
>
> I would typically adjust the "update" hook for that, but it looks
> like the "pre-receive" hook would also work.
I've put together a quick pre-receive hook (inlined below). Each
received commit on the "master" branch that touches the "gdb"
subdirectory gets its message checked. The check itself is fairly
cursory: it splits the message using the "YYYY-MM-DD NAME <EMAIL>"
headers, checks each is preceeded by a path starting with "gdb/" and
ending with "/", and checks each is followed by more "NAME <EMAIL>"
lines, blank lines, or lines starting with tab. I don't know how
comprehensive we want to be here as the message should already have
been checked over by the reviewer.
I've never done anything server-side with git before, so there may
well be things I'm missing here. I was mainly experimenting to see
how difficult this all was :)
Cheers,
Gary
--
#!/usr/bin/env python
import re
import subprocess
import sys
GIT = "/usr/bin/git"
SHA1HASH = re.compile(r"^[0-9a-f]{40}$", re.IGNORECASE)
name_mail = r".* <[^@]+@[^>]+>$"
CL_HDR_A = re.compile(r"^\d{4}-\d{2}-\d{2} " + name_mail)
CL_HDR_B = re.compile(r"^\s+" + name_mail)
class MessageChecker:
def __init__(self, rev):
self.rev = rev
def check(self, condition, msg):
if not condition:
print "error: %s: bad commit message" % self.rev
print "error: %s" % msg
sys.exit(1)
def check_message(self, lines):
self.check(len(lines) > 2, "message is too short")
self.check(lines[1] == "", "second line should be blank")
splits = [index
for index in xrange(2, len(lines))
if CL_HDR_A.match(lines[index]) is not None]
self.check(splits, "no ChangeLog entries found")
for start, limit in zip(splits, splits[1:] + [0]):
start -= 1
limit -= 1
self.check_changelog(lines[start:limit])
def check_changelog(self, lines):
self.check(len(lines) > 2, "ChangeLog entry is too short")
path = lines.pop(0)
self.check(path.startswith("gdb/") and path.endswith("/"),
"each ChangeLog entry should be preceeded by its path")
lines.pop(0) # lines[1] has already been checked
while lines and CL_HDR_B.match(lines[0]) is not None:
lines.pop(0)
self.check(lines, "only ChangeLog headers found (no data)")
for line in lines:
self.check(not line or line.startswith("\t"),
"bad ChangeLog line %s" % repr(line))
def check_hash(hash):
assert SHA1HASH.match(hash) is not None
def git(*command):
fp = subprocess.Popen((GIT,) + command, stdout=subprocess.PIPE)
output = fp.communicate()[0]
if fp.returncode:
sys.exit(1)
return output
def git_rev_list(oldrev, newrev):
check_hash(oldrev)
check_hash(newrev)
return git("rev-list", oldrev + ".." + newrev)
def git_diff_tree(rev):
check_hash(rev)
return git("diff-tree", rev)
def git_cat_file_commit(rev):
check_hash(rev)
return git("cat-file", "commit", rev)
def commit_touches_gdb(rev):
lines = git_diff_tree(rev).rstrip().split("\n")
check = lines.pop(0)
assert check == rev
for line in lines:
if line.split()[-1] == "gdb":
return True
return False
def check_commit(rev):
lines = git_cat_file_commit(rev).rstrip().split("\n")
while lines and lines[0]:
lines.pop(0)
assert lines
lines.pop(0)
MessageChecker(rev).check_message(lines)
def process_pack(oldrev, newrev, refname):
if refname == "refs/heads/master":
revs = git_rev_list(oldrev, newrev).rstrip().split("\n")
revs.reverse()
for rev in revs:
if commit_touches_gdb(rev):
check_commit(rev)
print "%s: ok" % rev
def main():
for line in sys.stdin.xreadlines():
bits = line.rstrip().split()
assert len(bits) == 3
process_pack(*bits)
if __name__ == "__main__":
main()
next prev parent reply other threads:[~2014-08-15 15:02 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-14 8:32 Gary Benson
2014-08-14 12:52 ` Joel Brobecker
2014-08-14 13:15 ` Gary Benson
2014-08-14 13:25 ` Joel Brobecker
2014-08-14 15:22 ` Eli Zaretskii
2014-08-15 8:05 ` Gary Benson
2014-08-15 8:41 ` Eli Zaretskii
2014-08-15 11:45 ` Andreas Schwab
2014-09-03 20:54 ` Sergio Durigan Junior
2014-09-03 21:22 ` Sergio Durigan Junior
2014-09-03 22:18 ` Andreas Schwab
2014-09-04 9:06 ` Gary Benson
2014-09-04 14:23 ` Sergio Durigan Junior
2014-09-04 16:08 ` Doug Evans
2014-09-04 17:36 ` Gary Benson
2014-09-05 10:13 ` Gary Benson
2014-09-05 16:43 ` Doug Evans
2014-09-08 9:50 ` Gary Benson
2014-09-08 13:08 ` James Hogan
2014-09-08 13:21 ` James Hogan
2014-09-08 13:24 ` Joel Brobecker
2014-09-08 15:31 ` Gary Benson
2014-09-09 8:51 ` James Hogan
2014-09-09 16:25 ` Doug Evans
[not found] ` <54102ED8.7060307@redhat.com>
2014-09-10 16:12 ` Doug Evans
2014-09-10 16:28 ` Joel Brobecker
2014-09-15 10:30 ` Gary Benson
2014-09-15 12:45 ` Joel Brobecker
2014-09-15 15:30 ` Doug Evans
2014-09-15 16:05 ` Joel Brobecker
2014-09-15 17:47 ` Doug Evans
2014-09-16 9:31 ` Gary Benson
2014-09-16 15:50 ` Doug Evans
[not found] ` <0CEE46EB9C50E44486A861D738D3E20645F67101@rsex2.realsil.com.cn>
2014-10-03 18:22 ` GDB bugs Pedro Alves
2014-08-14 12:57 ` ChangeLogs in commit messages Mike Frysinger
2014-08-14 13:12 ` Gary Benson
2014-08-14 13:29 ` Joel Brobecker
2014-08-14 13:39 ` Andreas Schwab
2014-08-14 13:48 ` Joel Brobecker
2014-08-14 13:57 ` Andreas Schwab
2014-08-14 14:22 ` Joel Brobecker
2014-08-14 14:45 ` Andreas Schwab
2014-08-14 15:01 ` Joel Brobecker
2014-08-14 15:13 ` Andreas Schwab
2014-08-14 15:22 ` Joel Brobecker
2014-08-14 15:44 ` Andreas Schwab
2014-08-14 15:49 ` Joel Brobecker
2014-08-14 19:04 ` Sergio Durigan Junior
2014-08-15 8:48 ` Gary Benson
2014-08-15 12:11 ` Joel Brobecker
2014-08-15 13:09 ` Gary Benson
2014-08-15 13:28 ` Joel Brobecker
2014-08-15 15:02 ` Gary Benson [this message]
2014-08-15 15:27 ` Andreas Arnez
2014-08-15 16:08 ` Joel Brobecker
2014-08-18 8:31 ` Gary Benson
2014-08-18 14:54 ` Doug Evans
2014-08-18 15:05 ` Joel Brobecker
2014-08-18 15:27 ` Gary Benson
2014-08-20 12:20 ` Gary Benson
2014-08-14 16:22 ` Andreas Arnez
2014-08-14 13:23 ` Mike Frysinger
2014-08-14 13:36 ` Siva Chandra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140815150202.GA5674@blade.nx \
--to=gbenson@redhat.com \
--cc=arnez@linux.vnet.ibm.com \
--cc=brobecker@adacore.com \
--cc=gdb@sourceware.org \
--cc=vapier@gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox