#!/usr/bin/python3 import sys import re import textwrap import datetime import email.utils import git package_name = 'UNKNOWN' alias_names = { 'julian': 'Julian Rother', 'Julian': 'Julian Rother', } ignore_commit_regexes = [ '^fixup!', ] def print_release(tag=None, commits=tuple(), last_tag=None): release_version = '0.0.0' release_author = git.objects.util.Actor('None', 'undefined@example.com') release_date = 0 release_status = 'UNRELEASED' message = '' if tag: release_status = 'unstable' release_version = tag.name[1:] # strip leading "v" if isinstance(tag.object, git.TagObject): release_author = tag.object.tagger release_date = tag.object.tagged_date message = tag.object.message.split('-----BEGIN PGP SIGNATURE-----')[0].strip() else: release_author = tag.object.committer release_date = tag.object.committed_date elif commits: release_author = commits[0].committer release_date = commits[0].committed_date date = datetime.datetime.fromtimestamp(release_date).strftime('%Y%m%dT%H%M%S') last_version = '0.0.0' if last_tag: last_version = last_tag.name[1:] # strip leading "v" release_version = f'{last_version}+git{date}-{commits[0].hexsha[:8]}' print(f'{package_name} ({release_version}) {release_status}; urgency=medium') print() if message: print(textwrap.indent(message, ' ')) print() commit_authors = [] # list of (key, author), sorted by first commit date commit_author_emails = {} # author email -> key commit_author_names = {} # author name -> key commit_author_commits = {} # key -> list of commits for commit in commits: if any(filter(lambda pattern: re.match(pattern, commit.summary), ignore_commit_regexes)): continue if len(commit.parents) > 1: continue # Ignore merge commits author_name = alias_names.get(commit.author.name, commit.author.name) key = commit_author_emails.get(commit.author.email) if key is None: key = commit_author_names.get(author_name) if key is None: key = commit.author.email commit_authors.append((key, author_name)) commit_author_emails[commit.author.email] = key commit_author_names[author_name] = key commit_author_commits[key] = commit_author_commits.get(key, []) + [commit] commit_authors.sort(key=lambda args: len(commit_author_commits[args[0]])) for key, author_name in commit_authors: print(f' [ {author_name} ]') for commit in commit_author_commits[key]: lines = '\n'.join(textwrap.wrap(commit.summary, 90)) lines = ' * ' + textwrap.indent(lines, ' ').strip() print(lines) print() print(f' -- {alias_names.get(release_author.name, release_author.name)} <{release_author.email}> {email.utils.formatdate(release_date)}') if __name__ == '__main__': repo = git.Repo('.') package_name = sys.argv[1] version_commits = {} for tag in repo.tags: if not re.fullmatch('v[0-9]+[.][0-9]+[.][0-9]+.*', tag.name): continue if isinstance(tag.object, git.TagObject): commit_hexsha = tag.object.object.hexsha else: commit_hexsha = tag.object.hexsha version_commits[commit_hexsha] = tag tag = None commits = [] for commit in repo.iter_commits('HEAD'): if commit.hexsha in version_commits: prev_tag = version_commits[commit.hexsha] if commits: print_release(tag, commits, last_tag=prev_tag) print() tag = prev_tag commits = [] commits.append(commit) print_release(tag, commits)