mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
I've been running my copybara syncs from this branch for a long time. Finally deciding to PR it. The biggest update was due to `mostrobotpy` absorbing the commands, examples, and pyfrc libraries, but I also added in hooks to "enable" the flakey `xfail` tests on the allwpilib side, and the ability to run verbose or force push updates.
251 lines
8.0 KiB
Python
Executable File
251 lines
8.0 KiB
Python
Executable File
import argparse
|
|
import dataclasses
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import subprocess
|
|
from typing import Optional
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class CopybaraConfig:
|
|
# Needed to run the additional updates for updating the rdev file
|
|
mostrobotpy_local_repo_path: Optional[str] = None
|
|
|
|
# Settings for migrating to a fork that you own
|
|
mostrobotpy_fork_repo: Optional[str] = None
|
|
allwpilib_fork_repo: Optional[str] = None
|
|
robotpy_commandsv2_fork_repo: Optional[str] = None
|
|
|
|
# Settings for truth repositories
|
|
mostrobotpy_truth_repo: str = "https://github.com/robotpy/mostrobotpy.git"
|
|
mostrobotpy_truth_branch: str = "2027"
|
|
|
|
allwpilib_truth_repo: str = "https://github.com/wpilibsuite/allwpilib.git"
|
|
allwpilib_truth_branch: str = "2027"
|
|
|
|
|
|
def run_copybara(
|
|
copybara_file: pathlib.Path,
|
|
migration: str,
|
|
destination_url: str,
|
|
force: bool,
|
|
verbose: bool,
|
|
):
|
|
args = [
|
|
"bazel",
|
|
"run",
|
|
"//:copybara",
|
|
"--",
|
|
"migrate",
|
|
str(copybara_file),
|
|
migration,
|
|
"--git-destination-url",
|
|
destination_url,
|
|
"--git-destination-non-fast-forward",
|
|
]
|
|
|
|
if force:
|
|
args.append("--force")
|
|
if verbose:
|
|
args.append("--verbose")
|
|
|
|
subprocess.check_call(args)
|
|
|
|
|
|
def checkout_branch(auto_delete_branch: bool, branch_name: str):
|
|
"""
|
|
This will attempt run a fetch on the repository in the cwd and checkout the given branch.
|
|
|
|
If the branch currently exists locally, it will be deleted before the fetch happens.
|
|
"""
|
|
# Check if the magic branch exists locally, and if so attempt to delete it
|
|
ret = subprocess.call(["git", "rev-parse", "--verify", branch_name])
|
|
branch_exists = ret == 0
|
|
if branch_exists:
|
|
if not auto_delete_branch:
|
|
ans = input(f"Delete local branch {branch_name}?")
|
|
if ans.lower() != "y":
|
|
raise Exception(
|
|
f"You must delete your local copy of {branch_name} before the script can finish"
|
|
)
|
|
|
|
subprocess.check_call(["git", "branch", "-D", branch_name])
|
|
|
|
subprocess.check_call(["git", "fetch", "--all"])
|
|
subprocess.check_call(["git", "checkout", branch_name])
|
|
|
|
|
|
def update_mostrobotpy_rdev(wpilib_bin_version: str, is_development_build: bool):
|
|
with open("rdev.toml") as f:
|
|
contents = f.read()
|
|
|
|
artifactory_path = "https://frcmaven.wpi.edu/artifactory/"
|
|
if is_development_build:
|
|
artifactory_path += "development-2027"
|
|
else:
|
|
artifactory_path += "release-2027"
|
|
|
|
contents = re.sub(
|
|
'wpilib_bin_version = ".*"',
|
|
f'wpilib_bin_version = "{wpilib_bin_version}"',
|
|
contents,
|
|
)
|
|
contents = re.sub(
|
|
'wpilib_bin_url = ".*"', f'wpilib_bin_url = "{artifactory_path}"', contents
|
|
)
|
|
|
|
with open("rdev.toml", "w") as f:
|
|
f.write(contents)
|
|
|
|
subprocess.check_call(["./rdev.sh", "update-pyproject", "--commit"])
|
|
|
|
|
|
def allwpilib_to_mostrobotpy(
|
|
copybara_file: pathlib.Path,
|
|
mostrobotpy_local_repository: str,
|
|
mostrobotpy_fork_repo: str,
|
|
wpilib_bin_version: str,
|
|
is_development_build: bool,
|
|
auto_delete_branch: bool,
|
|
force: bool,
|
|
verbose: bool,
|
|
):
|
|
run_copybara(
|
|
copybara_file, "allwpilib_to_mostrobotpy", mostrobotpy_fork_repo, force, verbose
|
|
)
|
|
|
|
os.chdir(mostrobotpy_local_repository)
|
|
checkout_branch(auto_delete_branch, "copybara_allwpilib_to_mostrobotpy")
|
|
update_mostrobotpy_rdev(wpilib_bin_version, is_development_build)
|
|
|
|
# Run black
|
|
subprocess.check_call(["black", "."])
|
|
subprocess.check_call(["git", "add", "-A"])
|
|
subprocess.call(["git", "commit", "-m", "Run black"])
|
|
|
|
subprocess.check_call(["git", "push", "-f"])
|
|
|
|
|
|
def mostrobotpy_to_allwpilib(
|
|
copybara_file: pathlib.Path, allwpilib_fork, force: bool, verbose: bool
|
|
):
|
|
run_copybara(
|
|
copybara_file, "mostrobotpy_to_allwpilib", allwpilib_fork, force, verbose
|
|
)
|
|
|
|
|
|
def load_user_config() -> CopybaraConfig:
|
|
script_dir = pathlib.Path(__file__).parent
|
|
user_config_file = script_dir / ".copybara.json"
|
|
if os.path.exists(user_config_file):
|
|
print(f"Loading user config from '{user_config_file}'")
|
|
with open(user_config_file, "r") as f:
|
|
json_config = json.load(f)
|
|
else:
|
|
print(
|
|
f"No user config present at '{user_config_file}', no defaults will be loaded"
|
|
)
|
|
json_config = {}
|
|
|
|
return CopybaraConfig(**json_config)
|
|
|
|
|
|
def main():
|
|
user_config = load_user_config()
|
|
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(
|
|
dest="migration", required=True, help="Available commands"
|
|
)
|
|
|
|
parser.add_argument("--force", action="store_true")
|
|
parser.add_argument("--verbose", action="store_true")
|
|
|
|
def add_allwpilib_fork_arg(subparser):
|
|
subparser.add_argument(
|
|
"--allwpilib_fork_repo",
|
|
default=user_config.allwpilib_fork_repo,
|
|
help="URL to your github fork of allwpilib that you have write permissions for",
|
|
)
|
|
|
|
# allwpilib -> mostrobotpy
|
|
allwpilib_to_mostrobotpy_parser = subparsers.add_parser(
|
|
"allwpilib_to_mostrobotpy",
|
|
help="Pushes changes from the allwpilib mirror to mostrobotpy",
|
|
)
|
|
allwpilib_to_mostrobotpy_parser.add_argument(
|
|
"--wpilib_bin_version",
|
|
required=True,
|
|
type=str,
|
|
help="The wpilib release version as hosted on artifactory",
|
|
)
|
|
allwpilib_to_mostrobotpy_parser.add_argument(
|
|
"--development_build",
|
|
action="store_true",
|
|
help="True if you are upgrading to a development build instead of a release build. Affects where artifacts will be downloaded from.",
|
|
)
|
|
allwpilib_to_mostrobotpy_parser.add_argument(
|
|
"--mostrobotpy_local_repo_path",
|
|
default=user_config.mostrobotpy_local_repo_path,
|
|
help="Path on your local computer to a mostrobotpy clone",
|
|
)
|
|
allwpilib_to_mostrobotpy_parser.add_argument(
|
|
"--mostrobotpy_fork_repo",
|
|
default=user_config.mostrobotpy_fork_repo,
|
|
help="URL to your github fork of mostrobotpy that you have write permissions for",
|
|
)
|
|
allwpilib_to_mostrobotpy_parser.add_argument(
|
|
"-y",
|
|
"--auto_delete_branch",
|
|
action="store_true",
|
|
help="If present, will automatically delete the local version of the copybara branch if it exists. Otherwise you will be prompted if it is ok to delete",
|
|
)
|
|
|
|
# mostrobotpy -> allwpilib
|
|
mostrobotpy_to_allwpilib_parser = subparsers.add_parser(
|
|
"mostrobotpy_to_allwpilib",
|
|
help="Pulls changes from the mostrobotpy source of truth to this mirror",
|
|
)
|
|
add_allwpilib_fork_arg(mostrobotpy_to_allwpilib_parser)
|
|
|
|
script_dir = pathlib.Path(__file__).parent
|
|
copybara_file = script_dir / "../../../copy.bara.sky"
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.migration == "allwpilib_to_mostrobotpy":
|
|
if args.mostrobotpy_local_repo_path is None:
|
|
raise Exception(
|
|
"You mist specify mostrobotpy_local_repo_path, either on the command line or in your user config"
|
|
)
|
|
if args.mostrobotpy_fork_repo is None:
|
|
raise Exception(
|
|
"You mist specify mostrobotpy_fork_repo, either on the command line or in your user config"
|
|
)
|
|
allwpilib_to_mostrobotpy(
|
|
copybara_file,
|
|
args.mostrobotpy_local_repo_path,
|
|
args.mostrobotpy_fork_repo,
|
|
args.wpilib_bin_version,
|
|
args.development_build,
|
|
args.auto_delete_branch,
|
|
args.force,
|
|
args.verbose,
|
|
)
|
|
elif args.migration == "mostrobotpy_to_allwpilib":
|
|
if args.allwpilib_fork_repo is None:
|
|
raise Exception(
|
|
"You mist specify allwpilib_fork_repo, either on the command line or in your user config"
|
|
)
|
|
mostrobotpy_to_allwpilib(
|
|
copybara_file, args.allwpilib_fork_repo, args.force, args.verbose
|
|
)
|
|
else:
|
|
raise Exception(f"Unexpected migration {args.migration}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|