#!/usr/bin/env python ## Copyright (C) 2014 Gary Benson ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. # GIT prepare-commit-msg hook for projects that want ChangeLog # entries included in the commit message. import copy import os import re import sys cl_hdr_re = re.compile(r"/ChangeLog:$") cl_old_re = re.compile(r"^\d{4}-\d{2}-\d{2}\s+.*?\s+<[^@]+@[^@]+>$") cl_mod_re = re.compile(r"^modified:\s+(.*/ChangeLog)$") msgfile = sys.argv[1] def cleanup_head(): global head if head and head[-1] and head[-1][-1] == "/": head.pop() while head and not head[-1]: head.pop() head.append("") in_foot = in_changelog = False changelogs, head, foot = [], [], [] for line in open(msgfile).xreadlines(): line = line.rstrip() bits = line.split("#", 1) if len(bits) == 2: comment = bits.pop().lstrip() if not in_foot: if comment.startswith("Please enter the commit message "): in_foot = True if in_foot: match = cl_mod_re.search(comment) if match is not None: changelogs.append(match.group(1)) if in_changelog: cleanup_head() in_changelog = False if not in_foot and not in_changelog: for ex in cl_hdr_re, cl_old_re: if ex.search(line) is not None: in_changelog = True break if in_foot: foot.append(line) elif not in_changelog: head.append(line) cleanup_head() def read_changelog(path): STARTUP, SKIP_HDR, READ_BODY = 1, 2, 3 lines, state = [path + ":"], STARTUP for line in open(path).xreadlines(): line = line.rstrip() if line and not line[0].isspace(): if state == STARTUP: state = SKIP_HDR continue assert state == READ_BODY break if state == SKIP_HDR: if line: continue state = READ_BODY assert state == READ_BODY lines.append(line) return lines lines = copy.copy(head) for changelog in changelogs: lines.extend(read_changelog(changelog)) lines.extend(foot) print >>open(msgfile, "w"), "\n".join(lines)