Bug 1857279 - Load @SettingsProvider settings early so that we can parse set aliases and load the correct virtualenv r=ahal

Aliased commands have not loaded the virtualenv associated with a
command/subcommand since bug 1695312. It has been defaulting to the
`common` virtualenv, which worked most of the time since most commands
use `common` and it also contains a large share of our dependencies.

Differential Revision: https://phabricator.services.mozilla.com/D192376
This commit is contained in:
ahochheiden
2023-11-06 17:08:32 +00:00
parent 6f6dff74e4
commit 9ac56c969c
2 changed files with 56 additions and 42 deletions

View File

@@ -167,7 +167,6 @@ def initialize(topsrcdir, args=()):
_maybe_activate_mozillabuild_environment() _maybe_activate_mozillabuild_environment()
import mach.main import mach.main
import mach.settings # noqa need @SettingsProvider hook to execute
from mach.command_util import ( from mach.command_util import (
MACH_COMMANDS, MACH_COMMANDS,
DetermineCommandVenvAction, DetermineCommandVenvAction,
@@ -175,30 +174,6 @@ def initialize(topsrcdir, args=()):
) )
from mach.main import get_argument_parser from mach.main import get_argument_parser
parser = get_argument_parser(
action=DetermineCommandVenvAction,
topsrcdir=topsrcdir,
)
namespace = parser.parse_args()
command_name = getattr(namespace, "command_name", None)
site_name = getattr(namespace, "site_name", "common")
command_site_manager = None
# the 'clobber' command needs to run in the 'mach' venv, so we
# don't want to activate any other virtualenv for it.
if command_name != "clobber":
from mach.site import CommandSiteManager
command_site_manager = CommandSiteManager.from_environment(
topsrcdir,
lambda: os.path.normpath(get_state_dir(True, topsrcdir=topsrcdir)),
site_name,
get_virtualenv_base_dir(topsrcdir),
)
command_site_manager.activate()
# Set a reasonable limit to the number of open files. # Set a reasonable limit to the number of open files.
# #
# Some linux systems set `ulimit -n` to a very high number, which works # Some linux systems set `ulimit -n` to a very high number, which works
@@ -322,7 +297,7 @@ def initialize(topsrcdir, args=()):
if "MACH_MAIN_PID" not in os.environ: if "MACH_MAIN_PID" not in os.environ:
setenv("MACH_MAIN_PID", str(os.getpid())) setenv("MACH_MAIN_PID", str(os.getpid()))
driver = mach.main.Mach(os.getcwd(), command_site_manager) driver = mach.main.Mach(os.getcwd())
driver.populate_context_handler = populate_context driver.populate_context_handler = populate_context
if not driver.settings_paths: if not driver.settings_paths:
@@ -330,6 +305,42 @@ def initialize(topsrcdir, args=()):
driver.settings_paths.append(state_dir) driver.settings_paths.append(state_dir)
# always load local repository configuration # always load local repository configuration
driver.settings_paths.append(topsrcdir) driver.settings_paths.append(topsrcdir)
driver.load_settings()
aliases = driver.settings.alias
command = args[0]
if command in aliases:
import shlex
alias = aliases[command]
defaults = shlex.split(alias)
args = defaults + args[1:]
parser = get_argument_parser(
action=DetermineCommandVenvAction,
topsrcdir=topsrcdir,
)
namespace = parser.parse_args(args)
command_name = getattr(namespace, "command_name", None)
site_name = getattr(namespace, "site_name", "common")
command_site_manager = None
# the 'clobber' command needs to run in the 'mach' venv, so we
# don't want to activate any other virtualenv for it.
if command_name != "clobber":
from mach.site import CommandSiteManager
command_site_manager = CommandSiteManager.from_environment(
topsrcdir,
lambda: os.path.normpath(get_state_dir(True, topsrcdir=topsrcdir)),
site_name,
get_virtualenv_base_dir(topsrcdir),
)
command_site_manager.activate()
for category, meta in CATEGORIES.items(): for category, meta in CATEGORIES.items():
driver.define_category(category, meta["short"], meta["long"], meta["priority"]) driver.define_category(category, meta["short"], meta["long"], meta["priority"])
@@ -383,6 +394,7 @@ def initialize(topsrcdir, args=()):
for command_name in command_names_to_load for command_name in command_names_to_load
} }
driver.command_site_manager = command_site_manager
load_commands_from_spec(command_modules_to_load, topsrcdir, missing_ok=missing_ok) load_commands_from_spec(command_modules_to_load, topsrcdir, missing_ok=missing_ok)
return driver return driver

View File

@@ -12,9 +12,7 @@ import os
import sys import sys
import traceback import traceback
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import List
from mach.site import CommandSiteManager
from .base import ( from .base import (
CommandContext, CommandContext,
@@ -200,9 +198,7 @@ To see more help for a specific command, run:
%(prog)s help <command> %(prog)s help <command>
""" """
def __init__( def __init__(self, cwd: str):
self, cwd: str, command_site_manager: Optional[CommandSiteManager] = None
):
assert Path(cwd).is_dir() assert Path(cwd).is_dir()
self.cwd = cwd self.cwd = cwd
@@ -210,7 +206,8 @@ To see more help for a specific command, run:
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
self.settings = ConfigSettings() self.settings = ConfigSettings()
self.settings_paths = [] self.settings_paths = []
self.command_site_manager = command_site_manager self.settings_loaded = False
self.command_site_manager = None
if "MACHRC" in os.environ: if "MACHRC" in os.environ:
self.settings_paths.append(os.environ["MACHRC"]) self.settings_paths.append(os.environ["MACHRC"])
@@ -259,13 +256,7 @@ To see more help for a specific command, run:
orig_env = dict(os.environ) orig_env = dict(os.environ)
try: try:
# Load settings as early as possible so things in dispatcher.py self.load_settings()
# can use them.
for provider in Registrar.settings_providers:
self.settings.register_provider(provider)
setting_paths_to_pass = [Path(path) for path in self.settings_paths]
self.load_settings(setting_paths_to_pass)
if sys.version_info < (3, 0): if sys.version_info < (3, 0):
if stdin.encoding is None: if stdin.encoding is None:
@@ -403,7 +394,7 @@ To see more help for a specific command, run:
if args.settings_file: if args.settings_file:
# Argument parsing has already happened, so settings that apply # Argument parsing has already happened, so settings that apply
# to command line handling (e.g alias, defaults) will be ignored. # to command line handling (e.g alias, defaults) will be ignored.
self.load_settings([Path(args.settings_file)]) self.load_settings_by_file([Path(args.settings_file)])
try: try:
return Registrar._run_command_handler( return Registrar._run_command_handler(
@@ -508,7 +499,18 @@ To see more help for a specific command, run:
fh.write("\nSentry event ID: {}\n".format(sentry_event_id)) fh.write("\nSentry event ID: {}\n".format(sentry_event_id))
def load_settings(self, paths: List[Path]): def load_settings(self):
if not self.settings_loaded:
import mach.settings # noqa need @SettingsProvider hook to execute
for provider in Registrar.settings_providers:
self.settings.register_provider(provider)
setting_paths_to_pass = [Path(path) for path in self.settings_paths]
self.load_settings_by_file(setting_paths_to_pass)
self.settings_loaded = True
def load_settings_by_file(self, paths: List[Path]):
"""Load the specified settings files. """Load the specified settings files.
If a directory is specified, the following basenames will be If a directory is specified, the following basenames will be