jolt 0.9.172__py3-none-any.whl → 0.9.435__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jolt/__init__.py +80 -7
- jolt/__main__.py +9 -1
- jolt/bin/fstree-darwin-x86_64 +0 -0
- jolt/bin/fstree-linux-x86_64 +0 -0
- jolt/cache.py +596 -252
- jolt/chroot.py +36 -11
- jolt/cli.py +143 -130
- jolt/common_pb2.py +45 -45
- jolt/config.py +76 -40
- jolt/error.py +19 -4
- jolt/filesystem.py +2 -6
- jolt/graph.py +400 -82
- jolt/influence.py +110 -3
- jolt/loader.py +338 -174
- jolt/log.py +127 -31
- jolt/manifest.py +13 -46
- jolt/options.py +35 -11
- jolt/pkgs/abseil.py +42 -0
- jolt/pkgs/asio.py +25 -0
- jolt/pkgs/autoconf.py +41 -0
- jolt/pkgs/automake.py +41 -0
- jolt/pkgs/b2.py +31 -0
- jolt/pkgs/boost.py +111 -0
- jolt/pkgs/boringssl.py +32 -0
- jolt/pkgs/busybox.py +39 -0
- jolt/pkgs/bzip2.py +43 -0
- jolt/pkgs/cares.py +29 -0
- jolt/pkgs/catch2.py +36 -0
- jolt/pkgs/cbindgen.py +17 -0
- jolt/pkgs/cista.py +19 -0
- jolt/pkgs/clang.py +44 -0
- jolt/pkgs/cli11.py +24 -0
- jolt/pkgs/cmake.py +48 -0
- jolt/pkgs/cpython.py +196 -0
- jolt/pkgs/crun.py +29 -0
- jolt/pkgs/curl.py +38 -0
- jolt/pkgs/dbus.py +18 -0
- jolt/pkgs/double_conversion.py +24 -0
- jolt/pkgs/fastfloat.py +21 -0
- jolt/pkgs/ffmpeg.py +28 -0
- jolt/pkgs/flatbuffers.py +29 -0
- jolt/pkgs/fmt.py +27 -0
- jolt/pkgs/fstree.py +20 -0
- jolt/pkgs/gflags.py +18 -0
- jolt/pkgs/glib.py +18 -0
- jolt/pkgs/glog.py +25 -0
- jolt/pkgs/glslang.py +21 -0
- jolt/pkgs/golang.py +16 -11
- jolt/pkgs/googlebenchmark.py +18 -0
- jolt/pkgs/googletest.py +46 -0
- jolt/pkgs/gperf.py +15 -0
- jolt/pkgs/grpc.py +73 -0
- jolt/pkgs/hdf5.py +19 -0
- jolt/pkgs/help2man.py +14 -0
- jolt/pkgs/inja.py +28 -0
- jolt/pkgs/jsoncpp.py +31 -0
- jolt/pkgs/libarchive.py +43 -0
- jolt/pkgs/libcap.py +44 -0
- jolt/pkgs/libdrm.py +44 -0
- jolt/pkgs/libedit.py +42 -0
- jolt/pkgs/libevent.py +31 -0
- jolt/pkgs/libexpat.py +27 -0
- jolt/pkgs/libfastjson.py +21 -0
- jolt/pkgs/libffi.py +16 -0
- jolt/pkgs/libglvnd.py +30 -0
- jolt/pkgs/libogg.py +28 -0
- jolt/pkgs/libpciaccess.py +18 -0
- jolt/pkgs/libseccomp.py +21 -0
- jolt/pkgs/libtirpc.py +24 -0
- jolt/pkgs/libtool.py +42 -0
- jolt/pkgs/libunwind.py +35 -0
- jolt/pkgs/libva.py +18 -0
- jolt/pkgs/libvorbis.py +33 -0
- jolt/pkgs/libxml2.py +35 -0
- jolt/pkgs/libxslt.py +17 -0
- jolt/pkgs/libyajl.py +16 -0
- jolt/pkgs/llvm.py +81 -0
- jolt/pkgs/lua.py +54 -0
- jolt/pkgs/lz4.py +26 -0
- jolt/pkgs/m4.py +14 -0
- jolt/pkgs/make.py +17 -0
- jolt/pkgs/mesa.py +81 -0
- jolt/pkgs/meson.py +17 -0
- jolt/pkgs/mstch.py +28 -0
- jolt/pkgs/mysql.py +60 -0
- jolt/pkgs/nasm.py +49 -0
- jolt/pkgs/ncurses.py +30 -0
- jolt/pkgs/ng_log.py +25 -0
- jolt/pkgs/ninja.py +45 -0
- jolt/pkgs/nlohmann_json.py +25 -0
- jolt/pkgs/nodejs.py +19 -11
- jolt/pkgs/opencv.py +24 -0
- jolt/pkgs/openjdk.py +26 -0
- jolt/pkgs/openssl.py +103 -0
- jolt/pkgs/paho.py +76 -0
- jolt/pkgs/patchelf.py +16 -0
- jolt/pkgs/perl.py +42 -0
- jolt/pkgs/pkgconfig.py +64 -0
- jolt/pkgs/poco.py +39 -0
- jolt/pkgs/protobuf.py +77 -0
- jolt/pkgs/pugixml.py +27 -0
- jolt/pkgs/python.py +19 -0
- jolt/pkgs/qt.py +35 -0
- jolt/pkgs/rapidjson.py +26 -0
- jolt/pkgs/rapidyaml.py +28 -0
- jolt/pkgs/re2.py +30 -0
- jolt/pkgs/re2c.py +17 -0
- jolt/pkgs/readline.py +15 -0
- jolt/pkgs/rust.py +41 -0
- jolt/pkgs/sdl.py +28 -0
- jolt/pkgs/simdjson.py +27 -0
- jolt/pkgs/soci.py +46 -0
- jolt/pkgs/spdlog.py +29 -0
- jolt/pkgs/spirv_llvm.py +21 -0
- jolt/pkgs/spirv_tools.py +24 -0
- jolt/pkgs/sqlite.py +83 -0
- jolt/pkgs/ssl.py +12 -0
- jolt/pkgs/texinfo.py +15 -0
- jolt/pkgs/tomlplusplus.py +22 -0
- jolt/pkgs/wayland.py +26 -0
- jolt/pkgs/x11.py +58 -0
- jolt/pkgs/xerces_c.py +20 -0
- jolt/pkgs/xorg.py +360 -0
- jolt/pkgs/xz.py +29 -0
- jolt/pkgs/yamlcpp.py +30 -0
- jolt/pkgs/zeromq.py +47 -0
- jolt/pkgs/zlib.py +87 -0
- jolt/pkgs/zstd.py +33 -0
- jolt/plugins/alias.py +3 -0
- jolt/plugins/allure.py +2 -2
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cache.py +1 -1
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/conan.py +238 -0
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/docker.py +76 -19
- jolt/plugins/email.xslt +141 -118
- jolt/plugins/environ.py +11 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/gdb.py +33 -14
- jolt/plugins/gerrit.py +0 -13
- jolt/plugins/git.py +248 -66
- jolt/plugins/googletest.py +1 -1
- jolt/plugins/http.py +1 -1
- jolt/plugins/libtool.py +63 -0
- jolt/plugins/linux.py +990 -0
- jolt/plugins/logstash.py +4 -4
- jolt/plugins/meson.py +61 -0
- jolt/plugins/ninja-compdb.py +96 -28
- jolt/plugins/ninja.py +424 -150
- jolt/plugins/paths.py +11 -1
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/podman.py +131 -87
- jolt/plugins/python.py +137 -0
- jolt/plugins/remote_execution/administration_pb2.py +27 -19
- jolt/plugins/remote_execution/log_pb2.py +12 -12
- jolt/plugins/remote_execution/scheduler_pb2.py +23 -23
- jolt/plugins/remote_execution/worker_pb2.py +19 -19
- jolt/plugins/report.py +7 -2
- jolt/plugins/rust.py +25 -0
- jolt/plugins/scheduler.py +135 -86
- jolt/plugins/selfdeploy/setup.py +6 -6
- jolt/plugins/selfdeploy.py +49 -31
- jolt/plugins/strings.py +35 -22
- jolt/plugins/symlinks.py +11 -4
- jolt/plugins/telemetry.py +1 -2
- jolt/plugins/timeline.py +13 -3
- jolt/scheduler.py +467 -165
- jolt/tasks.py +427 -111
- jolt/templates/timeline.html.template +44 -47
- jolt/timer.py +22 -0
- jolt/tools.py +527 -188
- jolt/utils.py +183 -3
- jolt/version.py +1 -1
- jolt/xmldom.py +12 -2
- {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/METADATA +97 -41
- jolt-0.9.435.dist-info/RECORD +207 -0
- {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/WHEEL +1 -1
- jolt/plugins/amqp.py +0 -855
- jolt/plugins/debian.py +0 -338
- jolt/plugins/repo.py +0 -253
- jolt/plugins/snap.py +0 -122
- jolt-0.9.172.dist-info/RECORD +0 -92
- {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/top_level.txt +0 -0
jolt/cli.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from os import _exit, environ, getcwd
|
|
2
1
|
import atexit
|
|
3
2
|
import click
|
|
4
3
|
import datetime
|
|
4
|
+
import os
|
|
5
5
|
import platform
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
@@ -18,13 +18,12 @@ from jolt import log
|
|
|
18
18
|
from jolt import __version__
|
|
19
19
|
from jolt.log import logfile
|
|
20
20
|
from jolt import config
|
|
21
|
-
from jolt.loader import JoltLoader
|
|
21
|
+
from jolt.loader import JoltLoader, import_workspace
|
|
22
22
|
from jolt import tools
|
|
23
23
|
from jolt import utils
|
|
24
24
|
from jolt.influence import HashInfluenceRegistry
|
|
25
25
|
from jolt.options import JoltOptions
|
|
26
26
|
from jolt import hooks
|
|
27
|
-
from jolt.manifest import JoltManifest
|
|
28
27
|
from jolt.error import JoltError
|
|
29
28
|
from jolt.error import raise_error
|
|
30
29
|
from jolt.error import raise_error_if
|
|
@@ -32,7 +31,7 @@ from jolt.error import raise_task_error_if
|
|
|
32
31
|
from jolt.plugins import report
|
|
33
32
|
|
|
34
33
|
debug_enabled = False
|
|
35
|
-
workdir = getcwd()
|
|
34
|
+
workdir = os.getcwd()
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
class ArgRequiredUnless(click.Argument):
|
|
@@ -56,10 +55,12 @@ class PluginGroup(click.Group):
|
|
|
56
55
|
|
|
57
56
|
if cmd_name in ["export", "inspect"]:
|
|
58
57
|
log.set_level(log.SILENCE)
|
|
59
|
-
elif ctx.params.get("verbose"
|
|
60
|
-
log.set_level(log.
|
|
61
|
-
elif ctx.params.get("
|
|
58
|
+
elif ctx.params.get("verbose") >= 3:
|
|
59
|
+
log.set_level(log.EXCEPTION)
|
|
60
|
+
elif ctx.params.get("verbose") >= 2:
|
|
62
61
|
log.set_level(log.DEBUG)
|
|
62
|
+
elif ctx.params.get("verbose") >= 1:
|
|
63
|
+
log.set_level(log.VERBOSE)
|
|
63
64
|
|
|
64
65
|
config_files = ctx.params.get("config_file") or []
|
|
65
66
|
for config_file in config_files:
|
|
@@ -74,10 +75,12 @@ class PluginGroup(click.Group):
|
|
|
74
75
|
|
|
75
76
|
@click.group(cls=PluginGroup, invoke_without_command=True)
|
|
76
77
|
@click.version_option(__version__)
|
|
77
|
-
@click.option("-v", "--verbose",
|
|
78
|
-
@click.option("-vv", "--extra-verbose", is_flag=True, help="Extra verbose output.")
|
|
78
|
+
@click.option("-v", "--verbose", count=True, help="Verbose output (repeat to raise verbosity).")
|
|
79
79
|
@click.option("-c", "--config", "config_file", multiple=True, type=str,
|
|
80
80
|
help="Load a configuration file or set a configuration key.")
|
|
81
|
+
@click.option("-C", "--chdir", type=str,
|
|
82
|
+
help="Change working directory before executing command.")
|
|
83
|
+
@click.option("--interpreter", "machine_interface", type=str, help="Used for debugging.", hidden=True)
|
|
81
84
|
@click.option("-d", "--debugger", is_flag=True,
|
|
82
85
|
help="Attach debugger on exception.")
|
|
83
86
|
@click.option("-p", "--profile", is_flag=True, hidden=True,
|
|
@@ -88,6 +91,7 @@ class PluginGroup(click.Group):
|
|
|
88
91
|
help="Add salt as task influence.")
|
|
89
92
|
@click.option("-g", "--debug", is_flag=True, default=False, hidden=True,
|
|
90
93
|
help="Start debug shell before executing task.")
|
|
94
|
+
@click.option("-m", "--mute", is_flag=True, help="Display task log only if it fails.")
|
|
91
95
|
@click.option("-n", "--network", is_flag=True, default=False, hidden=True,
|
|
92
96
|
help="Build on network.")
|
|
93
97
|
@click.option("-l", "--local", is_flag=True, default=False, hidden=True,
|
|
@@ -98,8 +102,8 @@ class PluginGroup(click.Group):
|
|
|
98
102
|
help="Number of tasks allowed to execute in parallel (1). ")
|
|
99
103
|
@click.option("-h", "--help", is_flag=True, help="Show this message and exit.")
|
|
100
104
|
@click.pass_context
|
|
101
|
-
def cli(ctx, verbose,
|
|
102
|
-
force, salt, debug, network, local, keep_going, jobs, help):
|
|
105
|
+
def cli(ctx, verbose, config_file, debugger, profile,
|
|
106
|
+
force, salt, debug, mute, network, local, keep_going, jobs, help, machine_interface, chdir):
|
|
103
107
|
"""
|
|
104
108
|
A task execution tool.
|
|
105
109
|
|
|
@@ -123,14 +127,24 @@ def cli(ctx, verbose, extra_verbose, config_file, debugger, profile,
|
|
|
123
127
|
global debug_enabled
|
|
124
128
|
debug_enabled = debugger
|
|
125
129
|
|
|
130
|
+
if machine_interface:
|
|
131
|
+
log.enable_gdb()
|
|
132
|
+
|
|
126
133
|
if ctx.invoked_subcommand not in ["log", "report"]:
|
|
127
134
|
log.start_file_log()
|
|
128
135
|
|
|
136
|
+
if chdir:
|
|
137
|
+
global workdir
|
|
138
|
+
workdir = chdir
|
|
139
|
+
os.chdir(workdir)
|
|
140
|
+
|
|
141
|
+
log.verbose("Jolt version: {}", __version__)
|
|
129
142
|
log.verbose("Jolt command: {}", " ".join([fs.path.basename(sys.argv[0])] + sys.argv[1:]))
|
|
130
|
-
log.verbose("Jolt host: {}", environ.get("HOSTNAME", "localhost"))
|
|
143
|
+
log.verbose("Jolt host: {}", os.environ.get("HOSTNAME", "localhost"))
|
|
131
144
|
log.verbose("Jolt install path: {}", fs.path.dirname(__file__))
|
|
145
|
+
log.verbose("Jolt workdir: {}", workdir)
|
|
132
146
|
|
|
133
|
-
if ctx.invoked_subcommand in ["config", "log"]:
|
|
147
|
+
if ctx.invoked_subcommand in ["config", "executor", "log"]:
|
|
134
148
|
# Don't attempt to load any task recipes as they might require
|
|
135
149
|
# plugins that are not yet configured.
|
|
136
150
|
return
|
|
@@ -142,27 +156,13 @@ def cli(ctx, verbose, extra_verbose, config_file, debugger, profile,
|
|
|
142
156
|
print(ctx.get_help())
|
|
143
157
|
sys.exit(0)
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
utils.call_and_catch(manifest.parse)
|
|
147
|
-
manifest.process_import()
|
|
148
|
-
ctx.obj["manifest"] = manifest
|
|
149
|
-
|
|
150
|
-
if manifest.version:
|
|
151
|
-
from jolt.version_utils import requirement, version
|
|
152
|
-
req = requirement(manifest.version)
|
|
153
|
-
ver = version(__version__)
|
|
154
|
-
raise_error_if(not req.satisfied(ver),
|
|
155
|
-
"This project requires Jolt version {} (running {})",
|
|
156
|
-
req, __version__)
|
|
157
|
-
|
|
159
|
+
registry = TaskRegistry.get()
|
|
158
160
|
loader = JoltLoader.get()
|
|
159
|
-
|
|
160
|
-
for cls in tasks:
|
|
161
|
-
TaskRegistry.get().add_task_class(cls)
|
|
161
|
+
loader.load(registry)
|
|
162
162
|
|
|
163
163
|
if ctx.invoked_subcommand in ["build", "clean"] and loader.joltdir:
|
|
164
164
|
ctx.obj["workspace_lock"] = utils.LockFile(
|
|
165
|
-
|
|
165
|
+
loader.build_path,
|
|
166
166
|
log.info, "Workspace is locked by another process, please wait...")
|
|
167
167
|
atexit.register(ctx.obj["workspace_lock"].close)
|
|
168
168
|
|
|
@@ -171,8 +171,8 @@ def cli(ctx, verbose, extra_verbose, config_file, debugger, profile,
|
|
|
171
171
|
if ctx.invoked_subcommand is None:
|
|
172
172
|
task = config.get("jolt", "default", "default")
|
|
173
173
|
taskname, _ = utils.parse_task_name(task)
|
|
174
|
-
if
|
|
175
|
-
ctx.invoke(build, task=[task], force=force, salt=salt, debug=debug,
|
|
174
|
+
if registry.get_task_class(taskname) is not None:
|
|
175
|
+
ctx.invoke(build, task=[task], force=force, salt=salt, debug=debug, mute=mute,
|
|
176
176
|
network=network, local=local, keep_going=keep_going, jobs=jobs)
|
|
177
177
|
else:
|
|
178
178
|
print(cli.get_help(ctx))
|
|
@@ -180,11 +180,8 @@ def cli(ctx, verbose, extra_verbose, config_file, debugger, profile,
|
|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
def _autocomplete_tasks(ctx, args, incomplete):
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
manifest.process_import()
|
|
186
|
-
|
|
187
|
-
tasks = JoltLoader.get().load()
|
|
183
|
+
loader = JoltLoader.get()
|
|
184
|
+
tasks = loader.load()
|
|
188
185
|
tasks = [task.name for task in tasks if task.name.startswith(incomplete or '')]
|
|
189
186
|
return sorted(tasks)
|
|
190
187
|
|
|
@@ -203,12 +200,13 @@ def _autocomplete_tasks(ctx, args, incomplete):
|
|
|
203
200
|
@click.option("-n", "--network", is_flag=True, default=False, help="Distribute tasks to network workers.")
|
|
204
201
|
@click.option("-s", "--salt", type=str, help="Add salt as hash influence for all tasks in dependency tree.", metavar="SALT")
|
|
205
202
|
@click.option("-m", "--mute", is_flag=True, help="Display task log only if it fails.")
|
|
206
|
-
@click.option("-v", "--verbose",
|
|
207
|
-
@click.option("-vv", "--extra-verbose", is_flag=True, help="Extra verbose output.")
|
|
203
|
+
@click.option("-v", "--verbose", count=True, help="Verbose output (repeat to raise verbosity).")
|
|
208
204
|
@click.option("--result", type=click.Path(), hidden=True,
|
|
209
205
|
help="Write result manifest to this file.")
|
|
210
206
|
@click.option("--no-download", is_flag=True, default=False,
|
|
211
|
-
help="Don't download artifacts from remote storage")
|
|
207
|
+
help="Don't download any artifacts from remote storage")
|
|
208
|
+
@click.option("--no-download-persistent", is_flag=True, default=False,
|
|
209
|
+
help="Don't download persistent artifacts from remote storage (only session artifacts)")
|
|
212
210
|
@click.option("--no-upload", is_flag=True, default=False,
|
|
213
211
|
help="Don't upload artifacts to remote storage")
|
|
214
212
|
@click.option("--download", is_flag=True, default=False,
|
|
@@ -219,12 +217,13 @@ def _autocomplete_tasks(ctx, args, incomplete):
|
|
|
219
217
|
help="Don't prune cached artifacts from the build graph. This option can be used to populate the local cache with remotely cached dependency artifacts.")
|
|
220
218
|
@click.option("--worker", is_flag=True, default=False,
|
|
221
219
|
help="Run with the worker build strategy", hidden=True)
|
|
220
|
+
@click.option("--environ", type=click.Path(), help="Import build environment from protobuf", hidden=True)
|
|
222
221
|
@click.pass_context
|
|
223
222
|
@hooks.cli_build
|
|
224
223
|
def build(ctx, task, network, keep_going, default, local,
|
|
225
|
-
no_download, no_upload, download, upload, worker, force,
|
|
226
|
-
salt, copy, debug, result, jobs, no_prune, verbose,
|
|
227
|
-
mute):
|
|
224
|
+
no_download, no_download_persistent, no_upload, download, upload, worker, force,
|
|
225
|
+
salt, copy, debug, result, jobs, no_prune, verbose,
|
|
226
|
+
mute, environ):
|
|
228
227
|
"""
|
|
229
228
|
Build task artifact.
|
|
230
229
|
|
|
@@ -256,6 +255,7 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
256
255
|
are removed before execution starts.
|
|
257
256
|
|
|
258
257
|
"""
|
|
258
|
+
|
|
259
259
|
raise_error_if(network and local,
|
|
260
260
|
"The -n and -l flags are mutually exclusive")
|
|
261
261
|
|
|
@@ -268,10 +268,12 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
268
268
|
raise_error_if(no_upload and upload,
|
|
269
269
|
"The --upload and --no-upload flags are mutually exclusive")
|
|
270
270
|
|
|
271
|
-
if verbose:
|
|
272
|
-
log.set_level(log.
|
|
273
|
-
elif
|
|
271
|
+
if verbose >= 3:
|
|
272
|
+
log.set_level(log.EXCEPTION)
|
|
273
|
+
elif verbose >= 2:
|
|
274
274
|
log.set_level(log.DEBUG)
|
|
275
|
+
elif verbose >= 1:
|
|
276
|
+
log.set_level(log.VERBOSE)
|
|
275
277
|
|
|
276
278
|
ts_start = utils.duration()
|
|
277
279
|
task = list(task)
|
|
@@ -283,6 +285,7 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
283
285
|
else:
|
|
284
286
|
_download = config.getboolean("jolt", "download", True)
|
|
285
287
|
_upload = config.getboolean("jolt", "upload", True)
|
|
288
|
+
_download_session = _download
|
|
286
289
|
|
|
287
290
|
if local:
|
|
288
291
|
_download = False
|
|
@@ -290,17 +293,52 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
290
293
|
else:
|
|
291
294
|
if no_download:
|
|
292
295
|
_download = False
|
|
296
|
+
_download_session = False
|
|
297
|
+
if no_download_persistent:
|
|
298
|
+
_download = False
|
|
293
299
|
if no_upload:
|
|
294
300
|
_upload = False
|
|
295
301
|
if download:
|
|
296
302
|
_download = True
|
|
303
|
+
_download_session = True
|
|
297
304
|
if upload:
|
|
298
305
|
_upload = True
|
|
299
306
|
|
|
307
|
+
if keep_going:
|
|
308
|
+
config.set_keep_going(True)
|
|
309
|
+
|
|
310
|
+
# Import build environment from protobuf if provided
|
|
311
|
+
buildenv = None
|
|
312
|
+
if environ:
|
|
313
|
+
with open(environ, "rb") as f:
|
|
314
|
+
from jolt import common_pb2 as common_pb
|
|
315
|
+
buildenv = common_pb.BuildEnvironment()
|
|
316
|
+
try:
|
|
317
|
+
buildenv.ParseFromString(f.read())
|
|
318
|
+
except Exception as e:
|
|
319
|
+
raise_error("Failed to parse build environment protobuf: {}", e)
|
|
320
|
+
|
|
321
|
+
# Import log level
|
|
322
|
+
log.set_level_pb(buildenv.loglevel)
|
|
323
|
+
|
|
324
|
+
# Import workspace
|
|
325
|
+
import_workspace(buildenv)
|
|
326
|
+
|
|
327
|
+
# Import configuration snippet
|
|
328
|
+
config.import_config(buildenv.config)
|
|
329
|
+
|
|
330
|
+
# Import configuration parameters (-c params.key)
|
|
331
|
+
config.import_params({param.key: param.value for param in buildenv.parameters})
|
|
332
|
+
|
|
333
|
+
# Import default parameters (-d taskname:param=value)
|
|
334
|
+
default = utils.as_list(default)
|
|
335
|
+
default += buildenv.task_default_parameters
|
|
336
|
+
|
|
300
337
|
options = JoltOptions(
|
|
301
338
|
network=network,
|
|
302
339
|
local=local,
|
|
303
340
|
download=_download,
|
|
341
|
+
download_session=_download_session,
|
|
304
342
|
upload=_upload,
|
|
305
343
|
keep_going=keep_going,
|
|
306
344
|
default=default,
|
|
@@ -330,26 +368,20 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
330
368
|
for params in default:
|
|
331
369
|
registry.set_default_parameters(params)
|
|
332
370
|
|
|
333
|
-
manifest = ctx.obj["manifest"]
|
|
334
|
-
|
|
335
|
-
for mb in manifest.builds:
|
|
336
|
-
for mt in mb.tasks:
|
|
337
|
-
task.append(mt.name)
|
|
338
|
-
for mt in mb.defaults:
|
|
339
|
-
registry.set_default_parameters(mt.name)
|
|
340
|
-
|
|
341
|
-
if force:
|
|
342
|
-
for goal in task:
|
|
343
|
-
registry.get_task(goal, manifest=manifest).taint = uuid.uuid4()
|
|
344
|
-
|
|
345
371
|
log.info("Started: {}", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
|
346
372
|
|
|
347
|
-
gb = graph.GraphBuilder(registry, acache,
|
|
373
|
+
gb = graph.GraphBuilder(registry, acache, options, progress=True, buildenv=buildenv)
|
|
348
374
|
dag = gb.build(task)
|
|
349
375
|
|
|
376
|
+
# If asked to force rebuild, taint all goal tasks
|
|
377
|
+
if force:
|
|
378
|
+
for goal in dag.goals:
|
|
379
|
+
goal.get_extended_task().taint()
|
|
380
|
+
|
|
350
381
|
# Collect information about artifact presence before starting prune or build
|
|
351
|
-
acache.precheck(dag.persistent_artifacts)
|
|
382
|
+
acache.precheck(dag.persistent_artifacts, remote=not local)
|
|
352
383
|
|
|
384
|
+
# Prune the graph to remove tasks that are already available locally or remotely
|
|
353
385
|
if not no_prune:
|
|
354
386
|
gp = graph.GraphPruner(acache, strategy)
|
|
355
387
|
dag = gp.prune(dag)
|
|
@@ -358,7 +390,7 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
358
390
|
goal_task_duration = 0
|
|
359
391
|
|
|
360
392
|
session = executors.create_session(dag) if options.network else {}
|
|
361
|
-
queue = scheduler.TaskQueue(
|
|
393
|
+
queue = scheduler.TaskQueue()
|
|
362
394
|
|
|
363
395
|
try:
|
|
364
396
|
if not dag.has_tasks():
|
|
@@ -372,16 +404,20 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
372
404
|
debug=debug)
|
|
373
405
|
|
|
374
406
|
with progress:
|
|
407
|
+
in_progress = set()
|
|
408
|
+
|
|
375
409
|
while dag.has_tasks() or not queue.empty():
|
|
376
410
|
# Find all tasks ready to be executed
|
|
377
|
-
leafs = dag.select(lambda graph, task: task.is_ready())
|
|
411
|
+
leafs = dag.select(lambda graph, task: task.is_ready() and task not in in_progress)
|
|
378
412
|
|
|
379
413
|
# Order the tasks by their weights to improve build times
|
|
380
414
|
leafs.sort(key=lambda x: x.weight)
|
|
381
415
|
|
|
382
416
|
while leafs:
|
|
383
417
|
task = leafs.pop()
|
|
384
|
-
|
|
418
|
+
executor = strategy.create_executor(session, task)
|
|
419
|
+
queue.submit(executor)
|
|
420
|
+
in_progress.add(task)
|
|
385
421
|
|
|
386
422
|
task, error = queue.wait()
|
|
387
423
|
|
|
@@ -391,6 +427,7 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
391
427
|
elif task.is_goal() and task.duration_running:
|
|
392
428
|
goal_task_duration += task.duration_running.seconds
|
|
393
429
|
|
|
430
|
+
# Unpack tasks with overridden unpack() method
|
|
394
431
|
if not task.is_resource():
|
|
395
432
|
if no_prune and task.task.unpack.__func__ is not Task.unpack:
|
|
396
433
|
with acache.get_context(task):
|
|
@@ -398,8 +435,13 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
398
435
|
|
|
399
436
|
progress.update(1)
|
|
400
437
|
|
|
438
|
+
if no_prune and task.is_workspace_resource():
|
|
439
|
+
task.task.acquire_ws(force=True)
|
|
440
|
+
|
|
401
441
|
if not keep_going and error is not None:
|
|
402
442
|
queue.abort()
|
|
443
|
+
executors.shutdown()
|
|
444
|
+
task.raise_for_status()
|
|
403
445
|
raise error
|
|
404
446
|
|
|
405
447
|
if dag.failed or dag.unstable:
|
|
@@ -407,6 +449,8 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
407
449
|
for failed in dag.failed + dag.unstable:
|
|
408
450
|
log.error("- {}", failed.log_name.strip("()"))
|
|
409
451
|
|
|
452
|
+
for failed_task in dag.failed:
|
|
453
|
+
failed_task.raise_for_status()
|
|
410
454
|
if dag.failed:
|
|
411
455
|
raise_error("No more tasks could be executed")
|
|
412
456
|
|
|
@@ -415,12 +459,15 @@ def build(ctx, task, network, keep_going, default, local,
|
|
|
415
459
|
log.warning("Interrupted by user")
|
|
416
460
|
try:
|
|
417
461
|
queue.abort()
|
|
462
|
+
executors.shutdown()
|
|
418
463
|
sys.exit(1)
|
|
419
464
|
except KeyboardInterrupt:
|
|
420
465
|
print()
|
|
421
466
|
log.warning("Interrupted again, exiting")
|
|
422
|
-
_exit(1)
|
|
467
|
+
os._exit(1)
|
|
423
468
|
finally:
|
|
469
|
+
queue.shutdown()
|
|
470
|
+
|
|
424
471
|
for task in goal_tasks:
|
|
425
472
|
for artifact in task.artifacts:
|
|
426
473
|
if acache.is_available_locally(artifact):
|
|
@@ -467,7 +514,7 @@ def clean(ctx, task, deps, expired):
|
|
|
467
514
|
if task:
|
|
468
515
|
task = [utils.stable_task_name(t) for t in task]
|
|
469
516
|
registry = TaskRegistry.get()
|
|
470
|
-
dag = graph.GraphBuilder(registry, acache
|
|
517
|
+
dag = graph.GraphBuilder(registry, acache).build(task)
|
|
471
518
|
if deps:
|
|
472
519
|
tasks = dag.tasks
|
|
473
520
|
else:
|
|
@@ -614,7 +661,7 @@ def display(ctx, task, reverse=None, show_cache=False, prune=False):
|
|
|
614
661
|
registry = TaskRegistry.get()
|
|
615
662
|
options = JoltOptions()
|
|
616
663
|
acache = cache.ArtifactCache.get(options)
|
|
617
|
-
gb = graph.GraphBuilder(registry, acache
|
|
664
|
+
gb = graph.GraphBuilder(registry, acache)
|
|
618
665
|
dag = gb.build(task, influence=show_cache)
|
|
619
666
|
|
|
620
667
|
if reverse:
|
|
@@ -679,7 +726,14 @@ def docs():
|
|
|
679
726
|
"""
|
|
680
727
|
Opens the Jolt documentation in the default webbrowser.
|
|
681
728
|
"""
|
|
682
|
-
|
|
729
|
+
url = config.get("jolt", "docs", "http://jolt.readthedocs.io/")
|
|
730
|
+
success = False
|
|
731
|
+
try:
|
|
732
|
+
success = webbrowser.open(url)
|
|
733
|
+
except Exception:
|
|
734
|
+
pass
|
|
735
|
+
if not success:
|
|
736
|
+
print(f"Failed to open web browser. Visit {url} manually.")
|
|
683
737
|
|
|
684
738
|
|
|
685
739
|
@cli.command()
|
|
@@ -704,15 +758,14 @@ def download(ctx, task, deps, copy, copy_all):
|
|
|
704
758
|
if copy_all:
|
|
705
759
|
deps = True
|
|
706
760
|
|
|
707
|
-
manifest = ctx.obj["manifest"]
|
|
708
761
|
options = JoltOptions()
|
|
709
762
|
acache = cache.ArtifactCache.get(options)
|
|
710
763
|
hooks.TaskHookRegistry.get(options)
|
|
711
764
|
executors = scheduler.ExecutorRegistry.get(options)
|
|
712
765
|
registry = TaskRegistry.get()
|
|
713
766
|
strategy = scheduler.DownloadStrategy(executors, acache)
|
|
714
|
-
queue = scheduler.TaskQueue(
|
|
715
|
-
gb = graph.GraphBuilder(registry, acache,
|
|
767
|
+
queue = scheduler.TaskQueue()
|
|
768
|
+
gb = graph.GraphBuilder(registry, acache, options, progress=True)
|
|
716
769
|
dag = gb.build(task)
|
|
717
770
|
|
|
718
771
|
if not deps:
|
|
@@ -725,12 +778,16 @@ def download(ctx, task, deps, copy, copy_all):
|
|
|
725
778
|
|
|
726
779
|
try:
|
|
727
780
|
with log.progress("Progress", dag.number_of_tasks(), " tasks", estimates=False, debug=False) as p:
|
|
781
|
+
in_progress = set()
|
|
782
|
+
|
|
728
783
|
while dag.has_tasks() or not queue.empty():
|
|
729
|
-
leafs = dag.select(lambda graph, task: task.is_ready())
|
|
784
|
+
leafs = dag.select(lambda graph, task: task.is_ready() and task not in in_progress)
|
|
730
785
|
|
|
731
786
|
while leafs:
|
|
732
787
|
task = leafs.pop()
|
|
733
|
-
|
|
788
|
+
executor = strategy.create_executor({}, task)
|
|
789
|
+
queue.submit(executor)
|
|
790
|
+
in_progress.add(task)
|
|
734
791
|
|
|
735
792
|
task, error = queue.wait()
|
|
736
793
|
p.update(1)
|
|
@@ -753,62 +810,19 @@ def download(ctx, task, deps, copy, copy_all):
|
|
|
753
810
|
log.warning("Interrupted by user")
|
|
754
811
|
try:
|
|
755
812
|
queue.abort()
|
|
813
|
+
executors.shutdown()
|
|
756
814
|
sys.exit(1)
|
|
757
815
|
except KeyboardInterrupt:
|
|
758
816
|
print()
|
|
759
817
|
log.warning("Interrupted again, exiting")
|
|
760
|
-
_exit(1)
|
|
818
|
+
os._exit(1)
|
|
819
|
+
|
|
761
820
|
except Exception as e:
|
|
762
821
|
log.set_interactive(True)
|
|
763
822
|
raise e
|
|
764
823
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
@click.argument("task", type=str, nargs=-1, required=True)
|
|
768
|
-
@click.option("-r", "--remove", is_flag=True, help="Remove tasks from existing manifest.")
|
|
769
|
-
@click.option("-d", "--default", type=str, multiple=True, help="Override default parameter values.")
|
|
770
|
-
@click.option("-o", "--output", type=str, default="default.joltxmanifest", help="Manifest filename.")
|
|
771
|
-
@click.pass_context
|
|
772
|
-
def freeze(ctx, task, default, output, remove):
|
|
773
|
-
"""
|
|
774
|
-
Freeze the identity of a task.
|
|
775
|
-
|
|
776
|
-
<WIP>
|
|
777
|
-
"""
|
|
778
|
-
manifest = ctx.obj["manifest"]
|
|
779
|
-
|
|
780
|
-
options = JoltOptions(default=default)
|
|
781
|
-
acache = cache.ArtifactCache.get(options)
|
|
782
|
-
scheduler.ExecutorRegistry.get(options)
|
|
783
|
-
registry = TaskRegistry.get()
|
|
784
|
-
|
|
785
|
-
for params in default:
|
|
786
|
-
registry.set_default_parameters(params)
|
|
787
|
-
|
|
788
|
-
gb = graph.GraphBuilder(registry, acache, manifest)
|
|
789
|
-
dag = gb.build(task)
|
|
790
|
-
|
|
791
|
-
available, missing = acache.availability(dag.persistent_artifacts)
|
|
792
|
-
|
|
793
|
-
for artifact in missing:
|
|
794
|
-
raise_task_error_if(
|
|
795
|
-
not remove, artifact.get_task(),
|
|
796
|
-
"Task artifact is not available in any cache, build it first")
|
|
797
|
-
|
|
798
|
-
for task in dag.tasks:
|
|
799
|
-
if task.is_resource() or not task.is_cacheable():
|
|
800
|
-
continue
|
|
801
|
-
manifest_task = manifest.find_task(task)
|
|
802
|
-
if remove and manifest_task:
|
|
803
|
-
manifest.remove_task(manifest_task)
|
|
804
|
-
continue
|
|
805
|
-
if not remove:
|
|
806
|
-
if not manifest_task:
|
|
807
|
-
manifest_task = manifest.create_task()
|
|
808
|
-
manifest_task.name = task.qualified_name
|
|
809
|
-
manifest_task.identity = task.identity
|
|
810
|
-
|
|
811
|
-
manifest.write(fs.path.join(JoltLoader.get().joltdir, output))
|
|
824
|
+
finally:
|
|
825
|
+
queue.shutdown()
|
|
812
826
|
|
|
813
827
|
|
|
814
828
|
@cli.command(name="list")
|
|
@@ -846,7 +860,7 @@ def _list(ctx, task=None, all=False, reverse=None):
|
|
|
846
860
|
reverse = [utils.stable_task_name(t) for t in utils.as_list(reverse or [])]
|
|
847
861
|
|
|
848
862
|
try:
|
|
849
|
-
dag = graph.GraphBuilder(registry, acache
|
|
863
|
+
dag = graph.GraphBuilder(registry, acache).build(task, influence=False)
|
|
850
864
|
except JoltError as e:
|
|
851
865
|
raise e
|
|
852
866
|
except Exception:
|
|
@@ -891,7 +905,7 @@ def _log(follow, delete):
|
|
|
891
905
|
fs.unlink(file)
|
|
892
906
|
else:
|
|
893
907
|
t = tools.Tools()
|
|
894
|
-
configured_pager = config.get("jolt", "pager", environ.get("PAGER", None))
|
|
908
|
+
configured_pager = config.get("jolt", "pager", os.environ.get("PAGER", None))
|
|
895
909
|
for pager in [configured_pager, "less", "more", "cat"]:
|
|
896
910
|
if pager and t.which(pager):
|
|
897
911
|
return subprocess.call("{1} {0}".format(log.logfiles[-1], pager), shell=True)
|
|
@@ -946,9 +960,8 @@ def inspect(ctx, task, influence=False, artifact=False, salt=None):
|
|
|
946
960
|
|
|
947
961
|
print()
|
|
948
962
|
print(" Requirements")
|
|
949
|
-
manifest = ctx.obj["manifest"]
|
|
950
963
|
try:
|
|
951
|
-
task = task_registry.get_task(task_name
|
|
964
|
+
task = task_registry.get_task(task_name)
|
|
952
965
|
for req in sorted(utils.as_list(utils.call_or_return(task, task.requires))):
|
|
953
966
|
print(" {0}".format(task.tools.expand(req)))
|
|
954
967
|
if not task.requires:
|
|
@@ -970,7 +983,7 @@ def inspect(ctx, task, influence=False, artifact=False, salt=None):
|
|
|
970
983
|
if artifact:
|
|
971
984
|
options = JoltOptions(salt=salt)
|
|
972
985
|
acache = cache.ArtifactCache.get()
|
|
973
|
-
builder = graph.GraphBuilder(task_registry, acache,
|
|
986
|
+
builder = graph.GraphBuilder(task_registry, acache, options)
|
|
974
987
|
dag = builder.build([task.qualified_name])
|
|
975
988
|
tasks = dag.select(lambda graph, node: node.task is task)
|
|
976
989
|
assert len(tasks) == 1, "graph produced multiple tasks, one expected"
|
|
@@ -1034,7 +1047,7 @@ def _export(ctx, task):
|
|
|
1034
1047
|
executors = scheduler.ExecutorRegistry.get()
|
|
1035
1048
|
strategy = scheduler.LocalStrategy(executors, acache)
|
|
1036
1049
|
|
|
1037
|
-
dag = graph.GraphBuilder(registry, acache
|
|
1050
|
+
dag = graph.GraphBuilder(registry, acache)
|
|
1038
1051
|
dag = dag.build(task)
|
|
1039
1052
|
|
|
1040
1053
|
gp = graph.GraphPruner(acache, strategy)
|
|
@@ -1064,7 +1077,7 @@ def _export(ctx, task):
|
|
|
1064
1077
|
for task in context.tasks:
|
|
1065
1078
|
for artifact in task.artifacts:
|
|
1066
1079
|
raise_task_error_if(
|
|
1067
|
-
artifact.is_temporary(), task,
|
|
1080
|
+
not task.is_resource() and artifact.is_temporary(), task,
|
|
1068
1081
|
"Task artifact not found in local cache, build it first")
|
|
1069
1082
|
|
|
1070
1083
|
visitor = Export()
|
|
@@ -1105,15 +1118,15 @@ def _report(ctx):
|
|
|
1105
1118
|
session=True,
|
|
1106
1119
|
tools=t)
|
|
1107
1120
|
|
|
1108
|
-
with t.tmpdir("report") as tmp, t.cwd(tmp
|
|
1121
|
+
with t.tmpdir("report") as tmp, t.cwd(tmp):
|
|
1109
1122
|
log.info("Collecting environment")
|
|
1110
1123
|
env = ""
|
|
1111
|
-
for key, val in environ.items():
|
|
1124
|
+
for key, val in os.environ.items():
|
|
1112
1125
|
env += f"{key} = {val}\n"
|
|
1113
1126
|
t.write_file("environ.txt", env, expand=False)
|
|
1114
1127
|
|
|
1115
1128
|
log.info("Collecting configuration")
|
|
1116
|
-
config.save(tmp
|
|
1129
|
+
config.save(tmp)
|
|
1117
1130
|
artifact.collect("*.conf", "configs/")
|
|
1118
1131
|
|
|
1119
1132
|
log.info("Collecting platform information")
|