bundler 1.16.1 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +195 -0
  3. data/README.md +5 -1
  4. data/bundler.gemspec +9 -2
  5. data/lib/bundler/build_metadata.rb +19 -4
  6. data/lib/bundler/cli/add.rb +15 -5
  7. data/lib/bundler/cli/binstubs.rb +8 -2
  8. data/lib/bundler/cli/check.rb +1 -1
  9. data/lib/bundler/cli/doctor.rb +47 -1
  10. data/lib/bundler/cli/exec.rb +4 -4
  11. data/lib/bundler/cli/gem.rb +5 -2
  12. data/lib/bundler/cli/init.rb +5 -0
  13. data/lib/bundler/cli/install.rb +10 -7
  14. data/lib/bundler/cli/list.rb +41 -5
  15. data/lib/bundler/cli/outdated.rb +8 -2
  16. data/lib/bundler/cli/pristine.rb +4 -0
  17. data/lib/bundler/cli/remove.rb +18 -0
  18. data/lib/bundler/cli/update.rb +3 -3
  19. data/lib/bundler/cli.rb +66 -22
  20. data/lib/bundler/compact_index_client/updater.rb +10 -1
  21. data/lib/bundler/current_ruby.rb +8 -1
  22. data/lib/bundler/definition.rb +48 -39
  23. data/lib/bundler/dep_proxy.rb +2 -2
  24. data/lib/bundler/dependency.rb +3 -2
  25. data/lib/bundler/deprecate.rb +2 -1
  26. data/lib/bundler/dsl.rb +19 -3
  27. data/lib/bundler/endpoint_specification.rb +1 -1
  28. data/lib/bundler/env.rb +10 -8
  29. data/lib/bundler/feature_flag.rb +7 -0
  30. data/lib/bundler/fetcher/downloader.rb +10 -5
  31. data/lib/bundler/fetcher/index.rb +2 -2
  32. data/lib/bundler/fetcher.rb +3 -3
  33. data/lib/bundler/friendly_errors.rb +2 -0
  34. data/lib/bundler/gem_helper.rb +1 -1
  35. data/lib/bundler/gem_version_promoter.rb +16 -2
  36. data/lib/bundler/injector.rb +173 -14
  37. data/lib/bundler/installer/gem_installer.rb +9 -2
  38. data/lib/bundler/installer/parallel_installer.rb +6 -1
  39. data/lib/bundler/installer.rb +41 -10
  40. data/lib/bundler/lazy_specification.rb +1 -1
  41. data/lib/bundler/mirror.rb +2 -2
  42. data/lib/bundler/plugin/events.rb +61 -0
  43. data/lib/bundler/plugin/index.rb +7 -2
  44. data/lib/bundler/plugin.rb +12 -5
  45. data/lib/bundler/process_lock.rb +1 -1
  46. data/lib/bundler/resolver/spec_group.rb +0 -5
  47. data/lib/bundler/resolver.rb +11 -10
  48. data/lib/bundler/ruby_version.rb +1 -1
  49. data/lib/bundler/rubygems_gem_installer.rb +7 -0
  50. data/lib/bundler/rubygems_integration.rb +9 -3
  51. data/lib/bundler/runtime.rb +10 -4
  52. data/lib/bundler/settings/validator.rb +23 -0
  53. data/lib/bundler/settings.rb +24 -3
  54. data/lib/bundler/shared_helpers.rb +33 -5
  55. data/lib/bundler/source/git/git_proxy.rb +6 -1
  56. data/lib/bundler/source/git.rb +2 -1
  57. data/lib/bundler/source/metadata.rb +2 -3
  58. data/lib/bundler/source/rubygems/remote.rb +4 -1
  59. data/lib/bundler/source/rubygems.rb +11 -2
  60. data/lib/bundler/source.rb +9 -9
  61. data/lib/bundler/spec_set.rb +4 -1
  62. data/lib/bundler/templates/Executable +1 -1
  63. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
  64. data/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
  65. data/lib/bundler/templates/newgem/travis.yml.tt +2 -0
  66. data/lib/bundler/ui/shell.rb +3 -1
  67. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -1
  68. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +7 -2
  69. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  70. data/lib/bundler/version.rb +1 -1
  71. data/lib/bundler.rb +38 -16
  72. data/man/bundle-add.1 +18 -3
  73. data/man/bundle-add.1.txt +17 -5
  74. data/man/bundle-add.ronn +13 -2
  75. data/man/bundle-binstubs.1 +4 -4
  76. data/man/bundle-binstubs.1.txt +4 -4
  77. data/man/bundle-binstubs.ronn +3 -3
  78. data/man/bundle-check.1 +4 -4
  79. data/man/bundle-check.1.txt +6 -5
  80. data/man/bundle-check.ronn +3 -3
  81. data/man/bundle-clean.1 +1 -1
  82. data/man/bundle-clean.1.txt +1 -1
  83. data/man/bundle-config.1 +48 -6
  84. data/man/bundle-config.1.txt +64 -26
  85. data/man/bundle-config.ronn +34 -9
  86. data/man/bundle-doctor.1 +44 -0
  87. data/man/bundle-doctor.1.txt +44 -0
  88. data/man/bundle-doctor.ronn +33 -0
  89. data/man/bundle-exec.1 +4 -4
  90. data/man/bundle-exec.1.txt +9 -9
  91. data/man/bundle-exec.ronn +3 -3
  92. data/man/bundle-gem.1 +2 -2
  93. data/man/bundle-gem.1.txt +2 -2
  94. data/man/bundle-gem.ronn +1 -1
  95. data/man/bundle-info.1 +1 -1
  96. data/man/bundle-info.1.txt +1 -1
  97. data/man/bundle-init.1 +9 -4
  98. data/man/bundle-init.1.txt +16 -6
  99. data/man/bundle-init.ronn +15 -4
  100. data/man/bundle-inject.1 +4 -4
  101. data/man/bundle-inject.1.txt +5 -5
  102. data/man/bundle-inject.ronn +3 -3
  103. data/man/bundle-install.1 +7 -4
  104. data/man/bundle-install.1.txt +119 -108
  105. data/man/bundle-install.ronn +13 -4
  106. data/man/bundle-list.1 +32 -2
  107. data/man/bundle-list.1.txt +24 -2
  108. data/man/bundle-list.ronn +19 -1
  109. data/man/bundle-lock.1 +2 -2
  110. data/man/bundle-lock.1.txt +2 -2
  111. data/man/bundle-lock.ronn +1 -1
  112. data/man/bundle-open.1 +1 -1
  113. data/man/bundle-open.1.txt +1 -1
  114. data/man/bundle-outdated.1 +7 -3
  115. data/man/bundle-outdated.1.txt +11 -7
  116. data/man/bundle-outdated.ronn +5 -1
  117. data/man/bundle-package.1 +3 -3
  118. data/man/bundle-package.1.txt +6 -6
  119. data/man/bundle-package.ronn +3 -3
  120. data/man/bundle-platform.1 +1 -1
  121. data/man/bundle-platform.1.txt +1 -1
  122. data/man/bundle-pristine.1 +1 -1
  123. data/man/bundle-pristine.1.txt +1 -1
  124. data/man/bundle-remove.1 +31 -0
  125. data/man/bundle-remove.1.txt +34 -0
  126. data/man/bundle-remove.ronn +23 -0
  127. data/man/bundle-show.1 +3 -3
  128. data/man/bundle-show.1.txt +6 -4
  129. data/man/bundle-show.ronn +3 -2
  130. data/man/bundle-update.1 +17 -13
  131. data/man/bundle-update.1.txt +68 -63
  132. data/man/bundle-update.ronn +19 -15
  133. data/man/bundle-viz.1 +2 -2
  134. data/man/bundle-viz.1.txt +3 -2
  135. data/man/bundle-viz.ronn +1 -1
  136. data/man/bundle.1 +32 -28
  137. data/man/bundle.1.txt +31 -28
  138. data/man/bundle.ronn +30 -27
  139. data/man/gemfile.5 +19 -9
  140. data/man/gemfile.5.ronn +24 -9
  141. data/man/gemfile.5.txt +114 -97
  142. data/man/index.txt +2 -0
  143. metadata +16 -3
