bundler 2.5.17 → 2.5.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/lib/bundler/build_metadata.rb +2 -2
  4. data/lib/bundler/cli/add.rb +1 -1
  5. data/lib/bundler/cli/gem.rb +4 -1
  6. data/lib/bundler/cli/install.rb +9 -4
  7. data/lib/bundler/cli/lock.rb +5 -5
  8. data/lib/bundler/cli/outdated.rb +16 -18
  9. data/lib/bundler/definition.rb +15 -26
  10. data/lib/bundler/dsl.rb +27 -17
  11. data/lib/bundler/errors.rb +7 -5
  12. data/lib/bundler/fetcher.rb +2 -2
  13. data/lib/bundler/inline.rb +30 -9
  14. data/lib/bundler/installer/gem_installer.rb +4 -2
  15. data/lib/bundler/installer/parallel_installer.rb +3 -2
  16. data/lib/bundler/installer.rb +9 -11
  17. data/lib/bundler/lockfile_parser.rb +1 -1
  18. data/lib/bundler/man/bundle-add.1 +27 -16
  19. data/lib/bundler/man/bundle-add.1.ronn +37 -14
  20. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  21. data/lib/bundler/man/bundle-cache.1 +1 -1
  22. data/lib/bundler/man/bundle-check.1 +1 -1
  23. data/lib/bundler/man/bundle-clean.1 +1 -1
  24. data/lib/bundler/man/bundle-config.1 +1 -1
  25. data/lib/bundler/man/bundle-console.1 +1 -1
  26. data/lib/bundler/man/bundle-doctor.1 +1 -1
  27. data/lib/bundler/man/bundle-exec.1 +1 -1
  28. data/lib/bundler/man/bundle-gem.1 +1 -1
  29. data/lib/bundler/man/bundle-help.1 +1 -1
  30. data/lib/bundler/man/bundle-info.1 +1 -1
  31. data/lib/bundler/man/bundle-init.1 +1 -1
  32. data/lib/bundler/man/bundle-inject.1 +1 -1
  33. data/lib/bundler/man/bundle-install.1 +1 -1
  34. data/lib/bundler/man/bundle-list.1 +1 -1
  35. data/lib/bundler/man/bundle-lock.1 +1 -1
  36. data/lib/bundler/man/bundle-open.1 +1 -1
  37. data/lib/bundler/man/bundle-outdated.1 +1 -1
  38. data/lib/bundler/man/bundle-platform.1 +1 -1
  39. data/lib/bundler/man/bundle-plugin.1 +1 -1
  40. data/lib/bundler/man/bundle-pristine.1 +1 -1
  41. data/lib/bundler/man/bundle-remove.1 +1 -1
  42. data/lib/bundler/man/bundle-show.1 +1 -1
  43. data/lib/bundler/man/bundle-update.1 +1 -1
  44. data/lib/bundler/man/bundle-version.1 +1 -1
  45. data/lib/bundler/man/bundle-viz.1 +1 -1
  46. data/lib/bundler/man/bundle.1 +1 -1
  47. data/lib/bundler/man/gemfile.5 +3 -1
  48. data/lib/bundler/man/gemfile.5.ronn +6 -0
  49. data/lib/bundler/resolver/base.rb +6 -0
  50. data/lib/bundler/resolver/package.rb +10 -1
  51. data/lib/bundler/resolver.rb +31 -9
  52. data/lib/bundler/retry.rb +1 -1
  53. data/lib/bundler/ruby_version.rb +7 -1
  54. data/lib/bundler/rubygems_ext.rb +43 -16
  55. data/lib/bundler/rubygems_gem_installer.rb +4 -3
  56. data/lib/bundler/self_manager.rb +4 -4
  57. data/lib/bundler/source/git/git_proxy.rb +6 -2
  58. data/lib/bundler/source/git.rb +21 -6
  59. data/lib/bundler/source/path.rb +2 -0
  60. data/lib/bundler/source/rubygems.rb +5 -12
  61. data/lib/bundler/stub_specification.rb +2 -2
  62. data/lib/bundler/templates/newgem/README.md.tt +6 -2
  63. data/lib/bundler/ui/shell.rb +24 -2
  64. data/lib/bundler/ui/silent.rb +12 -1
  65. data/lib/bundler/vendor/securerandom/.document +1 -0
  66. data/lib/bundler/vendor/securerandom/LICENSE.txt +22 -0
  67. data/lib/bundler/vendor/securerandom/lib/random/formatter.rb +373 -0
  68. data/lib/bundler/vendor/securerandom/lib/securerandom.rb +96 -0
  69. data/lib/bundler/vendored_securerandom.rb +14 -0
  70. data/lib/bundler/version.rb +1 -1
  71. data/lib/bundler.rb +30 -22
  72. metadata +8 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60cb5ee8526a6f8eb3c413e7d3d2ae8c9b32315685862943fc2a956f2fdcd5a1
