jolt 0.9.123__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 +832 -362
- jolt/chroot.py +156 -0
- jolt/cli.py +281 -162
- jolt/common_pb2.py +63 -0
- jolt/common_pb2_grpc.py +4 -0
- jolt/config.py +98 -41
- jolt/error.py +19 -4
- jolt/filesystem.py +2 -6
- jolt/graph.py +705 -117
- jolt/hooks.py +43 -0
- jolt/influence.py +122 -3
- jolt/loader.py +369 -121
- jolt/log.py +225 -63
- jolt/manifest.py +28 -38
- jolt/options.py +35 -10
- 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 +5 -2
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cache.py +133 -0
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/conan.py +238 -0
- jolt/plugins/cxx.py +698 -0
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/dashboard.py +1 -1
- jolt/plugins/docker.py +80 -23
- jolt/plugins/email.py +2 -2
- jolt/plugins/email.xslt +144 -101
- jolt/plugins/environ.py +11 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/gdb.py +39 -19
- jolt/plugins/gerrit.py +1 -14
- jolt/plugins/git.py +283 -85
- jolt/plugins/googletest.py +2 -1
- jolt/plugins/http.py +36 -38
- 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 +99 -30
- jolt/plugins/ninja.py +468 -166
- jolt/plugins/paths.py +11 -1
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/podman.py +136 -92
- jolt/plugins/python.py +137 -0
- jolt/plugins/remote_execution/__init__.py +0 -0
- jolt/plugins/remote_execution/administration_pb2.py +46 -0
- jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
- jolt/plugins/remote_execution/log_pb2.py +32 -0
- jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
- jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
- jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
- jolt/plugins/remote_execution/worker_pb2.py +38 -0
- jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
- jolt/plugins/report.py +12 -2
- jolt/plugins/rust.py +25 -0
- jolt/plugins/scheduler.py +710 -0
- jolt/plugins/selfdeploy/setup.py +8 -4
- jolt/plugins/selfdeploy.py +138 -88
- jolt/plugins/strings.py +35 -22
- jolt/plugins/symlinks.py +26 -11
- jolt/plugins/telemetry.py +5 -2
- jolt/plugins/timeline.py +13 -3
- jolt/plugins/volume.py +46 -48
- jolt/scheduler.py +589 -192
- jolt/tasks.py +625 -121
- jolt/templates/timeline.html.template +44 -47
- jolt/timer.py +22 -0
- jolt/tools.py +638 -282
- jolt/utils.py +211 -7
- jolt/version.py +1 -1
- jolt/xmldom.py +12 -2
- {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/METADATA +97 -38
- jolt-0.9.435.dist-info/RECORD +207 -0
- {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/WHEEL +1 -1
- jolt/plugins/amqp.py +0 -834
- jolt/plugins/debian.py +0 -338
- jolt/plugins/ftp.py +0 -181
- jolt/plugins/repo.py +0 -253
- jolt-0.9.123.dist-info/RECORD +0 -77
- {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/top_level.txt +0 -0
jolt/log.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
|
+
import glob
|
|
2
3
|
import os
|
|
3
4
|
import re
|
|
4
5
|
import sys
|
|
6
|
+
import time
|
|
5
7
|
import tqdm
|
|
6
8
|
if os.name == "nt":
|
|
7
9
|
# FIXME: Workaround to make tqdm behave correctly on Windows
|
|
@@ -23,34 +25,40 @@ from jolt import config
|
|
|
23
25
|
from jolt.error import JoltError
|
|
24
26
|
from jolt import filesystem as fs
|
|
25
27
|
from jolt import colors
|
|
28
|
+
from jolt import common_pb2 as common_pb
|
|
29
|
+
from jolt import utils
|
|
26
30
|
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
logcount = config.getint("jolt", "logcount", os.environ.get("JOLT_LOGCOUNT",
|
|
32
|
+
current_time = datetime.now().strftime("%Y-%m-%dT%H%M%S.%f")
|
|
33
|
+
logpath = config.get_logpath()
|
|
34
|
+
logfile = fs.path.join(logpath, f"{current_time}.log")
|
|
35
|
+
logcount = config.getint("jolt", "logcount", os.environ.get("JOLT_LOGCOUNT", 100))
|
|
36
|
+
logfiles = list(sorted(glob.glob(os.path.join(logpath, "*T*.log"))))
|
|
32
37
|
|
|
33
38
|
dirpath = fs.path.dirname(logfile)
|
|
34
39
|
if not fs.path.exists(dirpath):
|
|
35
40
|
fs.makedirs(dirpath)
|
|
36
|
-
with open(logfile, "a") as f:
|
|
37
|
-
f.write("--------------------------------------------------------------------------------\n")
|
|
38
41
|
|
|
39
42
|
################################################################################
|
|
40
43
|
|
|
41
|
-
ERROR =
|
|
42
|
-
WARNING =
|
|
43
|
-
INFO =
|
|
44
|
-
VERBOSE =
|
|
45
|
-
DEBUG =
|
|
46
|
-
EXCEPTION =
|
|
47
|
-
STDOUT =
|
|
48
|
-
STDERR =
|
|
49
|
-
SILENCE = STDERR +
|
|
44
|
+
ERROR = common_pb.LogLevel.ERROR + 1
|
|
45
|
+
WARNING = common_pb.LogLevel.WARNING + 1
|
|
46
|
+
INFO = common_pb.LogLevel.INFO + 1
|
|
47
|
+
VERBOSE = common_pb.LogLevel.VERBOSE + 1
|
|
48
|
+
DEBUG = common_pb.LogLevel.DEBUG + 1
|
|
49
|
+
EXCEPTION = common_pb.LogLevel.EXCEPTION + 1
|
|
50
|
+
STDOUT = common_pb.LogLevel.STDOUT + 1
|
|
51
|
+
STDERR = common_pb.LogLevel.STDERR + 1
|
|
52
|
+
SILENCE = STDERR + 2
|
|
53
|
+
|
|
50
54
|
logging.addLevelName(VERBOSE, "VERBOSE")
|
|
51
55
|
logging.addLevelName(STDOUT, "STDOUT")
|
|
52
56
|
logging.addLevelName(STDERR, "STDERR")
|
|
53
57
|
logging.addLevelName(EXCEPTION, "EXCEPT")
|
|
58
|
+
logging.addLevelName(WARNING, "WARNING")
|
|
59
|
+
logging.addLevelName(INFO, "INFO")
|
|
60
|
+
logging.addLevelName(ERROR, "ERROR")
|
|
61
|
+
logging.addLevelName(DEBUG, "DEBUG")
|
|
54
62
|
|
|
55
63
|
logging.raiseExceptions = False
|
|
56
64
|
|
|
@@ -135,13 +143,37 @@ class TqdmStream(object):
|
|
|
135
143
|
getattr(self.stream, 'flush', lambda: None)()
|
|
136
144
|
|
|
137
145
|
|
|
146
|
+
class ThreadPrefix(logging.LoggerAdapter):
|
|
147
|
+
thread_prefix = {}
|
|
148
|
+
|
|
149
|
+
def process(self, msg, kwargs):
|
|
150
|
+
tid = threading.current_thread()
|
|
151
|
+
if tid in self.thread_prefix:
|
|
152
|
+
msg = f"[{self.thread_prefix[tid]}] {msg}"
|
|
153
|
+
return msg, kwargs
|
|
154
|
+
|
|
155
|
+
def set_thread_prefix(self, prefix):
|
|
156
|
+
tid = threading.current_thread()
|
|
157
|
+
self.thread_prefix[tid] = prefix
|
|
158
|
+
|
|
159
|
+
def clear_thread_prefix(self):
|
|
160
|
+
tid = threading.current_thread()
|
|
161
|
+
if tid in self.thread_prefix:
|
|
162
|
+
del self.thread_prefix[tid]
|
|
163
|
+
|
|
164
|
+
|
|
138
165
|
# silence root logger
|
|
139
166
|
_root = logging.getLogger()
|
|
140
167
|
_root.setLevel(logging.CRITICAL)
|
|
141
168
|
|
|
142
|
-
# create jolt logger
|
|
169
|
+
# create jolt logger and protect it's methods against interrupts
|
|
143
170
|
_logger = logging.getLogger('jolt')
|
|
144
|
-
_logger.setLevel(
|
|
171
|
+
_logger.setLevel(EXCEPTION)
|
|
172
|
+
_logger.handle = utils.delay_interrupt(_logger.handle)
|
|
173
|
+
_logger.log = utils.delay_interrupt(_logger.log)
|
|
174
|
+
_logger.addHandler = utils.delay_interrupt(_logger.addHandler)
|
|
175
|
+
_logger.removeHandler = utils.delay_interrupt(_logger.removeHandler)
|
|
176
|
+
|
|
145
177
|
|
|
146
178
|
_console_formatter = ConsoleFormatter('[{levelname:>7}] {message}', '{message}')
|
|
147
179
|
|
|
@@ -149,91 +181,134 @@ if sys.stdout.isatty() and sys.stderr.isatty():
|
|
|
149
181
|
_stdout = logging.StreamHandler(TqdmStream(sys.stdout))
|
|
150
182
|
else:
|
|
151
183
|
_stdout = logging.StreamHandler(sys.stdout)
|
|
152
|
-
_stdout.setLevel(INFO)
|
|
153
184
|
_stdout.setFormatter(_console_formatter)
|
|
154
185
|
_stdout.addFilter(Filter(lambda r: r.levelno < ERROR))
|
|
186
|
+
_stdout.addFilter(Filter(lambda r: r.levelno != EXCEPTION))
|
|
155
187
|
|
|
156
188
|
if sys.stdout.isatty() and sys.stderr.isatty():
|
|
157
189
|
_stderr = logging.StreamHandler(TqdmStream(sys.stdout))
|
|
158
190
|
else:
|
|
159
191
|
_stderr = logging.StreamHandler(sys.stderr)
|
|
160
|
-
_stderr.setLevel(INFO)
|
|
161
192
|
_stderr.setFormatter(_console_formatter)
|
|
162
|
-
_stderr.addFilter(Filter(lambda r: r.levelno >= ERROR))
|
|
163
|
-
_stderr.addFilter(Filter(lambda r: r.levelno != EXCEPTION))
|
|
164
|
-
|
|
165
|
-
_file = logging.handlers.RotatingFileHandler(logfile, maxBytes=logsize, backupCount=logcount)
|
|
166
|
-
_file.setLevel(logging.DEBUG)
|
|
167
|
-
_file_formatter = Formatter('{asctime} [{levelname:>7}] {message}')
|
|
168
|
-
_file.setFormatter(_file_formatter)
|
|
193
|
+
_stderr.addFilter(Filter(lambda r: r.levelno >= ERROR or r.levelno == EXCEPTION))
|
|
169
194
|
|
|
170
195
|
_logger.addHandler(_stdout)
|
|
171
196
|
_logger.addHandler(_stderr)
|
|
172
|
-
_logger
|
|
197
|
+
_logger_frontend = ThreadPrefix(_logger, {})
|
|
198
|
+
|
|
199
|
+
_file_formatter = Formatter('{asctime} [{levelname:>7}] {message}')
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def start_file_log():
|
|
203
|
+
global logfiles
|
|
204
|
+
|
|
205
|
+
if len(logfiles) >= logcount:
|
|
206
|
+
outdated = logfiles[:len(logfiles) - logcount + 1]
|
|
207
|
+
logfiles = logfiles[-logcount + 1:]
|
|
208
|
+
for file in outdated:
|
|
209
|
+
os.unlink(file)
|
|
210
|
+
|
|
211
|
+
_file = logging.FileHandler(logfile)
|
|
212
|
+
_file.setLevel(EXCEPTION)
|
|
213
|
+
_file.setFormatter(_file_formatter)
|
|
214
|
+
_logger.addHandler(_file)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def log(level, message, created=None, context=None, prefix=False):
|
|
218
|
+
created = created or time.time()
|
|
219
|
+
message = f"[{context}] {message}" if context else message
|
|
220
|
+
record = logging.LogRecord(
|
|
221
|
+
name="log",
|
|
222
|
+
level=level,
|
|
223
|
+
pathname=__file__,
|
|
224
|
+
lineno=0,
|
|
225
|
+
msg=message,
|
|
226
|
+
args={},
|
|
227
|
+
exc_info=None,
|
|
228
|
+
)
|
|
229
|
+
record.created = created
|
|
230
|
+
record.prefix = prefix
|
|
231
|
+
_logger.handle(record)
|
|
173
232
|
|
|
174
233
|
|
|
175
234
|
def info(fmt, *args, **kwargs):
|
|
176
|
-
|
|
235
|
+
_logger_frontend.log(INFO, fmt, *args, **kwargs)
|
|
177
236
|
|
|
178
237
|
|
|
179
238
|
def warning(fmt, *args, **kwargs):
|
|
180
|
-
|
|
239
|
+
_logger_frontend.log(WARNING, fmt, *args, **kwargs)
|
|
181
240
|
|
|
182
241
|
|
|
183
242
|
def verbose(fmt, *args, **kwargs):
|
|
184
|
-
|
|
243
|
+
_logger_frontend.log(VERBOSE, fmt, *args, **kwargs)
|
|
185
244
|
|
|
186
245
|
|
|
187
246
|
def debug(fmt, *args, **kwargs):
|
|
188
|
-
|
|
247
|
+
_logger_frontend.log(DEBUG, fmt, *args, **kwargs)
|
|
189
248
|
|
|
190
249
|
|
|
191
250
|
def error(fmt, *args, **kwargs):
|
|
192
|
-
|
|
251
|
+
_logger_frontend.log(ERROR, fmt, *args, **kwargs)
|
|
193
252
|
|
|
194
253
|
|
|
195
254
|
def stdout(line, **kwargs):
|
|
196
255
|
line = line.replace("{", "{{")
|
|
197
256
|
line = line.replace("}", "}}")
|
|
198
|
-
|
|
257
|
+
_logger_frontend.log(STDOUT, line, extra=kwargs)
|
|
199
258
|
|
|
200
259
|
|
|
201
260
|
def stderr(line, **kwargs):
|
|
202
261
|
line = line.replace("{", "{{")
|
|
203
262
|
line = line.replace("}", "}}")
|
|
204
|
-
|
|
263
|
+
_logger_frontend.log(STDERR, line, extra=kwargs)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def format_exception_msg(exc):
|
|
267
|
+
te = traceback.TracebackException.from_exception(exc)
|
|
205
268
|
|
|
269
|
+
if isinstance(exc, JoltError):
|
|
270
|
+
return str(exc)
|
|
206
271
|
|
|
207
|
-
|
|
272
|
+
elif isinstance(exc, SyntaxError):
|
|
273
|
+
filename = fs.path.relpath(
|
|
274
|
+
te.filename,
|
|
275
|
+
fs.path.commonprefix([os.getcwd(), te.filename]))
|
|
276
|
+
return "SyntaxError: {} ({}, line {})".format(
|
|
277
|
+
te.text.strip(),
|
|
278
|
+
filename,
|
|
279
|
+
te.lineno)
|
|
280
|
+
|
|
281
|
+
else:
|
|
282
|
+
filename = fs.path.relpath(
|
|
283
|
+
te.stack[-1].filename,
|
|
284
|
+
fs.path.commonprefix([os.getcwd(), te.stack[-1].filename]))
|
|
285
|
+
return "{}: {} ({}, line {}, in {})".format(
|
|
286
|
+
type(exc).__name__,
|
|
287
|
+
str(exc) or te.stack[-1].line,
|
|
288
|
+
filename,
|
|
289
|
+
te.stack[-1].lineno,
|
|
290
|
+
te.stack[-1].name)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def exception(exc=None, error=True):
|
|
208
294
|
if exc:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
filename,
|
|
219
|
-
te.lineno)
|
|
220
|
-
else:
|
|
221
|
-
filename = fs.path.relpath(
|
|
222
|
-
te.stack[-1].filename,
|
|
223
|
-
fs.path.commonprefix([os.getcwd(), te.stack[-1].filename]))
|
|
224
|
-
_logger.error("{}: {} ({}, line {}, in {})",
|
|
225
|
-
type(exc).__name__,
|
|
226
|
-
str(exc) or te.stack[-1].line,
|
|
227
|
-
filename,
|
|
228
|
-
te.stack[-1].lineno,
|
|
229
|
-
te.stack[-1].name)
|
|
230
|
-
backtrace = traceback.format_exc().splitlines()
|
|
295
|
+
if error:
|
|
296
|
+
_logger_frontend.log(ERROR, format_exception_msg(exc))
|
|
297
|
+
|
|
298
|
+
tb = traceback.format_exception(type(exc), value=exc, tb=exc.__traceback__)
|
|
299
|
+
installdir = fs.path.dirname(__file__)
|
|
300
|
+
if any(map(lambda frame: installdir not in frame, tb[1:-1])):
|
|
301
|
+
while len(tb) > 2 and installdir in tb[1]:
|
|
302
|
+
del tb[1]
|
|
303
|
+
backtrace = "".join(tb).splitlines()
|
|
231
304
|
else:
|
|
232
305
|
backtrace = traceback.format_exc().splitlines()
|
|
306
|
+
|
|
233
307
|
for line in backtrace:
|
|
234
308
|
line = line.replace("{", "{{")
|
|
235
309
|
line = line.replace("}", "}}")
|
|
236
|
-
|
|
310
|
+
line = line.strip()
|
|
311
|
+
_logger_frontend.log(EXCEPTION, line)
|
|
237
312
|
|
|
238
313
|
|
|
239
314
|
def transfer(line, context):
|
|
@@ -242,6 +317,8 @@ def transfer(line, context):
|
|
|
242
317
|
outline2 = context + line
|
|
243
318
|
if line.startswith("[ ERROR]"):
|
|
244
319
|
error(outline1)
|
|
320
|
+
elif line.startswith("[WARNING]"):
|
|
321
|
+
warning(outline1)
|
|
245
322
|
elif line.startswith("[VERBOSE]"):
|
|
246
323
|
verbose(outline1)
|
|
247
324
|
elif line.startswith("[ DEBUG]"):
|
|
@@ -251,7 +328,7 @@ def transfer(line, context):
|
|
|
251
328
|
elif line.startswith("[ EXCEPT]"):
|
|
252
329
|
outline1 = outline1.replace("{", "{{")
|
|
253
330
|
outline1 = outline1.replace("}", "}}")
|
|
254
|
-
|
|
331
|
+
_logger_frontend.log(EXCEPTION, outline1)
|
|
255
332
|
elif line.startswith("[ STDERR]"):
|
|
256
333
|
stderr(outline1, prefix=True)
|
|
257
334
|
elif line.startswith("[ STDOUT]"):
|
|
@@ -281,26 +358,90 @@ class _Progress(object):
|
|
|
281
358
|
def update(self, *args, **kwargs):
|
|
282
359
|
pass
|
|
283
360
|
|
|
361
|
+
def refresh(self, *args, **kwargs):
|
|
362
|
+
pass
|
|
363
|
+
|
|
364
|
+
def reset(self, *args, **kwargs):
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
def set_description(self, *args, **kwargs):
|
|
368
|
+
pass
|
|
369
|
+
|
|
284
370
|
|
|
285
371
|
def progress_log(desc, count, unit):
|
|
286
372
|
return _Progress(desc)
|
|
287
373
|
|
|
288
374
|
|
|
289
375
|
def progress(desc, count, unit, estimates=True, debug=False):
|
|
290
|
-
|
|
291
|
-
|
|
376
|
+
if count:
|
|
377
|
+
bar_format = '{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}]' \
|
|
378
|
+
if not estimates else None
|
|
379
|
+
else:
|
|
380
|
+
bar_format = '{desc}{n_fmt}{unit} [{elapsed}]'
|
|
292
381
|
if not debug and is_interactive() and not is_verbose():
|
|
293
|
-
|
|
294
|
-
|
|
382
|
+
class ProgressTqdm(tqdm.tqdm):
|
|
383
|
+
def __init__(self, *args, **kwargs):
|
|
384
|
+
super(ProgressTqdm, self).__init__(*args, **kwargs)
|
|
385
|
+
|
|
386
|
+
def set_description(self, desc=None, refresh=True):
|
|
387
|
+
return super().set_description("[ INFO] " + desc, refresh)
|
|
388
|
+
|
|
389
|
+
p = ProgressTqdm(total=count, unit=unit, unit_scale=True, bar_format=bar_format, dynamic_ncols=True)
|
|
390
|
+
p.set_description(desc)
|
|
295
391
|
return p
|
|
296
392
|
return progress_log(desc, count, unit)
|
|
297
393
|
|
|
298
394
|
|
|
395
|
+
_level = INFO
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def level_to_pb(level):
|
|
399
|
+
""" Convert a log level to a protobuf enum value. """
|
|
400
|
+
return level - 1
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def pb_to_level(level):
|
|
404
|
+
""" Convert a protobuf enum value to a log level. """
|
|
405
|
+
return level + 1
|
|
406
|
+
|
|
407
|
+
|
|
299
408
|
def set_level(level):
|
|
409
|
+
""" Set the log level for terminal output. """
|
|
410
|
+
|
|
411
|
+
if level not in [
|
|
412
|
+
DEBUG,
|
|
413
|
+
ERROR,
|
|
414
|
+
EXCEPTION,
|
|
415
|
+
INFO,
|
|
416
|
+
SILENCE,
|
|
417
|
+
STDERR,
|
|
418
|
+
STDOUT,
|
|
419
|
+
VERBOSE,
|
|
420
|
+
WARNING,
|
|
421
|
+
]:
|
|
422
|
+
raise ValueError("invalid log level")
|
|
423
|
+
|
|
424
|
+
global _level
|
|
425
|
+
_level = level
|
|
300
426
|
_stdout.setLevel(level)
|
|
301
427
|
_stderr.setLevel(level)
|
|
302
428
|
|
|
303
429
|
|
|
430
|
+
def set_level_pb(level):
|
|
431
|
+
""" Set the log level from a protobuf enum value. """
|
|
432
|
+
set_level(pb_to_level(level))
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def get_level():
|
|
436
|
+
global _level
|
|
437
|
+
return _level
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def get_level_pb():
|
|
441
|
+
""" Get the log level as a protobuf enum value. """
|
|
442
|
+
return level_to_pb(_level)
|
|
443
|
+
|
|
444
|
+
|
|
304
445
|
def set_worker():
|
|
305
446
|
_console_formatter.enable_prefixes()
|
|
306
447
|
|
|
@@ -361,6 +502,15 @@ def threadsink(level=DEBUG):
|
|
|
361
502
|
_logger.removeHandler(handler)
|
|
362
503
|
|
|
363
504
|
|
|
505
|
+
@contextmanager
|
|
506
|
+
def handler(h):
|
|
507
|
+
_logger.addHandler(h)
|
|
508
|
+
try:
|
|
509
|
+
yield
|
|
510
|
+
finally:
|
|
511
|
+
_logger.removeHandler(h)
|
|
512
|
+
|
|
513
|
+
|
|
364
514
|
@contextmanager
|
|
365
515
|
def map_thread(thread_from, thread_to):
|
|
366
516
|
tid = thread_from.ident
|
|
@@ -371,6 +521,15 @@ def map_thread(thread_from, thread_to):
|
|
|
371
521
|
_thread_map.unmap(tid)
|
|
372
522
|
|
|
373
523
|
|
|
524
|
+
@contextmanager
|
|
525
|
+
def thread_prefix(prefix):
|
|
526
|
+
try:
|
|
527
|
+
_logger_frontend.set_thread_prefix(prefix)
|
|
528
|
+
yield
|
|
529
|
+
finally:
|
|
530
|
+
_logger_frontend.clear_thread_prefix()
|
|
531
|
+
|
|
532
|
+
|
|
374
533
|
class _LogStream(object):
|
|
375
534
|
def __init__(self):
|
|
376
535
|
self.buf = ""
|
|
@@ -396,3 +555,6 @@ class _LogStream(object):
|
|
|
396
555
|
@contextmanager
|
|
397
556
|
def stream():
|
|
398
557
|
yield _LogStream()
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
set_level(STDOUT)
|
jolt/manifest.py
CHANGED
|
@@ -40,6 +40,14 @@ class _JoltProjectModule(SubElement):
|
|
|
40
40
|
def __init__(self, elem=None):
|
|
41
41
|
super(_JoltProjectModule, self).__init__('module', elem=elem)
|
|
42
42
|
|
|
43
|
+
@property
|
|
44
|
+
def path(self):
|
|
45
|
+
return self.src
|
|
46
|
+
|
|
47
|
+
@path.setter
|
|
48
|
+
def path(self, value):
|
|
49
|
+
self.src = value
|
|
50
|
+
|
|
43
51
|
|
|
44
52
|
@Attribute('name')
|
|
45
53
|
class _JoltProjectResource(SubElement):
|
|
@@ -70,6 +78,7 @@ class _JoltTaskError(SubElement):
|
|
|
70
78
|
@Attribute('duration', child=True)
|
|
71
79
|
@Attribute('goal', child=True)
|
|
72
80
|
@Attribute('identity', child=True)
|
|
81
|
+
@Attribute('instance', child=True)
|
|
73
82
|
@Attribute('logstash', child=True)
|
|
74
83
|
@Attribute('result', child=True)
|
|
75
84
|
@Composition(_JoltAttribute, "attribute")
|
|
@@ -104,7 +113,9 @@ class _JoltNetworkParameter(SubElement):
|
|
|
104
113
|
@Attribute("stderr", child=True, zlib=True)
|
|
105
114
|
@Attribute("result", child=True)
|
|
106
115
|
@Attribute("duration", child=True)
|
|
116
|
+
@Attribute("name")
|
|
107
117
|
@Attribute("workspace")
|
|
118
|
+
@Attribute("build")
|
|
108
119
|
@Attribute("version")
|
|
109
120
|
@Composition(_JoltRecipe, "recipe")
|
|
110
121
|
@Composition(_JoltTask, "task")
|
|
@@ -118,8 +129,10 @@ class JoltManifest(ElementTree):
|
|
|
118
129
|
self._elem = self.getroot()
|
|
119
130
|
self.path = None
|
|
120
131
|
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
def is_valid(self):
|
|
133
|
+
return self.path is not None
|
|
134
|
+
|
|
135
|
+
def get_workspace_path(self):
|
|
123
136
|
if self.path is None:
|
|
124
137
|
return None
|
|
125
138
|
joltdir = fs.path.dirname(self.path)
|
|
@@ -127,6 +140,13 @@ class JoltManifest(ElementTree):
|
|
|
127
140
|
joltdir = fs.path.normpath(fs.path.join(joltdir, self.workspace))
|
|
128
141
|
return joltdir
|
|
129
142
|
|
|
143
|
+
def get_workspace_name(self):
|
|
144
|
+
if self.name:
|
|
145
|
+
return self.name
|
|
146
|
+
if self.path is None:
|
|
147
|
+
return None
|
|
148
|
+
return fs.path.basename(fs.path.dirname(self.path))
|
|
149
|
+
|
|
130
150
|
@property
|
|
131
151
|
def attrib(self):
|
|
132
152
|
return self.getroot().attrib
|
|
@@ -195,6 +215,12 @@ class JoltManifest(ElementTree):
|
|
|
195
215
|
return True
|
|
196
216
|
return self.find("./task[result='FAILED']") is not None
|
|
197
217
|
|
|
218
|
+
def has_unstable(self):
|
|
219
|
+
return self.find("./task[result='UNSTABLE']") is not None
|
|
220
|
+
|
|
221
|
+
def has_tasks(self):
|
|
222
|
+
return self.find("./task") is not None
|
|
223
|
+
|
|
198
224
|
def find_task(self, task):
|
|
199
225
|
match = self.find("./task[@name='{0}']".format(task))
|
|
200
226
|
if match is None:
|
|
@@ -215,39 +241,3 @@ class JoltManifest(ElementTree):
|
|
|
215
241
|
for manifest_task in self.tasks:
|
|
216
242
|
self._identities[manifest_task.name] = manifest_task.identity
|
|
217
243
|
return self._identities
|
|
218
|
-
|
|
219
|
-
@staticmethod
|
|
220
|
-
def export(task):
|
|
221
|
-
manifest = JoltManifest()
|
|
222
|
-
ManifestExtensionRegistry.export_manifest(manifest, task)
|
|
223
|
-
return manifest
|
|
224
|
-
|
|
225
|
-
def process_import(self):
|
|
226
|
-
ManifestExtensionRegistry.import_manifest(self)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
class ManifestExtensionRegistry(object):
|
|
230
|
-
extensions = []
|
|
231
|
-
|
|
232
|
-
@staticmethod
|
|
233
|
-
def add(extension, priority=0):
|
|
234
|
-
ManifestExtensionRegistry.extensions.append((extension, priority))
|
|
235
|
-
ManifestExtensionRegistry.extensions.sort(key=lambda x: x[1])
|
|
236
|
-
|
|
237
|
-
@staticmethod
|
|
238
|
-
def export_manifest(manifest, task):
|
|
239
|
-
for extension, _ in ManifestExtensionRegistry.extensions:
|
|
240
|
-
extension.export_manifest(manifest, task)
|
|
241
|
-
|
|
242
|
-
@staticmethod
|
|
243
|
-
def import_manifest(manifest):
|
|
244
|
-
for extension, _ in ManifestExtensionRegistry.extensions:
|
|
245
|
-
extension.import_manifest(manifest)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
class ManifestExtension(object):
|
|
249
|
-
def export_manifest(self, manifest, task):
|
|
250
|
-
pass
|
|
251
|
-
|
|
252
|
-
def import_manifest(self, manifest):
|
|
253
|
-
pass
|
jolt/options.py
CHANGED
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
|
|
2
2
|
class JoltOptions(object):
|
|
3
|
+
""" Jolt options that control the behavior of builds. """
|
|
4
|
+
|
|
5
|
+
debug = False
|
|
6
|
+
""" Enable debug mode. Break into debugger on exceptions. """
|
|
7
|
+
|
|
8
|
+
download = True
|
|
9
|
+
""" Enable downloading of remote artifacts, both session and persistent. """
|
|
10
|
+
|
|
11
|
+
download_session = True
|
|
12
|
+
""" Enable downloading of remote session artifacts. """
|
|
13
|
+
|
|
14
|
+
keep_going = False
|
|
15
|
+
""" Keep going with the build after a task fails. """
|
|
16
|
+
|
|
17
|
+
local = False
|
|
18
|
+
""" Disable network access. """
|
|
19
|
+
|
|
20
|
+
network = False
|
|
21
|
+
""" Distribute tasks to workers. """
|
|
22
|
+
|
|
23
|
+
upload = True
|
|
24
|
+
""" Enable uploading of artifacts. """
|
|
25
|
+
|
|
26
|
+
worker = False
|
|
27
|
+
""" Running as a worker. """
|
|
28
|
+
|
|
29
|
+
salt = None
|
|
30
|
+
""" Salt for hashing (--salt). """
|
|
31
|
+
|
|
32
|
+
jobs = 1
|
|
33
|
+
""" Number of concurrent local tasks to run (1). """
|
|
34
|
+
|
|
35
|
+
mute = False
|
|
36
|
+
""" Mute task output, until a task fails. """
|
|
37
|
+
|
|
3
38
|
def __init__(self, **kwargs):
|
|
4
|
-
self.debug = False
|
|
5
|
-
self.default = []
|
|
6
|
-
self.download = True
|
|
7
|
-
self.keep_going = False
|
|
8
|
-
self.local = False
|
|
9
|
-
self.network = False
|
|
10
|
-
self.upload = True
|
|
11
|
-
self.worker = False
|
|
12
|
-
self.salt = None
|
|
13
|
-
self.jobs = 1
|
|
14
39
|
self.__dict__.update(kwargs)
|
jolt/pkgs/abseil.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from jolt import attributes, BooleanParameter, Parameter, Task
|
|
2
|
+
from jolt.plugins import cmake, git
|
|
3
|
+
from jolt.tasks import TaskRegistry
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@attributes.requires("requires_git")
|
|
8
|
+
@attributes.system
|
|
9
|
+
@cmake.requires()
|
|
10
|
+
@cmake.use_ninja()
|
|
11
|
+
class Abseil(cmake.CMake):
|
|
12
|
+
""" Abseil C++ Common Libraries """
|
|
13
|
+
|
|
14
|
+
name = "abseil"
|
|
15
|
+
version = Parameter("20250814.1")
|
|
16
|
+
shared = BooleanParameter(False, help="Build shared libraries")
|
|
17
|
+
requires_git = ["git:url=https://github.com/abseil/abseil-cpp.git,rev={version}"]
|
|
18
|
+
srcdir = "{git[abseil-cpp]}"
|
|
19
|
+
options = [
|
|
20
|
+
"ABSL_MSVC_STATIC_RUNTIME=OFF",
|
|
21
|
+
"BUILD_SHARED_LIBS={shared[ON,OFF]}",
|
|
22
|
+
"CMAKE_CXX_STANDARD=17",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
def publish(self, artifact, tools):
|
|
26
|
+
super().publish(artifact, tools)
|
|
27
|
+
artifact.cxxinfo.crt = "Dynamic"
|
|
28
|
+
artifact.cxxinfo.incpaths.append("include")
|
|
29
|
+
artifact.cxxinfo.libpaths.append("lib")
|
|
30
|
+
if self.shared:
|
|
31
|
+
artifact.environ.LD_LIBRARY_PATH.append("lib")
|
|
32
|
+
|
|
33
|
+
with tools.cwd(artifact.path, "lib"):
|
|
34
|
+
for libfile in tools.glob("*.lib"):
|
|
35
|
+
libname, _ = os.path.splitext(libfile)
|
|
36
|
+
artifact.cxxinfo.libraries.append(libname)
|
|
37
|
+
for libfile in tools.glob("lib*.a"):
|
|
38
|
+
libname, _ = os.path.splitext(libfile)
|
|
39
|
+
artifact.cxxinfo.libraries.append(libname[3:])
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
TaskRegistry.get().add_task_class(Abseil)
|
jolt/pkgs/asio.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from jolt import attributes, Parameter
|
|
2
|
+
from jolt.plugins import cmake, git, autotools, pkgconfig
|
|
3
|
+
from jolt.tasks import TaskRegistry
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@attributes.requires("requires_git")
|
|
7
|
+
@autotools.requires()
|
|
8
|
+
@pkgconfig.requires()
|
|
9
|
+
@pkgconfig.to_cxxinfo("asio")
|
|
10
|
+
class Asio(autotools.Autotools):
|
|
11
|
+
name = "asio"
|
|
12
|
+
version = Parameter("1.36.0", help="asio version.")
|
|
13
|
+
requires_git = ["git:url=https://github.com/chriskohlhoff/asio.git,rev=asio-{_version}"]
|
|
14
|
+
srcdir = "{git[asio]}/asio"
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def _version(self):
|
|
18
|
+
return str(self.version).replace(".", "-")
|
|
19
|
+
|
|
20
|
+
def publish(self, artifact, tools):
|
|
21
|
+
super().publish(artifact, tools)
|
|
22
|
+
artifact.environ.CMAKE_PREFIX_PATH.append(".")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
TaskRegistry.get().add_task_class(Asio)
|