#!/usr/bin/env python3 import sys import codecs import urllib.request import json import textwrap sys.stdin = codecs.getreader("utf-8")(sys.stdin.detach()) sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) entries = [] def add_entry(entry): if entry and 'ignore' not in entry: combo = [] for bug in set(entry.get('bugs', [])): combo.append(bug) for cve in set(entry.get('cves', [])): combo.append(cve) combo = sorted(combo) if len(combo) == 0: if entry.get('subject', "").startswith('UBUNTU'): combo = '__packaging__' else: combo = '__mainline__' else: if entry.get('subject', "") == 'UBUNTU: link-to-tracker: update tracking bug': # Construct a key with '__trackingbug__' on the first position # and the tracking bug number afterwards combo.insert(0, '__trackingbug__') # Tracking bug goes at the top keys.insert(0, combo) else: if combo not in keys: keys.append(combo) entry['key'] = combo entries.append(entry) # Suck up the git log output and extract the information we need. keys = [] entry = None subject_wait = False for line in sys.stdin: if line.startswith('commit '): add_entry(entry) entry = {} subject_wait = True elif line.startswith('Author: '): bits = line.strip().split(maxsplit=1) entry['author'] = bits[1] elif subject_wait and line.startswith(' '): subject_wait = False entry['subject'] = line.strip() elif line.startswith(' BugLink: '): bits = line.strip().split(maxsplit=2) if len(bits) > 2: # There is text after the URL, so use that (after stripping the # enclosing characters) entry.setdefault('bugs', []).append(bits[2][1:-1]) elif 'launchpad.net' in bits[1]: # Extract the bug number from the launchpad URL bits = bits[1].split('/') entry.setdefault('bugs', []).append(bits[-1]) elif line.startswith(' CVE-'): entry.setdefault('cves', []).append(line.strip()) elif line.startswith(' Ignore:'): entry['ignore'] = True elif line.startswith(' Properties:'): for prop in line.strip().split()[1:]: if prop in ('ignore', 'no-changelog'): entry['ignore'] = True add_entry(entry) entries.reverse() # Go through the entries and clear out authors for upstream commits. for entry in entries: if entry['subject'].startswith('UBUNTU:'): entry['subject'] = entry['subject'][7:].strip() else: del entry['author'] # Lump everything without a bug at the bottom. keys.append('__packaging__') keys.append('__mainline__') emit_nl = False for key in keys: if key == '__packaging__': title_set = ['Miscellaneous Ubuntu changes'] elif key == '__mainline__': title_set = ['Miscellaneous upstream changes'] else: title_set = [] for bug in key: if bug.startswith('CVE-'): title_set.append(bug) elif bug == '__trackingbug__': # Look for the tracking bug number on the second # position of the key continue elif bug.isdigit(): # Assume that it is an LP bug number if 'bug' contains only digits bug_info = None try: # urllib.request.urlcleanup() request = urllib.request.Request('https://api.launchpad.net/devel/bugs/' + bug) request.add_header('Cache-Control', 'no-cache') with urllib.request.urlopen(request) as response: data = response.read() bug_info = json.loads(data.decode('utf-8')) title = bug_info['title'] if 'description' in bug_info: for line in bug_info['description'].split('\n'): if line.startswith('Kernel-Description:'): title = line.split(' ', 1)[1] except urllib.error.HTTPError: title = 'INVALID or PRIVATE BUG' title += ' (LP###' + bug + ')' title_set.append(title) else: # Finally treat 'bug' itself as the title title_set.append(bug) emit_title = True for entry in entries: if entry['key'] != key: continue if emit_title: if emit_nl: print('') emit_nl = True title_lines = textwrap.wrap('#// '.join(title_set), 76) print(' * ' + title_lines[0].replace('LP###', 'LP: #').replace('#//', ' //')) for line in title_lines[1:]: line = line.replace('LP###', 'LP: #').replace('#//', ' //') print(' ' + line) emit_title = False if key[0] != '__trackingbug__': title_lines = textwrap.wrap(entry['subject'], 76) print(' - ' + title_lines[0]) for line in title_lines[1:]: line = line.replace('LP###', 'LP: #') print(' ' + line)