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.
Files changed (196) hide show
  1. jolt/__init__.py +80 -7
  2. jolt/__main__.py +9 -1
  3. jolt/bin/fstree-darwin-x86_64 +0 -0
  4. jolt/bin/fstree-linux-x86_64 +0 -0
  5. jolt/cache.py +832 -362
  6. jolt/chroot.py +156 -0
  7. jolt/cli.py +281 -162
  8. jolt/common_pb2.py +63 -0
  9. jolt/common_pb2_grpc.py +4 -0
  10. jolt/config.py +98 -41
  11. jolt/error.py +19 -4
  12. jolt/filesystem.py +2 -6
  13. jolt/graph.py +705 -117
  14. jolt/hooks.py +43 -0
  15. jolt/influence.py +122 -3
  16. jolt/loader.py +369 -121
  17. jolt/log.py +225 -63
  18. jolt/manifest.py +28 -38
  19. jolt/options.py +35 -10
  20. jolt/pkgs/abseil.py +42 -0
  21. jolt/pkgs/asio.py +25 -0
  22. jolt/pkgs/autoconf.py +41 -0
  23. jolt/pkgs/automake.py +41 -0
  24. jolt/pkgs/b2.py +31 -0
  25. jolt/pkgs/boost.py +111 -0
  26. jolt/pkgs/boringssl.py +32 -0
  27. jolt/pkgs/busybox.py +39 -0
  28. jolt/pkgs/bzip2.py +43 -0
  29. jolt/pkgs/cares.py +29 -0
  30. jolt/pkgs/catch2.py +36 -0
  31. jolt/pkgs/cbindgen.py +17 -0
  32. jolt/pkgs/cista.py +19 -0
  33. jolt/pkgs/clang.py +44 -0
  34. jolt/pkgs/cli11.py +24 -0
  35. jolt/pkgs/cmake.py +48 -0
  36. jolt/pkgs/cpython.py +196 -0
  37. jolt/pkgs/crun.py +29 -0
  38. jolt/pkgs/curl.py +38 -0
  39. jolt/pkgs/dbus.py +18 -0
  40. jolt/pkgs/double_conversion.py +24 -0
  41. jolt/pkgs/fastfloat.py +21 -0
  42. jolt/pkgs/ffmpeg.py +28 -0
  43. jolt/pkgs/flatbuffers.py +29 -0
  44. jolt/pkgs/fmt.py +27 -0
  45. jolt/pkgs/fstree.py +20 -0
  46. jolt/pkgs/gflags.py +18 -0
  47. jolt/pkgs/glib.py +18 -0
  48. jolt/pkgs/glog.py +25 -0
  49. jolt/pkgs/glslang.py +21 -0
  50. jolt/pkgs/golang.py +16 -11
  51. jolt/pkgs/googlebenchmark.py +18 -0
  52. jolt/pkgs/googletest.py +46 -0
  53. jolt/pkgs/gperf.py +15 -0
  54. jolt/pkgs/grpc.py +73 -0
  55. jolt/pkgs/hdf5.py +19 -0
  56. jolt/pkgs/help2man.py +14 -0
  57. jolt/pkgs/inja.py +28 -0
  58. jolt/pkgs/jsoncpp.py +31 -0
  59. jolt/pkgs/libarchive.py +43 -0
  60. jolt/pkgs/libcap.py +44 -0
  61. jolt/pkgs/libdrm.py +44 -0
  62. jolt/pkgs/libedit.py +42 -0
  63. jolt/pkgs/libevent.py +31 -0
  64. jolt/pkgs/libexpat.py +27 -0
  65. jolt/pkgs/libfastjson.py +21 -0
  66. jolt/pkgs/libffi.py +16 -0
  67. jolt/pkgs/libglvnd.py +30 -0
  68. jolt/pkgs/libogg.py +28 -0
  69. jolt/pkgs/libpciaccess.py +18 -0
  70. jolt/pkgs/libseccomp.py +21 -0
  71. jolt/pkgs/libtirpc.py +24 -0
  72. jolt/pkgs/libtool.py +42 -0
  73. jolt/pkgs/libunwind.py +35 -0
  74. jolt/pkgs/libva.py +18 -0
  75. jolt/pkgs/libvorbis.py +33 -0
  76. jolt/pkgs/libxml2.py +35 -0
  77. jolt/pkgs/libxslt.py +17 -0
  78. jolt/pkgs/libyajl.py +16 -0
  79. jolt/pkgs/llvm.py +81 -0
  80. jolt/pkgs/lua.py +54 -0
  81. jolt/pkgs/lz4.py +26 -0
  82. jolt/pkgs/m4.py +14 -0
  83. jolt/pkgs/make.py +17 -0
  84. jolt/pkgs/mesa.py +81 -0
  85. jolt/pkgs/meson.py +17 -0
  86. jolt/pkgs/mstch.py +28 -0
  87. jolt/pkgs/mysql.py +60 -0
  88. jolt/pkgs/nasm.py +49 -0
  89. jolt/pkgs/ncurses.py +30 -0
  90. jolt/pkgs/ng_log.py +25 -0
  91. jolt/pkgs/ninja.py +45 -0
  92. jolt/pkgs/nlohmann_json.py +25 -0
  93. jolt/pkgs/nodejs.py +19 -11
  94. jolt/pkgs/opencv.py +24 -0
  95. jolt/pkgs/openjdk.py +26 -0
  96. jolt/pkgs/openssl.py +103 -0
  97. jolt/pkgs/paho.py +76 -0
  98. jolt/pkgs/patchelf.py +16 -0
  99. jolt/pkgs/perl.py +42 -0
  100. jolt/pkgs/pkgconfig.py +64 -0
  101. jolt/pkgs/poco.py +39 -0
  102. jolt/pkgs/protobuf.py +77 -0
  103. jolt/pkgs/pugixml.py +27 -0
  104. jolt/pkgs/python.py +19 -0
  105. jolt/pkgs/qt.py +35 -0
  106. jolt/pkgs/rapidjson.py +26 -0
  107. jolt/pkgs/rapidyaml.py +28 -0
  108. jolt/pkgs/re2.py +30 -0
  109. jolt/pkgs/re2c.py +17 -0
  110. jolt/pkgs/readline.py +15 -0
  111. jolt/pkgs/rust.py +41 -0
  112. jolt/pkgs/sdl.py +28 -0
  113. jolt/pkgs/simdjson.py +27 -0
  114. jolt/pkgs/soci.py +46 -0
  115. jolt/pkgs/spdlog.py +29 -0
  116. jolt/pkgs/spirv_llvm.py +21 -0
  117. jolt/pkgs/spirv_tools.py +24 -0
  118. jolt/pkgs/sqlite.py +83 -0
  119. jolt/pkgs/ssl.py +12 -0
  120. jolt/pkgs/texinfo.py +15 -0
  121. jolt/pkgs/tomlplusplus.py +22 -0
  122. jolt/pkgs/wayland.py +26 -0
  123. jolt/pkgs/x11.py +58 -0
  124. jolt/pkgs/xerces_c.py +20 -0
  125. jolt/pkgs/xorg.py +360 -0
  126. jolt/pkgs/xz.py +29 -0
  127. jolt/pkgs/yamlcpp.py +30 -0
  128. jolt/pkgs/zeromq.py +47 -0
  129. jolt/pkgs/zlib.py +87 -0
  130. jolt/pkgs/zstd.py +33 -0
  131. jolt/plugins/alias.py +3 -0
  132. jolt/plugins/allure.py +5 -2
  133. jolt/plugins/autotools.py +66 -0
  134. jolt/plugins/cache.py +133 -0
  135. jolt/plugins/cmake.py +74 -6
  136. jolt/plugins/conan.py +238 -0
  137. jolt/plugins/cxx.py +698 -0
  138. jolt/plugins/cxxinfo.py +7 -0
  139. jolt/plugins/dashboard.py +1 -1
  140. jolt/plugins/docker.py +80 -23
  141. jolt/plugins/email.py +2 -2
  142. jolt/plugins/email.xslt +144 -101
  143. jolt/plugins/environ.py +11 -0
  144. jolt/plugins/fetch.py +141 -0
  145. jolt/plugins/gdb.py +39 -19
  146. jolt/plugins/gerrit.py +1 -14
  147. jolt/plugins/git.py +283 -85
  148. jolt/plugins/googletest.py +2 -1
  149. jolt/plugins/http.py +36 -38
  150. jolt/plugins/libtool.py +63 -0
  151. jolt/plugins/linux.py +990 -0
  152. jolt/plugins/logstash.py +4 -4
  153. jolt/plugins/meson.py +61 -0
  154. jolt/plugins/ninja-compdb.py +99 -30
  155. jolt/plugins/ninja.py +468 -166
  156. jolt/plugins/paths.py +11 -1
  157. jolt/plugins/pkgconfig.py +219 -0
  158. jolt/plugins/podman.py +136 -92
  159. jolt/plugins/python.py +137 -0
  160. jolt/plugins/remote_execution/__init__.py +0 -0
  161. jolt/plugins/remote_execution/administration_pb2.py +46 -0
  162. jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
  163. jolt/plugins/remote_execution/log_pb2.py +32 -0
  164. jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
  165. jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
  166. jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
  167. jolt/plugins/remote_execution/worker_pb2.py +38 -0
  168. jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
  169. jolt/plugins/report.py +12 -2
  170. jolt/plugins/rust.py +25 -0
  171. jolt/plugins/scheduler.py +710 -0
  172. jolt/plugins/selfdeploy/setup.py +8 -4
  173. jolt/plugins/selfdeploy.py +138 -88
  174. jolt/plugins/strings.py +35 -22
  175. jolt/plugins/symlinks.py +26 -11
  176. jolt/plugins/telemetry.py +5 -2
  177. jolt/plugins/timeline.py +13 -3
  178. jolt/plugins/volume.py +46 -48
  179. jolt/scheduler.py +589 -192
  180. jolt/tasks.py +625 -121
  181. jolt/templates/timeline.html.template +44 -47
  182. jolt/timer.py +22 -0
  183. jolt/tools.py +638 -282
  184. jolt/utils.py +211 -7
  185. jolt/version.py +1 -1
  186. jolt/xmldom.py +12 -2
  187. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/METADATA +97 -38
  188. jolt-0.9.435.dist-info/RECORD +207 -0
  189. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/WHEEL +1 -1
  190. jolt/plugins/amqp.py +0 -834
  191. jolt/plugins/debian.py +0 -338
  192. jolt/plugins/ftp.py +0 -181
  193. jolt/plugins/repo.py +0 -253
  194. jolt-0.9.123.dist-info/RECORD +0 -77
  195. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/entry_points.txt +0 -0
  196. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/top_level.txt +0 -0
