Simon Glass | 515ce96 | 2020-04-17 18:08:53 -0600 | [diff] [blame] | 1 | #! /usr/bin/python3 |
Simon Glass | 00ba3b1 | 2019-05-18 10:07:17 -0600 | [diff] [blame] | 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 | |
Simon Glass | 00ba3b1 | 2019-05-18 10:07:17 -0600 | [diff] [blame] | 26 | import glob |
| 27 | import os |
| 28 | import re |
| 29 | import sys |
| 30 | |
Simon Glass | bf77667 | 2020-04-17 18:09:04 -0600 | [diff] [blame] | 31 | from patman import command |
Simon Glass | 00ba3b1 | 2019-05-18 10:07:17 -0600 | [diff] [blame] | 32 | |
| 33 | def rm_kconfig_include(path): |
| 34 | """Remove a path from Kconfig files |
| 35 | |
| 36 | This function finds the given path in a 'source' statement in a Kconfig |
| 37 | file and removes that line from the file. This is needed because the path |
| 38 | is going to be removed, so any reference to it will cause a problem with |
| 39 | Kconfig parsing. |
| 40 | |
| 41 | The changes are made locally and then added to the git staging area. |
| 42 | |
| 43 | Args: |
| 44 | path: Path to search for and remove |
| 45 | """ |
| 46 | cmd = ['git', 'grep', path] |
| 47 | stdout = command.RunPipe([cmd], capture=True, raise_on_error=False).stdout |
| 48 | if not stdout: |
| 49 | return |
| 50 | fname = stdout.split(':')[0] |
| 51 | |
| 52 | print("Fixing up '%s' to remove reference to '%s'" % (fname, path)) |
| 53 | cmd = ['sed', '-i', '\|%s|d' % path, fname] |
| 54 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 55 | |
| 56 | cmd = ['git', 'add', fname] |
| 57 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 58 | |
| 59 | def rm_board(board): |
| 60 | """Create a commit which removes a single board |
| 61 | |
| 62 | This looks up the MAINTAINERS file to file files that need to be removed, |
| 63 | then removes pieces from the Kconfig files that mention the board. |
| 64 | |
| 65 | |
| 66 | Args: |
| 67 | board: Board name to remove |
| 68 | """ |
| 69 | |
| 70 | # Find all MAINTAINERS and Kconfig files which mention the board |
| 71 | cmd = ['git', 'grep', '-l', board] |
| 72 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 73 | maintain = [] |
| 74 | kconfig = [] |
| 75 | for line in stdout.splitlines(): |
| 76 | line = line.strip() |
| 77 | if 'MAINTAINERS' in line: |
| 78 | if line not in maintain: |
| 79 | maintain.append(line) |
| 80 | elif 'Kconfig' in line: |
| 81 | kconfig.append(line) |
| 82 | paths = [] |
| 83 | cc = [] |
| 84 | |
| 85 | # Look through the MAINTAINERS file to find things to remove |
| 86 | for fname in maintain: |
| 87 | with open(fname) as fd: |
| 88 | for line in fd: |
| 89 | line = line.strip() |
| 90 | fields = re.split('[ \t]', line, 1) |
| 91 | if len(fields) == 2: |
| 92 | if fields[0] == 'M:': |
| 93 | cc.append(fields[1]) |
| 94 | elif fields[0] == 'F:': |
| 95 | paths.append(fields[1].strip()) |
| 96 | |
| 97 | # Expand any wildcards in the MAINTAINERS file |
| 98 | real = [] |
| 99 | for path in paths: |
| 100 | if path[-1] == '/': |
| 101 | path = path[:-1] |
| 102 | if '*' in path: |
| 103 | globbed = glob.glob(path) |
| 104 | print("Expanded '%s' to '%s'" % (path, globbed)) |
| 105 | real += globbed |
| 106 | else: |
| 107 | real.append(path) |
| 108 | |
| 109 | # Search for Kconfig files in the resulting list. Remove any 'source' lines |
| 110 | # which reference Kconfig files we want to remove |
| 111 | for path in real: |
| 112 | cmd = ['find', path] |
| 113 | stdout = (command.RunPipe([cmd], capture=True, raise_on_error=False). |
| 114 | stdout) |
| 115 | for fname in stdout.splitlines(): |
| 116 | if fname.endswith('Kconfig'): |
| 117 | rm_kconfig_include(fname) |
| 118 | |
| 119 | # Remove unwanted files |
| 120 | cmd = ['git', 'rm', '-r'] + real |
| 121 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 122 | |
| 123 | ## Change the messages as needed |
| 124 | msg = '''arm: Remove %s board |
| 125 | |
| 126 | This board has not been converted to CONFIG_DM_MMC by the deadline. |
| 127 | Remove it. |
| 128 | |
| 129 | ''' % board |
| 130 | for name in cc: |
| 131 | msg += 'Patch-cc: %s\n' % name |
| 132 | |
| 133 | # Create the commit |
| 134 | cmd = ['git', 'commit', '-s', '-m', msg] |
| 135 | stdout = command.RunPipe([cmd], capture=True).stdout |
| 136 | |
| 137 | # Check if the board is mentioned anywhere else. The user will need to deal |
| 138 | # with this |
| 139 | cmd = ['git', 'grep', '-il', board] |
| 140 | print(command.RunPipe([cmd], capture=True, raise_on_error=False).stdout) |
| 141 | print(' '.join(cmd)) |
| 142 | |
| 143 | for board in sys.argv[1:]: |
| 144 | rm_board(board) |