hgext/releasenotes.py
author Gregory Szorc <gregory.szorc@gmail.com>
Fri, 02 Jun 2017 23:33:30 +0200
changeset 32778 91e355a0408b
child 33012 5814db57941c
permissions -rw-r--r--
releasenotes: command to manage release notes files Per discussion on the mailing list, we want better release notes for Mercurial. This patch introduces an extension that provides a command for producing release notes files. Functionality is implemented as an extension because it could be useful outside of the Mercurial project and because there is some code (like rst parsing) that already exists in Mercurial and it doesn't make sense to reinvent the wheel. The general idea with the extension is that changeset authors declare release notes in commit messages using rst directives. Periodically (such as at publishing or release time), a project maintainer runs `hg releasenotes` to extract release notes fragments from commit messages and format them to an auto-generated release notes file. More details are explained inline in docstrings. There are several things that need addressed before this is ready for prime time: * Moar tests * Interactive merge mode * Implement similarity detection for individual notes items * Support customizing section names/titles * Parsing improvements for bullet lists and paragraphs * Document which rst primitives can be parsed * Retain arbitrary content (e.g. header section/paragraphs) from existing release notes file * Better error messages (line numbers, hints, etc)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
32778
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     1
# Copyright 2017-present Gregory Szorc <gregory.szorc@gmail.com>
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     2
#
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     3
# This software may be used and distributed according to the terms of the
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     4
# GNU General Public License version 2 or any later version.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     5
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     6
"""generate release notes from commit messages (EXPERIMENTAL)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     7
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     8
It is common to maintain files detailing changes in a project between
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     9
releases. Maintaining these files can be difficult and time consuming.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    10
The :hg:`releasenotes` command provided by this extension makes the
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    11
process simpler by automating it.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    12
"""
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    13
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    14
from __future__ import absolute_import
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    15
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    16
import errno
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    17
import re
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    18
import sys
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    19
import textwrap
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    20
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    21
from mercurial.i18n import _
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    22
from mercurial import (
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    23
    error,
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    24
    minirst,
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    25
    registrar,
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    26
    scmutil,
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    27
)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    28
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    29
cmdtable = {}
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    30
command = registrar.command(cmdtable)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    31
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    32
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    33
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    34
# be specifying the version(s) of Mercurial they are tested with, or
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    35
# leave the attribute unspecified.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    36
testedwith = 'ships-with-hg-core'
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    37
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    38
DEFAULT_SECTIONS = [
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    39
    ('feature', _('New Features')),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    40
    ('bc', _('Backwards Compatibility Changes')),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    41
    ('fix', _('Bug Fixes')),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    42
    ('perf', _('Performance Improvements')),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    43
    ('api', _('API Changes')),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    44
]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    45
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    46
RE_DIRECTIVE = re.compile('^\.\. ([a-zA-Z0-9_]+)::\s*([^$]+)?$')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    47
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    48
BULLET_SECTION = _('Other Changes')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    49
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    50
class parsedreleasenotes(object):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    51
    def __init__(self):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    52
        self.sections = {}
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    53
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    54
    def __contains__(self, section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    55
        return section in self.sections
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    56
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    57
    def __iter__(self):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    58
        return iter(sorted(self.sections))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    59
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    60
    def addtitleditem(self, section, title, paragraphs):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    61
        """Add a titled release note entry."""
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    62
        self.sections.setdefault(section, ([], []))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    63
        self.sections[section][0].append((title, paragraphs))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    64
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    65
    def addnontitleditem(self, section, paragraphs):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    66
        """Adds a non-titled release note entry.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    67
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    68
        Will be rendered as a bullet point.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    69
        """
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    70
        self.sections.setdefault(section, ([], []))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    71
        self.sections[section][1].append(paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    72
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    73
    def titledforsection(self, section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    74
        """Returns titled entries in a section.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    75
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    76
        Returns a list of (title, paragraphs) tuples describing sub-sections.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    77
        """
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    78
        return self.sections.get(section, ([], []))[0]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    79
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    80
    def nontitledforsection(self, section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    81
        """Returns non-titled, bulleted paragraphs in a section."""
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    82
        return self.sections.get(section, ([], []))[1]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    83
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    84
    def hastitledinsection(self, section, title):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    85
        return any(t[0] == title for t in self.titledforsection(section))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    86
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    87
    def merge(self, ui, other):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    88
        """Merge another instance into this one.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    89
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    90
        This is used to combine multiple sources of release notes together.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    91
        """
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    92
        for section in other:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    93
            for title, paragraphs in other.titledforsection(section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    94
                if self.hastitledinsection(section, title):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    95
                    # TODO prompt for resolution if different and running in
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    96
                    # interactive mode.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    97
                    ui.write(_('%s already exists in %s section; ignoring\n') %
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    98
                             (title, section))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    99
                    continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   100
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   101
                # TODO perform similarity comparison and try to match against
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   102
                # existing.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   103
                self.addtitleditem(section, title, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   104
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   105
            for paragraphs in other.nontitledforsection(section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   106
                if paragraphs in self.nontitledforsection(section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   107
                    continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   108
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   109
                # TODO perform similarily comparison and try to match against
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   110
                # existing.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   111
                self.addnontitleditem(section, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   112
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   113
class releasenotessections(object):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   114
    def __init__(self, ui):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   115
        # TODO support defining custom sections from config.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   116
        self._sections = list(DEFAULT_SECTIONS)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   117
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   118
    def __iter__(self):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   119
        return iter(self._sections)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   120
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   121
    def names(self):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   122
        return [t[0] for t in self._sections]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   123
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   124
    def sectionfromtitle(self, title):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   125
        for name, value in self._sections:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   126
            if value == title:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   127
                return name
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   128
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   129
        return None
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   130
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   131
def parsenotesfromrevisions(repo, directives, revs):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   132
    notes = parsedreleasenotes()
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   133
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   134
    for rev in revs:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   135
        ctx = repo[rev]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   136
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   137
        blocks, pruned = minirst.parse(ctx.description(),
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   138
                                       admonitions=directives)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   139
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   140
        for i, block in enumerate(blocks):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   141
            if block['type'] != 'admonition':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   142
                continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   143
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   144
            directive = block['admonitiontitle']
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   145
            title = block['lines'][0].strip() if block['lines'] else None
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   146
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   147
            if i + 1 == len(blocks):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   148
                raise error.Abort(_('release notes directive %s lacks content')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   149
                                  % directive)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   150
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   151
            # Now search ahead and find all paragraphs attached to this
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   152
            # admonition.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   153
            paragraphs = []
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   154
            for j in range(i + 1, len(blocks)):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   155
                pblock = blocks[j]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   156
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   157
                # Margin blocks may appear between paragraphs. Ignore them.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   158
                if pblock['type'] == 'margin':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   159
                    continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   160
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   161
                if pblock['type'] != 'paragraph':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   162
                    raise error.Abort(_('unexpected block in release notes '
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   163
                                        'directive %s') % directive)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   164
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   165
                if pblock['indent'] > 0:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   166
                    paragraphs.append(pblock['lines'])
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   167
                else:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   168
                    break
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   169
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   170
            # TODO consider using title as paragraph for more concise notes.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   171
            if not paragraphs:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   172
                raise error.Abort(_('could not find content for release note '
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   173
                                    '%s') % directive)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   174
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   175
            if title:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   176
                notes.addtitleditem(directive, title, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   177
            else:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   178
                notes.addnontitleditem(directive, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   179
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   180
    return notes
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   181
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   182
def parsereleasenotesfile(sections, text):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   183
    """Parse text content containing generated release notes."""
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   184
    notes = parsedreleasenotes()
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   185
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   186
    blocks = minirst.parse(text)[0]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   187
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   188
    def gatherparagraphs(offset):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   189
        paragraphs = []
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   190
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   191
        for i in range(offset + 1, len(blocks)):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   192
            block = blocks[i]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   193
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   194
            if block['type'] == 'margin':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   195
                continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   196
            elif block['type'] == 'section':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   197
                break
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   198
            elif block['type'] == 'bullet':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   199
                if block['indent'] != 0:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   200
                    raise error.Abort(_('indented bullet lists not supported'))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   201
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   202
                lines = [l[1:].strip() for l in block['lines']]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   203
                paragraphs.append(lines)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   204
                continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   205
            elif block['type'] != 'paragraph':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   206
                raise error.Abort(_('unexpected block type in release notes: '
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   207
                                    '%s') % block['type'])
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   208
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   209
            paragraphs.append(block['lines'])
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   210
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   211
        return paragraphs
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   212
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   213
    currentsection = None
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   214
    for i, block in enumerate(blocks):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   215
        if block['type'] != 'section':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   216
            continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   217
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   218
        title = block['lines'][0]
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   219
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   220
        # TODO the parsing around paragraphs and bullet points needs some
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   221
        # work.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   222
        if block['underline'] == '=':  # main section
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   223
            name = sections.sectionfromtitle(title)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   224
            if not name:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   225
                raise error.Abort(_('unknown release notes section: %s') %
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   226
                                  title)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   227
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   228
            currentsection = name
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   229
            paragraphs = gatherparagraphs(i)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   230
            if paragraphs:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   231
                notes.addnontitleditem(currentsection, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   232
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   233
        elif block['underline'] == '-':  # sub-section
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   234
            paragraphs = gatherparagraphs(i)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   235
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   236
            if title == BULLET_SECTION:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   237
                notes.addnontitleditem(currentsection, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   238
            else:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   239
                notes.addtitleditem(currentsection, title, paragraphs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   240
        else:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   241
            raise error.Abort(_('unsupported section type for %s') % title)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   242
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   243
    return notes
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   244
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   245
def serializenotes(sections, notes):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   246
    """Serialize release notes from parsed fragments and notes.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   247
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   248
    This function essentially takes the output of ``parsenotesfromrevisions()``
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   249
    and ``parserelnotesfile()`` and produces output combining the 2.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   250
    """
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   251
    lines = []
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   252
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   253
    for sectionname, sectiontitle in sections:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   254
        if sectionname not in notes:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   255
            continue
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   256
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   257
        lines.append(sectiontitle)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   258
        lines.append('=' * len(sectiontitle))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   259
        lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   260
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   261
        # First pass to emit sub-sections.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   262
        for title, paragraphs in notes.titledforsection(sectionname):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   263
            lines.append(title)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   264
            lines.append('-' * len(title))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   265
            lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   266
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   267
            wrapper = textwrap.TextWrapper(width=78)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   268
            for i, para in enumerate(paragraphs):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   269
                if i:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   270
                    lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   271
                lines.extend(wrapper.wrap(' '.join(para)))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   272
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   273
            lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   274
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   275
        # Second pass to emit bullet list items.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   276
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   277
        # If the section has titled and non-titled items, we can't
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   278
        # simply emit the bullet list because it would appear to come
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   279
        # from the last title/section. So, we emit a new sub-section
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   280
        # for the non-titled items.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   281
        nontitled = notes.nontitledforsection(sectionname)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   282
        if notes.titledforsection(sectionname) and nontitled:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   283
            # TODO make configurable.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   284
            lines.append(BULLET_SECTION)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   285
            lines.append('-' * len(BULLET_SECTION))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   286
            lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   287
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   288
        for paragraphs in nontitled:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   289
            wrapper = textwrap.TextWrapper(initial_indent='* ',
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   290
                                           subsequent_indent='  ',
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   291
                                           width=78)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   292
            lines.extend(wrapper.wrap(' '.join(paragraphs[0])))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   293
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   294
            wrapper = textwrap.TextWrapper(initial_indent='  ',
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   295
                                           subsequent_indent='  ',
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   296
                                           width=78)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   297
            for para in paragraphs[1:]:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   298
                lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   299
                lines.extend(wrapper.wrap(' '.join(para)))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   300
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   301
            lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   302
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   303
    if lines[-1]:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   304
        lines.append('')
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   305
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   306
    return '\n'.join(lines)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   307
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   308
@command('releasenotes',
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   309
    [('r', 'rev', '', _('revisions to process for release notes'), _('REV'))],
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   310
    _('[-r REV] FILE'))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   311
def releasenotes(ui, repo, file_, rev=None):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   312
    """parse release notes from commit messages into an output file
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   313
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   314
    Given an output file and set of revisions, this command will parse commit
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   315
    messages for release notes then add them to the output file.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   316
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   317
    Release notes are defined in commit messages as ReStructuredText
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   318
    directives. These have the form::
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   319
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   320
       .. directive:: title
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   321
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   322
          content
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   323
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   324
    Each ``directive`` maps to an output section in a generated release notes
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   325
    file, which itself is ReStructuredText. For example, the ``.. feature::``
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   326
    directive would map to a ``New Features`` section.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   327
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   328
    Release note directives can be either short-form or long-form. In short-
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   329
    form, ``title`` is omitted and the release note is rendered as a bullet
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   330
    list. In long form, a sub-section with the title ``title`` is added to the
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   331
    section.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   332
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   333
    The ``FILE`` argument controls the output file to write gathered release
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   334
    notes to. The format of the file is::
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   335
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   336
       Section 1
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   337
       =========
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   338
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   339
       ...
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   340
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   341
       Section 2
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   342
       =========
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   343
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   344
       ...
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   345
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   346
    Only sections with defined release notes are emitted.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   347
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   348
    If a section only has short-form notes, it will consist of bullet list::
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   349
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   350
       Section
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   351
       =======
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   352
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   353
       * Release note 1
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   354
       * Release note 2
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   355
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   356
    If a section has long-form notes, sub-sections will be emitted::
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   357
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   358
       Section
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   359
       =======
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   360
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   361
       Note 1 Title
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   362
       ------------
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   363
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   364
       Description of the first long-form note.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   365
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   366
       Note 2 Title
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   367
       ------------
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   368
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   369
       Description of the second long-form note.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   370
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   371
    If the ``FILE`` argument points to an existing file, that file will be
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   372
    parsed for release notes having the format that would be generated by this
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   373
    command. The notes from the processed commit messages will be *merged*
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   374
    into this parsed set.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   375
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   376
    During release notes merging:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   377
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   378
    * Duplicate items are automatically ignored
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   379
    * Items that are different are automatically ignored if the similarity is
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   380
      greater than a threshold.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   381
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   382
    This means that the release notes file can be updated independently from
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   383
    this command and changes should not be lost when running this command on
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   384
    that file. A particular use case for this is to tweak the wording of a
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   385
    release note after it has been added to the release notes file.
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   386
    """
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   387
    sections = releasenotessections(ui)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   388
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   389
    revs = scmutil.revrange(repo, [rev or 'not public()'])
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   390
    incoming = parsenotesfromrevisions(repo, sections.names(), revs)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   391
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   392
    try:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   393
        with open(file_, 'rb') as fh:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   394
            notes = parsereleasenotesfile(sections, fh.read())
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   395
    except IOError as e:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   396
        if e.errno != errno.ENOENT:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   397
            raise
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   398
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   399
        notes = parsedreleasenotes()
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   400
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   401
    notes.merge(ui, incoming)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   402
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   403
    with open(file_, 'wb') as fh:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   404
        fh.write(serializenotes(sections, notes))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   405
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   406
@command('debugparsereleasenotes', norepo=True)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   407
def debugparsereleasenotes(ui, path):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   408
    """parse release notes and print resulting data structure"""
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   409
    if path == '-':
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   410
        text = sys.stdin.read()
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   411
    else:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   412
        with open(path, 'rb') as fh:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   413
            text = fh.read()
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   414
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   415
    sections = releasenotessections(ui)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   416
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   417
    notes = parsereleasenotesfile(sections, text)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   418
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   419
    for section in notes:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   420
        ui.write(_('section: %s\n') % section)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   421
        for title, paragraphs in notes.titledforsection(section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   422
            ui.write(_('  subsection: %s\n') % title)
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   423
            for para in paragraphs:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   424
                ui.write(_('    paragraph: %s\n') % ' '.join(para))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   425
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   426
        for paragraphs in notes.nontitledforsection(section):
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   427
            ui.write(_('  bullet point:\n'))
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   428
            for para in paragraphs:
91e355a0408b releasenotes: command to manage release notes files
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   429
                ui.write(_('    paragraph: %s\n') % ' '.join(para))