• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# SPDX-License-Identifier: LGPL-2.0-or-later
3#
4# -*- mode: python -*-
5#
6# This python program has been copied from
7# https://github.com/GNOME/gnet/blob/master/gen-changelog.py
8#
9# It has been authored by Edward Hervey, of GStreamer fame.  I have
10# asked his permission to copy it and re-use it here, as part of the
11# Libabigail project.  He granted me the permission to distribute the
12# program under the terms of the GNU Lesser Public License as
13# published by the Free Software Foundaion; either version 2, or (at
14# your option) any later version.
15#
16
17import sys
18import subprocess
19import re
20
21# Makes a GNU-Style ChangeLog from a git repository
22# Handles git-svn repositories also
23
24# Arguments : same as for git log
25release_refs={}
26
27def process_commit(lines, files):
28    # DATE NAME
29    # BLANK LINE
30    # Subject
31    # BLANK LINE
32    # ...
33    # FILES
34    fileincommit = False
35    lines = [x.strip() for x in lines if x.strip() and not x.startswith('git-svn-id')]
36    files = [x.strip() for x in files if x.strip()]
37    for l in lines:
38        if l.startswith('* '):
39            fileincommit = True
40            break
41
42    top_line = lines[0]
43    subject_line_index = 0 if lines[1].startswith('*') else 1;
44    first_cl_body_line_index = 0;
45
46    for i in range(1, len(lines)):
47        if lines[i].startswith('*'):
48            first_cl_body_line_index = i
49            break;
50
51    # Clean up top line of ChangeLog entry:
52    fields = top_line.split(' ')
53
54    # 1. remove the time and timezone stuff in "2008-05-13 07:10:28 +0000  name"
55    if fields[2].startswith('+') or fields[2].startswith('-'):
56      del fields[2]
57    if fields[1][2] == ':' and fields[1][5] == ':':
58      del fields[1]
59
60    # 2. munge at least my @src.gnome.org e-mail address...
61    if fields[-1] == '<tpm@src.gnome.org>':
62      fields[-1] = '<tim@centricular.net>'
63
64    top_line = ' '.join(fields)
65    print(top_line.strip())
66    print()
67
68    if subject_line_index > 0:
69        print('\t%s' % lines[subject_line_index].strip())
70
71    if not fileincommit:
72        for f in files:
73            print('\t* %s:' % f.strip())
74        print()
75
76    if first_cl_body_line_index > 0:
77        for l in lines[first_cl_body_line_index:]:
78            if l.startswith('Signed-off-by:'):
79                continue
80            print('\t%s' % l.strip())
81        print()
82
83def output_commits():
84    cmd = ['git', 'log', '--pretty=format:--START-COMMIT--%H%n%ai  %an <%ae>%n%n%s%n%b%n--END-COMMIT--',
85           '--date=short', '--name-only']
86
87    start_tag = find_start_tag()
88
89    if start_tag is None:
90        cmd.extend(sys.argv[1:])
91    else:
92        cmd.extend(["%s..HEAD" % (start_tag)])
93
94    p = subprocess.Popen(args=cmd, shell=False,
95                         stdout=subprocess.PIPE,
96                         text=True)
97    buf = []
98    files = []
99    filemode = False
100    for lin in p.stdout.readlines():
101        if lin.startswith("--START-COMMIT--"):
102            if buf != []:
103                process_commit(buf, files)
104            hash = lin[16:].strip()
105            try:
106                rel = release_refs[hash]
107                print("=== release %d.%d.%d ===\n" % (int(rel[0]), int(rel[1]), int(rel[2])))
108            except:
109                pass
110            buf = []
111            files = []
112            filemode = False
113        elif lin.startswith("--END-COMMIT--"):
114            filemode = True
115        elif filemode == True:
116            files.append(lin)
117        else:
118            buf.append(lin)
119    if buf != []:
120        process_commit(buf, files)
121
122def get_rel_tags():
123    # Populate the release_refs dict with the tags for previous releases
124    reltagre = re.compile("^([a-z0-9]{40}) refs\/tags\/GNET-([0-9]+)[-_.]([0-9]+)[-_.]([0-9]+)")
125
126    cmd = ['git', 'show-ref', '--tags', '--dereference']
127    p = subprocess.Popen(args=cmd, shell=False,
128                         stdout=subprocess.PIPE,
129                         text=True)
130    for lin in p.stdout:
131       match = reltagre.search(lin)
132       if match:
133           (sha, maj, min, nano) = match.groups()
134           release_refs[sha] = (maj, min, nano)
135
136def find_start_tag():
137    starttagre = re.compile("^([a-z0-9]{40}) refs\/tags\/CHANGELOG_START")
138    cmd = ['git', 'show-ref', '--tags']
139    p = subprocess.Popen(args=cmd, shell=False,
140                         stdout=subprocess.PIPE,
141                         text=True)
142    for lin in p.stdout:
143       match = starttagre.search(lin)
144       if match:
145           return match.group(1)
146    return None
147
148if __name__ == "__main__":
149    get_rel_tags()
150    output_commits()
151