@@ -30,6 +30,7 @@ module Bundler
30
30
  settings_flag(:allow_bundler_dependency_conflicts) { bundler_2_mode? }
31
31
  settings_flag(:allow_offline_install) { bundler_2_mode? }
32
32
  settings_flag(:auto_clean_without_path) { bundler_2_mode? }
33
+ settings_flag(:auto_config_jobs) { bundler_2_mode? }
33
34
  settings_flag(:cache_all) { bundler_2_mode? }
34
35
  settings_flag(:cache_command_is_package) { bundler_2_mode? }
35
36
  settings_flag(:console_command) { !bundler_2_mode? }
@@ -38,11 +39,13 @@ module Bundler
38
39
  settings_flag(:disable_multisource) { bundler_2_mode? }
39
40
  settings_flag(:error_on_stderr) { bundler_2_mode? }
40
41
  settings_flag(:forget_cli_options) { bundler_2_mode? }
42
+ settings_flag(:global_path_appends_ruby_scope) { bundler_2_mode? }
41
43
  settings_flag(:global_gem_cache) { bundler_2_mode? }
42
44
  settings_flag(:init_gems_rb) { bundler_2_mode? }
43
45
  settings_flag(:list_command) { bundler_2_mode? }
44
46
  settings_flag(:lockfile_uses_separate_rubygems_sources) { bundler_2_mode? }
