bundler 2.2.24 → 2.2.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +149 -1
- data/README.md +1 -1
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/cli/cache.rb +1 -1
- data/lib/bundler/cli/doctor.rb +4 -3
- data/lib/bundler/cli/exec.rb +1 -6
- data/lib/bundler/cli/gem.rb +90 -10
- data/lib/bundler/cli/info.rb +16 -4
- data/lib/bundler/cli/install.rb +4 -17
- data/lib/bundler/cli/issue.rb +4 -3
- data/lib/bundler/cli/list.rb +7 -1
- data/lib/bundler/cli/open.rb +1 -2
- data/lib/bundler/cli/remove.rb +1 -2
- data/lib/bundler/cli/update.rb +3 -3
- data/lib/bundler/cli.rb +16 -10
- data/lib/bundler/compact_index_client/updater.rb +0 -5
- data/lib/bundler/compact_index_client.rb +2 -2
- data/lib/bundler/definition.rb +84 -150
- data/lib/bundler/digest.rb +71 -0
- data/lib/bundler/dsl.rb +32 -4
- data/lib/bundler/environment_preserver.rb +4 -1
- data/lib/bundler/errors.rb +19 -3
- data/lib/bundler/fetcher.rb +2 -1
- data/lib/bundler/friendly_errors.rb +5 -30
- data/lib/bundler/gem_helper.rb +6 -17
- data/lib/bundler/installer/gem_installer.rb +3 -16
- data/lib/bundler/installer/standalone.rb +13 -8
- data/lib/bundler/installer.rb +0 -1
- data/lib/bundler/lazy_specification.rb +17 -1
- data/lib/bundler/lockfile_parser.rb +2 -0
- data/lib/bundler/man/bundle-add.1 +1 -1
- data/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/lib/bundler/man/bundle-cache.1 +1 -1
- data/lib/bundler/man/bundle-check.1 +1 -1
- data/lib/bundler/man/bundle-clean.1 +1 -1
- data/lib/bundler/man/bundle-config.1 +3 -3
- data/lib/bundler/man/bundle-config.1.ronn +2 -2
- data/lib/bundler/man/bundle-doctor.1 +1 -1
- data/lib/bundler/man/bundle-exec.1 +1 -1
- data/lib/bundler/man/bundle-gem.1 +14 -1
- data/lib/bundler/man/bundle-gem.1.ronn +16 -0
- data/lib/bundler/man/bundle-info.1 +1 -1
- data/lib/bundler/man/bundle-init.1 +1 -1
- data/lib/bundler/man/bundle-inject.1 +1 -1
- data/lib/bundler/man/bundle-install.1 +1 -1
- data/lib/bundler/man/bundle-list.1 +1 -1
- data/lib/bundler/man/bundle-lock.1 +1 -1
- data/lib/bundler/man/bundle-open.1 +1 -1
- data/lib/bundler/man/bundle-outdated.1 +1 -1
- data/lib/bundler/man/bundle-platform.1 +1 -1
- data/lib/bundler/man/bundle-pristine.1 +1 -1
- data/lib/bundler/man/bundle-remove.1 +1 -1
- data/lib/bundler/man/bundle-show.1 +1 -1
- data/lib/bundler/man/bundle-update.1 +1 -1
- data/lib/bundler/man/bundle-viz.1 +1 -1
- data/lib/bundler/man/bundle.1 +1 -1
- data/lib/bundler/man/gemfile.5 +27 -1
- data/lib/bundler/man/gemfile.5.ronn +8 -0
- data/lib/bundler/plugin/api/source.rb +1 -0
- data/lib/bundler/plugin/installer.rb +2 -0
- data/lib/bundler/plugin.rb +23 -6
- data/lib/bundler/resolver.rb +8 -17
- data/lib/bundler/rubygems_ext.rb +4 -0
- data/lib/bundler/rubygems_gem_installer.rb +25 -5
- data/lib/bundler/rubygems_integration.rb +28 -9
- data/lib/bundler/runtime.rb +17 -8
- data/lib/bundler/settings.rb +13 -1
- data/lib/bundler/setup.rb +2 -2
- data/lib/bundler/shared_helpers.rb +2 -10
- data/lib/bundler/source/git/git_proxy.rb +8 -6
- data/lib/bundler/source/git.rb +22 -4
- data/lib/bundler/source/rubygems.rb +70 -81
- data/lib/bundler/source/rubygems_aggregate.rb +4 -0
- data/lib/bundler/source.rb +4 -0
- data/lib/bundler/source_list.rb +22 -31
- data/lib/bundler/spec_set.rb +14 -36
- data/lib/bundler/templates/Executable.bundler +6 -6
- data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
- data/lib/bundler/templates/newgem/Rakefile.tt +5 -1
- data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +13 -2
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +16 -14
- data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
- data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
- data/lib/bundler/vendor/.document +1 -0
- data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
- data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
- data/lib/bundler/vendor/molinillo/LICENSE +9 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
- data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
- data/lib/bundler/vendor/thor/LICENSE.md +20 -0
- data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
- data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
- data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
- data/lib/bundler/vendored_tsort.rb +4 -0
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler/worker.rb +19 -4
- data/lib/bundler.rb +13 -22
- metadata +20 -7
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
data/lib/bundler/cli.rb
CHANGED
@@ -73,14 +73,6 @@ module Bundler
|
|
73
73
|
Bundler.ui = UI::Shell.new(options)
|
74
74
|
Bundler.ui.level = "debug" if options["verbose"]
|
75
75
|
unprinted_warnings.each {|w| Bundler.ui.warn(w) }
|
76
|
-
|
77
|
-
if ENV["RUBYGEMS_GEMDEPS"] && !ENV["RUBYGEMS_GEMDEPS"].empty?
|
78
|
-
Bundler.ui.warn(
|
79
|
-
"The RUBYGEMS_GEMDEPS environment variable is set. This enables RubyGems' " \
|
80
|
-
"experimental Gemfile mode, which may conflict with Bundler and cause unexpected errors. " \
|
81
|
-
"To remove this warning, unset RUBYGEMS_GEMDEPS.", :wrap => true
|
82
|
-
)
|
83
|
-
end
|
84
76
|
end
|
85
77
|
|
86
78
|
check_unknown_options!(:except => [:config, :exec])
|
@@ -192,6 +184,7 @@ module Bundler
|
|
192
184
|
method_option "install", :type => :boolean, :banner =>
|
193
185
|
"Runs 'bundle install' after removing the gems from the Gemfile"
|
194
186
|
def remove(*gems)
|
187
|
+
SharedHelpers.major_deprecation(2, "The `--install` flag has been deprecated. `bundle install` is triggered by default.") if ARGV.include?("--install")
|
195
188
|
require_relative "cli/remove"
|
196
189
|
Remove.new(gems, options).run
|
197
190
|
end
|
@@ -338,6 +331,7 @@ module Bundler
|
|
338
331
|
|
339
332
|
desc "info GEM [OPTIONS]", "Show information for the given gem"
|
340
333
|
method_option "path", :type => :boolean, :banner => "Print full path to gem"
|
334
|
+
method_option "version", :type => :boolean, :banner => "Print gem version"
|
341
335
|
def info(gem_name)
|
342
336
|
require_relative "cli/info"
|
343
337
|
Info.new(options, gem_name).run
|
@@ -456,6 +450,12 @@ module Bundler
|
|
456
450
|
"do in future versions. Instead please use `bundle config set cache_all true`, " \
|
457
451
|
"and stop using this flag" if ARGV.include?("--all")
|
458
452
|
|
453
|
+
SharedHelpers.major_deprecation 2,
|
454
|
+
"The `--path` flag is deprecated because its semantics are unclear. " \
|
455
|
+
"Use `bundle config cache_path` to configure the path of your cache of gems, " \
|
456
|
+
"and `bundle config path` to configure the path where your gems are installed, " \
|
457
|
+
"and stop using this flag" if ARGV.include?("--path")
|
458
|
+
|
459
459
|
require_relative "cli/cache"
|
460
460
|
Cache.new(options).run
|
461
461
|
end
|
@@ -463,7 +463,7 @@ module Bundler
|
|
463
463
|
map aliases_for("cache")
|
464
464
|
|
465
465
|
desc "exec [OPTIONS]", "Run the command in context of the bundle"
|
466
|
-
method_option :keep_file_descriptors, :type => :boolean, :default =>
|
466
|
+
method_option :keep_file_descriptors, :type => :boolean, :default => true
|
467
467
|
method_option :gemfile, :type => :string, :required => false
|
468
468
|
long_desc <<-D
|
469
469
|
Exec runs a command, providing it access to the gems in the bundle. While using
|
@@ -471,6 +471,10 @@ module Bundler
|
|
471
471
|
into the system wide RubyGems repository.
|
472
472
|
D
|
473
473
|
def exec(*args)
|
474
|
+
if ARGV.include?("--no-keep-file-descriptors")
|
475
|
+
SharedHelpers.major_deprecation(2, "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to")
|
476
|
+
end
|
477
|
+
|
474
478
|
require_relative "cli/exec"
|
475
479
|
Exec.new(options, args).run
|
476
480
|
end
|
@@ -549,7 +553,7 @@ module Bundler
|
|
549
553
|
method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
|
550
554
|
method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
|
551
555
|
def viz
|
552
|
-
SharedHelpers.major_deprecation 2, "The `viz` command has been
|
556
|
+
SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
|
553
557
|
require_relative "cli/viz"
|
554
558
|
Viz.new(options.dup).run
|
555
559
|
end
|
@@ -572,6 +576,8 @@ module Bundler
|
|
572
576
|
:desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
|
573
577
|
method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "",
|
574
578
|
:desc => "Generate CI configuration, either GitHub Actions, Travis CI, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|travis|gitlab|circle)`"
|
579
|
+
method_option :linter, :type => :string, :lazy_default => Bundler.settings["gem.linter"] || "",
|
580
|
+
:desc => "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
|
575
581
|
method_option :github_username, :type => :string, :default => Bundler.settings["gem.github_username"], :banner => "Set your username on GitHub", :desc => "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username <your_username>`."
|
576
582
|
|
577
583
|
def gem(name)
|
@@ -76,11 +76,6 @@ module Bundler
|
|
76
76
|
|
77
77
|
update(local_path, remote_path, :retrying)
|
78
78
|
end
|
79
|
-
rescue Errno::EACCES
|
80
|
-
raise Bundler::PermissionError,
|
81
|
-
"Bundler does not have write access to create a temp directory " \
|
82
|
-
"within #{Dir.tmpdir}. Bundler must have write access to your " \
|
83
|
-
"systems temp directory to function properly. "
|
84
79
|
rescue Zlib::GzipFile::Error
|
85
80
|
raise Bundler::HTTPError
|
86
81
|
end
|
@@ -5,7 +5,7 @@ require "set"
|
|
5
5
|
|
6
6
|
module Bundler
|
7
7
|
class CompactIndexClient
|
8
|
-
DEBUG_MUTEX = Mutex.new
|
8
|
+
DEBUG_MUTEX = Thread::Mutex.new
|
9
9
|
def self.debug
|
10
10
|
return unless ENV["DEBUG_COMPACT_INDEX"]
|
11
11
|
DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
|
@@ -25,7 +25,7 @@ module Bundler
|
|
25
25
|
@endpoints = Set.new
|
26
26
|
@info_checksums_by_name = {}
|
27
27
|
@parsed_checksums = false
|
28
|
-
@mutex = Mutex.new
|
28
|
+
@mutex = Thread::Mutex.new
|
29
29
|
end
|
30
30
|
|
31
31
|
def execution_mode=(block)
|
data/lib/bundler/definition.rb
CHANGED
@@ -73,7 +73,6 @@ module Bundler
|
|
73
73
|
@lockfile_contents = String.new
|
74
74
|
@locked_bundler_version = nil
|
75
75
|
@locked_ruby_version = nil
|
76
|
-
@locked_specs_incomplete_for_platform = false
|
77
76
|
@new_platform = nil
|
78
77
|
|
79
78
|
if lockfile && File.exist?(lockfile)
|
@@ -133,12 +132,14 @@ module Bundler
|
|
133
132
|
@unlock[:gems] ||= @dependencies.map(&:name)
|
134
133
|
else
|
135
134
|
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
|
136
|
-
@unlock[:gems] = @locked_specs.for(eager_unlock, false, false
|
135
|
+
@unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
|
137
136
|
end
|
138
137
|
|
139
138
|
@dependency_changes = converge_dependencies
|
140
139
|
@local_changes = converge_locals
|
141
140
|
|
141
|
+
@locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
|
142
|
+
|
142
143
|
@requires = compute_requires
|
143
144
|
end
|
144
145
|
|
@@ -157,10 +158,6 @@ module Bundler
|
|
157
158
|
end
|
158
159
|
end
|
159
160
|
|
160
|
-
def multisource_allowed?
|
161
|
-
@multisource_allowed
|
162
|
-
end
|
163
|
-
|
164
161
|
def resolve_only_locally!
|
165
162
|
@remote = false
|
166
163
|
sources.local_only!
|
@@ -185,15 +182,7 @@ module Bundler
|
|
185
182
|
#
|
186
183
|
# @return [Bundler::SpecSet]
|
187
184
|
def specs
|
188
|
-
@specs ||=
|
189
|
-
rescue GemNotFound => e # Handle yanked gem
|
190
|
-
gem_name, gem_version = extract_gem_info(e)
|
191
|
-
locked_gem = @locked_specs[gem_name].last
|
192
|
-
raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
|
193
|
-
raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
|
194
|
-
"no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
|
195
|
-
"You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
|
196
|
-
"removed in order to install."
|
185
|
+
@specs ||= materialize(requested_dependencies)
|
197
186
|
end
|
198
187
|
|
199
188
|
def new_specs
|
@@ -205,9 +194,7 @@ module Bundler
|
|
205
194
|
end
|
206
195
|
|
207
196
|
def missing_specs
|
208
|
-
|
209
|
-
resolve.materialize(requested_dependencies, missing)
|
210
|
-
missing
|
197
|
+
resolve.materialize(requested_dependencies).missing_specs
|
211
198
|
end
|
212
199
|
|
213
200
|
def missing_specs?
|
@@ -238,17 +225,22 @@ module Bundler
|
|
238
225
|
end
|
239
226
|
end
|
240
227
|
|
228
|
+
def locked_dependencies
|
229
|
+
@locked_deps.values
|
230
|
+
end
|
231
|
+
|
241
232
|
def specs_for(groups)
|
242
|
-
|
233
|
+
return specs if groups.empty?
|
243
234
|
deps = dependencies_for(groups)
|
244
|
-
|
235
|
+
materialize(deps)
|
245
236
|
end
|
246
237
|
|
247
238
|
def dependencies_for(groups)
|
248
239
|
groups.map!(&:to_sym)
|
249
|
-
current_dependencies.reject do |d|
|
240
|
+
deps = current_dependencies.reject do |d|
|
250
241
|
(d.groups & groups).empty?
|
251
242
|
end
|
243
|
+
expand_dependencies(deps)
|
252
244
|
end
|
253
245
|
|
254
246
|
# Resolve all the dependencies specified in Gemfile. It ensures that
|
@@ -274,10 +266,6 @@ module Bundler
|
|
274
266
|
end
|
275
267
|
end
|
276
268
|
|
277
|
-
def has_rubygems_remotes?
|
278
|
-
sources.rubygems_sources.any? {|s| s.remotes.any? }
|
279
|
-
end
|
280
|
-
|
281
269
|
def spec_git_paths
|
282
270
|
sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
|
283
271
|
end
|
@@ -376,44 +364,26 @@ module Bundler
|
|
376
364
|
added.concat new_platforms.map {|p| "* platform: #{p}" }
|
377
365
|
deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
|
378
366
|
|
379
|
-
|
380
|
-
|
381
|
-
new_sources = gemfile_sources - @locked_sources
|
382
|
-
deleted_sources = @locked_sources - gemfile_sources
|
383
|
-
|
384
|
-
new_deps = @dependencies - @locked_deps.values
|
385
|
-
deleted_deps = @locked_deps.values - @dependencies
|
386
|
-
|
387
|
-
# Check if it is possible that the source is only changed thing
|
388
|
-
if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
|
389
|
-
new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
|
390
|
-
deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
|
391
|
-
end
|
392
|
-
|
393
|
-
if @locked_sources != gemfile_sources
|
394
|
-
if new_sources.any?
|
395
|
-
added.concat new_sources.map {|source| "* source: #{source}" }
|
396
|
-
end
|
397
|
-
|
398
|
-
if deleted_sources.any?
|
399
|
-
deleted.concat deleted_sources.map {|source| "* source: #{source}" }
|
400
|
-
end
|
401
|
-
end
|
367
|
+
new_deps = @dependencies - locked_dependencies
|
368
|
+
deleted_deps = locked_dependencies - @dependencies
|
402
369
|
|
403
370
|
added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
|
404
|
-
if deleted_deps.any?
|
405
|
-
deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
|
406
|
-
end
|
371
|
+
deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
|
407
372
|
|
408
373
|
both_sources = Hash.new {|h, k| h[k] = [] }
|
409
374
|
@dependencies.each {|d| both_sources[d.name][0] = d }
|
410
|
-
|
375
|
+
locked_dependencies.each {|d| both_sources[d.name][1] = d }
|
376
|
+
|
377
|
+
both_sources.each do |name, (dep, lock_dep)|
|
378
|
+
next if dep.nil? || lock_dep.nil?
|
411
379
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
380
|
+
gemfile_source = dep.source || sources.default_source
|
381
|
+
lock_source = lock_dep.source || sources.default_source
|
382
|
+
next if lock_source.include?(gemfile_source)
|
383
|
+
|
384
|
+
gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
|
385
|
+
lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
|
386
|
+
changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
|
417
387
|
end
|
418
388
|
|
419
389
|
reason = change_reason
|
@@ -493,7 +463,23 @@ module Bundler
|
|
493
463
|
|
494
464
|
private
|
495
465
|
|
496
|
-
def
|
466
|
+
def materialize(dependencies)
|
467
|
+
specs = resolve.materialize(dependencies)
|
468
|
+
missing_specs = specs.missing_specs
|
469
|
+
|
470
|
+
if missing_specs.any?
|
471
|
+
missing_specs.each do |s|
|
472
|
+
locked_gem = @locked_specs[s.name].last
|
473
|
+
next if locked_gem.nil? || locked_gem.version != s.version || !@remote
|
474
|
+
raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
|
475
|
+
"no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
|
476
|
+
"You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
|
477
|
+
"removed in order to install."
|
478
|
+
end
|
479
|
+
|
480
|
+
raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
|
481
|
+
end
|
482
|
+
|
497
483
|
unless specs["bundler"].any?
|
498
484
|
bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
|
499
485
|
specs["bundler"] = bundler
|
@@ -503,7 +489,7 @@ module Bundler
|
|
503
489
|
end
|
504
490
|
|
505
491
|
def precompute_source_requirements_for_indirect_dependencies?
|
506
|
-
sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
|
492
|
+
@remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
|
507
493
|
end
|
508
494
|
|
509
495
|
def current_ruby_platform_locked?
|
@@ -558,7 +544,7 @@ module Bundler
|
|
558
544
|
|
559
545
|
def dependencies_for_source_changed?(source, locked_source = source)
|
560
546
|
deps_for_source = @dependencies.select {|s| s.source == source }
|
561
|
-
locked_deps_for_source =
|
547
|
+
locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
|
562
548
|
|
563
549
|
deps_for_source.uniq.sort != locked_deps_for_source.sort
|
564
550
|
end
|
@@ -641,25 +627,14 @@ module Bundler
|
|
641
627
|
end
|
642
628
|
|
643
629
|
def converge_dependencies
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
# after locked_source and sources don't match, we still use locked_source.
|
649
|
-
if frozen && !locked_source.nil? &&
|
650
|
-
locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
|
651
|
-
dep.source = locked_source.source
|
652
|
-
elsif dep.source
|
630
|
+
changes = false
|
631
|
+
|
632
|
+
@dependencies.each do |dep|
|
633
|
+
if dep.source
|
653
634
|
dep.source = sources.get(dep.source)
|
654
635
|
end
|
655
|
-
end
|
656
636
|
|
657
|
-
|
658
|
-
# We want to know if all match, but don't want to check all entries
|
659
|
-
# This means we need to return false if any dependency doesn't match
|
660
|
-
# the lock or doesn't exist in the lock.
|
661
|
-
@dependencies.each do |dependency|
|
662
|
-
unless locked_dep = @locked_deps[dependency.name]
|
637
|
+
unless locked_dep = @locked_deps[dep.name]
|
663
638
|
changes = true
|
664
639
|
next
|
665
640
|
end
|
@@ -670,11 +645,11 @@ module Bundler
|
|
670
645
|
# directive, the lockfile dependencies and resolved dependencies end up
|
671
646
|
# with a mismatch on #type. Work around that by setting the type on the
|
672
647
|
# dep from the lockfile.
|
673
|
-
locked_dep.instance_variable_set(:@type,
|
648
|
+
locked_dep.instance_variable_set(:@type, dep.type)
|
674
649
|
|
675
650
|
# We already know the name matches from the hash lookup
|
676
651
|
# so we only need to check the requirement now
|
677
|
-
changes ||=
|
652
|
+
changes ||= dep.requirement != locked_dep.requirement
|
678
653
|
end
|
679
654
|
|
680
655
|
changes
|
@@ -684,39 +659,36 @@ module Bundler
|
|
684
659
|
# commonly happen if the Gemfile has changed since the lockfile was last
|
685
660
|
# generated
|
686
661
|
def converge_locked_specs
|
687
|
-
|
662
|
+
resolve = converge_specs(@locked_specs)
|
688
663
|
|
689
|
-
|
690
|
-
# and Gemfile.lock. If the Gemfile modified a dependency, but
|
691
|
-
# the gem in the Gemfile.lock still satisfies it, this is fine
|
692
|
-
# too.
|
693
|
-
@dependencies.each do |dep|
|
694
|
-
locked_dep = @locked_deps[dep.name]
|
664
|
+
diff = nil
|
695
665
|
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
|
700
|
-
deps << dep
|
701
|
-
elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
|
702
|
-
@locked_specs.each do |s|
|
703
|
-
@unlock[:gems] << s.name if s.source == dep.source
|
704
|
-
end
|
666
|
+
# Now, we unlock any sources that do not have anymore gems pinned to it
|
667
|
+
sources.all_sources.each do |source|
|
668
|
+
next unless source.respond_to?(:unlock!)
|
705
669
|
|
706
|
-
|
707
|
-
|
670
|
+
unless resolve.any? {|s| s.source == source }
|
671
|
+
diff ||= @locked_specs.to_a - resolve.to_a
|
672
|
+
source.unlock! if diff.any? {|s| s.source == source }
|
708
673
|
end
|
709
674
|
end
|
710
675
|
|
676
|
+
resolve
|
677
|
+
end
|
678
|
+
|
679
|
+
def converge_specs(specs)
|
680
|
+
deps = []
|
711
681
|
converged = []
|
712
|
-
|
682
|
+
specs.each do |s|
|
713
683
|
# Replace the locked dependency's source with the equivalent source from the Gemfile
|
714
684
|
dep = @dependencies.find {|d| s.satisfies?(d) }
|
715
|
-
s.source = (dep && dep.source) || sources.get(s.source)
|
716
685
|
|
717
|
-
|
718
|
-
|
719
|
-
|
686
|
+
if dep && (!dep.source || s.source.include?(dep.source))
|
687
|
+
deps << dep
|
688
|
+
end
|
689
|
+
|
690
|
+
s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?
|
691
|
+
|
720
692
|
next if @unlock[:sources].include?(s.source.name)
|
721
693
|
|
722
694
|
# If the spec is from a path source and it doesn't exist anymore
|
@@ -729,8 +701,8 @@ module Bundler
|
|
729
701
|
rescue PathError, GitError
|
730
702
|
# if we won't need the source (according to the lockfile),
|
731
703
|
# don't error if the path/git source isn't available
|
732
|
-
next if
|
733
|
-
for(requested_dependencies, false, true
|
704
|
+
next if specs.
|
705
|
+
for(requested_dependencies, false, true).
|
734
706
|
none? {|locked_spec| locked_spec.source == s.source }
|
735
707
|
|
736
708
|
raise
|
@@ -745,36 +717,15 @@ module Bundler
|
|
745
717
|
s.dependencies.replace(new_spec.dependencies)
|
746
718
|
end
|
747
719
|
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
@locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
|
753
|
-
resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
|
754
|
-
diff = nil
|
755
|
-
|
756
|
-
# Now, we unlock any sources that do not have anymore gems pinned to it
|
757
|
-
sources.all_sources.each do |source|
|
758
|
-
next unless source.respond_to?(:unlock!)
|
759
|
-
|
760
|
-
unless resolve.any? {|s| s.source == source }
|
761
|
-
diff ||= @locked_specs.to_a - resolve.to_a
|
762
|
-
source.unlock! if diff.any? {|s| s.source == source }
|
720
|
+
if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
|
721
|
+
@unlock[:gems] << s.name
|
722
|
+
else
|
723
|
+
converged << s
|
763
724
|
end
|
764
725
|
end
|
765
726
|
|
766
|
-
resolve
|
767
|
-
|
768
|
-
|
769
|
-
def in_locked_deps?(dep, locked_dep)
|
770
|
-
# Because the lockfile can't link a dep to a specific remote, we need to
|
771
|
-
# treat sources as equivalent anytime the locked dep has all the remotes
|
772
|
-
# that the Gemfile dep does.
|
773
|
-
locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
|
774
|
-
end
|
775
|
-
|
776
|
-
def satisfies_locked_spec?(dep)
|
777
|
-
@locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
|
727
|
+
resolve = SpecSet.new(converged)
|
728
|
+
SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
|
778
729
|
end
|
779
730
|
|
780
731
|
def metadata_dependencies
|
@@ -854,12 +805,6 @@ module Bundler
|
|
854
805
|
current == proposed
|
855
806
|
end
|
856
807
|
|
857
|
-
def extract_gem_info(error)
|
858
|
-
# This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
|
859
|
-
# to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
|
860
|
-
error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
|
861
|
-
end
|
862
|
-
|
863
808
|
def compute_requires
|
864
809
|
dependencies.reduce({}) do |requires, dep|
|
865
810
|
next requires unless dep.should_include?
|
@@ -873,22 +818,11 @@ module Bundler
|
|
873
818
|
|
874
819
|
def additional_base_requirements_for_resolve
|
875
820
|
return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
|
876
|
-
|
877
|
-
@locked_gems.specs.reduce({}) do |requirements, locked_spec|
|
821
|
+
converge_specs(@locked_gems.specs).map do |locked_spec|
|
878
822
|
name = locked_spec.name
|
879
|
-
dependency = dependencies_by_name[name]
|
880
|
-
next requirements if @locked_gems.dependencies[name] != dependency
|
881
|
-
next requirements if dependency && dependency.source.is_a?(Source::Path)
|
882
823
|
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
|
883
|
-
|
884
|
-
|
885
|
-
end.values
|
886
|
-
end
|
887
|
-
|
888
|
-
def equivalent_rubygems_remotes?(source)
|
889
|
-
return false unless source.is_a?(Source::Rubygems)
|
890
|
-
|
891
|
-
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
|
824
|
+
DepProxy.get_proxy(dep, locked_spec.platform)
|
825
|
+
end
|
892
826
|
end
|
893
827
|
|
894
828
|
def source_map
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This code was extracted from https://github.com/Solistra/ruby-digest which is under public domain
|
4
|
+
module Bundler
|
5
|
+
module Digest
|
6
|
+
# The initial constant values for the 32-bit constant words A, B, C, D, and
|
7
|
+
# E, respectively.
|
8
|
+
SHA1_WORDS = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0].freeze
|
9
|
+
|
10
|
+
# The 8-bit field used for bitwise `AND` masking. Defaults to `0xFFFFFFFF`.
|
11
|
+
SHA1_MASK = 0xFFFFFFFF
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def sha1(string)
|
15
|
+
unless string.is_a?(String)
|
16
|
+
raise TypeError, "can't convert #{string.class.inspect} into String"
|
17
|
+
end
|
18
|
+
|
19
|
+
buffer = string.b
|
20
|
+
|
21
|
+
words = SHA1_WORDS.dup
|
22
|
+
generate_split_buffer(buffer) do |chunk|
|
23
|
+
w = []
|
24
|
+
chunk.each_slice(4) do |a, b, c, d|
|
25
|
+
w << (((a << 8 | b) << 8 | c) << 8 | d)
|
26
|
+
end
|
27
|
+
a, b, c, d, e = *words
|
28
|
+
(16..79).each do |i|
|
29
|
+
w[i] = SHA1_MASK & rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1)
|
30
|
+
end
|
31
|
+
0.upto(79) do |i|
|
32
|
+
case i
|
33
|
+
when 0..19
|
34
|
+
f = ((b & c) | (~b & d))
|
35
|
+
k = 0x5A827999
|
36
|
+
when 20..39
|
37
|
+
f = (b ^ c ^ d)
|
38
|
+
k = 0x6ED9EBA1
|
39
|
+
when 40..59
|
40
|
+
f = ((b & c) | (b & d) | (c & d))
|
41
|
+
k = 0x8F1BBCDC
|
42
|
+
when 60..79
|
43
|
+
f = (b ^ c ^ d)
|
44
|
+
k = 0xCA62C1D6
|
45
|
+
end
|
46
|
+
t = SHA1_MASK & (SHA1_MASK & rotate(a, 5) + f + e + k + w[i])
|
47
|
+
a, b, c, d, e = t, a, SHA1_MASK & rotate(b, 30), c, d # rubocop:disable Style/ParallelAssignment
|
48
|
+
end
|
49
|
+
mutated = [a, b, c, d, e]
|
50
|
+
words.map!.with_index {|word, index| SHA1_MASK & (word + mutated[index]) }
|
51
|
+
end
|
52
|
+
|
53
|
+
words.pack("N*").unpack("H*").first
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def generate_split_buffer(string, &block)
|
59
|
+
size = string.bytesize * 8
|
60
|
+
buffer = string.bytes << 128
|
61
|
+
buffer << 0 while buffer.size % 64 != 56
|
62
|
+
buffer.concat([size].pack("Q>").bytes)
|
63
|
+
buffer.each_slice(64, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def rotate(value, spaces)
|
67
|
+
value << spaces | value >> (32 - spaces)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/bundler/dsl.rb
CHANGED
@@ -18,6 +18,8 @@ module Bundler
|
|
18
18
|
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
|
19
19
|
platform platforms type source install_if gemfile].freeze
|
20
20
|
|
21
|
+
GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}.freeze
|
22
|
+
|
21
23
|
attr_reader :gemspecs
|
22
24
|
attr_accessor :dependencies
|
23
25
|
|
@@ -278,8 +280,17 @@ module Bundler
|
|
278
280
|
warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
|
279
281
|
"https://github.com/#{repo_name}.git"
|
280
282
|
RUBY
|
281
|
-
|
282
|
-
|
283
|
+
if repo_name =~ GITHUB_PULL_REQUEST_URL
|
284
|
+
{
|
285
|
+
"git" => "https://github.com/#{$1}.git",
|
286
|
+
"branch" => "refs/pull/#{$2}/head",
|
287
|
+
"ref" => nil,
|
288
|
+
"tag" => nil,
|
289
|
+
}
|
290
|
+
else
|
291
|
+
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
|
292
|
+
"https://github.com/#{repo_name}.git"
|
293
|
+
end
|
283
294
|
end
|
284
295
|
|
285
296
|
git_source(:gist) do |repo_name|
|
@@ -365,7 +376,11 @@ repo_name ||= user_name
|
|
365
376
|
|
366
377
|
git_name = (git_names & opts.keys).last
|
367
378
|
if @git_sources[git_name]
|
368
|
-
|
379
|
+
git_opts = @git_sources[git_name].call(opts[git_name])
|
380
|
+
git_opts = { "git" => git_opts } if git_opts.is_a?(String)
|
381
|
+
opts.merge!(git_opts) do |key, _gemfile_value, _git_source_value|
|
382
|
+
raise GemfileError, %(The :#{key} option can't be used with `#{git_name}: #{opts[git_name].inspect}`)
|
383
|
+
end
|
369
384
|
end
|
370
385
|
|
371
386
|
%w[git path].each do |type|
|
@@ -447,8 +462,21 @@ repo_name ||= user_name
|
|
447
462
|
end
|
448
463
|
|
449
464
|
def check_rubygems_source_safety
|
450
|
-
|
465
|
+
if @sources.implicit_global_source?
|
466
|
+
implicit_global_source_warning
|
467
|
+
elsif @sources.aggregate_global_source?
|
468
|
+
multiple_global_source_warning
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def implicit_global_source_warning
|
473
|
+
Bundler::SharedHelpers.major_deprecation 2, "This Gemfile does not include an explicit global source. " \
|
474
|
+
"Not using an explicit global source may result in a different lockfile being generated depending on " \
|
475
|
+
"the gems you have installed locally before bundler is run. " \
|
476
|
+
"Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"."
|
477
|
+
end
|
451
478
|
|
479
|
+
def multiple_global_source_warning
|
452
480
|
if Bundler.feature_flag.bundler_3_mode?
|
453
481
|
msg = "This Gemfile contains multiple primary sources. " \
|
454
482
|
"Each source after the first must include a block to indicate which gems " \
|
@@ -38,7 +38,10 @@ module Bundler
|
|
38
38
|
|
39
39
|
# Replaces `ENV` with the bundler environment variables backed up
|
40
40
|
def replace_with_backup
|
41
|
-
|
41
|
+
unless Gem.win_platform?
|
42
|
+
ENV.replace(backup)
|
43
|
+
return
|
44
|
+
end
|
42
45
|
|
43
46
|
# Fallback logic for Windows below to workaround
|
44
47
|
# https://bugs.ruby-lang.org/issues/16798. Can be dropped once all
|