lnsocket

A minimal C library for connecting to the lightning network
git clone git://jb55.com/lnsocket
Log | Files | Refs | Submodules | README | LICENSE

changelog.py (4362B)


      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"])
     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 
     50     for l in logs.split('\n'):
     51         m = re.match(r'^commit ([A-Fa-f0-9]{40})$', l)
     52         if m:
     53             commit = m.group(1)
     54 
     55         m = re.match(
     56             r'^\s+Changelog-({}): (.*)$'.format("|".join(sections)), l, re.IGNORECASE)
     57         if not m:
     58             continue
     59 
     60         # Now try to resolve the pull request that originated this commit:
     61         headers = {
     62             'Accept': 'application/vnd.github.groot-preview+json',
     63         }
     64 
     65         if os.environ.get('GH_TOKEN'):
     66             headers['Authorization'] = 'token ' + os.environ.get('GH_TOKEN')
     67 
     68         url = 'https://api.github.com/repos/{repo}/commits/{commit}/pulls'.format(repo=repo, commit=commit)
     69         content = requests.get(url, headers=headers).json()
     70         if content and content.get(0) is not None:
     71             pullreq = content[0]['number']
     72         else:
     73             pullreq = None
     74 
     75         e = Entry(commit, pullreq, m.group(2), m.group(1).lower())
     76         entries.append(e)
     77 
     78     return entries
     79 
     80 
     81 def linkify(entries):
     82     links = []
     83     for e in entries:
     84         if e.pullreq is not None:
     85             links.append(Link(
     86                 ref='#{}'.format(e.pullreq),
     87                 content=e.content,
     88                 url="https://github.com/{repo}/pull/{pullreq}".format(repo=repo, pullreq=e.pullreq)
     89             ))
     90     return list(set(links))
     91 
     92 
     93 def group(entries):
     94     groups = {s: [] for s in sections}
     95     for e in entries:
     96         groups[e.section].append(e)
     97     for s in sections:
     98         if len(groups[s]) == 0:
     99             del groups[s]
    100     return groups
    101 
    102 
    103 def commit_date(commitsha):
    104     """Get the date of the specified commit.
    105     """
    106     line = git("show -s --format=%ci")
    107     dt = datetime.strptime(line.strip(), '%Y-%m-%d %H:%M:%S %z')
    108     return dt
    109 
    110 
    111 template = Template("""<%def name="group(entries)">
    112 % for e in entries:
    113  % if e.pullreq is not None:
    114      - ${e.content} ([#${e.pullreq}])
    115  % else:
    116      - ${e.content}
    117  % endif
    118 % endfor
    119 
    120 </%def><%def name="group_links(entries)">
    121 % for e in entries:
    122 [${e.pullreq}]: https://github.com/${repo}/pull/${e.pullreq}
    123 % endfor
    124 </%def>
    125 
    126 ${h2} [${version}] - ${date.strftime("%Y-%m-%d")}
    127 
    128 % for section in sections:
    129 ${h3} ${section.capitalize()}
    130 ${group(groups[section]) | trim}
    131 % endfor
    132 
    133 % for l in links:
    134 [${l.ref}]: ${l.url}
    135 % endfor
    136 [${version}]: https://github.com/${repo}/releases/tag/v${version}""")
    137 
    138 
    139 if __name__ == "__main__":
    140     parser = argparse.ArgumentParser(
    141         description='Generate a changelog summary for a given commit range'
    142     )
    143     parser.add_argument('commitrange', type=str, nargs='?',
    144                         help='Range of commits to consider (format: <from_commit>..<to_commit>',
    145                         default=get_commit_range())
    146 
    147     args = parser.parse_args()
    148 
    149     if '..' not in args.commitrange:
    150         print("Commit range must include '..' to separate 'from_commit' and 'to_commit'")
    151         sys.exit(1)
    152 
    153     fromcommit, tocommit = args.commitrange.split('..')
    154     entries = get_log_entries(args.commitrange)
    155     groups = group(entries)
    156     date = commit_date(tocommit)
    157 
    158     print(template.render(
    159         groups=groups,
    160         repo=repo,
    161         sections=groups.keys(),
    162         h2='##',
    163         h3='###',
    164         version=tocommit[1:],
    165         date=date,
    166         links=linkify(entries),
    167     ))
    168 
    169