45
47
  settings_flag(:only_update_to_newer_versions) { bundler_2_mode? }
48
+ settings_flag(:path_relative_to_cwd) { bundler_2_mode? }
46
49
  settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
47
50
  settings_flag(:prefer_gems_rb) { bundler_2_mode? }
48
51
  settings_flag(:print_only_version_number) { bundler_2_mode? }
@@ -52,9 +55,13 @@ module Bundler
52
55
  settings_flag(:suppress_install_using_messages) { bundler_2_mode? }
53
56
  settings_flag(:unlock_source_unlocks_spec) { !bundler_2_mode? }
54
57
  settings_flag(:update_requires_all_flag) { bundler_2_mode? }
58
+ settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_2_mode? }
59
+ settings_flag(:viz_command) { !bundler_2_mode? }
55
60
 
56
61
  settings_option(:default_cli_command) { bundler_2_mode? ? :cli_help : :install }
57
62
 
63
+ settings_method(:github_https?, "github.https") { bundler_2_mode? }
64
+
58
65
  def initialize(bundler_version)
59
66
  @bundler_version = Gem::Version.create(bundler_version)
60
67
  end
@@ -11,10 +11,10 @@ module Bundler
11
11
  @redirect_limit = redirect_limit
12
12
  end
13
13
 
14
- def fetch(uri, options = {}, counter = 0)
14
+ def fetch(uri, headers = {}, counter = 0)
15
15
  raise HTTPError, "Too many redirects" if counter >= redirect_limit
16
16
 
17
- response = request(uri, options)
17
+ response = request(uri, headers)
18
18
  Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}")
19
19
 
20
20
  case response
@@ -26,7 +26,12 @@ module Bundler
26
26
  new_uri.user = uri.user
27
27
  new_uri.password = uri.password
28
28
  end
29
- fetch(new_uri, options, counter + 1)
29
+ fetch(new_uri, headers, counter + 1)
30
+ when Net::HTTPRequestedRangeNotSatisfiable
31
+ new_headers = headers.dup
32
+ new_headers.delete("Range")
33
+ new_headers["Accept-Encoding"] = "gzip"
34
+ fetch(uri, new_headers)
30
35
  when Net::HTTPRequestEntityTooLarge
31
36
  raise FallbackError, response.body
32
37
  when Net::HTTPUnauthorized
@@ -38,11 +43,11 @@ module Bundler
38
43
  end
39
44
  end
40
45
 
41
- def request(uri, options)
46
+ def request(uri, headers)
42
47
  validate_uri_scheme!(uri)
43
48
 
44
49
  Bundler.ui.debug "HTTP GET #{uri}"
45
- req = Net::HTTP::Get.new uri.request_uri, options
50
+ req = Net::HTTP::Get.new uri.request_uri, headers
46
51
  if uri.user
47
52
  user = CGI.unescape(uri.user)
48
53
  password = uri.password ? CGI.unescape(uri.password) : nil
@@ -29,11 +29,11 @@ module Bundler
29
29
 
30
30
  uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
31
31
  if uri.scheme == "file"
32
- Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path))
32
+ Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(uri.path))
33
33
  elsif cached_spec_path = gemspec_cached_path(spec_file_name)
34
34
  Bundler.load_gemspec(cached_spec_path)
