130 lines · 3.0 KB · Python
RawDownload
#! /usr/bin/env python3# SPDX-License-Identifier: GPL-2.0## Copyright © 2025, Oracle and/or its affiliates.# Author: Vegard Nossum <vegard.nossum@oracle.com> """Trawl repository history for renames of Documentation/**.rst files. Example:     tools/docs/gen-renames.py --rev HEAD > Documentation/.renames.txt""" import argparseimport itertoolsimport osimport subprocessimport sys parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)parser.add_argument('--rev', default='HEAD', help='generate renames up to this revision') args = parser.parse_args() def normalize(path):    prefix = 'Documentation/'    suffix = '.rst'     assert path.startswith(prefix)    assert path.endswith(suffix)     return path[len(prefix):-len(suffix)] class Name(object):    def __init__(self, name):        self.names = [name]     def rename(self, new_name):        self.names.append(new_name) names = {} for line in subprocess.check_output([    'git', 'log',    '--reverse',    '--oneline',    '--find-renames',    '--diff-filter=RD',    '--name-status',    '--format=commit %H',    # ~v4.8-ish is when Sphinx/.rst was added in the first place    f'v4.8..{args.rev}',    '--',    'Documentation/'], text=True).splitlines():    # rename    if line.startswith('R'):        _, old, new = line[1:].split('\t', 2)         if old.endswith('.rst') and new.endswith('.rst'):            old = normalize(old)            new = normalize(new)             name = names.get(old)            if name is None:                name = Name(old)            else:                del names[old]             name.rename(new)            names[new] = name         continue     # delete    if line.startswith('D'):        _, old = line.split('\t', 1)         if old.endswith('.rst'):            old = normalize(old)             # TODO: we could save added/modified files as well and propose            # them as alternatives            name = names.get(old)            if name is None:                pass            else:                del names[old]         continue ## Get the set of current files so we can sanity check that we aren't# redirecting any of those# current_files = set()for line in subprocess.check_output([    'git', 'ls-tree',    '-r',    '--name-only',    args.rev,    'Documentation/',], text=True).splitlines():    if line.endswith('.rst'):        current_files.add(normalize(line)) ## Format/group/output result# result = []for _, v in names.items():    old_names = v.names[:-1]    new_name = v.names[-1]     for old_name in old_names:        if old_name == new_name:            # A file was renamed to its new name twice; don't redirect that            continue         if old_name in current_files:            # A file was recreated with a former name; don't redirect those            continue         result.append((old_name, new_name)) for old_name, new_name in sorted(result):    print(f"{old_name} {new_name}")