rubygems-update 3.4.5 → 3.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1115 -1095
- data/Manifest.txt +5 -5
- data/bundler/CHANGELOG.md +12 -0
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/cli/binstubs.rb +5 -1
- data/bundler/lib/bundler/inline.rb +6 -8
- data/bundler/lib/bundler/installer/standalone.rb +11 -7
- data/bundler/lib/bundler/rubygems_integration.rb +8 -4
- data/bundler/lib/bundler/version.rb +1 -1
- data/lib/rubygems/core_ext/kernel_require.rb +113 -109
- data/lib/rubygems/ext/builder.rb +1 -2
- data/lib/rubygems/ext/cargo_builder.rb +129 -89
- data/lib/rubygems/specification_policy.rb +1 -1
- data/lib/rubygems.rb +11 -1
- data/rubygems-update.gemspec +1 -1
- data/test/rubygems/bundler_test_gem.rb +419 -0
- data/test/rubygems/test_gem.rb +0 -412
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +2 -4
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{Cargo.lock → ext/custom_name_lib/Cargo.lock} +0 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{Cargo.toml → ext/custom_name_lib/Cargo.toml} +0 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{src → ext/custom_name_lib/src}/lib.rs +1 -1
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb +1 -0
- data/test/rubygems/test_gem_ext_cargo_builder.rb +9 -16
- data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +5 -10
- metadata +8 -8
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +0 -21
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +0 -21
@@ -6,30 +6,60 @@
|
|
6
6
|
class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
7
7
|
attr_accessor :spec, :runner, :profile
|
8
8
|
|
9
|
-
def initialize
|
9
|
+
def initialize
|
10
10
|
require_relative "../command"
|
11
11
|
require_relative "cargo_builder/link_flag_converter"
|
12
12
|
|
13
|
-
@spec = spec
|
14
13
|
@runner = self.class.method(:run)
|
15
14
|
@profile = :release
|
16
15
|
end
|
17
16
|
|
18
|
-
def build(
|
17
|
+
def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
|
18
|
+
require "tempfile"
|
19
19
|
require "fileutils"
|
20
|
-
require "shellwords"
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
# Where's the Cargo.toml of the crate we're building
|
22
|
+
cargo_toml = File.join(cargo_dir, "Cargo.toml")
|
23
|
+
# What's the crate's name
|
24
|
+
crate_name = cargo_crate_name(cargo_dir, cargo_toml, results)
|
25
|
+
|
26
|
+
begin
|
27
|
+
# Create a tmp dir to do the build in
|
28
|
+
tmp_dest = Dir.mktmpdir(".gem.", cargo_dir)
|
29
|
+
|
30
|
+
# Run the build
|
31
|
+
cmd = cargo_command(cargo_toml, tmp_dest, args, crate_name)
|
32
|
+
runner.call(cmd, results, "cargo", cargo_dir, build_env)
|
33
|
+
|
34
|
+
# Where do we expect Cargo to write the compiled library
|
35
|
+
dylib_path = cargo_dylib_path(tmp_dest, crate_name)
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
37
|
+
# Helpful error if we didn't find the compiled library
|
38
|
+
raise DylibNotFoundError, tmp_dest unless File.exist?(dylib_path)
|
39
|
+
|
40
|
+
# Cargo and Ruby differ on how the library should be named, rename from
|
41
|
+
# what Cargo outputs to what Ruby expects
|
42
|
+
dlext_name = "#{crate_name}.#{makefile_config("DLEXT")}"
|
43
|
+
dlext_path = File.join(File.dirname(dylib_path), dlext_name)
|
44
|
+
FileUtils.cp(dylib_path, dlext_path)
|
45
|
+
|
46
|
+
nesting = extension_nesting(extension)
|
47
|
+
|
48
|
+
# TODO: remove in RubyGems 4
|
49
|
+
if Gem.install_extension_in_lib && lib_dir
|
50
|
+
nested_lib_dir = File.join(lib_dir, nesting)
|
51
|
+
FileUtils.mkdir_p nested_lib_dir
|
52
|
+
FileUtils.cp_r dlext_path, nested_lib_dir, remove_destination: true
|
53
|
+
end
|
54
|
+
|
55
|
+
# move to final destination
|
56
|
+
nested_dest_path = File.join(dest_path, nesting)
|
57
|
+
FileUtils.mkdir_p nested_dest_path
|
58
|
+
FileUtils.cp_r dlext_path, nested_dest_path, remove_destination: true
|
59
|
+
ensure
|
60
|
+
# clean up intermediary build artifacts
|
61
|
+
FileUtils.rm_rf tmp_dest if tmp_dest
|
62
|
+
end
|
33
63
|
|
34
64
|
results
|
35
65
|
end
|
@@ -42,39 +72,59 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
|
42
72
|
build_env
|
43
73
|
end
|
44
74
|
|
45
|
-
def cargo_command(
|
46
|
-
|
47
|
-
cargo = ENV.fetch("CARGO", "cargo")
|
75
|
+
def cargo_command(cargo_toml, dest_path, args = [], crate_name = nil)
|
76
|
+
require "shellwords"
|
48
77
|
|
49
78
|
cmd = []
|
50
79
|
cmd += [cargo, "rustc"]
|
51
80
|
cmd += ["--crate-type", "cdylib"]
|
52
81
|
cmd += ["--target", ENV["CARGO_BUILD_TARGET"]] if ENV["CARGO_BUILD_TARGET"]
|
53
82
|
cmd += ["--target-dir", dest_path]
|
54
|
-
cmd += ["--manifest-path",
|
83
|
+
cmd += ["--manifest-path", cargo_toml]
|
55
84
|
cmd += ["--lib"]
|
56
85
|
cmd += ["--profile", profile.to_s]
|
57
86
|
cmd += ["--locked"]
|
58
87
|
cmd += Gem::Command.build_args
|
59
88
|
cmd += args
|
60
89
|
cmd += ["--"]
|
61
|
-
cmd += [*cargo_rustc_args(dest_path)]
|
90
|
+
cmd += [*cargo_rustc_args(dest_path, crate_name)]
|
62
91
|
cmd
|
63
92
|
end
|
64
93
|
|
65
94
|
private
|
66
95
|
|
96
|
+
def cargo
|
97
|
+
ENV.fetch("CARGO", "cargo")
|
98
|
+
end
|
99
|
+
|
100
|
+
# returns the directory nesting of the extension, ignoring the first part, so
|
101
|
+
# "ext/foo/bar/Cargo.toml" becomes "foo/bar"
|
102
|
+
def extension_nesting(extension)
|
103
|
+
parts = extension.to_s.split(Regexp.union([File::SEPARATOR, File::ALT_SEPARATOR].compact))
|
104
|
+
|
105
|
+
parts = parts.each_with_object([]) do |segment, final|
|
106
|
+
next if segment == "."
|
107
|
+
if segment == ".."
|
108
|
+
raise Gem::InstallError, "extension outside of gem root" if final.empty?
|
109
|
+
next final.pop
|
110
|
+
end
|
111
|
+
final << segment
|
112
|
+
end
|
113
|
+
|
114
|
+
File.join(parts[1...-1])
|
115
|
+
end
|
116
|
+
|
67
117
|
def rb_config_env
|
68
118
|
result = {}
|
69
119
|
RbConfig::CONFIG.each {|k, v| result["RBCONFIG_#{k}"] = v }
|
70
120
|
result
|
71
121
|
end
|
72
122
|
|
73
|
-
def cargo_rustc_args(dest_dir)
|
123
|
+
def cargo_rustc_args(dest_dir, crate_name)
|
74
124
|
[
|
75
125
|
*linker_args,
|
76
126
|
*mkmf_libpath,
|
77
|
-
*rustc_dynamic_linker_flags(dest_dir),
|
127
|
+
*rustc_dynamic_linker_flags(dest_dir, crate_name),
|
78
128
|
*rustc_lib_flags(dest_dir),
|
79
129
|
*platform_specific_rustc_args(dest_dir),
|
80
130
|
]
|
@@ -134,42 +184,70 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
|
134
184
|
makefile_config("ENABLE_SHARED") == "no"
|
135
185
|
end
|
136
186
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
187
|
+
def cargo_dylib_path(dest_path, crate_name)
|
188
|
+
prefix = so_ext == "dll" ? "" : "lib"
|
189
|
+
path_parts = [dest_path]
|
190
|
+
path_parts << ENV["CARGO_BUILD_TARGET"] if ENV["CARGO_BUILD_TARGET"]
|
191
|
+
path_parts += ["release", "#{prefix}#{crate_name}.#{so_ext}"]
|
192
|
+
File.join(*path_parts)
|
142
193
|
end
|
143
194
|
|
144
|
-
def
|
145
|
-
|
195
|
+
def cargo_crate_name(cargo_dir, manifest_path, results)
|
196
|
+
require "open3"
|
197
|
+
Gem.load_yaml
|
146
198
|
|
147
|
-
|
199
|
+
output, status =
|
200
|
+
begin
|
201
|
+
Open3.capture2e(cargo, "metadata", "--no-deps", "--format-version", "1", :chdir => cargo_dir)
|
202
|
+
rescue => error
|
203
|
+
raise Gem::InstallError, "cargo metadata failed #{error.message}"
|
204
|
+
end
|
148
205
|
|
149
|
-
|
150
|
-
|
206
|
+
unless status.success?
|
207
|
+
if Gem.configuration.really_verbose
|
208
|
+
puts output
|
209
|
+
else
|
210
|
+
results << output
|
211
|
+
end
|
151
212
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
213
|
+
exit_reason =
|
214
|
+
if status.exited?
|
215
|
+
", exit code #{status.exitstatus}"
|
216
|
+
elsif status.signaled?
|
217
|
+
", uncaught signal #{status.termsig}"
|
218
|
+
end
|
157
219
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
220
|
+
raise Gem::InstallError, "cargo metadata failed#{exit_reason}"
|
221
|
+
end
|
222
|
+
|
223
|
+
# cargo metadata output is specified as json, but with the
|
224
|
+
# --format-version 1 option the output is compatible with YAML, so we can
|
225
|
+
# avoid the json dependency
|
226
|
+
metadata = Gem::SafeYAML.safe_load(output)
|
227
|
+
package = metadata["packages"].find {|pkg| normalize_path(pkg["manifest_path"]) == manifest_path }
|
228
|
+
unless package
|
229
|
+
found = metadata["packages"].map {|md| "#{md["name"]} at #{md["manifest_path"]}" }
|
230
|
+
raise Gem::InstallError, <<-EOF
|
231
|
+
failed to determine cargo package name
|
232
|
+
|
233
|
+
looking for: #{manifest_path}
|
234
|
+
|
235
|
+
found:
|
236
|
+
#{found.join("\n")}
|
237
|
+
EOF
|
238
|
+
end
|
239
|
+
package["name"].tr("-", "_")
|
164
240
|
end
|
165
241
|
|
166
|
-
def
|
167
|
-
|
242
|
+
def normalize_path(path)
|
243
|
+
return path unless File::ALT_SEPARATOR
|
244
|
+
|
245
|
+
path.tr(File::ALT_SEPARATOR, File::SEPARATOR)
|
168
246
|
end
|
169
247
|
|
170
|
-
def rustc_dynamic_linker_flags(dest_dir)
|
248
|
+
def rustc_dynamic_linker_flags(dest_dir, crate_name)
|
171
249
|
split_flags("DLDFLAGS")
|
172
|
-
.map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir) }
|
250
|
+
.map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir, crate_name) }
|
173
251
|
.compact
|
174
252
|
.flat_map {|arg| ldflag_to_link_modifier(arg) }
|
175
253
|
end
|
@@ -204,7 +282,7 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
|
204
282
|
end
|
205
283
|
|
206
284
|
# Interpolate substitution vars in the arg (i.e. $(DEFFILE))
|
207
|
-
def maybe_resolve_ldflag_variable(input_arg, dest_dir)
|
285
|
+
def maybe_resolve_ldflag_variable(input_arg, dest_dir, crate_name)
|
208
286
|
var_matches = input_arg.match(/\$\((\w+)\)/)
|
209
287
|
|
210
288
|
return input_arg unless var_matches
|
@@ -217,19 +295,19 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
|
217
295
|
# On windows, it is assumed that mkmf has setup an exports file for the
|
218
296
|
# extension, so we have to to create one ourselves.
|
219
297
|
when "DEFFILE"
|
220
|
-
write_deffile(dest_dir)
|
298
|
+
write_deffile(dest_dir, crate_name)
|
221
299
|
else
|
222
300
|
RbConfig::CONFIG[var_name]
|
223
301
|
end
|
224
302
|
end
|
225
303
|
|
226
|
-
def write_deffile(dest_dir)
|
227
|
-
deffile_path = File.join(dest_dir, "#{
|
304
|
+
def write_deffile(dest_dir, crate_name)
|
305
|
+
deffile_path = File.join(dest_dir, "#{crate_name}-#{RbConfig::CONFIG["arch"]}.def")
|
228
306
|
export_prefix = makefile_config("EXPORT_PREFIX") || ""
|
229
307
|
|
230
308
|
File.open(deffile_path, "w") do |f|
|
231
309
|
f.puts "EXPORTS"
|
232
|
-
f.puts "#{export_prefix.strip}Init_#{
|
310
|
+
f.puts "#{export_prefix.strip}Init_#{crate_name}"
|
233
311
|
end
|
234
312
|
|
235
313
|
deffile_path
|
@@ -264,44 +342,6 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
|
|
264
342
|
RbConfig.expand(val.dup)
|
265
343
|
end
|
266
344
|
|
267
|
-
# Copied from ExtConfBuilder
|
268
|
-
def finalize_directory(dest_path, lib_dir, extension_dir)
|
269
|
-
require "fileutils"
|
270
|
-
require "tempfile"
|
271
|
-
|
272
|
-
ext_path = final_extension_path(dest_path)
|
273
|
-
|
274
|
-
begin
|
275
|
-
tmp_dest = Dir.mktmpdir(".gem.", extension_dir)
|
276
|
-
|
277
|
-
# Some versions of `mktmpdir` return absolute paths, which will break make
|
278
|
-
# if the paths contain spaces.
|
279
|
-
#
|
280
|
-
# As such, we convert to a relative path.
|
281
|
-
tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
|
282
|
-
|
283
|
-
full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
|
284
|
-
|
285
|
-
# TODO: remove in RubyGems 4
|
286
|
-
if Gem.install_extension_in_lib && lib_dir
|
287
|
-
FileUtils.mkdir_p lib_dir
|
288
|
-
FileUtils.cp_r ext_path, lib_dir, remove_destination: true
|
289
|
-
end
|
290
|
-
|
291
|
-
FileUtils::Entry_.new(full_tmp_dest).traverse do |ent|
|
292
|
-
destent = ent.class.new(dest_path, ent.rel)
|
293
|
-
destent.exist? || FileUtils.mv(ent.path, destent.path)
|
294
|
-
end
|
295
|
-
ensure
|
296
|
-
FileUtils.rm_rf tmp_dest if tmp_dest
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
def get_relative_path(path, base)
|
301
|
-
path[0..base.length - 1] = "." if path.start_with?(base)
|
302
|
-
path
|
303
|
-
end
|
304
|
-
|
305
345
|
# Error raised when no cdylib artifact was created
|
306
346
|
class DylibNotFoundError < StandardError
|
307
347
|
def initialize(dir)
|
@@ -466,7 +466,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
466
466
|
|
467
467
|
def validate_rust_extensions(builder) # :nodoc:
|
468
468
|
rust_extension = @specification.extensions.any? {|s| builder.builder_for(s).is_a? Gem::Ext::CargoBuilder }
|
469
|
-
missing_cargo_lock = !@specification.files.
|
469
|
+
missing_cargo_lock = !@specification.files.any? {|f| f.end_with?("Cargo.lock") }
|
470
470
|
|
471
471
|
error <<-ERROR if rust_extension && missing_cargo_lock
|
472
472
|
You have specified rust based extension, but Cargo.lock is not part of the gem files. Please run `cargo generate-lockfile` or any other command to generate Cargo.lock and ensure it is added to your gem files section in gemspec.
|
data/lib/rubygems.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
require "rbconfig"
|
9
9
|
|
10
10
|
module Gem
|
11
|
-
VERSION = "3.4.
|
11
|
+
VERSION = "3.4.6".freeze
|
12
12
|
end
|
13
13
|
|
14
14
|
# Must be first since it unloads the prelude from 1.9.2
|
@@ -181,6 +181,8 @@ module Gem
|
|
181
181
|
|
182
182
|
@default_source_date_epoch = nil
|
183
183
|
|
184
|
+
@discover_gems_on_require = true
|
185
|
+
|
184
186
|
##
|
185
187
|
# Try to activate a gem containing +path+. Returns true if
|
186
188
|
# activation succeeded or wasn't needed because it was already
|
@@ -1163,8 +1165,16 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
|
|
1163
1165
|
# RubyGems distributors (like operating system package managers) can
|
1164
1166
|
# disable RubyGems update by setting this to error message printed to
|
1165
1167
|
# end-users on gem update --system instead of actual update.
|
1168
|
+
|
1166
1169
|
attr_accessor :disable_system_update_message
|
1167
1170
|
|
1171
|
+
##
|
1172
|
+
# Whether RubyGems should enhance builtin `require` to automatically
|
1173
|
+
# check whether the path required is present in installed gems, and
|
1174
|
+
# automatically activate them and add them to `$LOAD_PATH`.
|
1175
|
+
|
1176
|
+
attr_accessor :discover_gems_on_require
|
1177
|
+
|
1168
1178
|
##
|
1169
1179
|
# Hash of loaded Gem::Specification keyed by name
|
1170
1180
|
|
data/rubygems-update.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rubygems-update"
|
5
|
-
s.version = "3.4.
|
5
|
+
s.version = "3.4.6"
|
6
6
|
s.authors = ["Jim Weirich", "Chad Fowler", "Eric Hodel", "Luis Lavena", "Aaron Patterson", "Samuel Giddins", "André Arko", "Evan Phoenix", "Hiroshi SHIBATA"]
|
7
7
|
s.email = ["", "", "drbrain@segment7.net", "luislavena@gmail.com", "aaron@tenderlovemaking.com", "segiddins@segiddins.me", "andre@arko.net", "evan@phx.io", "hsbt@ruby-lang.org"]
|
8
8
|
|