35
35
  else
36
- Bundler.load_marshal Gem.inflate(downloader.fetch(uri).body)
36
+ Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
37
37
  end
38
38
  rescue MarshalError
39
39
  raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
@@ -96,11 +96,11 @@ module Bundler
96
96
 
97
97
  uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
98
98
  if uri.scheme == "file"
99
- Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path))
99
+ Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(uri.path))
100
100
  elsif cached_spec_path = gemspec_cached_path(spec_file_name)
101
101
  Bundler.load_gemspec(cached_spec_path)
102
102
  else
103
- Bundler.load_marshal Gem.inflate(downloader.fetch(uri).body)
103
+ Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
104
104
  end
105
105
  rescue MarshalError
106
106
  raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
@@ -178,7 +178,7 @@ module Bundler
178
178
  # engine_version raises on unknown engines
179
179
  engine_version = begin
180
180
  ruby.engine_versions
181
- rescue
181
+ rescue RuntimeError
182
182
  "???"
183
183
  end
184
184
  agent << " #{ruby.engine}/#{ruby.versions_string(engine_version)}"
@@ -45,6 +45,8 @@ module Bundler
45
45
  "Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)."
46
46
  else request_issue_report_for(error)
47
47
  end
48
+ rescue
49
+ raise error
48
50
  end
49
51
 
50
52
  def exit_status(error)
@@ -153,7 +153,7 @@ module Bundler
153
153
  sh "git tag -m \"Version #{version}\" #{version_tag}"
154
154
  Bundler.ui.confirm "Tagged #{version_tag}."
155
155
  yield if block_given?
156
- rescue
156
+ rescue RuntimeError
157
157
  Bundler.ui.error "Untagging #{version_tag} due to error."
158
158
  sh_with_code "git tag -d #{version_tag}"
159
159
  raise
@@ -7,6 +7,8 @@ module Bundler
7
7
  # available dependency versions as found in its index, before returning it to
8
8
  # to the resolution engine to select the best version.
9
9
  class GemVersionPromoter
10
+ DEBUG = ENV["DEBUG_RESOLVER"]
11
+
10
12
  attr_reader :level, :locked_specs, :unlock_gems
11
13
 
12
14
  # By default, strict is false, meaning every available version of a gem
@@ -22,6 +24,8 @@ module Bundler
22
24
  # existing in the referenced source.
23
25
  attr_accessor :strict
24
26
 
27
+ attr_accessor :prerelease_specified
28
+
25
29
  # Given a list of locked_specs and a list of gems to unlock creates a
26
30
  # GemVersionPromoter instance.
27
31
  #
@@ -37,6 +41,7 @@ module Bundler
37
41
  @locked_specs = locked_specs
38
42
  @unlock_gems = unlock_gems
39
43
  @sort_versions = {}
44
+ @prerelease_specified = {}
40
45
  end
41
46
 
42
47
  # @param value [Symbol] One of three Symbols: :major, :minor or :patch.
@@ -61,7 +66,7 @@ module Bundler
61
66
  # @return [SpecGroup] A new instance of the SpecGroup Array sorted and
62
67
  # possibly filtered.
63
68
  def sort_versions(dep, spec_groups)
64
- before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if ENV["DEBUG_RESOLVER"]
69
+ before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if DEBUG
65
70
 
66
71
  @sort_versions[dep] ||= begin
67
72
  gem_name = dep.name
@@ -75,7 +80,7 @@ module Bundler
75
80
  else
76
81
  sort_dep_specs(spec_groups, locked_spec)
77
82
  end.tap do |specs|
78
- if ENV["DEBUG_RESOLVER"]
83
+ if DEBUG
79
84
  STDERR.puts before_result
80
85
  STDERR.puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
81
86
  end
@@ -121,6 +126,15 @@ module Bundler
121
126
  result = spec_groups.sort do |a, b|
122
127
  @a_ver = a.version
123
128
  @b_ver = b.version
129
+
130
+ unless @prerelease_specified[@gem_name]
131
+ a_pre = @a_ver.prerelease?
132
+ b_pre = @b_ver.prerelease?
133
+
134
+ next -1 if a_pre && !b_pre
135
+ next 1 if b_pre && !a_pre
136
+ end
137
+
124
138
  if major?
125
139
  @a_ver <=> @b_ver