jolt/common_pb2.py ADDED
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: jolt/common.proto
4
+ """Generated protocol buffer code."""
5
+ from google.protobuf import descriptor as _descriptor
6
+ from google.protobuf import descriptor_pool as _descriptor_pool
7
+ from google.protobuf import symbol_database as _symbol_database
8
+ from google.protobuf.internal import builder as _builder
9
+ # @@protoc_insertion_point(imports)
10
+
11
+ _sym_db = _symbol_database.Default()
12
+
13
+
14
+ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11jolt/common.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"-\n\x06\x44igest\x12\x16\n\talgorithm\x18\x01 \x01(\tR\x03\x61lg\x12\x0b\n\x03hex\x18\x02 \x01(\t\"o\n\x07LogLine\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12(\n\x04time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x63ontext\x18\x03 \x01(\t\x12\x0f\n\x07message\x18\x04 \x01(\t\"&\n\x08Property\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\")\n\x08Platform\x12\x1d\n\nproperties\x18\x01 \x03(\x0b\x32\t.Property\"\x83\x01\n\x04Task\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x10\n\x08instance\x18\x03 \x01(\t\x12\r\n\x05taint\x18\x04 \x01(\t\x12\x1d\n\nproperties\x18\x05 \x03(\x0b\x32\t.Property\x12\x1b\n\x08platform\x18\x06 \x01(\x0b\x32\t.Platform\"M\n\tTaskError\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x10\n\x08location\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\x12\x0f\n\x07\x64\x65tails\x18\x04 \x01(\t\"5\n\x04\x46ile\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0e\n\x06\x64igest\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\"\xf1\x01\n\x07Project\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\"\n\x05paths\x18\x02 \x03(\x0b\x32\x13.Project.SystemPath\x12 \n\x07recipes\x18\x03 \x03(\x0b\x32\x0f.Project.Recipe\x12$\n\tresources\x18\x04 \x03(\x0b\x32\x11.Project.Resource\x1a\x1a\n\nSystemPath\x12\x0c\n\x04path\x18\x01 \x01(\t\x1a\'\n\x08Resource\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x61lias\x18\x02 \x01(\t\x1a\'\n\x06Recipe\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0f\n\x07workdir\x18\x03 \x01(\t\"\x8e\x01\n\tWorkspace\x12\x0f\n\x07rootdir\x18\x01 \x01(\t\x12\x10\n\x08\x63\x61\x63hedir\x18\x02 \x01(\t\x12\x14\n\x05\x66iles\x18\x03 \x03(\x0b\x32\x05.File\x12\x1a\n\x08projects\x18\x04 \x03(\x0b\x32\x08.Project\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x0c\n\x04tree\x18\x06 \x01(\t\x12\x10\n\x08\x62uilddir\x18\x07 \x01(\t\"i\n\x06\x43lient\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x0c\n\x04tree\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0b\n\x03url\x18\x04 \x01(\t\x12\x14\n\x0crequirements\x18\x05 \x03(\t\x12\x0b\n\x03nix\x18\x06 \x01(\x08\"\x99\x02\n\x10\x42uildEnvironment\x12\x17\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x07.Client\x12\x1d\n\tworkspace\x18\x02 \x01(\x0b\x32\n.Workspace\x12\x1d\n\nparameters\x18\x03 \x03(\x0b\x32\t.Property\x12\x1f\n\x17task_default_parameters\x18\x04 \x03(\t\x12+\n\x05tasks\x18\x05 \x03(\x0b\x32\x1c.BuildEnvironment.TasksEntry\x12\x1b\n\x08loglevel\x18\x06 \x01(\x0e\x32\t.LogLevel\x12\x0e\n\x06\x63onfig\x18\x07 \x01(\t\x1a\x33\n\nTasksEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x14\n\x05value\x18\x02 \x01(\x0b\x32\x05.Task:\x02\x38\x01*k\n\x08LogLevel\x12\r\n\tEXCEPTION\x10\x00\x12\t\n\x05\x44\x45\x42UG\x10\x01\x12\x0b\n\x07VERBOSE\x10\x02\x12\n\n\x06STDOUT\x10\x03\x12\x08\n\x04INFO\x10\x04\x12\x0b\n\x07WARNING\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\n\n\x06STDERR\x10\x07*_\n\x0b\x42uildStatus\x12\x12\n\x0e\x42UILD_ACCEPTED\x10\x00\x12\x12\n\x0e\x42UILD_REJECTED\x10\x01\x12\x13\n\x0f\x42UILD_COMPLETED\x10\x03\x12\x13\n\x0f\x42UILD_CANCELLED\x10\x04*\xd4\x01\n\nTaskStatus\x12\x0f\n\x0bTASK_QUEUED\x10\x00\x12\x10\n\x0cTASK_RUNNING\x10\x01\x12\x0f\n\x0bTASK_FAILED\x10\x02\x12\x0f\n\x0bTASK_PASSED\x10\x03\x12\x11\n\rTASK_UNSTABLE\x10\x04\x12\x13\n\x0fTASK_DOWNLOADED\x10\x05\x12\x11\n\rTASK_UPLOADED\x10\x06\x12\x10\n\x0cTASK_SKIPPED\x10\x07\x12\x12\n\x0eTASK_CANCELLED\x10\x08\x12\x0e\n\nTASK_ERROR\x10\t\x12\x10\n\x0cTASK_CREATED\x10\nB\x0eZ\x0cpkg/protocolb\x06proto3')
18
+
19
+ _globals = globals()
20
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'jolt.common_pb2', _globals)
22
+ if _descriptor._USE_C_DESCRIPTORS == False:
23
+ _globals['DESCRIPTOR']._options = None
24
+ _globals['DESCRIPTOR']._serialized_options = b'Z\014pkg/protocol'
25
+ _globals['_BUILDENVIRONMENT_TASKSENTRY']._options = None
26
+ _globals['_BUILDENVIRONMENT_TASKSENTRY']._serialized_options = b'8\001'
27
+ _globals['_LOGLEVEL']._serialized_start=1345
28
+ _globals['_LOGLEVEL']._serialized_end=1452
29
+ _globals['_BUILDSTATUS']._serialized_start=1454
30
+ _globals['_BUILDSTATUS']._serialized_end=1549
31
+ _globals['_TASKSTATUS']._serialized_start=1552
32
+ _globals['_TASKSTATUS']._serialized_end=1764
33
+ _globals['_DIGEST']._serialized_start=54
34
+ _globals['_DIGEST']._serialized_end=99
35
+ _globals['_LOGLINE']._serialized_start=101
36
+ _globals['_LOGLINE']._serialized_end=212
37
+ _globals['_PROPERTY']._serialized_start=214
38
+ _globals['_PROPERTY']._serialized_end=252
39
+ _globals['_PLATFORM']._serialized_start=254
40
+ _globals['_PLATFORM']._serialized_end=295
41
+ _globals['_TASK']._serialized_start=298
42
+ _globals['_TASK']._serialized_end=429
43
+ _globals['_TASKERROR']._serialized_start=431
44
+ _globals['_TASKERROR']._serialized_end=508
45
+ _globals['_FILE']._serialized_start=510
46
+ _globals['_FILE']._serialized_end=563
47
+ _globals['_PROJECT']._serialized_start=566
48
+ _globals['_PROJECT']._serialized_end=807
49
+ _globals['_PROJECT_SYSTEMPATH']._serialized_start=699
50
+ _globals['_PROJECT_SYSTEMPATH']._serialized_end=725
51
+ _globals['_PROJECT_RESOURCE']._serialized_start=727
52
+ _globals['_PROJECT_RESOURCE']._serialized_end=766
53
+ _globals['_PROJECT_RECIPE']._serialized_start=768
54
+ _globals['_PROJECT_RECIPE']._serialized_end=807
55
+ _globals['_WORKSPACE']._serialized_start=810
56
+ _globals['_WORKSPACE']._serialized_end=952
57
+ _globals['_CLIENT']._serialized_start=954
58
+ _globals['_CLIENT']._serialized_end=1059
59
+ _globals['_BUILDENVIRONMENT']._serialized_start=1062
60
+ _globals['_BUILDENVIRONMENT']._serialized_end=1343
61
+ _globals['_BUILDENVIRONMENT_TASKSENTRY']._serialized_start=1292
62
+ _globals['_BUILDENVIRONMENT_TASKSENTRY']._serialized_end=1343
63
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,4 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
jolt/config.py CHANGED
@@ -1,10 +1,12 @@
1
1
  from configparser import ConfigParser, NoOptionError, NoSectionError
2
+ from urllib.parse import urlparse
2
3
  import os
4
+ import re
3
5
 
6
+ from jolt import common_pb2 as common_pb
4
7
  from jolt import filesystem as fs
5
8
  from jolt import utils
6
9
  from jolt.error import raise_error_if
7
- from jolt.manifest import ManifestExtension, ManifestExtensionRegistry
8
10
 
9
11
 
10
12
  _workdir = os.getcwd()
@@ -13,13 +15,18 @@ _workdir = os.getcwd()
13
15
  if os.getenv("JOLT_CONFIG_PATH"):
14
16
  location = fs.path.join(os.getenv("JOLT_CONFIG_PATH"), "config")
15
17
  location_user = fs.path.join(os.getenv("JOLT_CONFIG_PATH"), "user")
18
+ location_overlay = os.getenv("JOLT_CONFIG_OVERLAY")
19
+ if location_overlay:
20
+ location_overlay = fs.path.join(os.getenv("JOLT_CONFIG_PATH"), location_overlay)
16
21
  elif os.name == "nt":
17
22
  appdata = os.getenv("APPDATA", fs.path.join(fs.userhome(), "AppData", "Roaming"))
18
23
  location = fs.path.join(appdata, "Jolt", "config")
19
24
  location_user = fs.path.join(appdata, "Jolt", "user")
25
+ location_overlay = os.getenv("JOLT_CONFIG_OVERLAY")
20
26
  else:
21
27
  location = fs.path.join(fs.userhome(), ".config", "jolt", "config")
22
28
  location_user = fs.path.join(fs.userhome(), ".config", "jolt", "user")
29
+ location_overlay = os.getenv("JOLT_CONFIG_OVERLAY")
23
30
 
24
31
 
25
32
  class ConfigFile(ConfigParser):
@@ -37,10 +44,10 @@ class ConfigFile(ConfigParser):
37
44
  if not self.has_section("jolt"):
38
45
  self.add_section("jolt")
39
46
 
40
- def save(self):
41
- if self._location is None:
47
+ def save(self, path=None):
48
+ if self._location is None and path is None:
42
49
  return
43
- with open(self._location, 'w') as configfile:
50
+ with open(path or self._location, 'w') as configfile:
44
51
  super().write(configfile)
45
52
 
46
53
  def delete(self, section, key):
@@ -122,14 +129,16 @@ class Config(object):
122
129
  for config in self.configs():
123
130
  config.load()
124
131
 
125
- def save(self):
126
- for config in self.configs():
127
- config.save()
132
+ def save(self, path=None):
133
+ for name, config in self._configs:
134
+ config.save(os.path.join(path, f"{name}.conf") if path else None)
128
135
 
129
136
 
130
137
  _config = Config()
131
138
  _config.add_file("global", location)
132
139
  _config.add_file("user", location_user)
140
+ if location_overlay:
141
+ _config.add_file("overlay", location_overlay)
133
142
  _manifest = _config.add_file("manifest", None)
134
143
  # Note: cli configs are added next to last in the chain,
135
144
  # before manifest, and can therefore not override the
@@ -144,30 +153,51 @@ def get(section, key, default=None, expand=True, alias=None):
144
153
 
145
154
 
146
155
  def getint(section, key, default=None, alias=None):
147
- return int(get(section, key, default=default, alias=alias))
156
+ value = get(section, key, default=default, alias=alias)
157
+ if value is not None:
158
+ try:
159
+ return int(value)
160
+ except ValueError:
161
+ raise_error_if(True, "Config: value '{0}' invalid for '{1}.{2}', expected integer", value, section, key)
162
+ return None
148
163
 
149
164
 
150
165
  def getsize(section, key, default=None, alias=None):
151
- units = {"B": 1, "K": 1024, "M": 1024**2, "G": 1024**3, "T": 1024**4}
166
+ units = {
167
+ None: 1,
168
+ "B": 1,
169
+
170
+ "K": 1000,
171
+ "M": 1000**2,
172
+ "G": 1000**3,
173
+ "T": 1000**4,
174
+ "P": 1000**5,
175
+ "E": 1000**6,
176
+
177
+ "Ki": 1024,
178
+ "Mi": 1024**2,
179
+ "Gi": 1024**3,
180
+ "Ti": 1024**4,
181
+ "Pi": 1024**5,
182
+ "Ei": 1024**6,
183
+ }
184
+
152
185
  value = get(section, key, default=None, alias=alias)
153
186
  if value is None:
154
187
  if type(default) is int:
155
188
  return default
156
189
  else:
157
190
  value = str(default)
158
- value = value.strip()
159
- value = value.split()
160
- if len(value) == 1 and value[0][-1] in units:
161
- size, unit = value[0][:-1], value[0][-1]
162
- else:
163
- raise_error_if(
164
- len(value) != 2,
165
- "Config: size '{2}' invalid for '{0}.{1}', expected '<size> <unit>'", value, section, key)
166
- size, unit = value[0], value[1]
191
+
192
+ m = re.search(r"^(0|[1-9][0-9]*) ?([KMGTPE]i?)?B?$", value)
193
+ raise_error_if(
194
+ not m,
195
+ "Config: size '{0}' invalid for '{1}.{2}', expected '<size> <unit>'", value, section, key)
167
196
  raise_error_if(
168
- unit not in units,
169
- "Config: unit invalid for '{0}.{1}', expected [B,K,M,G,T]", section, key)
170
- return int(size) * units[unit]
197
+ m[2] not in units,
198
+ "Config: unit invalid for '{0}.{1}', expected [B,K,M,G,T,P,E,Mi,Gi,Ti,Pi,Ei]", section, key)
199
+
200
+ return int(m[1]) * units.get(m[2], 1)
171
201
 
172
202
 
173
203
  def getfloat(section, key, default=None, alias=None):
@@ -179,6 +209,13 @@ def getboolean(section, key, default=None, alias=None):
179
209
  return value is not None and str(value).lower() in ["true", "yes", "on", "1"]
180
210
 
181
211
 
212
+ def geturi(section, key, default=None, alias=None):
213
+ value = get(section, key, default=default, alias=alias)
214
+ if value is None:
215
+ return None
216
+ return urlparse(value)
217
+
218
+
182
219
  def get_jolthome():
183
220
  if os.name == "nt":
184
221
  return fs.path.join(os.getenv("LOCALAPPDATA", fs.path.join(fs.userhome(), "AppData", "Local")), "Jolt")
@@ -187,7 +224,7 @@ def get_jolthome():
187
224
 
188
225
 
189
226
  def get_logpath():
190
- return get_jolthome()
227
+ return get("jolt", "logpath", get_jolthome())
191
228
 
192
229
 
193
230
  def get_cachedir():
@@ -209,6 +246,23 @@ def get_shell():
209
246
  return get("jolt", "shell", cmd)
210
247
 
211
248
 
249
+ def get_keep_going():
250
+ return getboolean("params", "keep_going", False)
251
+
252
+
253
+ def is_incremental_build():
254
+ """
255
+ Whether to enable incremental builds.
256
+
257
+ If disabled, all build directories are deleted upon completion of tasks.
258
+ """
259
+ return getboolean("jolt", "incremental_dirs", True)
260
+
261
+
262
+ def set_keep_going(value=False):
263
+ return set("params", "keep_going", str(value).lower())
264
+
265
+
212
266
  def set(section, key, value, alias=None):
213
267
  _config.set(section, key, value, alias or "user")
214
268
 
@@ -229,8 +283,8 @@ def load_or_set(file_or_str):
229
283
  _config.set(section_key[0], section_key[1], key_value[1], alias="cli")
230
284
 
231
285
 
232
- def save():
233
- _config.save()
286
+ def save(path=None):
287
+ _config.save(path)
234
288
 
235
289
 
236
290
  def delete(key, alias=None):
@@ -263,25 +317,28 @@ def split(string):
263
317
  return section, key
264
318
 
265
319
 
266
- class ConfigExtension(ManifestExtension):
267
- def export_manifest(self, manifest, task):
268
- manifest.config = get("network", "config", "", expand=False)
320
+ def import_config(snippet: str):
321
+ """ Apply extra configuration for the worker, provided by the client. """
322
+ _manifest.read_string(snippet)
323
+ from jolt.loader import JoltLoader
324
+ JoltLoader.get().load_plugins()
325
+
269
326
 
270
- for key, value in options("params"):
271
- p = manifest.create_parameter()
272
- p.key = "config." + key
273
- p.value = value
327
+ def export_config():
328
+ """ Get extra configuration for the worker. """
329
+ return get("network", "config", "", expand=False)
274
330
 
275
- def import_manifest(self, manifest):
276
- if manifest.config:
277
- _manifest.read_string(manifest.config)
278
- from jolt.loader import JoltLoader
279
- JoltLoader.get().load_plugins()
280
331
 
281
- for param in manifest.parameters:
282
- if param.key.startswith("config."):
283
- set("params", param.key.split(".", 1)[1], param.value)
332
+ def import_params(params: dict):
333
+ """ Apply user-defined parameters (-c params.key=value). """
334
+ for key, value in params.items():
335
+ if key.startswith("config."):
336
+ set("params", key.split(".", 1)[1], value)
284
337
 
285
338
 
286
- # High priority so that plugins are loaded before resources are acquired.
287
- ManifestExtensionRegistry.add(ConfigExtension(), -10)
339
+ def export_params():
340
+ """ Get user-defined parameters (-c params.key=value). """
341
+ parameters = []
342
+ for key, value in options("params"):
343
+ parameters.append(common_pb.Property(key="config." + key, value=value))
344
+ return parameters
jolt/error.py CHANGED
@@ -4,17 +4,30 @@ from jolt import utils
4
4
 
5
5
  class JoltError(Exception):
6
6
  def __init__(self, *args, **kwargs):
7
- super(JoltError, self).__init__(*args, **kwargs)
7
+ super().__init__(*args, **kwargs)
8
8
 
9
9
 
10
10
  class JoltCommandError(JoltError):
11
11
  def __init__(self, what, stdout=[], stderr=[], returncode=None, *args, **kwargs):
12
- super(JoltCommandError, self).__init__(what, *args, **kwargs)
12
+ super().__init__(what, *args, **kwargs)
13
13
  self.stdout = stdout
14
14
  self.stderr = stderr
15
15
  self.returncode = returncode
16
16
 
17
17
 
18
+ class JoltTimeoutError(JoltError):
19
+ def __init__(self, *args, **kwargs):
20
+ super().__init__(*args, **kwargs)
21
+
22
+ def __str__(self):
23
+ return super().__str__() or "Timeout"
24
+
25
+
26
+ class LoggedJoltError(JoltError):
27
+ def __init__(self, exc):
28
+ self.exc = exc
29
+
30
+
18
31
  def raise_error(msg, *args, **kwargs):
19
32
  raise JoltError(msg.format(*args, **kwargs))
20
33
 
@@ -23,8 +36,10 @@ def raise_task_error(task, msg, *args, **kwargs):
23
36
  if task:
24
37
  with utils.ignore_exception():
25
38
  with task.report() as report:
26
- report.add_error("Error", inspection.getfile(task.__class__),
27
- msg.format(*args, **kwargs))
39
+ report.add_error(
40
+ kwargs.pop("type", "Error"),
41
+ inspection.getfile(task.__class__),
42
+ msg.format(*args, **kwargs))
28
43
  raise_error(msg + " (" + str(task) + ")", *args, **kwargs)
29
44
  else:
30
45
  raise_error(msg, *args, **kwargs)
jolt/filesystem.py CHANGED
@@ -88,10 +88,10 @@ def move(src, dst):
88
88
 
89
89
  def onerror_warning(func, path, exc_info):
90
90
  from jolt import log
91
- if type(exc_info[1]) is OSError:
91
+ if hasattr(exc_info[1], "strerror"):
92
92
  msg = exc_info[1].strerror
93
93
  else:
94
- msg = "Reason unknown"
94
+ msg = "Reason unknown: " + str(exc_info[1])
95
95
  if os.path.exists(path):
96
96
  log.warning("Could not remove file or directory: {} ({})", path, msg)
97
97
 
@@ -238,7 +238,3 @@ def scandir(scanpath, filterfn=lambda path: path[0] != ".", relative=False):
238
238
  for path, dirs, files in os.walk(scanpath)
239
239
  for f in files
240
240
  if filterfn(f)]
241
-
242
-
243
- def get_archive(path):
244
- return path + ".tar.gz"