File Index
Files and directories
Sign in
FILE

gen-renames.py

File preview with syntax highlighting.

linux-6.19.14/tools/docs/gen-renames.py PYTHON
  1#! /usr/bin/env python3
  2# SPDX-License-Identifier: GPL-2.0
  3#
  4# Copyright © 2025, Oracle and/or its affiliates.
  5# Author: Vegard Nossum <vegard.nossum@oracle.com>
  6
  7"""Trawl repository history for renames of Documentation/**.rst files.
  8
  9Example:
 10
 11    tools/docs/gen-renames.py --rev HEAD > Documentation/.renames.txt
 12"""
 13
 14import argparse
 15import itertools
 16import os
 17import subprocess
 18import sys
 19
 20parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
 21parser.add_argument('--rev', default='HEAD', help='generate renames up to this revision')
 22
 23args = parser.parse_args()
 24
 25def normalize(path):
 26    prefix = 'Documentation/'
 27    suffix = '.rst'
 28
 29    assert path.startswith(prefix)
 30    assert path.endswith(suffix)
 31
 32    return path[len(prefix):-len(suffix)]
 33
 34class Name(object):
 35    def __init__(self, name):
 36        self.names = [name]
 37
 38    def rename(self, new_name):
 39        self.names.append(new_name)
 40
 41names = {
 42}
 43
 44for line in subprocess.check_output([
 45    'git', 'log',
 46    '--reverse',
 47    '--oneline',
 48    '--find-renames',
 49    '--diff-filter=RD',
 50    '--name-status',
 51    '--format=commit %H',
 52    # ~v4.8-ish is when Sphinx/.rst was added in the first place
 53    f'v4.8..{args.rev}',
 54    '--',
 55    'Documentation/'
 56], text=True).splitlines():
 57    # rename
 58    if line.startswith('R'):
 59        _, old, new = line[1:].split('\t', 2)
 60
 61        if old.endswith('.rst') and new.endswith('.rst'):
 62            old = normalize(old)
 63            new = normalize(new)
 64
 65            name = names.get(old)
 66            if name is None:
 67                name = Name(old)
 68            else:
 69                del names[old]
 70
 71            name.rename(new)
 72            names[new] = name
 73
 74        continue
 75
 76    # delete
 77    if line.startswith('D'):
 78        _, old = line.split('\t', 1)
 79
 80        if old.endswith('.rst'):
 81            old = normalize(old)
 82
 83            # TODO: we could save added/modified files as well and propose
 84            # them as alternatives
 85            name = names.get(old)
 86            if name is None:
 87                pass
 88            else:
 89                del names[old]
 90
 91        continue
 92
 93#
 94# Get the set of current files so we can sanity check that we aren't
 95# redirecting any of those
 96#
 97
 98current_files = set()
 99for line in subprocess.check_output([
100    'git', 'ls-tree',
101    '-r',
102    '--name-only',
103    args.rev,
104    'Documentation/',
105], text=True).splitlines():
106    if line.endswith('.rst'):
107        current_files.add(normalize(line))
108
109#
110# Format/group/output result
111#
112
113result = []
114for _, v in names.items():
115    old_names = v.names[:-1]
116    new_name = v.names[-1]
117
118    for old_name in old_names:
119        if old_name == new_name:
120            # A file was renamed to its new name twice; don't redirect that
121            continue
122
123        if old_name in current_files:
124            # A file was recreated with a former name; don't redirect those
125            continue
126
127        result.append((old_name, new_name))
128
129for old_name, new_name in sorted(result):
130    print(f"{old_name} {new_name}")
~/ Read-only file preview.