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-20 18:05:57 +00:00
parent f605774f28
commit 272742b40d
4 changed files with 58 additions and 44 deletions

View File

@ -167,7 +167,6 @@ def initialize(topsrcdir, args=()):
_maybe_activate_mozillabuild_environment()
import mach.main
import mach.settings # noqa need @SettingsProvider hook to execute
from mach.command_util import (
MACH_COMMANDS,
DetermineCommandVenvAction,
@ -175,30 +174,6 @@ def initialize(topsrcdir, args=()):
)
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.
#
# 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:
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
if not driver.settings_paths:
@ -330,6 +305,37 @@ def initialize(topsrcdir, args=()):
driver.settings_paths.append(state_dir)
# always load local repository configuration
driver.settings_paths.append(topsrcdir)
driver.load_settings()
aliases = driver.settings.alias
parser = get_argument_parser(
action=DetermineCommandVenvAction,
topsrcdir=topsrcdir,
)
from argparse import Namespace
namespace_in = Namespace()
setattr(namespace_in, "mach_command_aliases", aliases)
namespace = parser.parse_args(args, namespace_in)
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():
driver.define_category(category, meta["short"], meta["long"], meta["priority"])
@ -383,6 +389,7 @@ def initialize(topsrcdir, args=()):
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)
return driver

View File

@ -341,6 +341,13 @@ class DetermineCommandVenvAction(argparse.Action):
return
command = values[0]
aliases = namespace.mach_command_aliases
if command in aliases:
alias = aliases[command]
command = alias
setattr(namespace, "command_name", command)
# the "help" command does not have a module file, it's handled

View File

@ -12,9 +12,7 @@ import os
import sys
import traceback
from pathlib import Path
from typing import List, Optional
from mach.site import CommandSiteManager
from typing import List
from .base import (
CommandContext,
@ -200,9 +198,7 @@ To see more help for a specific command, run:
%(prog)s help <command>
"""
def __init__(
self, cwd: str, command_site_manager: Optional[CommandSiteManager] = None
):
def __init__(self, cwd: str):
assert Path(cwd).is_dir()
self.cwd = cwd
@ -210,7 +206,8 @@ To see more help for a specific command, run:
self.logger = logging.getLogger(__name__)
self.settings = ConfigSettings()
self.settings_paths = []
self.command_site_manager = command_site_manager
self.settings_loaded = False
self.command_site_manager = None
if "MACHRC" in os.environ:
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)
try:
# Load settings as early as possible so things in dispatcher.py
# 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)
self.load_settings()
if sys.version_info < (3, 0):
if stdin.encoding is None:
@ -403,7 +394,7 @@ To see more help for a specific command, run:
if args.settings_file:
# Argument parsing has already happened, so settings that apply
# 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:
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))
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.
If a directory is specified, the following basenames will be

View File

@ -54,13 +54,11 @@ def patch_vcs(monkeypatch):
@pytest.fixture(scope="session")
def run_mach():
import mach_initialize
from mach.config import ConfigSettings
from tryselect.tasks import build
mach = mach_initialize.initialize(build.topsrcdir)
def inner(args):
mach.settings = ConfigSettings()
return mach.run(args)
return inner