rubygems-update 3.4.6 → 3.4.8
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/CHANGELOG.md +45 -0
- data/Manifest.txt +2 -1
- data/POLICIES.md +5 -5
- data/README.md +1 -4
- data/bundler/CHANGELOG.md +40 -0
- data/bundler/README.md +1 -4
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/cli/init.rb +2 -2
- data/bundler/lib/bundler/cli.rb +1 -0
- data/bundler/lib/bundler/current_ruby.rb +2 -0
- data/bundler/lib/bundler/dependency.rb +1 -1
- data/bundler/lib/bundler/environment_preserver.rb +2 -2
- data/bundler/lib/bundler/fetcher.rb +2 -2
- data/bundler/lib/bundler/index.rb +2 -2
- data/bundler/lib/bundler/injector.rb +1 -1
- data/bundler/lib/bundler/installer/parallel_installer.rb +3 -2
- data/bundler/lib/bundler/installer/standalone.rb +1 -1
- data/bundler/lib/bundler/lockfile_generator.rb +1 -1
- data/bundler/lib/bundler/lockfile_parser.rb +9 -9
- data/bundler/lib/bundler/man/bundle-add.1 +1 -1
- data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
- data/bundler/lib/bundler/man/bundle-check.1 +1 -1
- data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
- data/bundler/lib/bundler/man/bundle-config.1 +1 -1
- data/bundler/lib/bundler/man/bundle-console.1 +1 -1
- data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
- data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
- data/bundler/lib/bundler/man/bundle-gem.1 +1 -1
- data/bundler/lib/bundler/man/bundle-help.1 +1 -1
- data/bundler/lib/bundler/man/bundle-info.1 +1 -1
- data/bundler/lib/bundler/man/bundle-init.1 +5 -1
- data/bundler/lib/bundler/man/bundle-init.1.ronn +2 -0
- data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
- data/bundler/lib/bundler/man/bundle-install.1 +1 -1
- data/bundler/lib/bundler/man/bundle-list.1 +1 -1
- data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
- data/bundler/lib/bundler/man/bundle-open.1 +1 -1
- data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
- data/bundler/lib/bundler/man/bundle-platform.1 +1 -1
- data/bundler/lib/bundler/man/bundle-plugin.1 +1 -1
- data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
- data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
- data/bundler/lib/bundler/man/bundle-show.1 +1 -1
- data/bundler/lib/bundler/man/bundle-update.1 +1 -1
- data/bundler/lib/bundler/man/bundle-version.1 +1 -1
- data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
- data/bundler/lib/bundler/man/bundle.1 +1 -1
- data/bundler/lib/bundler/man/gemfile.5 +1 -1
- data/bundler/lib/bundler/plugin.rb +1 -1
- data/bundler/lib/bundler/rubygems_integration.rb +1 -1
- data/bundler/lib/bundler/setup.rb +4 -1
- data/bundler/lib/bundler/source/git/git_proxy.rb +22 -8
- data/bundler/lib/bundler/source/git.rb +1 -0
- data/bundler/lib/bundler/source/path.rb +1 -1
- data/bundler/lib/bundler/spec_set.rb +8 -2
- data/bundler/lib/bundler/templates/Executable.bundler +1 -1
- data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +6 -2
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +8 -1
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +5 -4
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +4 -2
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +4 -1
- data/bundler/lib/bundler/version.rb +1 -1
- data/bundler/lib/bundler.rb +9 -9
- data/lib/rubygems/bundler_version_finder.rb +1 -1
- data/lib/rubygems/command.rb +10 -6
- data/lib/rubygems/command_manager.rb +1 -0
- data/lib/rubygems/commands/exec_command.rb +248 -0
- data/lib/rubygems/commands/help_command.rb +3 -3
- data/lib/rubygems/defaults.rb +2 -2
- data/lib/rubygems/dependency.rb +1 -1
- data/lib/rubygems/deprecate.rb +2 -2
- data/lib/rubygems/package/tar_reader/entry.rb +88 -7
- data/lib/rubygems/package/tar_reader.rb +0 -28
- data/lib/rubygems/platform.rb +2 -2
- data/lib/rubygems/request_set/gem_dependency_api.rb +0 -1
- data/lib/rubygems/requirement.rb +1 -1
- data/lib/rubygems/resolver/stats.rb +1 -1
- data/lib/rubygems/source/git.rb +1 -1
- data/lib/rubygems/specification.rb +9 -1
- data/lib/rubygems/specification_policy.rb +5 -0
- data/lib/rubygems/stub_specification.rb +7 -7
- data/lib/rubygems/text.rb +1 -1
- data/lib/rubygems/util/licenses.rb +2 -2
- data/lib/rubygems/version.rb +2 -2
- data/lib/rubygems.rb +3 -3
- data/rubygems-update.gemspec +1 -1
- data/test/rubygems/helper.rb +2 -3
- data/test/rubygems/package/tar_test_case.rb +49 -14
- data/test/rubygems/simple_gem.rb +1 -1
- data/test/rubygems/test_gem.rb +24 -0
- data/test/rubygems/test_gem_bundler_version_finder.rb +2 -2
- data/test/rubygems/test_gem_command_manager.rb +25 -0
- data/test/rubygems/test_gem_commands_exec_command.rb +851 -0
- data/test/rubygems/test_gem_commands_install_command.rb +1 -1
- data/test/rubygems/test_gem_commands_setup_command.rb +1 -1
- data/test/rubygems/test_gem_ext_builder.rb +3 -5
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +20 -6
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
- data/test/rubygems/test_gem_gem_runner.rb +2 -2
- data/test/rubygems/test_gem_package.rb +0 -25
- data/test/rubygems/test_gem_package_tar_reader.rb +48 -1
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +151 -6
- data/test/rubygems/test_gem_remote_fetcher.rb +1 -1
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +10 -10
- data/test/rubygems/test_gem_request_set_lockfile_parser.rb +2 -2
- data/test/rubygems/test_gem_resolver_git_set.rb +9 -9
- data/test/rubygems/test_gem_resolver_git_specification.rb +1 -1
- data/test/rubygems/test_gem_source.rb +1 -1
- data/test/rubygems/test_gem_source_git.rb +13 -12
- data/test/rubygems/test_gem_source_installed.rb +1 -1
- data/test/rubygems/test_gem_source_lock.rb +3 -3
- data/test/rubygems/test_gem_source_vendor.rb +1 -1
- data/test/rubygems/test_gem_specification.rb +36 -2
- data/test/rubygems/test_gem_version.rb +2 -2
- data/test/rubygems/test_kernel.rb +0 -8
- metadata +5 -4
- data/bundler/lib/bundler/templates/gems.rb +0 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
|
3
3
|
.
|
|
4
|
-
.TH "BUNDLE\-UPDATE" "1" "
|
|
4
|
+
.TH "BUNDLE\-UPDATE" "1" "February 2023" "" ""
|
|
5
5
|
.
|
|
6
6
|
.SH "NAME"
|
|
7
7
|
\fBbundle\-update\fR \- Update your gems to the latest available versions
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
|
3
3
|
.
|
|
4
|
-
.TH "BUNDLE\-VIZ" "1" "
|
|
4
|
+
.TH "BUNDLE\-VIZ" "1" "February 2023" "" ""
|
|
5
5
|
.
|
|
6
6
|
.SH "NAME"
|
|
7
7
|
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
|
|
@@ -453,7 +453,7 @@ module Bundler
|
|
|
453
453
|
fetcher = gem_remote_fetcher
|
|
454
454
|
fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
|
|
455
455
|
string = fetcher.fetch_path(path)
|
|
456
|
-
Bundler.
|
|
456
|
+
Bundler.safe_load_marshal(string)
|
|
457
457
|
rescue Gem::RemoteFetcher::FetchError
|
|
458
458
|
# it's okay for prerelease to fail
|
|
459
459
|
raise unless name == "prerelease_specs"
|
|
@@ -12,7 +12,10 @@ if Bundler::SharedHelpers.in_bundle?
|
|
|
12
12
|
Bundler.ui.error e.message
|
|
13
13
|
Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
|
|
14
14
|
if e.is_a?(Bundler::GemNotFound)
|
|
15
|
-
|
|
15
|
+
suggested_cmd = "bundle install"
|
|
16
|
+
original_gemfile = Bundler.original_env["BUNDLE_GEMFILE"]
|
|
17
|
+
suggested_cmd += " --gemfile #{original_gemfile}" if original_gemfile
|
|
18
|
+
Bundler.ui.warn "Run `#{suggested_cmd}` to install missing gems."
|
|
16
19
|
end
|
|
17
20
|
exit e.status_code
|
|
18
21
|
end
|
|
@@ -28,8 +28,9 @@ module Bundler
|
|
|
28
28
|
def initialize(command, path, extra_info = nil)
|
|
29
29
|
@command = command
|
|
30
30
|
|
|
31
|
-
msg = String.new
|
|
32
|
-
msg << "
|
|
31
|
+
msg = String.new("Git error: command `#{command}`")
|
|
32
|
+
msg << " in directory #{path}" if path
|
|
33
|
+
msg << " has failed."
|
|
33
34
|
msg << "\n#{extra_info}" if extra_info
|
|
34
35
|
super msg
|
|
35
36
|
end
|
|
@@ -139,8 +140,8 @@ module Bundler
|
|
|
139
140
|
out, err, status = capture(command, path)
|
|
140
141
|
return out if status.success?
|
|
141
142
|
|
|
142
|
-
if err.include?("couldn't find remote ref")
|
|
143
|
-
raise MissingGitRevisionError.new(command_with_no_credentials, path, explicit_ref, credential_filtered_uri)
|
|
143
|
+
if err.include?("couldn't find remote ref") || err.include?("not our ref")
|
|
144
|
+
raise MissingGitRevisionError.new(command_with_no_credentials, path, commit || explicit_ref, credential_filtered_uri)
|
|
144
145
|
else
|
|
145
146
|
raise GitCommandError.new(command_with_no_credentials, path, err)
|
|
146
147
|
end
|
|
@@ -153,9 +154,20 @@ module Bundler
|
|
|
153
154
|
SharedHelpers.filesystem_access(path.dirname) do |p|
|
|
154
155
|
FileUtils.mkdir_p(p)
|
|
155
156
|
end
|
|
156
|
-
git_retry "clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
command = ["clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s]
|
|
159
|
+
command_with_no_credentials = check_allowed(command)
|
|
160
|
+
|
|
161
|
+
Bundler::Retry.new("`#{command_with_no_credentials}`", [MissingGitRevisionError]).attempts do
|
|
162
|
+
_, err, status = capture(command, nil)
|
|
163
|
+
return extra_ref if status.success?
|
|
164
|
+
|
|
165
|
+
if err.include?("Could not find remote branch")
|
|
166
|
+
raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
|
|
167
|
+
else
|
|
168
|
+
raise GitCommandError.new(command_with_no_credentials, path, err)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
159
171
|
end
|
|
160
172
|
|
|
161
173
|
def clone_needs_unshallow?
|
|
@@ -186,8 +198,6 @@ module Bundler
|
|
|
186
198
|
end
|
|
187
199
|
|
|
188
200
|
def refspec
|
|
189
|
-
commit = pinned_to_full_sha? ? ref : @revision
|
|
190
|
-
|
|
191
201
|
if commit
|
|
192
202
|
@commit_ref = "refs/#{commit}-sha"
|
|
193
203
|
return "#{commit}:#{@commit_ref}"
|
|
@@ -206,6 +216,10 @@ module Bundler
|
|
|
206
216
|
"#{reference}:#{reference}"
|
|
207
217
|
end
|
|
208
218
|
|
|
219
|
+
def commit
|
|
220
|
+
@commit ||= pinned_to_full_sha? ? ref : @revision
|
|
221
|
+
end
|
|
222
|
+
|
|
209
223
|
def fully_qualified_ref
|
|
210
224
|
if branch
|
|
211
225
|
"refs/heads/#{branch}"
|
|
@@ -24,6 +24,7 @@ module Bundler
|
|
|
24
24
|
|
|
25
25
|
name = dep[0].name
|
|
26
26
|
platform = dep[1]
|
|
27
|
+
incomplete = false
|
|
27
28
|
|
|
28
29
|
key = [name, platform]
|
|
29
30
|
next if handled.key?(key)
|
|
@@ -36,10 +37,15 @@ module Bundler
|
|
|
36
37
|
|
|
37
38
|
specs_for_dep.first.dependencies.each do |d|
|
|
38
39
|
next if d.type == :development
|
|
40
|
+
incomplete = true if d.name != "bundler" && lookup[d.name].empty?
|
|
39
41
|
deps << [d, dep[1]]
|
|
40
42
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
else
|
|
44
|
+
incomplete = true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if incomplete && check
|
|
48
|
+
@incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
|
|
43
49
|
end
|
|
44
50
|
end
|
|
45
51
|
|
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
30
30
|
spec.files = Dir.chdir(__dir__) do
|
|
31
31
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
32
|
-
(f == __FILE__) || f.
|
|
32
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
spec.bindir = "exe"
|
|
@@ -76,9 +76,13 @@ module Bundler::PubGrub
|
|
|
76
76
|
elsif terms.length == 1
|
|
77
77
|
term = terms[0]
|
|
78
78
|
if term.positive?
|
|
79
|
-
|
|
79
|
+
if term.constraint.any?
|
|
80
|
+
"#{term.package} cannot be used"
|
|
81
|
+
else
|
|
82
|
+
"#{term.to_s(allow_every: true)} cannot be used"
|
|
83
|
+
end
|
|
80
84
|
else
|
|
81
|
-
"#{
|
|
85
|
+
"#{term.invert} is required"
|
|
82
86
|
end
|
|
83
87
|
else
|
|
84
88
|
if terms.all?(&:positive?)
|
|
@@ -19,7 +19,14 @@ module Bundler::PubGrub
|
|
|
19
19
|
version = Gem::Version.new(version)
|
|
20
20
|
@packages[name] ||= {}
|
|
21
21
|
raise ArgumentError, "#{name} #{version} declared twice" if @packages[name].key?(version)
|
|
22
|
-
@packages[name][version] = deps
|
|
22
|
+
@packages[name][version] = clean_deps(name, version, deps)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# Exclude redundant self-referencing dependencies
|
|
28
|
+
def clean_deps(name, version, deps)
|
|
29
|
+
deps.reject {|dep_name, req| name == dep_name && Bundler::PubGrub::RubyGems.parse_range(req).include?(version) }
|
|
23
30
|
end
|
|
24
31
|
end
|
|
25
32
|
|
|
@@ -15,15 +15,16 @@ module Bundler::PubGrub
|
|
|
15
15
|
package.hash ^ range.hash
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def ==(other)
|
|
19
|
+
package == other.package &&
|
|
20
|
+
range == other.range
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
def eql?(other)
|
|
19
24
|
package.eql?(other.package) &&
|
|
20
25
|
range.eql?(other.range)
|
|
21
26
|
end
|
|
22
27
|
|
|
23
|
-
def ==(other)
|
|
24
|
-
package == other.package && range == other.range
|
|
25
|
-
end
|
|
26
|
-
|
|
27
28
|
class << self
|
|
28
29
|
def exact(package, version)
|
|
29
30
|
range = VersionRange.new(min: version, max: version, include_min: true, include_max: true)
|
|
@@ -19,7 +19,7 @@ module Bundler::PubGrub
|
|
|
19
19
|
true
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def eql?
|
|
22
|
+
def eql?(other)
|
|
23
23
|
other.empty?
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -65,6 +65,7 @@ module Bundler::PubGrub
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
EMPTY = Empty.new
|
|
68
|
+
Empty.singleton_class.undef_method(:new)
|
|
68
69
|
|
|
69
70
|
def self.empty
|
|
70
71
|
EMPTY
|
|
@@ -88,7 +89,8 @@ module Bundler::PubGrub
|
|
|
88
89
|
|
|
89
90
|
def eql?(other)
|
|
90
91
|
if other.is_a?(VersionRange)
|
|
91
|
-
|
|
92
|
+
!other.empty? &&
|
|
93
|
+
min.eql?(other.min) &&
|
|
92
94
|
max.eql?(other.max) &&
|
|
93
95
|
include_min.eql?(other.include_min) &&
|
|
94
96
|
include_max.eql?(other.include_max)
|
|
@@ -125,6 +125,7 @@ module Bundler::PubGrub
|
|
|
125
125
|
package = next_package_to_try
|
|
126
126
|
unsatisfied_term = solution.unsatisfied.find { |t| t.package == package }
|
|
127
127
|
version = source.versions_for(package, unsatisfied_term.constraint.range).first
|
|
128
|
+
logger.debug { "attempting #{package} #{version}" }
|
|
128
129
|
|
|
129
130
|
if version.nil?
|
|
130
131
|
add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term)
|
|
@@ -148,9 +149,11 @@ module Bundler::PubGrub
|
|
|
148
149
|
end
|
|
149
150
|
|
|
150
151
|
unless conflict
|
|
151
|
-
logger.info { "
|
|
152
|
+
logger.info { "selected #{package} #{version}" }
|
|
152
153
|
|
|
153
154
|
solution.decide(package, version)
|
|
155
|
+
else
|
|
156
|
+
logger.info { "conflict: #{conflict.inspect}" }
|
|
154
157
|
end
|
|
155
158
|
|
|
156
159
|
package
|
data/bundler/lib/bundler.rb
CHANGED
|
@@ -39,8 +39,8 @@ module Bundler
|
|
|
39
39
|
environment_preserver.replace_with_backup
|
|
40
40
|
SUDO_MUTEX = Thread::Mutex.new
|
|
41
41
|
|
|
42
|
-
SAFE_MARSHAL_CLASSES = [Symbol, TrueClass, String, Array, Hash].freeze
|
|
43
|
-
SAFE_MARSHAL_ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed."
|
|
42
|
+
SAFE_MARSHAL_CLASSES = [Symbol, TrueClass, String, Array, Hash, Gem::Version, Gem::Specification].freeze
|
|
43
|
+
SAFE_MARSHAL_ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed."
|
|
44
44
|
SAFE_MARSHAL_PROC = proc do |object|
|
|
45
45
|
object.tap do
|
|
46
46
|
unless SAFE_MARSHAL_CLASSES.include?(object.class)
|
|
@@ -506,7 +506,7 @@ EOF
|
|
|
506
506
|
if File.file?(executable) && File.executable?(executable)
|
|
507
507
|
executable
|
|
508
508
|
elsif paths = ENV["PATH"]
|
|
509
|
-
quote = '"'
|
|
509
|
+
quote = '"'
|
|
510
510
|
paths.split(File::PATH_SEPARATOR).find do |path|
|
|
511
511
|
path = path[1..-2] if path.start_with?(quote) && path.end_with?(quote)
|
|
512
512
|
executable_path = File.expand_path(executable, path)
|
|
@@ -525,12 +525,6 @@ EOF
|
|
|
525
525
|
load_marshal(data, :marshal_proc => SAFE_MARSHAL_PROC)
|
|
526
526
|
end
|
|
527
527
|
|
|
528
|
-
def load_marshal(data, marshal_proc: nil)
|
|
529
|
-
Marshal.load(data, marshal_proc)
|
|
530
|
-
rescue TypeError => e
|
|
531
|
-
raise MarshalError, "#{e.class}: #{e.message}"
|
|
532
|
-
end
|
|
533
|
-
|
|
534
528
|
def load_gemspec(file, validate = false)
|
|
535
529
|
@gemspec_cache ||= {}
|
|
536
530
|
key = File.expand_path(file)
|
|
@@ -619,6 +613,12 @@ EOF
|
|
|
619
613
|
|
|
620
614
|
private
|
|
621
615
|
|
|
616
|
+
def load_marshal(data, marshal_proc: nil)
|
|
617
|
+
Marshal.load(data, marshal_proc)
|
|
618
|
+
rescue TypeError => e
|
|
619
|
+
raise MarshalError, "#{e.class}: #{e.message}"
|
|
620
|
+
end
|
|
621
|
+
|
|
622
622
|
def eval_yaml_gemspec(path, contents)
|
|
623
623
|
Kernel.require "psych"
|
|
624
624
|
|
|
@@ -21,7 +21,7 @@ module Gem::BundlerVersionFinder
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def self.bundle_update_bundler_version
|
|
24
|
-
return unless File.basename($0) == "bundle"
|
|
24
|
+
return unless File.basename($0) == "bundle"
|
|
25
25
|
return unless "update".start_with?(ARGV.first || " ")
|
|
26
26
|
bundler_version = nil
|
|
27
27
|
update_index = nil
|
data/lib/rubygems/command.rb
CHANGED
|
@@ -201,11 +201,15 @@ class Gem::Command
|
|
|
201
201
|
# respectively.
|
|
202
202
|
def get_all_gem_names_and_versions
|
|
203
203
|
get_all_gem_names.map do |name|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
extract_gem_name_and_version(name)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def extract_gem_name_and_version(name) # :nodoc:
|
|
209
|
+
if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name
|
|
210
|
+
[$1, $2]
|
|
211
|
+
else
|
|
212
|
+
[name]
|
|
209
213
|
end
|
|
210
214
|
end
|
|
211
215
|
|
|
@@ -624,7 +628,7 @@ class Gem::Command
|
|
|
624
628
|
|
|
625
629
|
# :stopdoc:
|
|
626
630
|
|
|
627
|
-
HELP = <<-HELP
|
|
631
|
+
HELP = <<-HELP
|
|
628
632
|
RubyGems is a package manager for Ruby.
|
|
629
633
|
|
|
630
634
|
Usage:
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative "../command"
|
|
3
|
+
require_relative "../dependency_installer"
|
|
4
|
+
require_relative "../gem_runner"
|
|
5
|
+
require_relative "../package"
|
|
6
|
+
require_relative "../version_option"
|
|
7
|
+
|
|
8
|
+
class Gem::Commands::ExecCommand < Gem::Command
|
|
9
|
+
include Gem::VersionOption
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
super "exec", "Run a command from a gem", {
|
|
13
|
+
version: Gem::Requirement.default,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
add_version_option
|
|
17
|
+
add_prerelease_option "to be installed"
|
|
18
|
+
|
|
19
|
+
add_option "-g", "--gem GEM", "run the executable from the given gem" do |value, options|
|
|
20
|
+
options[:gem_name] = value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
add_option(:"Install/Update", "--conservative",
|
|
24
|
+
"Prefer the most recent installed version, ",
|
|
25
|
+
"rather than the latest version overall") do |value, options|
|
|
26
|
+
options[:conservative] = true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def arguments # :nodoc:
|
|
31
|
+
"COMMAND the executable command to run"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def defaults_str # :nodoc:
|
|
35
|
+
"--version '#{Gem::Requirement.default}'"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def description # :nodoc:
|
|
39
|
+
<<-EOF
|
|
40
|
+
The exec command handles installing (if necessary) and running an executable
|
|
41
|
+
from a gem, regardless of whether that gem is currently installed.
|
|
42
|
+
|
|
43
|
+
The exec command can be thought of as a shortcut to running `gem install` and
|
|
44
|
+
then the executable from the installed gem.
|
|
45
|
+
|
|
46
|
+
For example, `gem exec rails new .` will run `rails new .` in the current
|
|
47
|
+
directory, without having to manually run `gem install rails`.
|
|
48
|
+
Additionally, the exec command ensures the most recent version of the gem
|
|
49
|
+
is used (unless run with `--conservative`), and that the gem is not installed
|
|
50
|
+
to the same gem path as user-installed gems.
|
|
51
|
+
EOF
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def usage # :nodoc:
|
|
55
|
+
"#{program_name} [options --] COMMAND [args]"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def execute
|
|
59
|
+
gem_paths = { "GEM_HOME" => Gem.paths.home, "GEM_PATH" => Gem.paths.path.join(File::PATH_SEPARATOR), "GEM_SPEC_CACHE" => Gem.paths.spec_cache_dir }.compact
|
|
60
|
+
|
|
61
|
+
check_executable
|
|
62
|
+
|
|
63
|
+
print_command
|
|
64
|
+
if options[:gem_name] == "gem" && options[:executable] == "gem"
|
|
65
|
+
set_gem_exec_install_paths
|
|
66
|
+
Gem::GemRunner.new.run options[:args]
|
|
67
|
+
return
|
|
68
|
+
elsif options[:conservative]
|
|
69
|
+
install_if_needed
|
|
70
|
+
else
|
|
71
|
+
install
|
|
72
|
+
activate!
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
load!
|
|
76
|
+
ensure
|
|
77
|
+
ENV.update(gem_paths) if gem_paths
|
|
78
|
+
Gem.clear_paths
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def handle_options(args)
|
|
84
|
+
args = add_extra_args(args)
|
|
85
|
+
check_deprecated_options(args)
|
|
86
|
+
@options = Marshal.load Marshal.dump @defaults # deep copy
|
|
87
|
+
parser.order!(args) do |v|
|
|
88
|
+
# put the non-option back at the front of the list of arguments
|
|
89
|
+
args.unshift(v)
|
|
90
|
+
|
|
91
|
+
# stop parsing once we hit the first non-option,
|
|
92
|
+
# so you can call `gem exec rails --version` and it prints the rails
|
|
93
|
+
# version rather than rubygem's
|
|
94
|
+
break
|
|
95
|
+
end
|
|
96
|
+
@options[:args] = args
|
|
97
|
+
|
|
98
|
+
options[:executable], gem_version = extract_gem_name_and_version(options[:args].shift)
|
|
99
|
+
options[:gem_name] ||= options[:executable]
|
|
100
|
+
|
|
101
|
+
if gem_version
|
|
102
|
+
if options[:version].none?
|
|
103
|
+
options[:version] = Gem::Requirement.new(gem_version)
|
|
104
|
+
else
|
|
105
|
+
options[:version].concat [gem_version]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if options[:prerelease] && !options[:version].prerelease?
|
|
110
|
+
if options[:version].none?
|
|
111
|
+
options[:version] = Gem::Requirement.default_prerelease
|
|
112
|
+
else
|
|
113
|
+
options[:version].concat [Gem::Requirement.default_prerelease]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def check_executable
|
|
119
|
+
if options[:executable].nil?
|
|
120
|
+
raise Gem::CommandLineError,
|
|
121
|
+
"Please specify an executable to run (e.g. #{program_name} COMMAND)"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def print_command
|
|
126
|
+
verbose "running #{program_name} with:\n"
|
|
127
|
+
opts = options.reject {|_, v| v.nil? || Array(v).empty? }
|
|
128
|
+
max_length = opts.map {|k, _| k.size }.max
|
|
129
|
+
opts.each do |k, v|
|
|
130
|
+
next if v.nil?
|
|
131
|
+
verbose "\t#{k.to_s.rjust(max_length)}: #{v}"
|
|
132
|
+
end
|
|
133
|
+
verbose ""
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def install_if_needed
|
|
137
|
+
activate!
|
|
138
|
+
rescue Gem::MissingSpecError
|
|
139
|
+
verbose "#{Gem::Dependency.new(options[:gem_name], options[:version])} not available locally, installing from remote"
|
|
140
|
+
install
|
|
141
|
+
activate!
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def set_gem_exec_install_paths
|
|
145
|
+
home = File.join(Gem.dir, "gem_exec")
|
|
146
|
+
|
|
147
|
+
ENV["GEM_PATH"] = ([home] + Gem.path).join(File::PATH_SEPARATOR)
|
|
148
|
+
ENV["GEM_HOME"] = home
|
|
149
|
+
Gem.clear_paths
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def install
|
|
153
|
+
set_gem_exec_install_paths
|
|
154
|
+
|
|
155
|
+
gem_name = options[:gem_name]
|
|
156
|
+
gem_version = options[:version]
|
|
157
|
+
|
|
158
|
+
install_options = options.merge(
|
|
159
|
+
minimal_deps: false,
|
|
160
|
+
wrappers: true
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
suppress_always_install do
|
|
164
|
+
dep_installer = Gem::DependencyInstaller.new install_options
|
|
165
|
+
|
|
166
|
+
request_set = dep_installer.resolve_dependencies gem_name, gem_version
|
|
167
|
+
|
|
168
|
+
verbose "Gems to install:"
|
|
169
|
+
request_set.sorted_requests.each do |activation_request|
|
|
170
|
+
verbose "\t#{activation_request.full_name}"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
request_set.install install_options
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
Gem::Specification.reset
|
|
177
|
+
rescue Gem::InstallError => e
|
|
178
|
+
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
|
|
179
|
+
terminate_interaction 1
|
|
180
|
+
rescue Gem::GemNotFoundException => e
|
|
181
|
+
show_lookup_failure e.name, e.version, e.errors, false
|
|
182
|
+
|
|
183
|
+
terminate_interaction 2
|
|
184
|
+
rescue Gem::UnsatisfiableDependencyError => e
|
|
185
|
+
show_lookup_failure e.name, e.version, e.errors, false,
|
|
186
|
+
"'#{gem_name}' (#{gem_version})"
|
|
187
|
+
|
|
188
|
+
terminate_interaction 2
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def activate!
|
|
192
|
+
gem(options[:gem_name], options[:version])
|
|
193
|
+
Gem.finish_resolve
|
|
194
|
+
|
|
195
|
+
verbose "activated #{options[:gem_name]} (#{Gem.loaded_specs[options[:gem_name]].version})"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def load!
|
|
199
|
+
argv = ARGV.clone
|
|
200
|
+
ARGV.replace options[:args]
|
|
201
|
+
|
|
202
|
+
exe = executable = options[:executable]
|
|
203
|
+
|
|
204
|
+
contains_executable = Gem.loaded_specs.values.select do |spec|
|
|
205
|
+
spec.executables.include?(executable)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
if contains_executable.any? {|s| s.name == executable }
|
|
209
|
+
contains_executable.select! {|s| s.name == executable }
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
if contains_executable.empty?
|
|
213
|
+
if (spec = Gem.loaded_specs[executable]) && (exe = spec.executable)
|
|
214
|
+
contains_executable << spec
|
|
215
|
+
else
|
|
216
|
+
alert_error "Failed to load executable `#{executable}`," \
|
|
217
|
+
" are you sure the gem `#{options[:gem_name]}` contains it?"
|
|
218
|
+
terminate_interaction 1
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
if contains_executable.size > 1
|
|
223
|
+
alert_error "Ambiguous which gem `#{executable}` should come from: " \
|
|
224
|
+
"the options are #{contains_executable.map(&:name)}, " \
|
|
225
|
+
"specify one via `-g`"
|
|
226
|
+
terminate_interaction 1
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
load Gem.activate_bin_path(contains_executable.first.name, exe, ">= 0.a")
|
|
230
|
+
ensure
|
|
231
|
+
ARGV.replace argv
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def suppress_always_install
|
|
235
|
+
name = :always_install
|
|
236
|
+
cls = ::Gem::Resolver::InstallerSet
|
|
237
|
+
method = cls.instance_method(name)
|
|
238
|
+
cls.remove_method(name)
|
|
239
|
+
cls.define_method(name) { [] }
|
|
240
|
+
|
|
241
|
+
begin
|
|
242
|
+
yield
|
|
243
|
+
ensure
|
|
244
|
+
cls.remove_method(name)
|
|
245
|
+
cls.define_method(name, method)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|