# 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 json import os import sys from functools import cache from typing import Optional
from mach.util import get_state_dir from mozbuild.base import MozbuildObject from mozversioncontrol import MissingVCSExtension, get_repository_object
from .lando import push_to_lando_try
GIT_CINNABAR_NOT_FOUND = """
Could not detect `git-cinnabar`.
The `mach try` command requires git-cinnabar to be installed when
pushing from git. Please install it by running:
$ ./mach vcs-setup """.lstrip()
HG_PUSH_TO_TRY_NOT_FOUND = """
Could not detect `push-to-try`.
The `mach try` command requires the push-to-try extension enabled
when pushing from hg. Please install it by running:
$ ./mach vcs-setup """.lstrip()
VCS_NOT_FOUND = """
error: could not detect version control (only `hg` or `git` are supported) """.strip()
NO_REMOTE_CONFIGURED = """
error: no version control remote configured """.strip()
UNCOMMITTED_CHANGES = """
error: commit changes before continuing """.strip()
LARGE_PUSH_THRESHOLD = 1000
LARGE_PUSH_WARNING = f"""
Your push would schedule at least {{}} tasks. To avoid backlogs that cause delays for
others, your tasks will be scheduled at the lowest priority and may not run before
their deadline. Consider selecting fewer than {LARGE_PUSH_THRESHOLD} tasks to save resources and
get results faster. """
def write_task_config_history(msg, try_task_config): ifnot os.path.isfile(history_path): ifnot os.path.isdir(os.path.dirname(history_path)):
os.makedirs(os.path.dirname(history_path))
history = [] else: with open(history_path) as fh:
history = fh.read().strip().splitlines()
history.insert(0, json.dumps([msg, try_task_config]))
history = history[:MAX_HISTORY] with open(history_path, "w") as fh:
fh.write("\n".join(history))
def generate_try_task_config(method, labels, params=None, routes=None):
params = params or {}
# The user has explicitly requested a set of jobs, so run them all # regardless of optimization (unless the selector explicitly sets this to # True). Their dependencies can be optimized though.
params.setdefault("optimize_target_tasks", False)
# Remove selected labels from 'existing_tasks' parameter if present if"existing_tasks"in params:
params["existing_tasks"] = {
label: tid for label, tid in params["existing_tasks"].items() if label notin labels
}
# In reality, the number of tasks will likely be much larger thanks to test # chunks being collapsed behind a wildcard. However because we use # `taskgraph.fast` when generating tasks, we don't process test manifests # and have no way of knowing how many chunks will be scheduled for a given # task. For the purposes of this check, we'll ignore test chunks as it's # causing us to underestimate anyway.
rebuild = try_config.get("rebuild", 1) if isinstance(rebuild, dict):
num_tasks = sum(rebuild.get(label, 1) for label in labels) else:
num_tasks = len(labels) * rebuild if"priority"notin try_config and num_tasks > LARGE_PUSH_THRESHOLD:
print(LARGE_PUSH_WARNING.format(num_tasks)) whileTrue:
answer = input("Would you like to proceed anyway? [Y/n]: ").lower() if answer in ("n", "no"):
sys.exit(1)
# improves on `" ".join(sys.argv[:])` by requoting argv items containing spaces or single quotes def get_sys_argv(injected_argv=None):
argv_to_use = injected_argv or sys.argv[:]
formatted_argv = [] for item in argv_to_use: if" "in item or"'"in item:
formatted_item = f'"{item}"' else:
formatted_item = item
formatted_argv.append(formatted_item)
if push andnot remote:
print(NO_REMOTE_CONFIGURED)
sys.exit(1)
# Use direct push if explicitly requested or we aren't pushing to hg.mozilla.org/try.
push_to_vcs |= MACH_TRY_PUSH_TO_VCS ornot _is_hg_try(remote)
check_working_directory(push)
# Format the commit message
closed_tree_string = " ON A CLOSED TREE"if closed_tree else""
the_cmdline = get_sys_argv()
full_commandline_entry = f"mach try command: `{the_cmdline}`"
commit_message = f"{msg}{closed_tree_string}\n\n{full_commandline_entry}\n\nPushed via `mach try {method}`"
changed_files = {}
if try_task_config:
changed_files["try_task_config.json"] = (
json.dumps(
try_task_config, indent=4, separators=(",", ": "), sort_keys=True
)
+ "\n"
) if push and method notin ("again", "auto", "empty"):
write_task_config_history(msg, try_task_config)
if (push or stage_changes) and files_to_change:
changed_files.update(files_to_change.items())
ifnot push:
print("Commit message:")
print(commit_message)
config = changed_files.pop("try_task_config.json", None) if config:
print("Calculated try_task_config.json:")
print(config) if stage_changes:
vcs.stage_changes(changed_files)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.