Add a script to automatically generate both changelogs from a single file
This avoids the need to manually copy entries between NEWS.rst and NEWS-dev.rst, and also helps fix some inconsistencies automatically. Pre-0.44.07 changelogs have not been converted yet.develop
parent
573fcb4bd0
commit
476483adb3
@ -0,0 +1,14 @@
|
||||
.. comment
|
||||
This is the changelog for stable releases. Entries are included from
|
||||
changelog.txt.
|
||||
|
||||
.. _changelog:
|
||||
|
||||
#########
|
||||
Changelog
|
||||
#########
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
|
||||
.. include:: /docs/_auto/news.rst
|
@ -0,0 +1,46 @@
|
||||
================================================================================
|
||||
# Future
|
||||
|
||||
|
||||
================================================================================
|
||||
# 0.44.09-alpha1
|
||||
|
||||
## Fixes
|
||||
- `digtype`: stopped designating non-vein tiles (open space, trees, etc.)
|
||||
- `labormanager`: fixed crash due to dig jobs targeting some unrevealed map blocks
|
||||
|
||||
|
||||
================================================================================
|
||||
# 0.44.08-alpha1
|
||||
|
||||
## Fixes
|
||||
- `fix/dead-units`: fixed a bug that could remove some arriving (not dead) units
|
||||
|
||||
|
||||
================================================================================
|
||||
# 0.44.07-beta1
|
||||
|
||||
## Structures
|
||||
-@ Added symbols for Toady's `0.44.07 Linux test build <http://www.bay12forums.com/smf/index.php?topic=169839.msg7720111#msg7720111>`_ to fix :bug:`10615`
|
||||
-@ ``world_site``: fixed alignment
|
||||
|
||||
## Misc improvements
|
||||
- `modtools/item-trigger`: added the ability to specify inventory mode(s) to trigger on
|
||||
|
||||
|
||||
================================================================================
|
||||
# 0.44.07-alpha1
|
||||
|
||||
## Fixes
|
||||
- `embark-assistant`: fixed detection of reanimating biomes
|
||||
|
||||
## Structures
|
||||
- Several new names in instrument raw structures
|
||||
- ``identity``: identified ``profession``, ``civ``
|
||||
- ``manager_order_template``: fixed last field type
|
||||
- ``viewscreen_createquotast``: fixed layout
|
||||
- ``world.language``: moved ``colors``, ``shapes``, ``patterns`` to ``world.descriptors``
|
||||
- ``world.reactions``, ``world.reaction_categories``:\ moved to new compound, ``world.reactions``. Requires renaming
|
||||
|
||||
- ``world.reactions`` to ``world.reactions.reactions``
|
||||
- ``world.reaction_categories`` to ``world.reactions.reaction_categories``
|
@ -0,0 +1,177 @@
|
||||
import collections
|
||||
import copy
|
||||
import itertools
|
||||
import os
|
||||
|
||||
CHANGELOG_SECTIONS = [
|
||||
'New Plugins',
|
||||
'New Scripts',
|
||||
'New Tweaks',
|
||||
'New Features',
|
||||
'New Internal Commands',
|
||||
'Fixes',
|
||||
'Misc Improvements',
|
||||
'Removed',
|
||||
'Internals',
|
||||
'Structures',
|
||||
'Lua',
|
||||
'Ruby',
|
||||
]
|
||||
|
||||
class ChangelogEntry(object):
|
||||
def __init__(self, text, section, stable_version, dev_version):
|
||||
text = text.lstrip('- ')
|
||||
# normalize section to title case
|
||||
self.section = ' '.join(word[0].upper() + word[1:].lower()
|
||||
for word in section.strip().split())
|
||||
self.stable_version = stable_version
|
||||
self.dev_version = dev_version
|
||||
self.dev_only = text.startswith('@')
|
||||
text = text.lstrip('@ ')
|
||||
self.children = []
|
||||
|
||||
split_index = text.find(': ')
|
||||
if split_index != -1:
|
||||
self.feature, description = text[:split_index], text[split_index+1:]
|
||||
if description.strip():
|
||||
self.children.insert(0, description.strip())
|
||||
else:
|
||||
self.feature = text
|
||||
self.feature = self.feature.replace(':\\', ':')
|
||||
|
||||
self.sort_key = self.feature.upper()
|
||||
|
||||
def __repr__(self):
|
||||
return 'ChangelogEntry(%r, %r)' % (self.feature, self.children)
|
||||
|
||||
def parse_changelog():
|
||||
cur_stable = None
|
||||
cur_dev = None
|
||||
cur_section = None
|
||||
last_entry = None
|
||||
entries = []
|
||||
|
||||
with open('docs/changelog.txt') as f:
|
||||
for line_id, line in enumerate(f.readlines()):
|
||||
line_id += 1
|
||||
if not line.strip() or line.startswith('==='):
|
||||
continue
|
||||
|
||||
if line.startswith('##'):
|
||||
cur_section = line.lstrip('#').strip()
|
||||
elif line.startswith('#'):
|
||||
cur_dev = line.lstrip('#').strip().lower()
|
||||
if ('alpha' not in cur_dev and 'beta' not in cur_dev and
|
||||
'rc' not in cur_dev):
|
||||
cur_stable = cur_dev
|
||||
elif line.startswith('-'):
|
||||
if not cur_stable or not cur_dev or not cur_section:
|
||||
raise ValueError(
|
||||
'changelog.txt:%i: Entry without section' % line_id)
|
||||
last_entry = ChangelogEntry(line.strip(), cur_section,
|
||||
cur_stable, cur_dev)
|
||||
entries.append(last_entry)
|
||||
# entries.setdefault(cur_stable, []).append(last_entry)
|
||||
# entries.setdefault(cur_dev, []).append(last_entry)
|
||||
elif line.lstrip().startswith('-'):
|
||||
if not cur_stable or not cur_dev:
|
||||
raise ValueError(
|
||||
'changelog.txt:%i: Sub-entry without section' % line_id)
|
||||
if not last_entry:
|
||||
raise ValueError(
|
||||
'changelog.txt:%i: Sub-entry without parent' % line_id)
|
||||
last_entry.children.append(line.strip('- \n'))
|
||||
else:
|
||||
raise ValueError('Invalid line: ' + line)
|
||||
|
||||
return entries
|
||||
|
||||
def consolidate_changelog(all_entries):
|
||||
for sections in all_entries.values():
|
||||
for section, entries in sections.items():
|
||||
# sort() is stable, so reverse entries so that older entries for the
|
||||
# same feature are on top
|
||||
entries.reverse()
|
||||
entries.sort(key=lambda entry: entry.sort_key)
|
||||
new_entries = []
|
||||
for feature, group in itertools.groupby(entries,
|
||||
lambda e: e.feature):
|
||||
old_entries = list(group)
|
||||
children = list(itertools.chain(*[entry.children
|
||||
for entry in old_entries]))
|
||||
new_entry = copy.deepcopy(old_entries[0])
|
||||
new_entry.children = children
|
||||
new_entries.append(new_entry)
|
||||
entries[:] = new_entries
|
||||
|
||||
|
||||
|
||||
def print_changelog(versions, all_entries, path):
|
||||
# all_entries: version -> section -> entry
|
||||
with open(path, 'w') as f:
|
||||
write = lambda s: f.write(s + '\n')
|
||||
for version in versions:
|
||||
sections = all_entries[version]
|
||||
if not sections:
|
||||
continue
|
||||
version = 'DFHack ' + version
|
||||
write(version)
|
||||
write('=' * len(version))
|
||||
write('')
|
||||
for section in CHANGELOG_SECTIONS:
|
||||
entries = sections[section]
|
||||
if not entries:
|
||||
continue
|
||||
write(section)
|
||||
write('-' * len(section))
|
||||
for entry in entries:
|
||||
if len(entry.children) == 1:
|
||||
write('- ' + entry.feature + ': ' +
|
||||
entry.children[0].strip('- '))
|
||||
continue
|
||||
elif entry.children:
|
||||
write('- ' + entry.feature + ':')
|
||||
write('')
|
||||
for child in entry.children:
|
||||
write(' - ' + child)
|
||||
write('')
|
||||
else:
|
||||
write('- ' + entry.feature)
|
||||
write('')
|
||||
write('')
|
||||
|
||||
|
||||
def generate_changelog():
|
||||
entries = parse_changelog()
|
||||
|
||||
# scan for unrecognized sections
|
||||
for entry in entries:
|
||||
if entry.section not in CHANGELOG_SECTIONS:
|
||||
raise RuntimeWarning('Unknown section: ' + entry.section)
|
||||
|
||||
# ordered versions
|
||||
versions = ['future']
|
||||
# map versions to stable versions
|
||||
stable_version_map = {}
|
||||
# version -> section -> entry
|
||||
stable_entries = collections.defaultdict(lambda:
|
||||
collections.defaultdict(list))
|
||||
dev_entries = collections.defaultdict(lambda:
|
||||
collections.defaultdict(list))
|
||||
for entry in entries:
|
||||
if entry.dev_version not in versions:
|
||||
versions.append(entry.dev_version)
|
||||
stable_version_map.setdefault(entry.dev_version, entry.stable_version)
|
||||
if not entry.dev_only:
|
||||
stable_entries[entry.stable_version][entry.section].append(entry)
|
||||
dev_entries[entry.dev_version][entry.section].append(entry)
|
||||
|
||||
consolidate_changelog(stable_entries)
|
||||
|
||||
print_changelog(versions, stable_entries, 'docs/_auto/news.rst')
|
||||
print_changelog(versions, dev_entries, 'docs/_auto/news-dev.rst')
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
||||
os.chdir('..')
|
||||
generate_changelog()
|
Loading…
Reference in New Issue