mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			140 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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
 | |
| # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
 | |
| 
 | |
| import mozfile
 | |
| from mach.decorators import Command, CommandArgument
 | |
| from mach.site import MozSiteMetadata
 | |
| 
 | |
| 
 | |
| @Command(
 | |
|     "install-moz-phab",
 | |
|     category="misc",
 | |
|     description="Install patch submission tool.",
 | |
| )
 | |
| @CommandArgument(
 | |
|     "--force",
 | |
|     "-f",
 | |
|     action="store_true",
 | |
|     help="Force installation even if already installed.",
 | |
| )
 | |
| def install_moz_phab(command_context, force=False):
 | |
|     import logging
 | |
|     import os
 | |
|     import re
 | |
|     import subprocess
 | |
|     import sys
 | |
| 
 | |
|     existing = mozfile.which("moz-phab")
 | |
|     if existing and not force:
 | |
|         command_context.log(
 | |
|             logging.ERROR,
 | |
|             "already_installed",
 | |
|             {},
 | |
|             "moz-phab is already installed in %s." % existing,
 | |
|         )
 | |
|         sys.exit(1)
 | |
| 
 | |
|     active_metadata = MozSiteMetadata.from_runtime()
 | |
|     original_python = active_metadata.original_python.python_path
 | |
|     is_external_python_virtualenv = (
 | |
|         subprocess.check_output(
 | |
|             [
 | |
|                 original_python,
 | |
|                 "-c",
 | |
|                 "import sys; print(sys.prefix != sys.base_prefix)",
 | |
|             ]
 | |
|         ).strip()
 | |
|         == b"True"
 | |
|     )
 | |
| 
 | |
|     # pip3 is part of Python since 3.4, however some distros choose to
 | |
|     # remove core components from languages, so show a useful error message
 | |
|     # if pip3 is missing.
 | |
|     has_pip = subprocess.run([original_python, "-c", "import pip"]).returncode == 0
 | |
|     if not has_pip:
 | |
|         command_context.log(
 | |
|             logging.ERROR,
 | |
|             "pip_not_installed",
 | |
|             {},
 | |
|             "Python 3's `pip` is not installed. Try installing it with your system "
 | |
|             "package manager.",
 | |
|         )
 | |
|         sys.exit(1)
 | |
| 
 | |
|     command = [original_python, "-m", "pip", "install", "--upgrade", "MozPhab"]
 | |
| 
 | |
|     if (
 | |
|         sys.platform.startswith("linux")
 | |
|         or sys.platform.startswith("openbsd")
 | |
|         or sys.platform.startswith("dragonfly")
 | |
|         or sys.platform.startswith("freebsd")
 | |
|         or sys.platform.startswith("netbsd")
 | |
|     ):
 | |
|         # On all Linux and BSD distros we consider doing a user installation.
 | |
|         platform_prefers_user_install = True
 | |
| 
 | |
|     elif sys.platform.startswith("darwin"):
 | |
|         # On MacOS we require brew or ports, which work better without --user.
 | |
|         platform_prefers_user_install = False
 | |
| 
 | |
|     elif sys.platform.startswith("win32") or sys.platform.startswith("msys"):
 | |
|         # Likewise for Windows we assume a system level install is preferred.
 | |
|         platform_prefers_user_install = False
 | |
| 
 | |
|     else:
 | |
|         # Unsupported, default to --user.
 | |
|         command_context.log(
 | |
|             logging.WARNING,
 | |
|             "unsupported_platform",
 | |
|             {},
 | |
|             "Unsupported platform (%s), assuming per-user installation is "
 | |
|             "preferred." % sys.platform,
 | |
|         )
 | |
|         platform_prefers_user_install = True
 | |
| 
 | |
|     command_env = os.environ.copy()
 | |
| 
 | |
|     if platform_prefers_user_install and not is_external_python_virtualenv:
 | |
|         # Virtual environments don't see user packages, so only perform a user
 | |
|         # installation if we're not within one.
 | |
|         command.append("--user")
 | |
|         # This is needed to work around a problem on Ubuntu 23.04 and Debian 12
 | |
|         # See bug 1831442 for more details
 | |
|         command_env["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
 | |
| 
 | |
|     command_context.log(logging.INFO, "run", {}, "Installing moz-phab")
 | |
|     subprocess.run(command, env=command_env)
 | |
| 
 | |
|     # There isn't an elegant way of determining the CLI location of a pip-installed package.
 | |
|     # The viable mechanism used here is to:
 | |
|     # 1. Get the list of info about the installed package via pip
 | |
|     # 2. Parse out the install location. This gives us the python environment in which the
 | |
|     #    package is installed
 | |
|     # 3. Parse out the relative location of the cli script
 | |
|     # 4. Join the two paths, and execute the script at that location
 | |
| 
 | |
|     info = subprocess.check_output(
 | |
|         [original_python, "-m", "pip", "show", "-f", "MozPhab"],
 | |
|         universal_newlines=True,
 | |
|     )
 | |
|     mozphab_package_location = re.compile(r"Location: (.*)").search(info).group(1)
 | |
|     # This needs to match "moz-phab" (*nix) and "moz-phab.exe" (Windows) while missing
 | |
|     # "moz-phab-script.py" (Windows).
 | |
|     potential_cli_paths = re.compile(
 | |
|         r"([^\s]*moz-phab(?:\.exe)?)$", re.MULTILINE
 | |
|     ).findall(info)
 | |
| 
 | |
|     if len(potential_cli_paths) != 1:
 | |
|         command_context.log(
 | |
|             logging.WARNING,
 | |
|             "no_mozphab_console_script",
 | |
|             {},
 | |
|             "Could not find the CLI script for moz-phab. Skipping install-certificate step.",
 | |
|         )
 | |
|         sys.exit(1)
 | |
| 
 | |
|     console_script = os.path.realpath(
 | |
|         os.path.join(mozphab_package_location, potential_cli_paths[0])
 | |
|     )
 | |
|     subprocess.run([console_script, "install-certificate"])
 | 
