1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
|
# 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 sys
from pathlib import PurePath
from gecko_taskgraph.target_tasks import filter_by_uncommon_try_tasks
from ..cli import BaseTryParser
from ..push import check_working_directory, generate_try_task_config, push_to_try
from ..tasks import filter_tasks_by_paths, filter_tasks_by_worker_type, generate_tasks
from ..util.fzf import (
FZF_NOT_FOUND,
PREVIEW_SCRIPT,
format_header,
fzf_bootstrap,
fzf_shortcuts,
run_fzf,
)
class FuzzyParser(BaseTryParser):
name = "fuzzy"
arguments = [
[
["-q", "--query"],
{
"metavar": "STR",
"action": "append",
"default": [],
"help": "Use the given query instead of entering the selection "
"interface. Equivalent to typing <query><ctrl-a><enter> "
"from the interface. Specifying multiple times schedules "
"the union of computed tasks.",
},
],
[
["-i", "--interactive"],
{
"action": "store_true",
"default": False,
"help": "Run fzf interactively, even if --preset or --query is used. "
"Tasks selected interactively will be unioned with tasks selected "
"by the --preset/--query flags. If -x/--and is also specified, tasks "
"selected interactively will instead be intersected with tasks "
"selected by --preset/--query.",
},
],
[
["-x", "--and"],
{
"dest": "intersection",
"action": "store_true",
"default": False,
"help": "When specifying queries on the command line with -q/--query, "
"use the intersection of tasks rather than the union. This is "
"especially useful for post filtering presets.",
},
],
[
["-e", "--exact"],
{
"action": "store_true",
"default": False,
"help": "Enable exact match mode. Terms will use an exact match "
"by default, and terms prefixed with ' will become fuzzy.",
},
],
[
["-u", "--update"],
{
"action": "store_true",
"default": False,
"help": "Update fzf before running.",
},
],
[
["--disable-target-task-filter", "--all-tasks"],
{
"action": "store_true",
"default": False,
"help": "Some tasks run on mozilla-central but are filtered out "
"of the default list due to resource constraints. This flag "
"disables this filtering.",
},
],
[
["--show-chunk-numbers"],
{
"action": "store_true",
"default": False,
"help": "Chunk numbers are hidden to simplify the selection. This flag "
"makes them appear again.",
},
],
]
common_groups = ["push", "task", "preset"]
task_configs = [
"artifact",
"browsertime",
"chemspill-prio",
"disable-pgo",
"env",
"existing-tasks",
"gecko-profile",
"new-test-config",
"path",
"target-tasks-method",
"test-tag",
"pernosco",
"rebuild",
"routes",
"worker-overrides",
]
def run(
update=False,
query=None,
intersect_query=None,
full=False,
parameters=None,
try_config_params=None,
save_query=False,
stage_changes=False,
dry_run=False,
message="{msg}",
test_paths=None,
test_tag=None,
exact=False,
closed_tree=False,
disable_target_task_filter=False,
push_to_vcs=False,
show_chunk_numbers=False,
new_test_config=False,
):
fzf = fzf_bootstrap(update)
if not fzf:
print(FZF_NOT_FOUND)
return 1
push = not stage_changes and not dry_run
check_working_directory(push)
target_tasks_method = None
if try_config_params and "target_tasks_method" in try_config_params:
target_tasks_method = try_config_params.pop("target_tasks_method")
tg = generate_tasks(
parameters,
full=full,
disable_target_task_filter=disable_target_task_filter,
target_tasks_method=target_tasks_method,
)
all_tasks = tg.tasks
if not full and not disable_target_task_filter:
all_tasks = {
task_name: task
for task_name, task in all_tasks.items()
if filter_by_uncommon_try_tasks(task_name)
}
if try_config_params.get("try_task_config", {}).get("worker-types", []):
all_tasks = filter_tasks_by_worker_type(all_tasks, try_config_params)
if not all_tasks:
return 1
if test_paths or test_tag:
all_tasks = filter_tasks_by_paths(all_tasks, test_paths, tag=test_tag)
if not all_tasks:
return 1
key_shortcuts = [k + ":" + v for k, v in fzf_shortcuts.items()]
base_cmd = [
fzf,
"-m",
"--bind",
",".join(key_shortcuts),
"--header",
format_header(),
"--preview-window=right:30%",
"--print-query",
"--preview",
f'{str(PurePath(sys.executable))} {PREVIEW_SCRIPT} -t "{{+f}}"',
]
if exact:
base_cmd.append("--exact")
selected = set()
queries = []
def get_tasks(query_arg=None, candidate_tasks=all_tasks):
cmd = base_cmd[:]
if query_arg and query_arg != "INTERACTIVE":
cmd.extend(["-f", query_arg])
if not show_chunk_numbers:
fzf_tasks = set(task.chunk_pattern for task in candidate_tasks.values())
else:
fzf_tasks = set(candidate_tasks.keys())
query_str, tasks = run_fzf(cmd, sorted(fzf_tasks))
queries.append(query_str)
return set(tasks)
for q in query or []:
selected |= get_tasks(q)
for q in intersect_query or []:
if not selected:
selected |= get_tasks(q)
else:
selected &= get_tasks(
q,
{
task_name: task
for task_name, task in all_tasks.items()
if task_name in selected or task.chunk_pattern in selected
},
)
if not queries:
selected = get_tasks()
if not selected:
print("no tasks selected")
return
if save_query:
return queries
# build commit message
msg = "Fuzzy"
args = [f"query={q}" for q in queries]
if test_paths:
args.append("paths={}".format(":".join(test_paths)))
if args:
msg = "{} {}".format(msg, "&".join(args))
return push_to_try(
"fuzzy",
message.format(msg=msg),
try_task_config=generate_try_task_config(
"fuzzy", selected, params=try_config_params
),
stage_changes=stage_changes,
dry_run=dry_run,
closed_tree=closed_tree,
push_to_vcs=push_to_vcs,
)
|