| #!/usr/bin/env python3 |
| # check out every commit added by the current branch, blackify them, |
| # and generate diffs to reconstruct the original commits, but then |
| # blackified |
| import logging |
| import os |
| import sys |
| from subprocess import PIPE, Popen, check_output, run |
| |
| |
| def git(*args: str) -> str: |
| return check_output(["git"] + list(args)).decode("utf8").strip() |
| |
| |
| def blackify(base_branch: str, black_command: str, logger: logging.Logger) -> int: |
| current_branch = git("branch", "--show-current") |
| |
| if not current_branch or base_branch == current_branch: |
| logger.error("You need to check out a feature branch to work on") |
| return 1 |
| |
| if not os.path.exists(".git"): |
| logger.error("Run me in the root of your repo") |
| return 1 |
| |
| merge_base = git("merge-base", "HEAD", base_branch) |
| if not merge_base: |
| logger.error( |
| "Could not find a common commit for current head and %s" % base_branch |
| ) |
| return 1 |
| |
| commits = git( |
| "log", "--reverse", "--pretty=format:%H", "%s~1..HEAD" % merge_base |
| ).split() |
| for commit in commits: |
| git("checkout", commit, "-b%s-black" % commit) |
| check_output(black_command, shell=True) |
| git("commit", "-aqm", "blackify") |
| |
| git("checkout", base_branch, "-b%s-black" % current_branch) |
| |
| for last_commit, commit in zip(commits, commits[1:]): |
| allow_empty = ( |
| b"--allow-empty" in run(["git", "apply", "-h"], stdout=PIPE).stdout |
| ) |
| quiet = b"--quiet" in run(["git", "apply", "-h"], stdout=PIPE).stdout |
| git_diff = Popen( |
| [ |
| "git", |
| "diff", |
| "--binary", |
| "--find-copies", |
| "%s-black..%s-black" % (last_commit, commit), |
| ], |
| stdout=PIPE, |
| ) |
| git_apply = Popen( |
| [ |
| "git", |
| "apply", |
| ] |
| + (["--quiet"] if quiet else []) |
| + [ |
| "-3", |
| "--intent-to-add", |
| ] |
| + (["--allow-empty"] if allow_empty else []) |
| + [ |
| "-", |
| ], |
| stdin=git_diff.stdout, |
| ) |
| if git_diff.stdout is not None: |
| git_diff.stdout.close() |
| git_apply.communicate() |
| git("commit", "--allow-empty", "-aqC", commit) |
| |
| for commit in commits: |
| git("branch", "-qD", "%s-black" % commit) |
| |
| return 0 |
| |
| |
| if __name__ == "__main__": |
| import argparse |
| |
| parser = argparse.ArgumentParser() |
| parser.add_argument("base_branch") |
| parser.add_argument("--black_command", default="black -q .") |
| parser.add_argument("--logfile", type=argparse.FileType("w"), default=sys.stdout) |
| args = parser.parse_args() |
| logger = logging.getLogger(__name__) |
| logger.addHandler(logging.StreamHandler(args.logfile)) |
| logger.setLevel(logging.INFO) |
| sys.exit(blackify(args.base_branch, args.black_command, logger)) |