126
140
  elsif either_version_older_than_locked
@@ -2,18 +2,28 @@
2
2
 
3
3
  module Bundler
4
4
  class Injector
5
+ INJECTED_GEMS = "injected gems".freeze
6
+
5
7
  def self.inject(new_deps, options = {})
6
8
  injector = new(new_deps, options)
7
9
  injector.inject(Bundler.default_gemfile, Bundler.default_lockfile)
8
10
  end
9
11
 
10
- def initialize(new_deps, options = {})
11
- @new_deps = new_deps
12
+ def self.remove(gems, options = {})
13
+ injector = new(gems, options)
14
+ injector.remove(Bundler.default_gemfile, Bundler.default_lockfile)
15
+ end
16
+
17
+ def initialize(deps, options = {})
18
+ @deps = deps
12
19
  @options = options
13
20
  end
14
21
 
22
+ # @param [Pathname] gemfile_path The Gemfile in which to inject the new dependency.
23
+ # @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
24
+ # @return [Array]
15
25
  def inject(gemfile_path, lockfile_path)
16
- if Bundler.frozen?
26
+ if Bundler.frozen_bundle?
17
27
  # ensure the lock and Gemfile are synced
18
28
  Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
19
29
  end
@@ -25,18 +35,19 @@ module Bundler
25
35
  builder.eval_gemfile(gemfile_path)
26
36
 
27
37
  # don't inject any gems that are already in the Gemfile
28
- @new_deps -= builder.dependencies
38
+ @deps -= builder.dependencies
29
39
 
30
40
  # add new deps to the end of the in-memory Gemfile
31
- # Set conservative versioning to false because we want to let the resolver resolve the version first
32
- builder.eval_gemfile("injected gems", build_gem_lines(false)) if @new_deps.any?
41
+ # Set conservative versioning to false because
42
+ # we want to let the resolver resolve the version first
43
+ builder.eval_gemfile(INJECTED_GEMS, build_gem_lines(false)) if @deps.any?
33
44
 
34
45
  # resolve to see if the new deps broke anything
35
46
  @definition = builder.to_definition(lockfile_path, {})
36
47
  @definition.resolve_remotely!
37
48
 
38
49
  # since nothing broke, we can add those gems to the gemfile
39
- append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @new_deps.any?
50
+ append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
40
51
 
41
52
  # since we resolved successfully, write out the lockfile
42
53
  @definition.lock(Bundler.default_lockfile)
@@ -45,7 +56,21 @@ module Bundler
45
56
  Bundler.reset_paths!
46
57
 
47
58
  # return an array of the deps that we added
48
- @new_deps
59
+ @deps
60
+ end
61
+ end
62
+
63
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
64
+ # @param [Pathname] lockfile_path The lockfile from which to remove dependencies.
65
+ # @return [Array]
66
+ def remove(gemfile_path, lockfile_path)
67
+ # remove gems from each gemfiles we have
68
+ Bundler.definition.gemfiles.each do |path|
69
+ deps = remove_deps(path)
70
+
71
+ show_warning("No gems were removed from the gemfile.") if deps.empty?
72
+
73
+ deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
49
74
  end
50
75
  end
51
76
 
@@ -58,11 +83,21 @@ module Bundler
58
83
  seg_end_index = version >= Gem::Version.new("1.0") ? 1 : 2
59
84
 
60
85
  prerelease_suffix = version.to_s.gsub(version.release.to_s, "") if version.prerelease?
61
- "~> #{segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
86
+ "#{version_prefix}#{segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
87
+ end
88
+
89
+ def version_prefix
90
+ if @options[:strict]
91
+ "= "
92
+ elsif @options[:optimistic]
93
+ ">= "
94
+ else
95
+ "~> "
96
+ end
62
97
  end
63
98
 
64
99
  def build_gem_lines(conservative_versioning)
65
- @new_deps.map do |d|
100
+ @deps.map do |d|
66
101
  name = d.name.dump
67
102
 
68
103
  requirement = if conservative_versioning
@@ -72,7 +107,7 @@ module Bundler
72
107
  end
73
108
 
74
109
  if d.groups != Array(:default)
75
- group = d.groups.size == 1 ? ", :group => #{d.groups.inspect}" : ", :groups => #{d.groups.inspect}"
110
+ group = d.groups.size == 1 ? ", :group => #{d.groups.first.inspect}" : ", :groups => #{d.groups.inspect}"
76
111
  end