4
- data.tar.gz: 52aa4c3a435ed97c8dbc2adcfa51dc6d2113fefcb5020df0a5b0be3b605cc49f
3
+ metadata.gz: 4d14e278135c6fa088c2fc0837815d8251449d7c0335d422ba2fcaa3e29bc3c8
4
+ data.tar.gz: 9b0704eae91833bf63ab346369e0a0a5e3ed39093cbf19bbc27fe7f8eb5ff1ae
5
5
  SHA512:
6
- metadata.gz: afafe4e932d1840de3938e609f45555b1fbdf3fea481ee6d395a1f1458d579606d2f5ac64edc90d74799d9b117aae3fd1028b6d3a660df97e087bb9f6475d583
7
- data.tar.gz: fd8907298e40c98124857ea7bf2594953d962946b66da695ce929db2623e67dacbee7dec6500a3dfb89cb6308377a26c305a25cd28a7083432ec10baf0d59810
6
+ metadata.gz: cad7762642146a6baba3c8cfab7528e667d0748da24fc442be84cc374bb10a8ef881ec9b87e0f019e4063bbf5112fd9a463ee9aab7567099e40811a9efcf5116
7
+ data.tar.gz: ad30723406fac680a09dac9d4c2dedb202888c86cbcfc79481f905d2d8e3ecde477ba1dda7f0270dedaf386d03b12e782ec350ed7cf83ea80cda5886450bb02f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,71 @@
1
+ # 2.5.21 (October 3, 2024)
2
+
3
+ ## Bug fixes:
4
+
5
+ - Fix bug report template printed when changing a path source to a git source in frozen mode [#8079](https://github.com/rubygems/rubygems/pull/8079)
6
+ - Fix `stub.activated?` sometimes returning false after activation under bundler [#8073](https://github.com/rubygems/rubygems/pull/8073)
7
+ - Fix old cache format detection when application is not source controlled [#8076](https://github.com/rubygems/rubygems/pull/8076)
8
+ - Fix `bundler/inline` resetting ENV changes [#8059](https://github.com/rubygems/rubygems/pull/8059)
9
+
10
+ # 2.5.20 (September 24, 2024)
11
+
12
+ ## Enhancements:
13
+
14
+ - Don't try to auto-install dev versions of Bundler not available remotely [#8045](https://github.com/rubygems/rubygems/pull/8045)
15
+ - Don't try to install locked bundler when `--local` is passed [#8041](https://github.com/rubygems/rubygems/pull/8041)
16
+
17
+ ## Bug fixes:
18
+
19
+ - Fix `bundler/inline` overwriting lockfiles [#8055](https://github.com/rubygems/rubygems/pull/8055)
20
+ - Ensure refs directory in cached git source [#8047](https://github.com/rubygems/rubygems/pull/8047)
21
+ - Fix `bundle outdated` with `--group` option [#8052](https://github.com/rubygems/rubygems/pull/8052)
22
+
23
+ # 2.5.19 (September 18, 2024)
24
+
25
+ ## Enhancements:
26
+
27
+ - Raise original errors when unexpected errors happen during Gemfile evaluation [#8003](https://github.com/rubygems/rubygems/pull/8003)
28
+ - Make an exe file executable when generating new gems [#8020](https://github.com/rubygems/rubygems/pull/8020)
29
+ - Gracefully handle gem activation conflicts in inline mode [#5535](https://github.com/rubygems/rubygems/pull/5535)
30
+ - Don't include hook templates in cached git source [#8013](https://github.com/rubygems/rubygems/pull/8013)
31
+ - Fix some errors about a previous installation folder that's unsafe to remove, when there's no need to remove it [#7985](https://github.com/rubygems/rubygems/pull/7985)
32
+ - Emit progress to stderr during `bundle outdated --parseable` [#7966](https://github.com/rubygems/rubygems/pull/7966)
33
+ - Reject unknown platforms when running `bundle lock --add-platform` [#7967](https://github.com/rubygems/rubygems/pull/7967)
34
+ - Emit progress to stderr when `--print` is passed to `bundle lock` [#7957](https://github.com/rubygems/rubygems/pull/7957)
35
+
36
+ ## Bug fixes:
37
+
38
+ - Fix `bundle install --local` hitting the network when default gems are included [#8027](https://github.com/rubygems/rubygems/pull/8027)
39
+ - Remove temporary `.lock` files unintentionally left around by gem installer [#8022](https://github.com/rubygems/rubygems/pull/8022)
40
+ - Fix `bundle exec rake install` failing when local gem has extensions [#7977](https://github.com/rubygems/rubygems/pull/7977)
41
+ - Load gemspecs in the context of its parent also when using local overrides [#7993](https://github.com/rubygems/rubygems/pull/7993)
42
+ - Fix `bundler/inline` failing in Ruby 3.2 due to conflicting `securerandom` versions [#7984](https://github.com/rubygems/rubygems/pull/7984)
43
+ - Don't blow up when explicit version is removed from some git sources [#7973](https://github.com/rubygems/rubygems/pull/7973)
44
+ - Fix `gem exec rails new project` failing on Ruby 3.2 [#7960](https://github.com/rubygems/rubygems/pull/7960)
45
+
46
+ ## Documentation:
47
+
48
+ - Improve `bundle add` man page [#5903](https://github.com/rubygems/rubygems/pull/5903)
49
+ - Add some documentation about backwards compatibility [#7964](https://github.com/rubygems/rubygems/pull/7964)
50
+
51
+ # 2.5.18 (August 26, 2024)
52
+
53
+ ## Enhancements:
54
+
55
+ - Don't remove existing platform gems when PLATFORMS section is badly indented [#7916](https://github.com/rubygems/rubygems/pull/7916)
56
+
57
+ ## Bug fixes:
58
+
59
+ - Fix error message when Bundler refuses to install due to frozen being set without a lockfile [#7955](https://github.com/rubygems/rubygems/pull/7955)
60
+ - Fix several issues with the `--prefer-local` flag [#7951](https://github.com/rubygems/rubygems/pull/7951)
61
+ - Restore support for passing relative paths to `git:` sources [#7950](https://github.com/rubygems/rubygems/pull/7950)
62
+ - Regenerate previous git application caches that didn't include bare repos [#7926](https://github.com/rubygems/rubygems/pull/7926)
63
+ - Fix `bundle update <indirect_dep>` failing to upgrade when versions present in two different sources [#7915](https://github.com/rubygems/rubygems/pull/7915)
64
+
65
+ ## Documentation:
66
+
67
+ - Change new gem README template to have copyable code blocks [#7935](https://github.com/rubygems/rubygems/pull/7935)
68
+
1
69
  # 2.5.17 (August 1, 2024)
2
70
 
3
71
  ## Enhancements:
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2024-08-01".freeze
8
- @git_commit_sha = "74d92b2502".freeze
7
+ @built_at = "2024-10-03".freeze
8
+ @git_commit_sha = "5cc66a2380b".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -34,7 +34,7 @@ module Bundler
34
34
  end
35
35
 
36
36
  def validate_options!
37
- raise InvalidOption, "You can not specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic]
37
+ raise InvalidOption, "You cannot specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic]
38
38
 
39
39
  # raise error when no gems are specified
40
40
  raise InvalidOption, "Please specify gems to add." if gems.empty?
@@ -191,7 +191,10 @@ module Bundler
191
191
  templates.merge!("standard.yml.tt" => ".standard.yml")
192
192
  end
193
193
 
194
- templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe]
194
+ if config[:exe]
195
+ templates.merge!("exe/newgem.tt" => "exe/#{name}")
196
+ executables.push("exe/#{name}")
197
+ end
195
198
 
196
199
  if extension == "c"
197
200
  templates.merge!(
@@ -12,7 +12,11 @@ module Bundler
12
12
 
13
13
  warn_if_root
14
14
 
15
- Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
15
+ if options[:local]
16
+ Bundler.self_manager.restart_with_locked_bundler_if_needed
17
+ else
18
+ Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
19
+ end
16
20
 
17
21
  Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Gem.freebsd_platform?
18
22
 
@@ -25,9 +29,10 @@ module Bundler
25
29
 
26
30
  if options[:deployment] || options[:frozen] || Bundler.frozen_bundle?
27
31
  unless Bundler.default_lockfile.exist?
28
- flag = "--deployment flag" if options[:deployment]
29
- flag ||= "--frozen flag" if options[:frozen]
30
- flag ||= "deployment setting"
32
+ flag = "--deployment flag" if options[:deployment]
33
+ flag ||= "--frozen flag" if options[:frozen]
34
+ flag ||= "deployment setting" if Bundler.settings[:deployment]
35
+ flag ||= "frozen setting" if Bundler.settings[:frozen]
31
36
  raise ProductionError, "The #{flag} requires a lockfile. Please make " \
32
37
  "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \
33
38
  "before deploying."
@@ -15,8 +15,8 @@ module Bundler
15
15
  end
16
16
 
17
17
  print = options[:print]
18
- previous_ui_level = Bundler.ui.level
19
- Bundler.ui.level = "silent" if print
18
+ previous_output_stream = Bundler.ui.output_stream
19
+ Bundler.ui.output_stream = :stderr if print
20
20
 
21
21
  Bundler::Fetcher.disable_endpoint = options["full-index"]
22
22
 
@@ -48,8 +48,8 @@ module Bundler
48
48
  options["add-platform"].each do |platform_string|
49
49
  platform = Gem::Platform.new(platform_string)
50
50
  if platform.to_s == "unknown"
51
- Bundler.ui.warn "The platform `#{platform_string}` is unknown to RubyGems " \
52
- "and adding it will likely lead to resolution errors"
51
+ Bundler.ui.error "The platform `#{platform_string}` is unknown to RubyGems and can't be added to the lockfile."
52
+ exit 1
53
53
  end
54
54
  definition.add_platform(platform)
55
55
  end
@@ -68,7 +68,7 @@ module Bundler
68
68
  end
69
69
  end
70
70
 
71
- Bundler.ui.level = previous_ui_level
71
+ Bundler.ui.output_stream = previous_output_stream
72
72
  end
73
73
  end
74
74
  end
@@ -54,7 +54,7 @@ module Bundler
54
54
  end
55
55
 
56
56
  if options[:parseable]
57
- Bundler.ui.silence(&definition_resolution)
57
+ Bundler.ui.progress(&definition_resolution)
58
58
  else
59
59
  definition_resolution.call
60
60
  end
@@ -97,28 +97,26 @@ module Bundler
97
97
  }
98
98
  end
99
99
 
100
- if outdated_gems.empty?
100
+ relevant_outdated_gems = if options_include_groups
101
+ outdated_gems.group_by {|g| g[:groups] }.sort.flat_map do |groups, gems|
102
+ contains_group = groups.split(", ").include?(options[:group])
103
+ next unless options[:groups] || contains_group
104
+
105
+ gems
106
+ end.compact
107
+ else
108
+ outdated_gems
109
+ end
110
+
111
+ if relevant_outdated_gems.empty?
101
112
  unless options[:parseable]
102
113
  Bundler.ui.info(nothing_outdated_message)
103
114
  end
104
115
  else
105
- if options_include_groups
106
- relevant_outdated_gems = outdated_gems.group_by {|g| g[:groups] }.sort.flat_map do |groups, gems|
107
- contains_group = groups.split(", ").include?(options[:group])
108
- next unless options[:groups] || contains_group
109
-
110
- gems
111
- end.compact
112
-
113
- if options[:parseable]
114
- print_gems(relevant_outdated_gems)
115
- else
116
- print_gems_table(relevant_outdated_gems)
117
- end
118
- elsif options[:parseable]
119
- print_gems(outdated_gems)
116
+ if options[:parseable]
117
+ print_gems(relevant_outdated_gems)
120
118
  else
121
- print_gems_table(outdated_gems)
119
+ print_gems_table(relevant_outdated_gems)
122
120
  end
123
121
 
124
122
  exit 1
@@ -214,6 +214,7 @@ module Bundler
214
214
  @resolve = nil
215
215
  @resolver = nil
216
216
  @resolution_packages = nil
217
+ @source_requirements = nil
217
218
  @specs = nil
218
219
 
219
220
  Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
@@ -316,7 +317,7 @@ module Bundler
316
317
 
317
318
  def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
318
319
  if [true, false, nil].include?(file_or_preserve_unknown_sections)
319
- target_lockfile = lockfile || Bundler.default_lockfile
320
+ target_lockfile = lockfile
320
321
  preserve_unknown_sections = file_or_preserve_unknown_sections
321
322
  else
322
323
  target_lockfile = file_or_preserve_unknown_sections
@@ -476,9 +477,6 @@ module Bundler
476
477
  end
477
478
  end
478
479
 
479
- attr_reader :sources
480
- private :sources
481
-
482
480
  def nothing_changed?
483
481
  return false unless lockfile_exists?
484
482
 
@@ -502,22 +500,22 @@ module Bundler
502
500
  @unlocking
503
501
  end
504
502
 
503
+ attr_writer :source_requirements
504
+
505
505
  private
506
506
 
507
+ attr_reader :sources
508
+
507
509
  def should_add_extra_platforms?
508
510
  !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
509
511
  end
510
512
 
511
513
  def lockfile_exists?
512
- file_exists?(lockfile)
513
- end
514
-
515
- def file_exists?(file)
516
- file && File.exist?(file)
514
+ lockfile && File.exist?(lockfile)
517
515
  end
518
516
 
519
517
  def write_lock(file, preserve_unknown_sections)
520
- return if Definition.no_lock
518
+ return if Definition.no_lock || file.nil?
521
519
 
522
520
  contents = to_lock
523
521
 
@@ -534,7 +532,7 @@ module Bundler
534
532
 
535
533
  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
536
534
 
537
- if file_exists?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
535
+ if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
538
536
  return if Bundler.frozen_bundle?
539
537
  SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
540
538
  return
@@ -569,7 +567,7 @@ module Bundler
569
567
  @resolution_packages ||= begin
570
568
  last_resolve = converge_locked_specs
571
569
  remove_invalid_platforms!
572
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?)
570
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local)
573
571
  packages = additional_base_requirements_to_prevent_downgrades(packages, last_resolve)
574
572
  packages = additional_base_requirements_to_force_updates(packages)
575
573
  packages
@@ -653,19 +651,6 @@ module Bundler
653
651
  sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
654
652
  end
655
653
 
656
- def pin_locally_available_names(source_requirements)
657
- source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
658
- local_source = original_source.dup
659
- local_source.local_only!
660
-
661
- new_source_requirements[name] = if local_source.specs.search(name).any?
662
- local_source
663
- else
664
- original_source
665
- end
666
- end
667
- end
668
-
669
654
  def current_platform_locked?
670
655
  @platforms.any? do |bundle_platform|
671
656
  MatchPlatform.platforms_match?(bundle_platform, local_platform)
@@ -972,12 +957,15 @@ module Bundler
972
957
  end
973
958
 
974
959
  def source_requirements
960
+ @source_requirements ||= find_source_requirements
961
+ end
962
+
963
+ def find_source_requirements
975
964
  # Record the specs available in each gem's source, so that those
976
965
  # specs will be available later when the resolver knows where to
977
966
  # look for that gemspec (or its dependencies)
978
967
  source_requirements = if precompute_source_requirements_for_indirect_dependencies?
979
968
  all_requirements = source_map.all_requirements
980
- all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
981
969
  { default: default_source }.merge(all_requirements)
982
970
  else
983
971
  { default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
@@ -1053,6 +1041,7 @@ module Bundler
1053
1041
 
1054
1042
  def dup_for_full_unlock
1055
1043
  unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
1044
+ unlocked_definition.source_requirements = source_requirements
1056
1045
  unlocked_definition.gem_version_promoter.tap do |gvp|
1057
1046
  gvp.level = gem_version_promoter.level
1058
1047
  gvp.strict = gem_version_promoter.strict
data/lib/bundler/dsl.rb CHANGED
@@ -42,20 +42,20 @@ module Bundler
42
42
  end
43
43
 
44
44
  def eval_gemfile(gemfile, contents = nil)
45
- expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
46
- original_gemfile = @gemfile
47
- @gemfile = expanded_gemfile_path
48
- @gemfiles << expanded_gemfile_path
49
- contents ||= Bundler.read_file(@gemfile.to_s)
50
- instance_eval(contents, @gemfile.to_s, 1)
51
- rescue Exception => e # rubocop:disable Lint/RescueException
52
- message = "There was an error " \
53
- "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
54
- "`#{File.basename gemfile.to_s}`: #{e.message}"
55
-
56
- raise DSLError.new(message, gemfile, e.backtrace, contents)
57
- ensure
58
- @gemfile = original_gemfile
45
+ with_gemfile(gemfile) do |current_gemfile|
46
+ contents ||= Bundler.read_file(current_gemfile)
47
+ instance_eval(contents, current_gemfile, 1)
48
+ rescue GemfileEvalError => e
49
+ message = "There was an error evaluating `#{File.basename current_gemfile}`: #{e.message}"
50
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
51
+ rescue GemfileError, InvalidArgumentError, InvalidOption, DeprecatedError, ScriptError => e
52
+ message = "There was an error parsing `#{File.basename current_gemfile}`: #{e.message}"
53
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
54
+ rescue StandardError => e
55
+ raise unless e.backtrace_locations.first.path == current_gemfile
56
+ message = "There was an error parsing `#{File.basename current_gemfile}`: #{e.message}"
57
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
58
+ end
59
59
  end
60
60
 
61
61
  def gemspec(opts = nil)
@@ -219,7 +219,7 @@ module Bundler
219
219
  end
220
220
 
221
221
  def github(repo, options = {})
222
- raise ArgumentError, "GitHub sources require a block" unless block_given?
222
+ raise InvalidArgumentError, "GitHub sources require a block" unless block_given?
223
223
  github_uri = @git_sources["github"].call(repo)
224
224
  git_options = normalize_hash(options).merge("uri" => github_uri)
225
225
  git_source = @sources.add_git_source(git_options)
@@ -285,6 +285,16 @@ module Bundler
285
285
 
286
286
  private
287
287
 
288
+ def with_gemfile(gemfile)
289
+ expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
290
+ original_gemfile = @gemfile
291
+ @gemfile = expanded_gemfile_path
292
+ @gemfiles << expanded_gemfile_path
293
+ yield @gemfile.to_s
294
+ ensure
295
+ @gemfile = original_gemfile
296
+ end
297
+
288
298
  def add_git_sources
289
299
  git_source(:github) do |repo_name|
290
300
  if repo_name =~ GITHUB_PULL_REQUEST_URL
@@ -577,7 +587,7 @@ module Bundler
577
587
 
578
588
  return m unless backtrace && dsl_path && contents
579
589
 
580
- trace_line = backtrace.find {|l| l.include?(dsl_path.to_s) } || trace_line
590
+ trace_line = backtrace.find {|l| l.include?(dsl_path) } || trace_line
581
591
  return m unless trace_line
582
592
  line_numer = trace_line.split(":")[1].to_i - 1
583
593
  return m unless line_numer
@@ -603,7 +613,7 @@ module Bundler
603
613
 
604
614
  def parse_line_number_from_description
605
615
  description = self.description
606
- if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/
616
+ if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path}):\d+)/
607
617
  trace_line = Regexp.last_match[1]
608
618
  description = description.sub(/\n.*\n(\.\.\.)? *\^~+$/, "").sub(/#{Regexp.quote trace_line}:\s*/, "").sub("\n", " - ")
609
619
  end
@@ -217,15 +217,15 @@ module Bundler
217
217
  end
218
218
 
219
219
  class InsecureInstallPathError < BundlerError
220
- def initialize(path)
220
+ def initialize(name, path)
221
+ @name = name
221
222
  @path = path
222
223
  end
223
224
 
224
225
  def message
225
- "The installation path is insecure. Bundler cannot continue.\n" \
226
- "#{@path} is world-writable (without sticky bit).\n" \
227
- "Bundler cannot safely replace gems in world-writeable directories due to potential vulnerabilities.\n" \
228
- "Please change the permissions of this directory or choose a different install path."
226
+ "Bundler cannot reinstall #{@name} because there's a previous installation of it at #{@path} that is unsafe to remove.\n" \
227
+ "The parent of #{@path} is world-writable and does not have the sticky bit set, making it insecure to remove due to potential vulnerabilities.\n" \
228
+ "Please change the permissions of #{File.dirname(@path)} or choose a different install path."
229
229
  end
230
230
 
231
231
  status_code(38)
@@ -244,4 +244,6 @@ module Bundler
244
244
 
245
245
  status_code(39)
246
246
  end
247
+
248
+ class InvalidArgumentError < BundlerError; status_code(40); end
247
249
  end
@@ -3,7 +3,7 @@
3
3
  require_relative "vendored_persistent"
4
4
  require_relative "vendored_timeout"
5
5
  require "cgi"
6
- require "securerandom"
6
+ require_relative "vendored_securerandom"
7
7
  require "zlib"
8
8
 
9
9
  module Bundler
@@ -182,7 +182,7 @@ module Bundler
182
182
  agent << " ci/#{cis.join(",")}" if cis.any?
183
183
 
184
184
  # add a random ID so we can consolidate runs server-side
185
- agent << " " << SecureRandom.hex(8)
185
+ agent << " " << Gem::SecureRandom.hex(8)
186
186
 
187
187
  # add any user agent strings set in the config
188
188
  extra_ua = Bundler.settings[:user_agent]
@@ -39,18 +39,20 @@ def gemfile(install = false, options = {}, &gemfile)
39
39
  Bundler.ui = ui
40
40
  raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
41
41
 
42
- Bundler.with_unbundled_env do
42
+ old_gemfile = ENV["BUNDLE_GEMFILE"]
43
+
44
+ Bundler.unbundle_env!
45
+
46
+ begin
43
47
  Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
44
48
  Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
45
49
 
46
50
  Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
47
51
  builder = Bundler::Dsl.new
48
52
  builder.instance_eval(&gemfile)
49
- builder.check_primary_source_safety
50
53
 
51
54
  Bundler.settings.temporary(deployment: false, frozen: false) do
52
55
  definition = builder.to_definition(nil, true)
53
- def definition.lock(*); end
54
56
  definition.validate_runtime!
55
57
 
56
58
  if install || definition.missing_specs?
@@ -62,12 +64,31 @@ def gemfile(install = false, options = {}, &gemfile)
62
64
  end
63
65
  end
64
66
 
65
- runtime = Bundler::Runtime.new(nil, definition)
66
- runtime.setup.require
67
- end
68
- end
67
+ begin
68
+ runtime = Bundler::Runtime.new(nil, definition).setup
69
+ rescue Gem::LoadError => e
70
+ name = e.name
71
+ version = e.requirement.requirements.first[1]
72
+ activated_version = Gem.loaded_specs[name].version
73
+
74
+ Bundler.ui.info \
75
+ "The #{name} gem was resolved to #{version}, but #{activated_version} was activated by Bundler while installing it, causing a conflict. " \
76
+ "Bundler will now retry resolving with #{activated_version} instead."
69
77
 
70
- if ENV["BUNDLE_GEMFILE"].nil?
71
- ENV["BUNDLE_GEMFILE"] = ""
78
+ builder.dependencies.delete_if {|d| d.name == name }
79
+ builder.instance_eval { gem name, activated_version }
80
+ definition = builder.to_definition(nil, true)
81
+
82
+ retry
83
+ end
84
+
85
+ runtime.require
86
+ end
87
+ ensure
88
+ if old_gemfile
89
+ ENV["BUNDLE_GEMFILE"] = old_gemfile
90
+ else
91
+ ENV["BUNDLE_GEMFILE"] = ""
92
+ end
72
93
  end
73
94
  end
@@ -2,14 +2,15 @@
2
2
 
3
3
  module Bundler
4
4
  class GemInstaller
5
- attr_reader :spec, :standalone, :worker, :force, :installer
5
+ attr_reader :spec, :standalone, :worker, :force, :local, :installer
6
6
 
7
- def initialize(spec, installer, standalone = false, worker = 0, force = false)
7
+ def initialize(spec, installer, standalone = false, worker = 0, force = false, local = false)
8
8
  @spec = spec
9
9
  @installer = installer
10
10
  @standalone = standalone
11
11
  @worker = worker
12
12
  @force = force
13
+ @local = local
13
14
  end
14
15
 
15
16
  def install_from_spec
@@ -54,6 +55,7 @@ module Bundler
54
55
  spec.source.install(
55
56
  spec,
56
57
  force: force,
58
+ local: local,
57
59
  build_args: Array(spec_settings),
58
60
  previous_spec: previous_spec,
59
61
  )
@@ -68,11 +68,12 @@ module Bundler
68
68
 
69
69
  attr_reader :size
70
70
 
71
- def initialize(installer, all_specs, size, standalone, force, skip: nil)
71
+ def initialize(installer, all_specs, size, standalone, force, local: false, skip: nil)
72
72
  @installer = installer
73
73
  @size = size
74
74
  @standalone = standalone
75
75
  @force = force
76
+ @local = local
76
77
  @specs = all_specs.map {|s| SpecInstallation.new(s) }
77
78
  @specs.each do |spec_install|
78
79
  spec_install.state = :installed if skip.include?(spec_install.name)
@@ -127,7 +128,7 @@ module Bundler
127
128
  def do_install(spec_install, worker_num)
128
129
  Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL, spec_install)
129
130
  gem_installer = Bundler::GemInstaller.new(
130
- spec_install.spec, @installer, @standalone, worker_num, @force
131
+ spec_install.spec, @installer, @standalone, worker_num, @force, @local
131
132
  )
132
133
  success, message = gem_installer.install_from_spec
133
134
  if success
@@ -194,9 +194,14 @@ module Bundler
194
194
  # that said, it's a rare situation (other than rake), and parallel
195
195
  # installation is SO MUCH FASTER. so we let people opt in.
196
196
  def install(options)
197
- force = options["force"]
197
+ standalone = options[:standalone]
198
+ force = options[:force]
199
+ local = options[:local]
198
200
  jobs = installation_parallelization(options)
199
- install_in_parallel jobs, options[:standalone], force
201
+ spec_installations = ParallelInstaller.call(self, @definition.specs, jobs, standalone, force, local: local)
202
+ spec_installations.each do |installation|
203
+ post_install_messages[installation.name] = installation.post_install_message if installation.has_post_install_message?
204
+ end
200
205
  end
201
206
 
202
207
  def installation_parallelization(options)
@@ -238,18 +243,11 @@ module Bundler
238
243
  end
239
244
  end
240
245
 
241
- def install_in_parallel(size, standalone, force = false)
242
- spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force)
243
- spec_installations.each do |installation|
244
- post_install_messages[installation.name] = installation.post_install_message if installation.has_post_install_message?
245
- end
246
- end
247
-
248
246
  # returns whether or not a re-resolve was needed
249
247
  def resolve_if_needed(options)
250
- @definition.prefer_local! if options["prefer-local"]
248
+ @definition.prefer_local! if options[:"prefer-local"]
251
249
 
252
- if options["local"] || (@definition.no_resolve_needed? && !@definition.missing_specs?)
250
+ if options[:local] || (@definition.no_resolve_needed? && !@definition.missing_specs?)
253
251
  @definition.resolve_with_cache!
254
252
  false
255
253
  else
@@ -272,7 +272,7 @@ module Bundler
272
272
  end
273
273
 
274
274
  def parse_platform(line)
275
- @platforms << Gem::Platform.new($1) if line =~ /^ (.*)$/
275
+ @platforms << Gem::Platform.new($1.strip) if line =~ /^ (.*)$/
276
276
  end
277
277
 
278
278
  def parse_bundled_with(line)