#!/usr/bin/env python # -*- mode: python -*- # # This python program has been copied from # https://github.com/GNOME/gnet/blob/master/gen-changelog.py # # It has been authored by Edward Hervey, of GStreamer fame. I have # asked his permission to copy it and re-use it here, as part of the # Libabigail project. He granted me the permission to distribute the # program under the terms of the GNU Lesser Public License as # published by the Free Software Foundaion; either version 2, or (at # your option) any later version. # # Thus, this program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; either version 2, 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 Lesser Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program; see the file COPYING-LGPLV2. If # not, see . import sys import subprocess import re # Makes a GNU-Style ChangeLog from a git repository # Handles git-svn repositories also # Arguments : same as for git log release_refs={} def process_commit(lines, files): # DATE NAME # BLANK LINE # Subject # BLANK LINE # ... # FILES fileincommit = False lines = [x.strip() for x in lines if x.strip() and not x.startswith('git-svn-id')] files = [x.strip() for x in files if x.strip()] for l in lines: if l.startswith('* '): fileincommit = True break top_line = lines[0] subject_line_index = 0 if lines[1].startswith('*') else 1; first_cl_body_line_index = 0; for i in range(1, len(lines)): if lines[i].startswith('*'): first_cl_body_line_index = i break; # Clean up top line of ChangeLog entry: fields = top_line.split(' ') # 1. remove the time and timezone stuff in "2008-05-13 07:10:28 +0000 name" if fields[2].startswith('+') or fields[2].startswith('-'): del fields[2] if fields[1][2] == ':' and fields[1][5] == ':': del fields[1] # 2. munge at least my @src.gnome.org e-mail address... if fields[-1] == '': fields[-1] = '' top_line = ' '.join(fields) print top_line.strip() print if subject_line_index > 0: print '\t', lines[subject_line_index] if not fileincommit: for f in files: print '\t* %s:' % f print if first_cl_body_line_index > 0: for l in lines[first_cl_body_line_index:]: if l.startswith('Signed-off-by:'): continue print '\t', l print def output_commits(): cmd = ['git', 'log', '--pretty=format:--START-COMMIT--%H%n%ai %an <%ae>%n%n%s%n%b%n--END-COMMIT--', '--date=short', '--name-only'] start_tag = find_start_tag() if start_tag is None: cmd.extend(sys.argv[1:]) else: cmd.extend(["%s..HEAD" % (start_tag)]) p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) buf = [] files = [] filemode = False for lin in p.stdout.readlines(): if lin.startswith("--START-COMMIT--"): if buf != []: process_commit(buf, files) hash = lin[16:].strip() try: rel = release_refs[hash] print "=== release %d.%d.%d ===\n" % (int(rel[0]), int(rel[1]), int(rel[2])) except: pass buf = [] files = [] filemode = False elif lin.startswith("--END-COMMIT--"): filemode = True elif filemode == True: files.append(lin) else: buf.append(lin) if buf != []: process_commit(buf, files) def get_rel_tags(): # Populate the release_refs dict with the tags for previous releases reltagre = re.compile("^([a-z0-9]{40}) refs\/tags\/GNET-([0-9]+)[-_.]([0-9]+)[-_.]([0-9]+)") cmd = ['git', 'show-ref', '--tags', '--dereference'] p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) for lin in p.stdout.readlines(): match = reltagre.search (lin) if match: (sha, maj, min, nano) = match.groups() release_refs[sha] = (maj, min, nano) def find_start_tag(): starttagre = re.compile("^([a-z0-9]{40}) refs\/tags\/CHANGELOG_START") cmd = ['git', 'show-ref', '--tags'] p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) for lin in p.stdout.readlines(): match = starttagre.search (lin) if match: return match.group(1) return None if __name__ == "__main__": get_rel_tags() output_commits()