77
112
 
78
113
  source = ", :source => \"#{d.source}\"" unless d.source.nil?
@@ -84,11 +119,135 @@ module Bundler
84
119
  def append_to(gemfile_path, new_gem_lines)
85
120
  gemfile_path.open("a") do |f|
86
121
  f.puts
87
- if @options["timestamp"] || @options["timestamp"].nil?
88
- f.puts "# Added at #{Time.now} by #{`whoami`.chomp}:"
89
- end
90
122
  f.puts new_gem_lines
91
123
  end
92
124
  end
125
+
126
+ # evalutes a gemfile to remove the specified gem
127
+ # from it.
128
+ def remove_deps(gemfile_path)
129
+ initial_gemfile = IO.readlines(gemfile_path)
130
+
131
+ Bundler.ui.info "Removing gems from #{gemfile_path}"
132
+
133
+ # evaluate the Gemfile we have
134
+ builder = Dsl.new
135
+ builder.eval_gemfile(gemfile_path)
136
+
137
+ removed_deps = remove_gems_from_dependencies(builder, @deps, gemfile_path)
138
+
139
+ # abort the opertion if no gems were removed
140
+ # no need to operate on gemfile furthur
141
+ return [] if removed_deps.empty?
142
+
143
+ cleaned_gemfile = remove_gems_from_gemfile(@deps, gemfile_path)
144
+
145
+ SharedHelpers.write_to_gemfile(gemfile_path, cleaned_gemfile)
146
+
147
+ # check for errors
148
+ # including extra gems being removed
149
+ # or some gems not being removed
150
+ # and return the actual removed deps
151
+ cross_check_for_errors(gemfile_path, builder.dependencies, removed_deps, initial_gemfile)
152
+ end
153
+
154
+ # @param [Dsl] builder Dsl object of current Gemfile.
155
+ # @param [Array] gems Array of names of gems to be removed.
156
+ # @param [Pathname] path of the Gemfile
157
+ # @return [Array] removed_deps Array of removed dependencies.
158
+ def remove_gems_from_dependencies(builder, gems, gemfile_path)
159
+ removed_deps = []
160
+
161
+ gems.each do |gem_name|
162
+ deleted_dep = builder.dependencies.find {|d| d.name == gem_name }
163
+
164
+ if deleted_dep.nil?
165
+ raise GemfileError, "`#{gem_name}` is not specified in #{gemfile_path} so it could not be removed."
166
+ end
167
+
168
+ builder.dependencies.delete(deleted_dep)
169
+
170
+ removed_deps << deleted_dep
171
+ end
172
+
173
+ removed_deps
174
+ end
175
+
176
+ # @param [Array] gems Array of names of gems to be removed.
177
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
178
+ def remove_gems_from_gemfile(gems, gemfile_path)
179
+ patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
180
+
181
+ # remove lines which match the regex
182
+ new_gemfile = IO.readlines(gemfile_path).reject {|line| line.match(patterns) }
183
+
184
+ # remove lone \n and append them with other strings
185
+ new_gemfile.each_with_index do |_line, index|
186
+ if new_gemfile[index + 1] == "\n"
187
+ new_gemfile[index] += new_gemfile[index + 1]
188
+ new_gemfile.delete_at(index + 1)
189
+ end
190
+ end
191
+
192
+ %w[group source env install_if].each {|block| remove_nested_blocks(new_gemfile, block) }
193
+
194
+ new_gemfile.join.chomp
195
+ end
196
+
197
+ # @param [Array] gemfile Array of gemfile contents.
198
+ # @param [String] block_name Name of block name to look for.
199
+ def remove_nested_blocks(gemfile, block_name)
200
+ nested_blocks = 0
201
+
202
+ # count number of nested blocks
203
+ gemfile.each_with_index {|line, index| nested_blocks += 1 if !gemfile[index + 1].nil? && gemfile[index + 1].include?(block_name) && line.include?(block_name) }
204
+
205
+ while nested_blocks >= 0
206
+ nested_blocks -= 1
207
+
208
+ gemfile.each_with_index do |line, index|
209
+ next unless !line.nil? && line.include?(block_name)
210
+ if gemfile[index + 1] =~ /^\s*end\s*$/
211
+ gemfile[index] = nil
212
+ gemfile[index + 1] = nil
213
+ end
214
+ end
215
+
216
+ gemfile.compact!
217
+ end
218
+ end
219
+
220
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
221
+ # @param [Array] original_deps Array of original dependencies.
222
+ # @param [Array] removed_deps Array of removed dependencies.
223
+ # @param [Array] initial_gemfile Contents of original Gemfile before any operation.
224
+ def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_gemfile)
225
+ # evalute the new gemfile to look for any failure cases
226
+ builder = Dsl.new
227
+ builder.eval_gemfile(gemfile_path)
228
+
229
+ # record gems which were removed but not requested
230
+ extra_removed_gems = original_deps - builder.dependencies
231
+
232
+ # if some extra gems were removed then raise error
233
+ # and revert Gemfile to original
234
+ unless extra_removed_gems.empty?
235
+ SharedHelpers.write_to_gemfile(gemfile_path, initial_gemfile.join)
236
+
237
+ raise InvalidOption, "Gems could not be removed. #{extra_removed_gems.join(", ")} would also have been removed. Bundler cannot continue."
238
+ end
239
+
240
+ # record gems which could not be removed due to some reasons
241
+ errored_deps = builder.dependencies.select {|d| d.gemfile == gemfile_path } & removed_deps.select {|d| d.gemfile == gemfile_path }
242
+
243
+ show_warning "#{errored_deps.map(&:name).join(", ")} could not be removed." unless errored_deps.empty?
244
+
245
+ # return actual removed dependencies
246
+ removed_deps - errored_deps
247
+ end
248
+
249
+ def show_warning(message)
250
+ Bundler.ui.info Bundler.ui.add_color(message, :yellow)
251
+ end
93
252
  end
