Skip to content

Instantly share code, notes, and snippets.

@choffmeister
Last active July 26, 2017 11:21
Show Gist options
  • Save choffmeister/1543dbdc5d152e7e95fb981952ed56e8 to your computer and use it in GitHub Desktop.
Save choffmeister/1543dbdc5d152e7e95fb981952ed56e8 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import subprocess
import os
import re
import sys
import itertools
semver_regex = '^(?:v)?(\d+)\.(\d+)\.(\d+)(\-(.*))?$'
def toint(strOrNone):
if strOrNone:
return int(strOrNone)
else:
return None
def run(cmd, cwd = None, stdout = subprocess.PIPE):
p = subprocess.Popen(cmd, cwd = cwd, env = os.environ, stdout = stdout, stderr = subprocess.PIPE)
stdout, err = p.communicate()
if p.wait() != 0: raise Exception(err)
return stdout
def git_tags():
return run(['git', 'tag']).splitlines()
def git_commits(ref_old, ref_new):
commits_raw = run(['git', 'log', '%s..%s' % (ref_old, ref_new), '--no-merges', '--pretty=%H %B|<|>|']).split('|<|>|')[:-1]
commits = filter(lambda c: c != None, map(lambda c: parse_commit(c), commits_raw))
return commits
def tags_filter(t):
global semver_regex
return re.search(semver_regex, t)
def tags_sort(a, b):
global semver_regex
semver_a = re.match(semver_regex, a)
semver_b = re.match(semver_regex, b)
va = [toint(semver_a.group(1)), toint(semver_a.group(2)), toint(semver_a.group(3))]
vb = [toint(semver_b.group(1)), toint(semver_b.group(2)), toint(semver_b.group(3))]
if cmp(va, vb) != 0:
return cmp(va, vb)
else:
return -cmp(semver_a.group(5), semver_b.group(5))
def parse_commit(raw_body):
parsed = re.match('^([a-z0-9]{40})\s(?:(\+|!|=|%|~)([^\s]+)?\s+)?(.*)$', raw_body.strip().splitlines()[0].strip())
if parsed:
return {
'raw_body': raw_body.strip(),
'hash': parsed.group(1),
'type': parsed.group(2).strip() if parsed.group(2) else '',
'scopes': map(lambda s: s.strip(), parsed.group(3).split(',')) if parsed.group(3) else [],
'subject': parsed.group(4).strip() if parsed.group(4) else ''
}
else:
return None
tags = ['HEAD'] + list(reversed(sorted(filter(tags_filter, git_tags()), cmp = tags_sort)))
print '# Changelog\n'
for ref_new, ref_old in zip(tags[:-1], tags[1:]):
print '## %s\n' % ref_new
commits = git_commits(ref_old, ref_new)
for commit in commits:
scopes_str = ' (' + ','.join(commit['scopes']) + ')' if len(commit['scopes']) > 0 else ''
subject_str = commit['subject']
hash_str = commit['hash'][:7]
print '*%s %s [%s]' % (scopes_str, subject_str, hash_str)
print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment