tebako-runtime 0.7.0 → 0.8.1
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.
- checksums.yaml +4 -4
- data/lib/cert/cacert.pem.mozilla +144 -876
- data/lib/tebako-runtime/adapters/jing.rb +24 -0
- data/lib/tebako-runtime/adapters/mn2pdf.rb +47 -0
- data/lib/tebako-runtime/memfs.rb +50 -1
- data/lib/tebako-runtime/pre/excavate.rb +4 -1
- data/lib/tebako-runtime/pre/seven-zip.rb +14 -9
- data/lib/tebako-runtime/version.rb +1 -1
- metadata +3 -3
|
@@ -36,9 +36,33 @@ class Jing
|
|
|
36
36
|
|
|
37
37
|
def initialize(schema, options = nil)
|
|
38
38
|
original_initialize(TebakoRuntime.extract_memfs(schema, wild: true), options)
|
|
39
|
+
# ruby-jing captures `:default => DEFAULT_JAR` at class-load time —
|
|
40
|
+
# before this adapter replaced the constant with the extracted host
|
|
41
|
+
# path. Force the extracted path per-instance (a nil option hash
|
|
42
|
+
# leaves @options empty, and the builder's stale default would win).
|
|
43
|
+
@options[:jar] = DEFAULT_JAR
|
|
44
|
+
# The mounted openjdk toolkit payload's java wins over PATH (the
|
|
45
|
+
# memfs-binary exec path; the bare "java" keeps the PATH answer).
|
|
46
|
+
@options[:java] = TebakoRuntime.mounted_exe("openjdk", "java")
|
|
39
47
|
end
|
|
40
48
|
|
|
41
49
|
def validate(xml)
|
|
42
50
|
original_validate(TebakoRuntime.extract_memfs(xml))
|
|
43
51
|
end
|
|
52
|
+
|
|
53
|
+
# The spawn shape, array form (the stock execute() backticks a shell
|
|
54
|
+
# string, which the tebako spawn hook deliberately skips; the mounted
|
|
55
|
+
# java only execs through the hook from an absolute-path array spawn).
|
|
56
|
+
def execute(options) # rubocop:disable Metrics/AbcSize
|
|
57
|
+
cmd = [options[:java]]
|
|
58
|
+
cmd += options[:java_opts].split if options[:java_opts]
|
|
59
|
+
cmd += ["-jar", options[:jar].to_s]
|
|
60
|
+
cmd << "-c" if options[:compact]
|
|
61
|
+
cmd += ["-e", options[:encoding]] if options[:encoding]
|
|
62
|
+
cmd << "-i" if options[:id_check]
|
|
63
|
+
cmd += [options[:schema].to_s, options[:xmlfile].to_s]
|
|
64
|
+
IO.popen(cmd, err: %i[child out], &:read)
|
|
65
|
+
rescue SystemCallError => e
|
|
66
|
+
raise ExecutionError, "jing execution failed: #{e}"
|
|
67
|
+
end
|
|
44
68
|
end
|
|
@@ -55,3 +55,50 @@ module Mn2pdf
|
|
|
55
55
|
options)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
# The java resolution + the spawn shape (the memfs-binary exec path):
|
|
60
|
+
# when the openjdk toolkit payload is mounted, its /opt/openjdk/bin/java
|
|
61
|
+
# wins over PATH; the spawn is the ARRAY form — the shell form
|
|
62
|
+
# (`Open3.capture3(string)`) goes through /bin/sh, which the tebako
|
|
63
|
+
# spawn hook deliberately skips.
|
|
64
|
+
module Jvm
|
|
65
|
+
singleton_class.send(:alias_method, :run_orig, :run)
|
|
66
|
+
singleton_class.send(:remove_method, :run)
|
|
67
|
+
|
|
68
|
+
def self.run(args = [])
|
|
69
|
+
java = TebakoRuntime.mounted_exe("openjdk", "java")
|
|
70
|
+
return run_orig(args) if java == "java"
|
|
71
|
+
|
|
72
|
+
# The stock form joins everything into a SHELL string: values ride
|
|
73
|
+
# shell-quoted (whole-value and inner forms), and legacy callers pass
|
|
74
|
+
# whole fragments in one element (`--param baseassetpath="/dir"`).
|
|
75
|
+
# The array spawn needs shell-word rules applied — split on unquoted
|
|
76
|
+
# spaces, shed the quotes — exactly what the shell did with the
|
|
77
|
+
# stock string.
|
|
78
|
+
clean = args.flat_map { |a| TebakoRuntime.shell_split(a.to_s) }
|
|
79
|
+
cmd = [java, *options, "-jar", MN2PDF_JAR_PATH.to_s, *clean]
|
|
80
|
+
puts cmd.join(" ")
|
|
81
|
+
Open3.capture3(*cmd).then { |stdout, stderr, status| [stdout, stderr, status] }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# options_to_cmd's joined form (`--param "k=v"` in ONE shell word) is
|
|
86
|
+
# shell-string machinery; the array spawn takes flag and value as
|
|
87
|
+
# separate elements with the shell quotes removed. Stock behavior
|
|
88
|
+
# stands for the PATH java.
|
|
89
|
+
module Mn2pdf
|
|
90
|
+
singleton_class.send(:alias_method, :options_to_cmd_orig, :options_to_cmd)
|
|
91
|
+
singleton_class.send(:remove_method, :options_to_cmd)
|
|
92
|
+
|
|
93
|
+
def self.options_to_cmd(options, cmd)
|
|
94
|
+
return options_to_cmd_orig(options, cmd) if TebakoRuntime.mounted_exe("openjdk", "java") == "java"
|
|
95
|
+
|
|
96
|
+
options.each do |k, v|
|
|
97
|
+
if k.to_s.end_with?("=")
|
|
98
|
+
cmd << "#{k}#{v.to_s.delete('"')}"
|
|
99
|
+
else
|
|
100
|
+
cmd << k.to_s << v.to_s.delete('"')
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/tebako-runtime/memfs.rb
CHANGED
|
@@ -29,12 +29,38 @@ require "fileutils"
|
|
|
29
29
|
require "pathname"
|
|
30
30
|
require "rubygems"
|
|
31
31
|
require "tempfile"
|
|
32
|
+
require "fiddle"
|
|
32
33
|
|
|
33
34
|
require_relative "string"
|
|
34
35
|
|
|
35
36
|
# Module TebakoRuntime
|
|
36
37
|
# Methods to extract files from memfs to temporary folder
|
|
37
38
|
module TebakoRuntime
|
|
39
|
+
# The v2 multi-mount world: an extractable path is one HELD by the TFS
|
|
40
|
+
# mounts (the env image at COMPILER_MEMFS, payloads at their declared
|
|
41
|
+
# points) — the compiled-in prefix can no longer express it. The
|
|
42
|
+
# runtime executable's own tebako_fs_stat is the discriminator: it
|
|
43
|
+
# answers only mounted content (0); host paths (and jail-denied ones)
|
|
44
|
+
# answer otherwise. Fiddle::Handle::DEFAULT addresses the process
|
|
45
|
+
# image WITHOUT this gem's own fiddle adapter (dlopen(nil) routes
|
|
46
|
+
# through it and chokes on the nil).
|
|
47
|
+
MEMFS_STAT_FN = begin
|
|
48
|
+
Fiddle::Function.new(Fiddle::Handle::DEFAULT["tebako_fs_stat"],
|
|
49
|
+
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
|
50
|
+
rescue StandardError
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# struct stat is at most 512 bytes on every supported platform
|
|
55
|
+
# (darwin-arm64 and linux x86_64 use 144).
|
|
56
|
+
MEMFS_STAT_BUF = "\0".b * 512
|
|
57
|
+
|
|
58
|
+
def self.embedded_path?(path)
|
|
59
|
+
return path.start_with?(COMPILER_MEMFS) if MEMFS_STAT_FN.nil?
|
|
60
|
+
|
|
61
|
+
MEMFS_STAT_FN.call(path, MEMFS_STAT_BUF).zero? || path.start_with?(COMPILER_MEMFS)
|
|
62
|
+
end
|
|
63
|
+
|
|
38
64
|
def self.initialize_compiler_memfs_lib_cache
|
|
39
65
|
Pathname.new(Dir.mktmpdir("tebako-runtime-"))
|
|
40
66
|
rescue StandardError
|
|
@@ -64,13 +90,36 @@ module TebakoRuntime
|
|
|
64
90
|
def self.extract_memfs(file, wild: false, cache_path: COMPILER_MEMFS_LIB_CACHE)
|
|
65
91
|
is_quoted = file.quoted?
|
|
66
92
|
file = file.unquote if is_quoted
|
|
67
|
-
return is_quoted ? file.quote : file unless File.exist?(file) &&
|
|
93
|
+
return is_quoted ? file.quote : file unless File.exist?(file) && embedded_path?(file)
|
|
68
94
|
|
|
69
95
|
memfs_extracted_file = cache_path + File.basename(file)
|
|
70
96
|
extract(file, wild, cache_path) unless memfs_extracted_file.exist?
|
|
71
97
|
|
|
72
98
|
is_quoted ? memfs_extracted_file.to_path.quote : memfs_extracted_file.to_path
|
|
73
99
|
end
|
|
100
|
+
|
|
101
|
+
# The mounted-toolkit resolution (spec 03 §2.2): an executable the
|
|
102
|
+
# named toolkit payload provides at its declared mount. Returns the
|
|
103
|
+
# in-image absolute path when the mounts hold it (the spawn hook
|
|
104
|
+
# execs those through dlmap2file + the preload), the bare name
|
|
105
|
+
# otherwise (the consumer's PATH answer stands).
|
|
106
|
+
#
|
|
107
|
+
# TebakoRuntime.mounted_exe("openjdk", "java")
|
|
108
|
+
# # => "/opt/openjdk/bin/java" when the openjdk payload is mounted,
|
|
109
|
+
# else "java"
|
|
110
|
+
def self.mounted_exe(toolkit, name)
|
|
111
|
+
mounted = "/opt/#{toolkit}/bin/#{name}"
|
|
112
|
+
embedded_path?(mounted) ? mounted : name
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Shell-word split for the array spawn (the memfs-binary exec path):
|
|
116
|
+
# legacy adapters compose arguments as a SHELL fragment in ONE element
|
|
117
|
+
# (`--param baseassetpath="/dir"`), and shell-quoted whole values ride
|
|
118
|
+
# as single elements. Split on unquoted spaces, then shed the quotes —
|
|
119
|
+
# exactly the shell's own word rules (a quoted space never splits).
|
|
120
|
+
def self.shell_split(word)
|
|
121
|
+
word.scan(/"([^"]*)"|(\S+)/).map { |quoted, bare| quoted || bare }
|
|
122
|
+
end
|
|
74
123
|
end
|
|
75
124
|
|
|
76
125
|
at_exit do
|
|
@@ -28,4 +28,7 @@
|
|
|
28
28
|
# For some reason on Windows an attempt to require "seven_zip_ruby" from excavate fails
|
|
29
29
|
# I cannot debug it effectively because of https://github.com/tamatebako/tebako/issues/119
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
# Only legacy excavate loads seven_zip_ruby; omnizip-era excavate has no
|
|
32
|
+
# seven-zip gem at all — wiring it then would crash the require chain
|
|
33
|
+
# with Gem::MissingSpecError (metanorma dogfood, 2026-08-11).
|
|
34
|
+
require "seven_zip_ruby" if Gem::Specification.find_all_by_name("seven-zip").any?
|
|
@@ -28,15 +28,20 @@
|
|
|
28
28
|
require_relative "../memfs"
|
|
29
29
|
require_relative "../../tebako-runtime"
|
|
30
30
|
|
|
31
|
-
# Fix path for 7zip load
|
|
31
|
+
# Fix path for 7zip load.
|
|
32
|
+
# Legacy-excavate only: omnizip-era excavate ships no seven-zip gem —
|
|
33
|
+
# when it is absent there is nothing to excavate, so the hook is a
|
|
34
|
+
# no-op (never a Gem::MissingSpecError — metanorma dogfood, 2026-08-11).
|
|
32
35
|
module TebakoRuntime
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
if Gem::Specification.find_all_by_name("seven-zip").any?
|
|
37
|
+
sevenz_lib = RUBY_PLATFORM.downcase.match(/mswin|mingw/) ? "7z*.dll" : "7z.so"
|
|
38
|
+
sevenz_path = File.join(full_gem_path("seven-zip"), "lib", "seven_zip_ruby", sevenz_lib)
|
|
39
|
+
sevenz_paths = Dir.glob(sevenz_path)
|
|
40
|
+
sevenz_new_folder = COMPILER_MEMFS_LIB_CACHE / "seven_zip_ruby"
|
|
41
|
+
FileUtils.mkdir_p(sevenz_new_folder)
|
|
42
|
+
sevenz_paths.each do |file|
|
|
43
|
+
FileUtils.cp(file, sevenz_new_folder)
|
|
44
|
+
end
|
|
45
|
+
$LOAD_PATH.unshift(COMPILER_MEMFS_LIB_CACHE.to_s)
|
|
40
46
|
end
|
|
41
|
-
$LOAD_PATH.unshift(COMPILER_MEMFS_LIB_CACHE.to_s)
|
|
42
47
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tebako-runtime
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rspec
|
|
@@ -243,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
243
243
|
- !ruby/object:Gem::Version
|
|
244
244
|
version: '0'
|
|
245
245
|
requirements: []
|
|
246
|
-
rubygems_version: 3.6.
|
|
246
|
+
rubygems_version: 3.6.9
|
|
247
247
|
specification_version: 4
|
|
248
248
|
summary: Run-time support of tebako executable packager
|
|
249
249
|
test_files: []
|