damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

changelog.py (4541B)


      1 #!/usr/bin/env python3
      2 # Copied from ElementsProject/lightning, thanks! :)
      3 
      4 from collections import namedtuple
      5 from datetime import datetime
      6 from mako.template import Template
      7 import argparse
      8 import os
      9 import re
     10 import requests
     11 import shlex
     12 import subprocess
     13 import sys
     14 
     15 # What sections do we support in the changelog:
     16 sections = [
     17     'added',
     18     'changed',
     19     'deprecated',
     20     'fixed',
     21     'removed',
     22     'experimental',
     23 ]
     24 
     25 repo = 'damus-io/damus'
     26 
     27 Entry = namedtuple("Entry", ["commit", "pullreq", "content", "section", "author"])
     28 Link = namedtuple("Link", ["ref", "content", "url"])
     29 
     30 
     31 def git(cmd):
     32     cmd = shlex.split(cmd)
     33     out = subprocess.check_output(['git'] + cmd)
     34     return out.decode('UTF-8')
     35 
     36 
     37 def get_commit_range():
     38     """Find a commit range that we should collect the CHANGELOG for.
     39     """
     40     description = git("describe")
     41     version = description.split('-')[0]
     42     return "{version}..master".format(version=version)
     43 
     44 
     45 def get_log_entries(commitrange):
     46     commit = None
     47     logs = git("log {commitrange}".format(commitrange=commitrange))
     48     entries = []
     49     author = ""
     50 
     51     for l in logs.split('\n'):
     52         m = re.match(r'^commit ([A-Fa-f0-9]{40})$', l)
     53         a = re.match(r'^Author: ([^<]+)<.*$', l)
     54         if m:
     55             commit = m.group(1)
     56 
     57         if a:
     58             author = "(" + a.group(1)[:-1] + ")"
     59 
     60         m = re.match(
     61             r'^\s+Changelog-({}): (.*)$'.format("|".join(sections)), l, re.IGNORECASE)
     62 
     63         if not m:
     64             continue
     65 
     66         # Now try to resolve the pull request that originated this commit:
     67         headers = {
     68             'Accept': 'application/vnd.github.groot-preview+json',
     69         }
     70 
     71         if os.environ.get('GH_TOKEN'):
     72             headers['Authorization'] = 'token ' + os.environ.get('GH_TOKEN')
     73 
     74         #url = 'https://api.github.com/repos/{repo}/commits/{commit}/pulls'.format(repo=repo, commit=commit)
     75         #content = requests.get(url, headers=headers).json()
     76         #if content and content.get(0) is not None:
     77         #    pullreq = content[0]['number']
     78         #else:
     79         #    pullreq = None
     80         pullreq = None
     81 
     82         e = Entry(commit, pullreq, m.group(2), m.group(1).lower(), author)
     83         entries.append(e)
     84 
     85     return entries
     86 
     87 
     88 def linkify(entries):
     89     links = []
     90     for e in entries:
     91         if e.pullreq is not None:
     92             links.append(Link(
     93                 ref='#{}'.format(e.pullreq),
     94                 content=e.content,
     95                 url="https://github.com/{repo}/pull/{pullreq}".format(repo=repo, pullreq=e.pullreq)
     96             ))
     97     return list(set(links))
     98 
     99 
    100 def group(entries):
    101     groups = {s: [] for s in sections}
    102     for e in entries:
    103         groups[e.section].append(e)
    104     for s in sections:
    105         if len(groups[s]) == 0:
    106             del groups[s]
    107     return groups
    108 
    109 
    110 def commit_date(commitsha):
    111     """Get the date of the specified commit.
    112     """
    113     line = git("show -s --format=%ci")
    114     dt = datetime.strptime(line.strip(), '%Y-%m-%d %H:%M:%S %z')
    115     return dt
    116 
    117 
    118 template = Template("""<%def name="group(entries)">
    119 % for e in entries:
    120  % if e.pullreq is not None:
    121 - ${e.content} ([#${e.pullreq}])
    122  % else:
    123 - ${e.content} ${e.author}
    124  % endif
    125 % endfor
    126 
    127 </%def><%def name="group_links(entries)">
    128 % for e in entries:
    129 [${e.pullreq}]: https://github.com/${repo}/pull/${e.pullreq}
    130 % endfor
    131 </%def>
    132 
    133 ${h2} [${version}] - ${date.strftime("%Y-%m-%d")}
    134 
    135 % for section in sections:
    136 ${h3} ${section.capitalize()}
    137 ${group(groups[section]) | trim}
    138 % endfor
    139 
    140 % for l in links:
    141 [${l.ref}]: ${l.url}
    142 % endfor
    143 [${version}]: https://github.com/${repo}/releases/tag/v${version}""")
    144 
    145 
    146 if __name__ == "__main__":
    147     parser = argparse.ArgumentParser(
    148         description='Generate a changelog summary for a given commit range'
    149     )
    150     parser.add_argument('commitrange', type=str, nargs='?',
    151                         help='Range of commits to consider (format: <from_commit>..<to_commit>',
    152                         default=get_commit_range())
    153 
    154     args = parser.parse_args()
    155 
    156     if '..' not in args.commitrange:
    157         print("Commit range must include '..' to separate 'from_commit' and 'to_commit'")
    158         sys.exit(1)
    159 
    160     fromcommit, tocommit = args.commitrange.split('..')
    161     entries = get_log_entries(args.commitrange)
    162     groups = group(entries)
    163     date = commit_date(tocommit)
    164 
    165     print(template.render(
    166         groups=groups,
    167         repo=repo,
    168         sections=groups.keys(),
    169         h2='##',
    170         h3='###',
    171         version=tocommit[1:],
    172         date=date,
    173         links=linkify(entries),
    174     ))
    175 
    176