| #!/usr/bin/env python | |
| # Copyright 2022 The IREE Authors | |
| # | |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. | |
| # See https://llvm.org/LICENSE.txt for license information. | |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| # Pushes module patches to an appropriate repository. | |
| # | |
| # Typical steps: | |
| # 1. Advance the main branches on our forks to get all upstream commits | |
| # (if you forget to do this, your cherry-pick will likely complain about | |
| # a bad ref). | |
| # 2. In your submodule: | |
| # git fetch | |
| # git cherry-pick <some commit> | |
| # 3. Run this script from the main IREE repository (one of the following): | |
| # patch_module.py --module=llvm-project | |
| # patch_module.py --module=stablehlo | |
| # 4. Send a PR on the main IREE repo to bump the submodule. Be sure to include | |
| # the name of the patch branch for posterity. | |
| import argparse | |
| from datetime import date | |
| import os | |
| import sys | |
| import iree_utils | |
| import iree_modules | |
| PATCH_REMOTE_ALIAS = "patched" | |
| def main(args): | |
| module_info = iree_modules.MODULE_INFOS.get(args.module) | |
| if not module_info: | |
| raise SystemExit( | |
| f"ERROR: Bad value for --module. Must be one of: " | |
| f"{', '.join(iree_modules.MODULE_INFOS.keys())}" | |
| ) | |
| if args.command == "patch": | |
| main_patch(args, module_info) | |
| else: | |
| raise SystemExit( | |
| f"ERROR: Unrecognized --command. Must be one of: patch, unpatch" | |
| ) | |
| def main_patch(args, module_info: iree_modules.ModuleInfo): | |
| module_root = os.path.join(iree_utils.get_repo_root(), module_info.path) | |
| setup_module_remotes(module_root, module_info) | |
| branch_name = find_unused_branch_name(module_info) | |
| print(f"Allocated branch: {branch_name}") | |
| current_commit, summary = iree_utils.git_current_commit(repo_dir=module_root) | |
| print(f"Module is currently at: {summary}") | |
| print(f"*** Pushing branch {branch_name} to {module_info.fork_repository_push} ***") | |
| print(f"(Please ignore any messages below about creating a PR)\n") | |
| iree_utils.git_exec( | |
| ["push", PATCH_REMOTE_ALIAS, f"{current_commit}:refs/heads/{branch_name}"], | |
| repo_dir=module_root, | |
| ) | |
| print(f"*** Branch {branch_name} pushed ***") | |
| print(f"******* Congratulations *******") | |
| print( | |
| f"You have pushed your commits to {branch_name} on {module_info.fork_repository_push}." | |
| ) | |
| print(f"Your main repository should now show that the submodule has been edited.") | |
| print(f"Make a commit, referencing the above branch cherry-picks and ") | |
| print(f"land the resulting PR.") | |
| print(f"You can push more commits to this module's patch branch via:") | |
| print( | |
| f" (cd {module_info.path} && git push {PATCH_REMOTE_ALIAS} HEAD:{branch_name})" | |
| ) | |
| def setup_module_remotes(module_root: str, module_info: iree_modules.ModuleInfo): | |
| iree_utils.git_setup_remote( | |
| PATCH_REMOTE_ALIAS, url=module_info.fork_repository_push, repo_dir=module_root | |
| ) | |
| def find_unused_branch_name(module_info: iree_modules.ModuleInfo): | |
| branch_base = f"{module_info.branch_prefix}{date.today().strftime('%Y%m%d')}" | |
| branch_name = branch_base | |
| existing_branches = iree_utils.git_ls_remote_branches( | |
| module_info.fork_repository_pull, | |
| filter=[f"refs/heads/{module_info.branch_prefix}*"], | |
| ) | |
| i = 1 | |
| while branch_name in existing_branches: | |
| branch_name = f"{branch_base}.{i}" | |
| i += 1 | |
| return branch_name | |
| def parse_arguments(argv): | |
| parser = argparse.ArgumentParser(description="IREE Submodule Patcher") | |
| parser.add_argument("--module", help="Submodule to operate on", default=None) | |
| parser.add_argument("--command", help="Command to execute", default="patch") | |
| args = parser.parse_args(argv) | |
| return args | |
| if __name__ == "__main__": | |
| main(parse_arguments(sys.argv[1:])) |