94
253
  end
@@ -21,7 +21,7 @@ module Bundler
21
21
  raise
22
22
  rescue Errno::ENOSPC
23
23
  return false, out_of_space_message
24
- rescue => e
24
+ rescue StandardError => e
25
25
  return false, specific_failure_message(e)
26
26
  end
27
27
 
@@ -44,7 +44,14 @@ module Bundler
44
44
  end
45
45
 
46
46
  def gem_install_message
47
- "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
47
+ source = spec.source
48
+ return unless source.respond_to?(:remotes)
49
+
50
+ if source.remotes.size == 1
51
+ "Make sure that `gem install #{spec.name} -v '#{spec.version}' --source '#{source.remotes.first}'` succeeds before bundling."
52
+ else
53
+ "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
54
+ end
48
55
  end
49
56
 
50
57
  def spec_settings
@@ -87,6 +87,7 @@ module Bundler
87
87
  @force = force
88
88
  @specs = all_specs.map {|s| SpecInstallation.new(s) }
89
89
  @spec_set = all_specs
90
+ @rake = @specs.find {|s| s.name == "rake" }
90
91
  end
91
92
 
92
93
  def call
@@ -155,12 +156,13 @@ module Bundler
155
156
  end
156
157
 
157
158
  def do_install(spec_install, worker_num)
159
+ Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL, spec_install)
158
160
  gem_installer = Bundler::GemInstaller.new(
159
161
  spec_install.spec, @installer, @standalone, worker_num, @force
160
162
  )
161
163
  success, message = begin
162
164
  gem_installer.install_from_spec
163
- rescue => e
165
+ rescue RuntimeError => e
164
166
  raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}"
165
167
  end
166
168
  if success
@@ -170,6 +172,7 @@ module Bundler
170
172
  spec_install.state = :failed
171
173
  spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}"
172
174
  end
175
+ Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL, spec_install)
173
176
  spec_install
174
177
  end
175
178
 
@@ -218,6 +221,8 @@ module Bundler
218
221
  # are installed.
219
222
  def enqueue_specs
220
223
  @specs.select(&:ready_to_enqueue?).each do |spec|
224
+ next if @rake && !@rake.installed? && spec.name != @rake.name
225
+
221
226
  if spec.dependencies_installed? @specs
222
227
  spec.state = :enqueued
223
228
  worker_pool.enq spec
@@ -21,8 +21,9 @@ module Bundler
21
21
  # For more information see the #run method on this class.
22
22
  def self.install(root, definition, options = {})
23
23
  installer = new(root, definition)
