Simon Glass | 1bc0686 | 2019-05-18 10:07:17 -0600 | [diff] [blame] | 1 | #! /usr/bin/python |
| 2 | # SPDX-License-Identifier: GPL-2.0+ |
| 3 | # Copyright 2019 Google LLC |
| 4 | # |
| 5 | |
| 6 | """ |
| 7 | Script to remove boards |
| 8 | |
| 9 | Usage: |
| 10 | rmboard.py <board_name>... |
| 11 | |
| 12 | A single commit is created for each board removed. |
| 13 | |
| 14 | Some boards may depend on files provided by another and this will cause |
| 15 | problems, generally the removal of files which should not be removed. |
| 16 | |
| 17 | This script works by: |
| 18 | - Looking through the MAINTAINERS files which mention a board to find out |
| 19 | what files the board uses |
| 20 | - Looking through the Kconfig files which mention a board to find one that |
| 21 | needs to have material removed |
| 22 | |
| 23 | Search for ## to update the commit message manually. |
| 24 | """ |
| 25 | |
| 26 | from __future__ import print_function |
| 27 | |
| 28 | import glob |
| 29 | import os |
| 30 | import re |
| 31 | import sys |
| 32 | |
| 33 | # Bring in the patman libraries |
| 34 | our_path = os.path.dirname(os.path.realpath(__file__)) |
| 35 | sys.path.append(os.path.join(our_path, '../tools/patman')) |
| 36 | |
| 37 | import command |
| 38 | |
| 39 | def rm_kconfig_include(path): |
| 40 | """Remove a path from Kconfig files |
| 41 | |
| 42 | This function finds the given path in a 'source' statement in a Kconfig |
| 43 | file and removes that line from the file. This is needed because the path |
| 44 | is going to be removed, so any reference to it will cause a problem with |
| 45 | Kconfig parsing. |
| 46 | |
| 47 | The changes are made locally and then added to the git staging area. |
| 48 | |
| 49 | Args: |
| 50 | path: Path to search for and remove |
| 51 | """ |
| 52 | cmd = ['git', 'grep', path] |
| 53 | stdout = command.RunPipe([cmd], capture=True, raise_on_error=False).stdout |
| 54 | if not stdout: |
| 55 | return |
| 56 | fname = stdout.split(':')[0] |
| 57 | |
| 58 | print("Fixing up '%s' to remove reference to '%s'" % (fname, path)) |
| 59 | cmd = ['sed', '-i', '\|%s|d' % path, fname] |
| 60 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 61 | |
| 62 | cmd = ['git', 'add', fname] |
| 63 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 64 | |
| 65 | def rm_board(board): |
| 66 | """Create a commit which removes a single board |
| 67 | |
| 68 | This looks up the MAINTAINERS file to file files that need to be removed, |
| 69 | then removes pieces from the Kconfig files that mention the board. |
| 70 | |
| 71 | |
| 72 | Args: |
| 73 | board: Board name to remove |
| 74 | """ |
| 75 | |
| 76 | # Find all MAINTAINERS and Kconfig files which mention the board |
| 77 | cmd = ['git', 'grep', '-l', board] |
| 78 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 79 | maintain = [] |
| 80 | kconfig = [] |
| 81 | for line in stdout.splitlines(): |
| 82 | line = line.strip() |
| 83 | if 'MAINTAINERS' in line: |
| 84 | if line not in maintain: |
| 85 | maintain.append(line) |
| 86 | elif 'Kconfig' in line: |
| 87 | kconfig.append(line) |
| 88 | paths = [] |
| 89 | cc = [] |
| 90 | |
| 91 | # Look through the MAINTAINERS file to find things to remove |
| 92 | for fname in maintain: |
| 93 | with open(fname) as fd: |
| 94 | for line in fd: |
| 95 | line = line.strip() |
| 96 | fields = re.split('[ \t]', line, 1) |
| 97 | if len(fields) == 2: |
| 98 | if fields[0] == 'M:': |
| 99 | cc.append(fields[1]) |
| 100 | elif fields[0] == 'F:': |
| 101 | paths.append(fields[1].strip()) |
| 102 | |
| 103 | # Expand any wildcards in the MAINTAINERS file |
| 104 | real = [] |
| 105 | for path in paths: |
| 106 | if path[-1] == '/': |
| 107 | path = path[:-1] |
| 108 | if '*' in path: |
| 109 | globbed = glob.glob(path) |
| 110 | print("Expanded '%s' to '%s'" % (path, globbed)) |
| 111 | real += globbed |
| 112 | else: |
| 113 | real.append(path) |
| 114 | |
| 115 | # Search for Kconfig files in the resulting list. Remove any 'source' lines |
| 116 | # which reference Kconfig files we want to remove |
| 117 | for path in real: |
| 118 | cmd = ['find', path] |
| 119 | stdout = (command.RunPipe([cmd], capture=True, raise_on_error=False). |
| 120 | stdout) |
| 121 | for fname in stdout.splitlines(): |
| 122 | if fname.endswith('Kconfig'): |
| 123 | rm_kconfig_include(fname) |
| 124 | |
| 125 | # Remove unwanted files |
| 126 | cmd = ['git', 'rm', '-r'] + real |
| 127 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 128 | |
| 129 | ## Change the messages as needed |
| 130 | msg = '''arm: Remove %s board |
| 131 | |
| 132 | This board has not been converted to CONFIG_DM_MMC by the deadline. |
| 133 | Remove it. |
| 134 | |
| 135 | ''' % board |
| 136 | for name in cc: |
| 137 | msg += 'Patch-cc: %s\n' % name |
| 138 | |
| 139 | # Create the commit |
| 140 | cmd = ['git', 'commit', '-s', '-m', msg] |
| 141 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 142 | |
| 143 | # Check if the board is mentioned anywhere else. The user will need to deal |
| 144 | # with this |
| 145 | cmd = ['git', 'grep', '-il', board] |
| 146 | print(command.RunPipe([cmd], capture=True, raise_on_error=False).stdout) |
| 147 | print(' '.join(cmd)) |
| 148 | |
| 149 | for board in sys.argv[1:]: |
| 150 | rm_board(board) |