169 lines
4.5 KiB
Python
Executable File
169 lines
4.5 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
import argparse
|
|
import sys
|
|
import logging
|
|
import subprocess
|
|
import shutil
|
|
import os
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
QMK_REPOSITORY = "https://github.com/qmk/qmk_firmware"
|
|
QMK_PINNED_COMMIT = "daabe2d8c5eab9d9d605f8e079dfae82d2b06a8d"
|
|
QMK_CLONE_PATH = Path("~/src/qmk_firmware").expanduser()
|
|
QMK_USERNAME = "ewpratten"
|
|
LOCAL_KEYMAPS_ROOT = Path(os.environ["EWCONFIG_ROOT"]) / "keyboards" / "qmk" / "keymaps"
|
|
|
|
|
|
def check_prerequisite_tools() -> bool:
|
|
# Ensure we have git
|
|
if shutil.which("git") is None:
|
|
logger.error("git is not installed")
|
|
return False
|
|
|
|
# Ensure we have make
|
|
if shutil.which("make") is None:
|
|
logger.error("make is not installed")
|
|
return False
|
|
|
|
# Ensure we have qmk
|
|
if shutil.which("qmk") is None:
|
|
logger.error("qmk is not installed")
|
|
return False
|
|
|
|
# OK
|
|
return True
|
|
|
|
|
|
def refresh_qmk_repo():
|
|
# If the repo doesn't exist, clone it
|
|
if not QMK_CLONE_PATH.exists():
|
|
logger.info("Cloning QMK repository")
|
|
QMK_CLONE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
subprocess.run(
|
|
["git", "clone", QMK_REPOSITORY, QMK_CLONE_PATH],
|
|
check=True,
|
|
)
|
|
|
|
# Drop any local changes
|
|
logger.info("Dropping local changes")
|
|
subprocess.run(
|
|
["git", "reset", "--hard"],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
|
|
# Pull the latest changes and then checkout the pinned commit
|
|
logger.info("Updating QMK repository")
|
|
subprocess.run(
|
|
["git", "fetch", "--all"],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
subprocess.run(
|
|
["git", "checkout", QMK_PINNED_COMMIT],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
|
|
# Update submodules
|
|
logger.info("Updating QMK submodules")
|
|
subprocess.run(
|
|
["git", "submodule", "update", "--init", "--recursive"],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
|
|
|
|
def copy_keymap(keyboard: str):
|
|
# Build the path that this keymap should be copied to
|
|
KEYMAP_PATH = QMK_CLONE_PATH / "keyboards" / keyboard / "keymaps" / QMK_USERNAME
|
|
|
|
# If the keymap already exists, delete it
|
|
if KEYMAP_PATH.exists():
|
|
logger.info("Removing existing keymap")
|
|
shutil.rmtree(KEYMAP_PATH)
|
|
|
|
# Copy the keymap
|
|
logger.info(f"Copying keymap to: {KEYMAP_PATH}")
|
|
shutil.copytree(LOCAL_KEYMAPS_ROOT / keyboard, KEYMAP_PATH)
|
|
|
|
|
|
def build_keymap(keyboard: str):
|
|
# Build the keymap
|
|
logger.info(f"Building keymap: {keyboard}")
|
|
subprocess.run(
|
|
["make", keyboard + ":" + QMK_USERNAME],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
|
|
|
|
def flash_keymap(keyboard: str, flash_mode: str):
|
|
# Flash the keymap
|
|
logger.info(f"Flashing keymap: {keyboard} ({flash_mode})")
|
|
subprocess.run(
|
|
["qmk", "flash", "-kb", keyboard, "-km", QMK_USERNAME, "-bl", flash_mode],
|
|
check=True,
|
|
cwd=QMK_CLONE_PATH,
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
# Handle program arguments
|
|
ap = argparse.ArgumentParser(
|
|
prog="qmk-helper", description="Utility for flashing QMK boards"
|
|
)
|
|
ap.add_argument("mode", choices=["build", "flash"], help="Mode to run in")
|
|
ap.add_argument(
|
|
"keyboard",
|
|
help="Keyboard to build/flash",
|
|
choices=["tg4x", "ferris/sweep"],
|
|
)
|
|
ap.add_argument("--flash-mode", "-f", help="Flash mode to use", default="flash")
|
|
ap.add_argument(
|
|
"-v", "--verbose", help="Enable verbose logging", action="store_true"
|
|
)
|
|
args = ap.parse_args()
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
level=logging.DEBUG if args.verbose else logging.INFO,
|
|
format="%(levelname)s: %(message)s",
|
|
)
|
|
|
|
# Check for prerequisite tools
|
|
if not check_prerequisite_tools():
|
|
return 1
|
|
logger.info("Prerequisite tools found")
|
|
|
|
# Refresh the QMK repository
|
|
refresh_qmk_repo()
|
|
|
|
# Figure out the keymap name
|
|
keymap = args.keyboard.split("/")[0]
|
|
|
|
# Copy the keymap
|
|
copy_keymap(keymap)
|
|
|
|
# Handle the modes
|
|
if args.mode == "build":
|
|
build_keymap(args.keyboard)
|
|
elif args.mode == "flash":
|
|
# Make sure that the flash mode is valid
|
|
if args.keyboard == "ferris/sweep" and args.flash_mode not in ["dfu-split-left", "dfu-split-right"]:
|
|
logger.error(
|
|
"Invalid flash mode. Must be one of: dfu-split-left, dfu-split-right"
|
|
)
|
|
return 1
|
|
|
|
# Flash
|
|
flash_keymap(args.keyboard, args.flash_mode)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|