mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Bug 1695272: Move --no-interactive
to global mach args r=firefox-build-system-reviewers,glandium
Updates `./mach bootstrap` to use `--no-interactive` from global args. Ensures all bootstrap prompts have a default option. Differential Revision: https://phabricator.services.mozilla.com/D106814
This commit is contained in:
parent
8133abcb41
commit
b7e0dfe1d1
1
mach
1
mach
@ -62,6 +62,7 @@ get_command() {
|
|||||||
shift 2
|
shift 2
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
--no-interactive) shift;;
|
||||||
--log-interval) shift;;
|
--log-interval) shift;;
|
||||||
--log-no-times) shift;;
|
--log-no-times) shift;;
|
||||||
-h) shift;;
|
-h) shift;;
|
||||||
|
@ -55,7 +55,7 @@ argument to automatically accept any license agreements.
|
|||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
./mach bootstrap [ --no-interactive]
|
./mach [--no-interactive] bootstrap
|
||||||
|
|
||||||
- Choose option \`4. Firefox for Android\` for GeckoView development.
|
- Choose option \`4. Firefox for Android\` for GeckoView development.
|
||||||
This will give you a version of Gecko configured for Android that has
|
This will give you a version of Gecko configured for Android that has
|
||||||
|
@ -23,6 +23,7 @@ class CommandContext(object):
|
|||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.log_manager = log_manager
|
self.log_manager = log_manager
|
||||||
self.commands = commands
|
self.commands = commands
|
||||||
|
self.is_interactive = None # Filled in after args are parsed
|
||||||
self.telemetry = telemetry
|
self.telemetry = telemetry
|
||||||
self.command_attrs = {}
|
self.command_attrs = {}
|
||||||
|
|
||||||
|
@ -447,6 +447,12 @@ To see more help for a specific command, run:
|
|||||||
if not hasattr(args, "mach_handler"):
|
if not hasattr(args, "mach_handler"):
|
||||||
raise MachError("ArgumentParser result missing mach handler info.")
|
raise MachError("ArgumentParser result missing mach handler info.")
|
||||||
|
|
||||||
|
context.is_interactive = (
|
||||||
|
args.is_interactive
|
||||||
|
and sys.__stdout__.isatty()
|
||||||
|
and sys.__stderr__.isatty()
|
||||||
|
and not os.environ.get("MOZ_AUTOMATION", None)
|
||||||
|
)
|
||||||
handler = getattr(args, "mach_handler")
|
handler = getattr(args, "mach_handler")
|
||||||
report_invocation_metrics(context.telemetry, handler.name)
|
report_invocation_metrics(context.telemetry, handler.name)
|
||||||
|
|
||||||
@ -643,6 +649,14 @@ To see more help for a specific command, run:
|
|||||||
"than relative time. Note that this is NOT execution time "
|
"than relative time. Note that this is NOT execution time "
|
||||||
"if there are parallel operations.",
|
"if there are parallel operations.",
|
||||||
)
|
)
|
||||||
|
global_group.add_argument(
|
||||||
|
"--no-interactive",
|
||||||
|
dest="is_interactive",
|
||||||
|
action="store_false",
|
||||||
|
help="Automatically selects the default option on any "
|
||||||
|
"interactive prompts. If the output is not a terminal, "
|
||||||
|
"then --no-interactive is assumed.",
|
||||||
|
)
|
||||||
suppress_log_by_default = False
|
suppress_log_by_default = False
|
||||||
if "INSIDE_EMACS" in os.environ:
|
if "INSIDE_EMACS" in os.environ:
|
||||||
suppress_log_by_default = True
|
suppress_log_by_default = True
|
||||||
|
@ -285,13 +285,20 @@ def clone(vcs, no_interactive):
|
|||||||
|
|
||||||
|
|
||||||
def bootstrap(srcdir, application_choice, no_interactive, no_system_changes):
|
def bootstrap(srcdir, application_choice, no_interactive, no_system_changes):
|
||||||
args = [sys.executable, os.path.join(srcdir, "mach"), "bootstrap"]
|
args = [sys.executable, os.path.join(srcdir, "mach")]
|
||||||
|
|
||||||
|
if no_interactive:
|
||||||
|
# --no-interactive is a global argument, not a command argument,
|
||||||
|
# so it needs to be specified before "bootstrap" is appended.
|
||||||
|
args += ["--no-interactive"]
|
||||||
|
|
||||||
|
args += ["bootstrap"]
|
||||||
|
|
||||||
if application_choice:
|
if application_choice:
|
||||||
args += ["--application-choice", application_choice]
|
args += ["--application-choice", application_choice]
|
||||||
if no_interactive:
|
|
||||||
args += ["--no-interactive"]
|
|
||||||
if no_system_changes:
|
if no_system_changes:
|
||||||
args += ["--no-system-changes"]
|
args += ["--no-system-changes"]
|
||||||
|
|
||||||
print("Running `%s`" % " ".join(args))
|
print("Running `%s`" % " ".join(args))
|
||||||
return subprocess.call(args, cwd=srcdir)
|
return subprocess.call(args, cwd=srcdir)
|
||||||
|
|
||||||
|
@ -466,11 +466,30 @@ class BaseBootstrapper(object):
|
|||||||
|
|
||||||
self.run_as_root(command)
|
self.run_as_root(command)
|
||||||
|
|
||||||
def prompt_int(self, prompt, low, high):
|
def prompt_int(self, prompt, low, high, default=None):
|
||||||
""" Prompts the user with prompt and requires an integer between low and high. """
|
"""Prompts the user with prompt and requires an integer between low and high.
|
||||||
|
|
||||||
|
If the user doesn't select an option and a default isn't provided, then
|
||||||
|
the lowest option is used. This is because some option must be implicitly
|
||||||
|
selected if mach is invoked with "--no-interactive"
|
||||||
|
"""
|
||||||
|
if default is not None:
|
||||||
|
assert isinstance(default, int)
|
||||||
|
assert low <= default <= high
|
||||||
|
else:
|
||||||
|
default = low
|
||||||
|
|
||||||
|
if self.no_interactive:
|
||||||
|
print(prompt)
|
||||||
|
print('Selecting "{}" because context is not interactive.'.format(default))
|
||||||
|
return default
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
choice = input(prompt)
|
||||||
|
if choice == "" and default is not None:
|
||||||
|
return default
|
||||||
try:
|
try:
|
||||||
choice = int(input(prompt))
|
choice = int(choice)
|
||||||
if low <= choice <= high:
|
if low <= choice <= high:
|
||||||
return choice
|
return choice
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -479,18 +498,20 @@ class BaseBootstrapper(object):
|
|||||||
|
|
||||||
def prompt_yesno(self, prompt):
|
def prompt_yesno(self, prompt):
|
||||||
""" Prompts the user with prompt and requires a yes/no answer."""
|
""" Prompts the user with prompt and requires a yes/no answer."""
|
||||||
valid = False
|
if self.no_interactive:
|
||||||
while not valid:
|
print(prompt)
|
||||||
|
print('Selecting "Y" because context is not interactive.')
|
||||||
|
return True
|
||||||
|
|
||||||
|
while True:
|
||||||
choice = input(prompt + " (Yn): ").strip().lower()[:1]
|
choice = input(prompt + " (Yn): ").strip().lower()[:1]
|
||||||
if choice == "":
|
if choice == "":
|
||||||
choice = "y"
|
return True
|
||||||
if choice not in ("y", "n"):
|
elif choice in ("y", "n"):
|
||||||
print("ERROR! Please enter y or n!")
|
|
||||||
else:
|
|
||||||
valid = True
|
|
||||||
|
|
||||||
return choice == "y"
|
return choice == "y"
|
||||||
|
|
||||||
|
print("ERROR! Please enter y or n!")
|
||||||
|
|
||||||
def _ensure_package_manager_updated(self):
|
def _ensure_package_manager_updated(self):
|
||||||
if self.package_manager_updated:
|
if self.package_manager_updated:
|
||||||
return
|
return
|
||||||
|
@ -365,11 +365,13 @@ class Bootstrapper(object):
|
|||||||
labels = [
|
labels = [
|
||||||
"%s. %s" % (i, name) for i, name in enumerate(APPLICATIONS.keys(), 1)
|
"%s. %s" % (i, name) for i, name in enumerate(APPLICATIONS.keys(), 1)
|
||||||
]
|
]
|
||||||
prompt = APPLICATION_CHOICE % "\n".join(
|
choices = [" {} [default]".format(labels[0])]
|
||||||
" {}".format(label) for label in labels
|
choices += [" {}".format(label) for label in labels[1:]]
|
||||||
)
|
prompt = APPLICATION_CHOICE % "\n".join(choices)
|
||||||
prompt_choice = self.instance.prompt_int(
|
prompt_choice = self.instance.prompt_int(
|
||||||
prompt=prompt, low=1, high=len(APPLICATIONS)
|
prompt=prompt,
|
||||||
|
low=1,
|
||||||
|
high=len(APPLICATIONS),
|
||||||
)
|
)
|
||||||
name, application = list(APPLICATIONS.items())[prompt_choice - 1]
|
name, application = list(APPLICATIONS.items())[prompt_choice - 1]
|
||||||
elif self.choice in APPLICATIONS.keys():
|
elif self.choice in APPLICATIONS.keys():
|
||||||
@ -428,7 +430,6 @@ class Bootstrapper(object):
|
|||||||
# Possibly configure Mercurial, but not if the current checkout or repo
|
# Possibly configure Mercurial, but not if the current checkout or repo
|
||||||
# type is Git.
|
# type is Git.
|
||||||
if hg_installed and checkout_type == "hg":
|
if hg_installed and checkout_type == "hg":
|
||||||
configure_hg = False
|
|
||||||
if not self.instance.no_interactive:
|
if not self.instance.no_interactive:
|
||||||
configure_hg = self.instance.prompt_yesno(prompt=CONFIGURE_MERCURIAL)
|
configure_hg = self.instance.prompt_yesno(prompt=CONFIGURE_MERCURIAL)
|
||||||
else:
|
else:
|
||||||
|
@ -20,7 +20,7 @@ Mercurial via the "pip" Python packaging utility. This will likely result
|
|||||||
in files being placed in /usr/local/bin and /usr/local/lib.
|
in files being placed in /usr/local/bin and /usr/local/lib.
|
||||||
|
|
||||||
How would you like to continue?
|
How would you like to continue?
|
||||||
1. Install a modern Mercurial via pip (recommended)
|
1. Install a modern Mercurial via pip [default]
|
||||||
2. Install a legacy Mercurial via apt
|
2. Install a legacy Mercurial via apt
|
||||||
3. Do not install Mercurial
|
3. Do not install Mercurial
|
||||||
Your choice: """
|
Your choice: """
|
||||||
|
@ -32,26 +32,18 @@ class Bootstrap(MachCommandBase):
|
|||||||
help="Pass in an application choice instead of using the default "
|
help="Pass in an application choice instead of using the default "
|
||||||
"interactive prompt.",
|
"interactive prompt.",
|
||||||
)
|
)
|
||||||
@CommandArgument(
|
|
||||||
"--no-interactive",
|
|
||||||
dest="no_interactive",
|
|
||||||
action="store_true",
|
|
||||||
help="Answer yes to any (Y/n) interactive prompts.",
|
|
||||||
)
|
|
||||||
@CommandArgument(
|
@CommandArgument(
|
||||||
"--no-system-changes",
|
"--no-system-changes",
|
||||||
dest="no_system_changes",
|
dest="no_system_changes",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Only execute actions that leave the system " "configuration alone.",
|
help="Only execute actions that leave the system " "configuration alone.",
|
||||||
)
|
)
|
||||||
def bootstrap(
|
def bootstrap(self, application_choice=None, no_system_changes=False):
|
||||||
self, application_choice=None, no_interactive=False, no_system_changes=False
|
|
||||||
):
|
|
||||||
from mozboot.bootstrap import Bootstrapper
|
from mozboot.bootstrap import Bootstrapper
|
||||||
|
|
||||||
bootstrapper = Bootstrapper(
|
bootstrapper = Bootstrapper(
|
||||||
choice=application_choice,
|
choice=application_choice,
|
||||||
no_interactive=no_interactive,
|
no_interactive=not self._mach_context.is_interactive,
|
||||||
no_system_changes=no_system_changes,
|
no_system_changes=no_system_changes,
|
||||||
mach_context=self._mach_context,
|
mach_context=self._mach_context,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user