cloud-init/packages/rpm-changelog
2012-06-25 20:29:58 -07:00

212 lines
5.4 KiB
Python
Executable File

#!/usr/bin/python
# vi: ts=4 expandtab
# A crappy little script
# that changes bzr 'log'
# into someting that rpm spec files can use (best effort)
import os
import re
import sys
from datetime import datetime
from datetime import date
import subprocess
E_TYPES = ['tags', 'revno', 'author', 'timestamp', 'committer']
def tiny_p(cmd):
# Darn python 2.6 doesn't have check_output (argggg)
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=None)
(out, err) = sp.communicate()
return (out, err)
def extract_entry(collecting):
entry = {}
for t in E_TYPES:
look_for = "%s:" % (t)
for v in collecting:
if v.startswith(look_for):
entry[t] = v[len(look_for):].strip()
break
i = -1
# Messages seem to be the last element so suck
# those all up
for a, v in enumerate(collecting):
if v.startswith("message:"):
i = a
break
if i != -1:
msg_lines = collecting[i + 1:]
entry['message'] = "\n".join(msg_lines)
return entry
def clean_authors(authors):
if not authors:
return ''
auth_cleaned = set()
for a in authors:
a = a.strip()
if a:
auth_cleaned.add(a)
if not auth_cleaned:
return ''
uniq_authors = list(auth_cleaned)
if len(uniq_authors) == 1:
return authors[0]
auths = "(%s)" % ", ".join(uniq_authors)
return auths
def clean_revnos(revnos):
novs = list()
for r in revnos:
r = r.strip()
r = r.replace("[merge]", "")
if r:
novs.append(int(r))
entries = list(novs)
if not entries:
return ''
entries.sort()
if len(entries) == 1:
return "%s" % (entries[0])
# Check if consecutive
start = entries[0]
consec = True
for (i, v) in enumerate(entries):
if v != start + i:
consec = False
break
if consec:
end = entries[-1]
return "%s => %s" % (start, end)
v = [str(b) for b in entries]
return ", ".join(v)
def spacey(am):
return " " * am
def justify(text, space_wanted):
c_bef = len(text)
t_c = len(text.lstrip())
space_am = (c_bef - t_c)
needed = (space_wanted - space_am)
if needed < 0:
return text
return (" " * (needed) + text)
def clean_messages(messages):
contents = []
for msg in messages:
# Split into sub-messages...
# if we can
lines = []
pieces = msg.splitlines()
if len(pieces) == 1:
lines.append("%s- %s " %
(spacey(4), msg.strip()))
else:
n_lines = []
n_lines.append(pieces[0].strip())
for line in pieces[1:]:
line = line.lstrip()
if not line:
continue
n_lines.append(justify(line, 6))
lines.append("%s- %s" % (spacey(4), "\n".join(n_lines)))
contents.extend(lines)
return "\n".join(contents)
def build_changelog(history=-1):
cmd = ['bzr', 'log', '--timezone=utc']
(stdout, _stderr) = tiny_p(cmd)
# Clean the format up
entries = stdout.splitlines()
all_entries = []
collecting = []
for e in entries:
if e.startswith("---"):
if collecting:
a_entry = extract_entry(collecting)
if a_entry:
all_entries.append(a_entry)
collecting = []
else:
collecting.append(e)
# Anything that we left behind??
entry = extract_entry(collecting)
if entry:
all_entries.append(entry)
if history > 0:
take_entries = list(all_entries[0:history])
else:
take_entries = list(all_entries)
# Merge those with same date
date_entries = {}
for e in take_entries:
author = e.get('author')
if not author:
author = e.get('committer')
if not author:
continue
timestamp = e.get('timestamp')
if not timestamp:
continue
msg = e.get('message')
if not msg:
continue
revno = e.get('revno')
if not revno:
continue
# http://bugs.python.org/issue6641
timestamp = timestamp.replace("+0000", '').strip()
ds = datetime.strptime(timestamp, '%a %Y-%m-%d %H:%M:%S')
ds = ds.date()
if ds not in date_entries:
entry = {}
entry['messages'] = []
entry['authors'] = []
entry['revnos'] = []
date_entries[ds] = entry
entry = date_entries[ds]
entry['messages'].append(msg)
entry['authors'].append(author)
entry['revnos'].append(revno)
# It wants them in chronological order...
dates = sorted(date_entries.keys())
chglog = []
for ds in reversed(dates):
e = date_entries[ds]
authors = clean_authors(e['authors'])
revnos = clean_revnos(e['revnos'])
top_line = "%s %s - [revison %s]" % (ds.strftime("%a %b %d %Y"),
authors, revnos)
chglog.append("* %s" % (top_line))
chglog.append(clean_messages(e['messages']))
return "\n".join(chglog)
if __name__ == '__main__':
args = sys.argv[1:]
history_am = -1
if args:
history_am = int(args[0])
chglog = build_changelog(history_am)
print chglog