diff options
author | David Robillard <d@drobilla.net> | 2019-10-20 22:13:43 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-10-21 00:46:39 +0200 |
commit | a3600d61f63899e28f5208336b2c8371d8b331eb (patch) | |
tree | 28a58a1085d913a300bd7b796cfb9f1a454370d0 /extras/autowaf.py | |
parent | 66304cc4e1e10e03630e6a823f2bc9e0ec2c669a (diff) | |
download | autowaf-a3600d61f63899e28f5208336b2c8371d8b331eb.tar.gz autowaf-a3600d61f63899e28f5208336b2c8371d8b331eb.tar.bz2 autowaf-a3600d61f63899e28f5208336b2c8371d8b331eb.zip |
Factor out release utilities
Diffstat (limited to 'extras/autowaf.py')
-rw-r--r-- | extras/autowaf.py | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/extras/autowaf.py b/extras/autowaf.py index fc1d488..2f2469b 100644 --- a/extras/autowaf.py +++ b/extras/autowaf.py @@ -1164,273 +1164,6 @@ def run_ldconfig(ctx): except Exception: pass -def get_rdf_news(name, - in_files, - top_entries=None, - extra_entries=None, - dev_dist=None): - import rdflib - from time import strptime - - doap = rdflib.Namespace('http://usefulinc.com/ns/doap#') - dcs = rdflib.Namespace('http://ontologi.es/doap-changeset#') - rdfs = rdflib.Namespace('http://www.w3.org/2000/01/rdf-schema#') - foaf = rdflib.Namespace('http://xmlns.com/foaf/0.1/') - rdf = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#') - m = rdflib.ConjunctiveGraph() - - try: - for i in in_files: - m.parse(i, format='n3') - except Exception: - Logs.warn('Error parsing data, unable to generate NEWS') - return - - proj = m.value(None, rdf.type, doap.Project) - for f in m.triples([proj, rdfs.seeAlso, None]): - if f[2].endswith('.ttl'): - m.parse(f[2], format='n3') - - entries = {} - for r in m.triples([proj, doap.release, None]): - release = r[2] - revision = m.value(release, doap.revision, None) - date = m.value(release, doap.created, None) - blamee = m.value(release, dcs.blame, None) - changeset = m.value(release, dcs.changeset, None) - dist = m.value(release, doap['file-release'], None) - - if not dist: - Logs.warn('No file release for %s %s' % (proj, revision)) - dist = dev_dist - - if revision and date and blamee and changeset: - entry = {} - entry['name'] = str(name) - entry['revision'] = str(revision) - entry['date'] = strptime(str(date), '%Y-%m-%d') - entry['status'] = 'stable' if dist != dev_dist else 'unstable' - entry['dist'] = str(dist) - entry['items'] = [] - - for i in m.triples([changeset, dcs.item, None]): - item = str(m.value(i[2], rdfs.label, None)) - entry['items'] += [item] - if dist and top_entries is not None: - if not str(dist) in top_entries: - top_entries[str(dist)] = {'items': []} - top_entries[str(dist)]['items'] += [ - '%s: %s' % (name, item)] - - if extra_entries and dist: - for i in extra_entries[str(dist)]: - entry['items'] += extra_entries[str(dist)]['items'] - - entry['blamee_name'] = str(m.value(blamee, foaf.name, None)) - entry['blamee_mbox'] = str(m.value(blamee, foaf.mbox, None)) - - entries[(str(date), str(revision))] = entry - else: - Logs.warn('Ignored incomplete %s release description' % name) - - return entries - -def write_news(entries, out_file): - import textwrap - from time import strftime - - if len(entries) == 0: - return - - revisions = sorted(entries.keys(), reverse=True) - news = open(out_file, 'w') - for r in revisions: - entry = entries[r] - if r != revisions[0]: - news.write('\n') - - news.write('%s (%s) %s;\n' % (entry['name'], entry['revision'], entry['status'])) - for item in entry['items']: - wrapped = textwrap.wrap(item, width=74) - news.write('\n * ' + '\n '.join(wrapped)) - - news.write('\n\n --') - news.write(' %s <%s>' % (entry['blamee_name'], - entry['blamee_mbox'].replace('mailto:', ''))) - - news.write(' %s\n' % ( - entry['date'].strftime('%a, %d %b %Y %H:%M:%S %z'))) - - news.close() - -def get_items_markdown(items, indent=""): - return ''.join([indent + '* %s\n' % item for item in items]) - -def write_posts(entries, meta, out_dir, status='stable'): - "Write news posts in Pelican Markdown format" - import datetime - try: - os.mkdir(out_dir) - except Exception: - pass - - for r, entry in entries.items(): - revision = entry['revision'] - if entry['status'] != status: - continue - - date = entry['date'].astimezone(datetime.timezone.utc) - date_str = date.strftime('%Y-%m-%d') - datetime_str = date.strftime('%Y-%m-%d %H:%M') - - path = os.path.join(out_dir, '%s-%s-%s.md' % ( - date_str, entry['name'], revision.replace('.', '-'))) - post = open(path, 'w') - title = entry['title'] if 'title' in entry else entry['name'] - post.write('Title: %s %s\n' % (title, revision)) - post.write('Date: %s\n' % datetime_str) - post.write('Slug: %s-%s\n' % (entry['name'], revision.replace('.', '-'))) - for k in meta: - post.write('%s: %s\n' % (k, meta[k])) - post.write('\n') - - url = entry['dist'] - if entry['status'] == status: - post.write('[%s %s](%s) has been released.' % ( - (entry['name'], revision, url))) - - if 'description' in entry: - post.write(' ' + entry['description']) - - post.write('\n') - if (len(entry['items']) > 0 and - not (len(entry['items']) == 1 and - entry['items'][0] == 'Initial release')): - post.write('\nChanges:\n\n') - post.write(get_items_markdown(entry['items'], indent=" ")) - - post.close() - -def get_blurb(in_file): - "Get the first paragraph of a Markdown formatted file, skipping the title" - f = open(in_file, 'r') - f.readline() # Title - f.readline() # Title underline - f.readline() # Blank - out = '' - line = f.readline() - while len(line) > 0 and line != '\n': - out += line.replace('\n', ' ') - line = f.readline() - return out.strip() - -def get_news(in_file, entry_props={}): - """Get NEWS entries in the format expected by write_posts(). - - Properties that should be set on every entry can be passed in - `entry_props`. If `entry_props` has a 'dist_pattern' value, it is used to - set the 'dist' entry of entries by substituting the version number. - """ - - import re - import email.utils - - f = open(in_file, 'r') - entries = {} - while True: - # Read header line - head = f.readline() - matches = re.compile(r'([^ ]*) \((.*)\) ([a-zA-z]*);').match(head) - if matches is None: - break - - entry = {} - entry['name'] = matches.group(1) - entry['revision'] = matches.group(2) - entry['status'] = matches.group(3) - entry['items'] = [] - if 'dist_pattern' in entry_props: - entry['dist'] = entry_props['dist_pattern'] % entry['revision'] - - # Read blank line after header - if f.readline() != '\n': - raise SyntaxError('expected blank line after NEWS header') - - def add_item(item): - if len(item) > 0: - entry['items'] += [item.replace('\n', ' ').strip()] - - # Read entries for this revision - item = '' - line = '' - while line != '\n': - line = f.readline() - if line.startswith(' * '): - add_item(item) - item = line[3:].lstrip() - else: - item += line.lstrip() - add_item(item) - - # Read footer line - foot = f.readline() - matches = re.compile(' -- (.*) <(.*)> (.*)').match(foot) - entry['date'] = email.utils.parsedate_to_datetime(matches.group(3)) - entry['blamee_name'] = matches.group(1) - entry['blamee_mbox'] = matches.group(2) - entry.update(entry_props) - - key = tuple(map(int, entry['revision'].split('.'))) - entries[key] = entry - - # Skip trailing blank line before next entry - f.readline() - - f.close() - - return entries - -def news_to_posts(news_file, entry_props, post_meta, default_post_dir): - post_dir = os.getenv('POST_DIR') - if not post_dir: - post_dir = default_post_dir - sys.stderr.write('POST_DIR not set in environment, writing to %s\n' % post_dir) - else: - sys.stderr.write('writing posts to %s\n' % post_dir) - - entries = get_news(news_file, entry_props) - write_posts(entries, post_meta, post_dir) - def run_script(cmds): for cmd in cmds: subprocess.check_call(cmd, shell=True) - -def release(name, version, dist_name=None): - if dist_name is None: - dist_name = name.lower() - - dist = '%s-%s.tar.bz2' % (dist_name or name.lower(), version) - try: - os.remove(dist) - os.remove(dist + '.sig') - except Exception: - pass - - status = subprocess.check_output('git status --porcelain', shell=True) - if status: - Logs.error('error: git working copy is dirty\n' + status) - raise Exception('git working copy is dirty') - - head = subprocess.check_output('git show -s --oneline', shell=True) - head_summary = head[8:].strip().lower() - expected_summary = '%s %s' % (name.lower(), version) - if head_summary != expected_summary: - raise Exception('latest commit "%s" does not match "%s"' % ( - head_summary, expected_summary)) - - run_script(['./waf configure --docs', - './waf', - './waf distcheck', - './waf posts', - 'gpg -b %s' % dist, - 'git tag -s v%s -m "%s %s"' % (version, name, version)]) |