| #!/usr/bin/env python3 |
| # |
| # Copyright © 2019 Endless Mobile, Inc. |
| # |
| # SPDX-License-Identifier: LGPL-2.1-or-later |
| # |
| # Original author: Philip Withnall |
| |
| """ |
| Checks that a merge request doesn’t add any instances of the string ‘todo’ |
| (in uppercase), or similar keywords. It may remove instances of that keyword, |
| or move them around, according to the logic of `git log -S`. |
| """ |
| |
| import argparse |
| import re |
| import subprocess |
| import sys |
| |
| |
| # We have to specify these keywords obscurely to avoid the script matching |
| # itself. The keyword ‘fixme’ (in upper case) is explicitly allowed because |
| # that’s conventionally used as a way of marking a workaround which needs to |
| # be merged for now, but is to be grepped for and reverted or reworked later. |
| BANNED_KEYWORDS = ["TO" + "DO", "X" + "XX", "W" + "IP"] |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| description="Check a range of commits to ensure they don’t contain " |
| "banned keywords." |
| ) |
| parser.add_argument("commits", help="SHA to diff from, or range of commits to diff") |
| args = parser.parse_args() |
| |
| banned_words_seen = set() |
| seen_in_log = False |
| seen_in_diff = False |
| |
| # Check the log messages for banned words. |
| log_process = subprocess.run( |
| ["git", "log", "--no-color", args.commits + "..HEAD"], |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE, |
| encoding="utf-8", |
| check=True, |
| ) |
| log_lines = log_process.stdout.strip().split("\n") |
| |
| for line in log_lines: |
| for keyword in BANNED_KEYWORDS: |
| if re.search(r"(^|\W+){}(\W+|$)".format(keyword), line): |
| banned_words_seen.add(keyword) |
| seen_in_log = True |
| |
| # Check the diff for banned words. |
| diff_process = subprocess.run( |
| ["git", "diff", "-U0", "--no-color", args.commits], |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE, |
| encoding="utf-8", |
| check=True, |
| ) |
| diff_lines = diff_process.stdout.strip().split("\n") |
| |
| for line in diff_lines: |
| if not line.startswith("+ "): |
| continue |
| |
| for keyword in BANNED_KEYWORDS: |
| if re.search(r"(^|\W+){}(\W+|$)".format(keyword), line): |
| banned_words_seen.add(keyword) |
| seen_in_diff = True |
| |
| if banned_words_seen: |
| if seen_in_log and seen_in_diff: |
| where = "commit message and diff" |
| elif seen_in_log: |
| where = "commit message" |
| elif seen_in_diff: |
| where = "commit diff" |
| |
| print( |
| "Saw banned keywords in a {}: {}. " |
| "This indicates the branch is a work in progress and should not " |
| "be merged in its current " |
| "form.".format(where, ", ".join(banned_words_seen)) |
| ) |
| sys.exit(1) |
| |
| |
| if __name__ == "__main__": |
| main() |