Source code
Revision control
Copy as Markdown
Other Tools
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
from pathlib import Path
import mozfile
from mach.decorators import Command, CommandArgument
@Command(
    "install-moz-phab",
    category="misc",
    description="Install patch submission tool.",
    virtualenv_name="uv",
)
@CommandArgument(
    "--force",
    "-f",
    action="store_true",
    help="Force installation even if already installed.",
)
def install_moz_phab(command_context, force=False):
    import logging
    import subprocess
    import sys
    moz_phab_executable = mozfile.which("moz-phab")
    if moz_phab_executable and not force:
        command_context.log(
            logging.INFO,
            "already_installed",
            {},
            f"moz-phab is already installed in {moz_phab_executable}.",
        )
        sys.exit(0)
    command_context.log(logging.INFO, "run", {}, "Installing moz-phab using uv")
    cmd = ["uv", "tool", "install", "MozPhab"]
    if force:
        cmd.append("--force")
    result = subprocess.run(cmd)
    if result.returncode != 0:
        command_context.log(
            logging.ERROR,
            "install_failed",
            {},
            "Failed to install moz-phab. Please check that uv is working correctly.",
        )
        sys.exit(1)
    # `uv tool update-shell` adds `moz-phab` to PATH but that requires a terminal restart.
    # We need the executable path now to add the API token, so we locate it via uv
    tool_dir_result = subprocess.run(
        ["uv", "tool", "dir", "--bin"], capture_output=True, text=True
    )
    if tool_dir_result.returncode == 0:
        tool_dir = Path(tool_dir_result.stdout.strip())
        moz_phab_path = tool_dir / "moz-phab"
        if not moz_phab_path.exists():
            moz_phab_path = moz_phab_path.with_suffix(".exe")
        subprocess.run([moz_phab_path, "install-certificate"])
    else:
        command_context.log(
            logging.WARNING,
            "certificate_setup_skipped",
            {},
            "Could not locate installed moz-phab. Please run 'moz-phab install-certificate' manually after restarting your shell.",
        )
    # We run this last, since it instructs the user to restart their shell (if necessary)
    subprocess.run(["uv", "tool", "update-shell"])