24
- Plugin.hook("before-install-all", definition.dependencies)
24
+ Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL_ALL, definition.dependencies)
25
25
  installer.run(options)
26
+ Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL_ALL, definition.dependencies)
26
27
  installer
27
28
  end
28
29
 
@@ -70,7 +71,7 @@ module Bundler
70
71
  create_bundle_path
71
72
 
72
73
  ProcessLock.lock do
73
- if Bundler.frozen?
74
+ if Bundler.frozen_bundle?
74
75
  @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
75
76
  end
76
77
 
@@ -90,7 +91,7 @@ module Bundler
90
91
  end
91
92
  install(options)
92
93
 
93
- lock unless Bundler.frozen?
94
+ lock unless Bundler.frozen_bundle?
94
95
  Standalone.new(options[:standalone], @definition).generate if options[:standalone]
95
96
  end
96
97
  end
@@ -135,7 +136,11 @@ module Bundler
135
136
  end
136
137
 
137
138
  File.open(binstub_path, "w", 0o777 & ~File.umask) do |f|
138
- f.puts ERB.new(template, nil, "-").result(binding)
139
+ if RUBY_VERSION >= "2.6"
140
+ f.puts ERB.new(template, :trim_mode => "-").result(binding)
141
+ else
142
+ f.puts ERB.new(template, nil, "-").result(binding)
143
+ end
139
144
  end
140
145
  end
141
146
 
@@ -171,7 +176,11 @@ module Bundler
171
176
  executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
172
177
  executable_path = executable_path
173
178
  File.open "#{bin_path}/#{executable}", "w", 0o755 do |f|
174
- f.puts ERB.new(template, nil, "-").result(binding)
179
+ if RUBY_VERSION >= "2.6"
180
+ f.puts ERB.new(template, :trim_mode => "-").result(binding)
181
+ else
182
+ f.puts ERB.new(template, nil, "-").result(binding)
183
+ end
175
184
  end
176
185
  end
177
186
  end
@@ -184,14 +193,36 @@ module Bundler
184
193
  # installation is SO MUCH FASTER. so we let people opt in.
185
194
  def install(options)
186
195
  force = options["force"]
187
- jobs = options.delete(:jobs) do
188
- if can_install_in_parallel?
189
- [Bundler.settings[:jobs].to_i - 1, 1].max
196
+ jobs = installation_parallelization(options)
197
+ install_in_parallel jobs, options[:standalone], force
198
+ end
199
+
200
+ def installation_parallelization(options)
201
+ if jobs = options.delete(:jobs)
202
+ return jobs
203
+ end
204
+
205
+ return 1 unless can_install_in_parallel?
206
+
207
+ auto_config_jobs = Bundler.feature_flag.auto_config_jobs?
208
+ if jobs = Bundler.settings[:jobs]
209
+ if auto_config_jobs
210
+ jobs
190
211
  else
191
- 1
212
+ [jobs.pred, 1].max
192
213
  end
214
+ elsif auto_config_jobs
215
+ processor_count
216
+ else
217
+ 1
193
218
  end
194
- install_in_parallel jobs, options[:standalone], force
219
+ end
220
+
221
+ def processor_count
222
+ require "etc"
223
+ Etc.nprocessors
224
+ rescue
225
+ 1
195
226
  end
196
227
 
197
228
  def load_plugins
@@ -80,7 +80,7 @@ module Bundler
80
80
  "To use the platform-specific version of the gem, run `bundle config specific_platform true` and install again."
81
81
  search = source.specs.search(self).last
82
82
  end
83
- search.dependencies = dependencies if search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)
83
+ search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
84
84
  search
85
85
  end
86
86
  end
@@ -152,7 +152,7 @@ module Bundler
152
152
  socket.connect_nonblock(address)
153
153
  rescue Errno::EINPROGRESS
154
154
  wait_for_writtable_socket(socket, address, timeout)
155
- rescue # Connection failed somehow, again
155
+ rescue RuntimeError # Connection failed somehow, again
156
156
  false
157
157
  end
158
158
  end
@@ -172,7 +172,7 @@ module Bundler
172
172
  socket.connect_nonblock(address)
173
173
  rescue Errno::EISCONN
174
174
  true
175
- rescue # Connection failed
175
+ rescue StandardError # Connection failed
176
176
  false
177
177
  end
178
178
  end