Julian Foad wrote on Thu, Jan 03, 2019 at 17:15:16 +0000:
> Julian Foad wrote:
> > [...] either inline or links to the verbose text samples above. [...]
> 
> More precisely: I propose the output of "svn log" as illustrated in those
> samples,

Here you go.

[[[
% ./upcoming.py | tail -46
------------------------------------------------------------------------
r1847610 | svn-role | 2018-11-28 04:00:29 +0000 (Wed, 28 Nov 2018)

Merge the r1847181 group from trunk:

 * r1847181, r1847182, r1847188, r1847264
   Fix issue SVN-4792: Foreign repo copy of file adding mergeinfo.
   Justification:
     We don't want bogus mergeinfo.
   Votes:
     +1: julianfoad, brane, rhuijben
------------------------------------------------------------------------
r1849266 | svn-role | 2018-12-19 04:00:55 +0000 (Wed, 19 Dec 2018)

Merge the r1847572 group from trunk:

 * r1847572, r1847596
   fsfs: Fix SVN-4791, an issue with the DAG open_path() that was causing
   unexpected SVN_ERR_FS_NOT_DIRECTORY errors when attempting to open a path
   with `open_path_node_only | open_path_allow_null` flags.
   Justification:
     Some valid FSFS read operations errored out. This could break some
     end-user operations like 'update'.
   Votes:
     +1: julianfoad, brane, stefan2
------------------------------------------------------------------------
]]]

> concatenated with the full content of the relevant 'STATUS' file.

Minus the "Veto-blocked" changes, though.

Cheers,

Daniel
#! /usr/bin/env python3

"""
WIP - INCOMPLETE

Generate 'svn log' output since the last tag to HEAD of the release branch,
filtering all but merge commits.
"""

import datetime
import os
import re
import subprocess
import sys
import tempfile

import xml.etree.ElementTree as ET

SINCE = '1.11.0'
SVN = os.getenv('SVN', 'svn')
LOG_SEPARATOR_LINE = ('-' * 72) + '\n'

def get_copyfrom_revision_of_tag(version_number):
    """Given a version number, return the copyfrom revision of that release's tag."""
    assert version_number == SINCE
    # TODO: parse and return `svn log -r0:HEAD --limit=1 --stop-on-copy ^/subversion/tags/1.11.0 -vq`
    return 1845131

def get_merges_for_range(start, end):
    """Return an array of revision numbers in the range -r START:END that are
    merges.  START must be an integer; END need not be."""

    cache = []
    revisions = \
        subprocess.check_output(
            [SVN, 'log', '--xml', '-v', '-r', str(start) + ":" + str(end)],
        ).decode()
    log_xml = ET.fromstring(revisions)

    relative_url = subprocess.check_output([SVN, 'info', '--show-item', 'relative-url']).decode().rstrip('\n')

    for logentry in log_xml.findall('./logentry'):
        is_merge = relative_url[1:] in (path.text for path in logentry.findall('.//path'))
        if is_merge:
            yield logentry

def main():
    for logentry in get_merges_for_range(get_copyfrom_revision_of_tag(SINCE) + 1, "HEAD") :
        f = lambda s: logentry.findall('./' + s)[0].text
        f.__doc__ = """Get the contents of the first child tag whose name is given as an argument."""
        print(LOG_SEPARATOR_LINE, end='')
        print("r%(revision)s | %(author)s | %(date)s | %(linecount)s lines" % dict(
            revision  = logentry.attrib['revision'],
            author    = f('author'),
            date      = datetime.datetime.strptime(f('date'), '%Y-%m-%dT%H:%M:%S.%fZ').strftime('%Y-%m-%d %H:%M:%S +0000 (%a, %d %b %Y)'),
            linecount = 1+len(f('msg').splitlines()), # increment because of the empty line printed next
        ))
        print()
        print(f('msg'))

    print(LOG_SEPARATOR_LINE)

if __name__ == '__main__':
    main()

Reply via email to