bundler 1.17.0.pre.1 → 1.17.0.pre.2

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -1
  3. data/README.md +1 -1
  4. data/bundler.gemspec +1 -1
  5. data/lib/bundler.rb +28 -10
  6. data/lib/bundler/build_metadata.rb +2 -2
  7. data/lib/bundler/cli.rb +33 -5
  8. data/lib/bundler/cli/binstubs.rb +8 -2
  9. data/lib/bundler/cli/remove.rb +18 -0
  10. data/lib/bundler/definition.rb +18 -13
  11. data/lib/bundler/dependency.rb +2 -2
  12. data/lib/bundler/dsl.rb +18 -2
  13. data/lib/bundler/endpoint_specification.rb +1 -1
  14. data/lib/bundler/env.rb +8 -6
  15. data/lib/bundler/fetcher.rb +1 -1
  16. data/lib/bundler/gem_helper.rb +1 -1
  17. data/lib/bundler/injector.rb +156 -8
  18. data/lib/bundler/installer/gem_installer.rb +1 -1
  19. data/lib/bundler/installer/parallel_installer.rb +1 -1
  20. data/lib/bundler/mirror.rb +2 -2
  21. data/lib/bundler/plugin.rb +5 -5
  22. data/lib/bundler/plugin/index.rb +1 -1
  23. data/lib/bundler/resolver/spec_group.rb +0 -4
  24. data/lib/bundler/runtime.rb +1 -1
  25. data/lib/bundler/settings.rb +1 -1
  26. data/lib/bundler/shared_helpers.rb +6 -0
  27. data/lib/bundler/source/metadata.rb +1 -1
  28. data/lib/bundler/templates/newgem/newgem.gemspec.tt +4 -0
  29. data/lib/bundler/version.rb +1 -1
  30. data/man/bundle-add.1 +1 -1
  31. data/man/bundle-add.1.txt +1 -1
  32. data/man/bundle-binstubs.1 +1 -1
  33. data/man/bundle-binstubs.1.txt +1 -1
  34. data/man/bundle-check.1 +1 -1
  35. data/man/bundle-check.1.txt +1 -1
  36. data/man/bundle-clean.1 +1 -1
  37. data/man/bundle-clean.1.txt +1 -1
  38. data/man/bundle-config.1 +1 -1
  39. data/man/bundle-config.1.txt +1 -1
  40. data/man/bundle-doctor.1 +1 -1
  41. data/man/bundle-doctor.1.txt +1 -1
  42. data/man/bundle-exec.1 +1 -1
  43. data/man/bundle-exec.1.txt +1 -1
  44. data/man/bundle-gem.1 +1 -1
  45. data/man/bundle-gem.1.txt +1 -1
  46. data/man/bundle-info.1 +1 -1
  47. data/man/bundle-info.1.txt +1 -1
  48. data/man/bundle-init.1 +1 -1
  49. data/man/bundle-init.1.txt +1 -1
  50. data/man/bundle-inject.1 +1 -1
  51. data/man/bundle-inject.1.txt +1 -1
  52. data/man/bundle-install.1 +6 -3
  53. data/man/bundle-install.1.txt +118 -107
  54. data/man/bundle-install.ronn +12 -3
  55. data/man/bundle-list.1 +1 -1
  56. data/man/bundle-list.1.txt +1 -1
  57. data/man/bundle-lock.1 +1 -1
  58. data/man/bundle-lock.1.txt +1 -1
  59. data/man/bundle-open.1 +1 -1
  60. data/man/bundle-open.1.txt +1 -1
  61. data/man/bundle-outdated.1 +1 -1
  62. data/man/bundle-outdated.1.txt +1 -1
  63. data/man/bundle-package.1 +1 -1
  64. data/man/bundle-package.1.txt +1 -1
  65. data/man/bundle-platform.1 +1 -1
  66. data/man/bundle-platform.1.txt +1 -1
  67. data/man/bundle-pristine.1 +1 -1
  68. data/man/bundle-pristine.1.txt +1 -1
  69. data/man/bundle-remove.1 +31 -0
  70. data/man/bundle-remove.1.txt +34 -0
  71. data/man/bundle-remove.ronn +23 -0
  72. data/man/bundle-show.1 +1 -1
  73. data/man/bundle-show.1.txt +1 -1
  74. data/man/bundle-update.1 +11 -7
  75. data/man/bundle-update.1.txt +71 -68
  76. data/man/bundle-update.ronn +11 -7
  77. data/man/bundle-viz.1 +1 -1
  78. data/man/bundle-viz.1.txt +1 -1
  79. data/man/bundle.1 +1 -1
  80. data/man/bundle.1.txt +1 -1
  81. data/man/gemfile.5 +1 -1
  82. data/man/gemfile.5.txt +1 -1
  83. data/man/index.txt +1 -0
  84. metadata +7 -2
@@ -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)}"
@@ -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
@@ -2,13 +2,20 @@
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
 
@@ -28,19 +35,19 @@ module Bundler
28
35
  builder.eval_gemfile(gemfile_path)
29
36
 
30
37
  # don't inject any gems that are already in the Gemfile
31
- @new_deps -= builder.dependencies
38
+ @deps -= builder.dependencies
32
39
 
33
40
  # add new deps to the end of the in-memory Gemfile
34
41
  # Set conservative versioning to false because
35
42
  # we want to let the resolver resolve the version first
36
- builder.eval_gemfile("injected gems", build_gem_lines(false)) if @new_deps.any?
43
+ builder.eval_gemfile(INJECTED_GEMS, build_gem_lines(false)) if @deps.any?
37
44
 
38
45
  # resolve to see if the new deps broke anything
39
46
  @definition = builder.to_definition(lockfile_path, {})
40
47
  @definition.resolve_remotely!
41
48
 
42
49
  # since nothing broke, we can add those gems to the gemfile
43
- 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?
44
51
 
45
52
  # since we resolved successfully, write out the lockfile
46
53
  @definition.lock(Bundler.default_lockfile)
@@ -49,7 +56,21 @@ module Bundler
49
56
  Bundler.reset_paths!
50
57
 
51
58
  # return an array of the deps that we added
52
- @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." }
53
74
  end
54
75
  end
55
76
 
@@ -76,7 +97,7 @@ module Bundler
76
97
  end
77
98
 
78
99
  def build_gem_lines(conservative_versioning)
79
- @new_deps.map do |d|
100
+ @deps.map do |d|
80
101
  name = d.name.dump
81
102
 
82
103
  requirement = if conservative_versioning
@@ -86,7 +107,7 @@ module Bundler
86
107
  end
87
108
 
88
109
  if d.groups != Array(:default)
89
- 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}"
90
111
  end
91
112
 
92
113
  source = ", :source => \"#{d.source}\"" unless d.source.nil?
@@ -101,5 +122,132 @@ module Bundler
101
122
  f.puts new_gem_lines
102
123
  end
103
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
104
252
  end
105
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
 
@@ -162,7 +162,7 @@ module Bundler
162
162
  )
163
163
  success, message = begin
164
164
  gem_installer.install_from_spec
165
- rescue => e
165
+ rescue RuntimeError => e
166
166
  raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}"
167
167
  end
168
168
  if success
@@ -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
@@ -67,7 +67,7 @@ module Bundler
67
67
  installed_specs = Installer.new.install_definition(definition)
68
68
 
69
69
  save_plugins plugins, installed_specs, builder.inferred_plugins
70
- rescue => e
70
+ rescue RuntimeError => e
71
71
  unless e.is_a?(GemfileError)
72
72
  Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
73
73
  end
@@ -81,8 +81,8 @@ module Bundler
81
81
 
82
82
  # The directory root for all plugin related data
83
83
  #
84
- # Points to root in app_config_path if ran in an app else points to the one
85
- # in user_bundle_path
84
+ # If run in an app, points to local root, in app_config_path
85
+ # Otherwise, points to global root, in Bundler.user_bundle_path("plugin")
86
86
  def root
87
87
  @root ||= if SharedHelpers.in_bundle?
88
88
  local_root
@@ -97,7 +97,7 @@ module Bundler
97
97
 
98
98
  # The global directory root for all plugin related data
99
99
  def global_root
100
- Bundler.user_bundle_path.join("plugin")
100
+ Bundler.user_bundle_path("plugin")
101
101
  end
102
102
 
103
103
  # The cache directory for plugin stuffs
@@ -271,7 +271,7 @@ module Bundler
271
271
  load path.join(PLUGIN_FILE_NAME)
272
272
 
273
273
  @loaded_plugin_names << name
274
- rescue => e
274
+ rescue RuntimeError => e
275
275
  Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
276
276
  raise
277
277
  end
@@ -63,7 +63,7 @@ module Bundler
63
63
  @plugin_paths[name] = path
64
64
  @load_paths[name] = load_paths
65
65
  save_index
66
- rescue
66
+ rescue StandardError
67
67
  @commands = old_commands
68
68
  raise
69
69
  end
@@ -54,10 +54,6 @@ module Bundler
54
54
  dependencies.concat(metadata_dependencies).flatten
55
55
  end
56
56
 
57
- def platforms_for_dependency_named(dependency)
58
- __dependencies.select {|_, deps| deps.map(&:name).include? dependency }.keys
59
- end
60
-
61
57
  def ==(other)
62
58
  return unless other.is_a?(SpecGroup)
63
59
  name == other.name &&
@@ -79,7 +79,7 @@ module Bundler
79
79
  required_file = file
80
80
  begin
81
81
  Kernel.require file
82
- rescue => e
82
+ rescue RuntimeError => e
83
83
  raise e if e.is_a?(LoadError) # we handle this a little later
84
84
  raise Bundler::GemRequireError.new e,
85
85
  "There was an error while trying to load the gem '#{file}'."
@@ -395,7 +395,7 @@ module Bundler
395
395
  Pathname.new(ENV["BUNDLE_CONFIG"])
396
396
  else
397
397
  begin
398
- Bundler.user_bundle_path.join("config")
398
+ Bundler.user_bundle_path("config")
399
399
  rescue PermissionError, GenericSystemCallError
400
400
  nil
401
401
  end
@@ -197,10 +197,12 @@ module Bundler
197
197
  def pretty_dependency(dep, print_source = false)
198
198
  msg = String.new(dep.name)
199
199
  msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
200
+
200
201
  if dep.is_a?(Bundler::Dependency)
201
202
  platform_string = dep.platforms.join(", ")
202
203
  msg << " " << platform_string if !platform_string.empty? && platform_string != Gem::Platform::RUBY
203
204
  end
205
+
204
206
  msg << " from the `#{dep.source}` source" if print_source && dep.source
205
207
  msg
206
208
  end
@@ -223,6 +225,10 @@ module Bundler
223
225
  Digest(name)
224
226
  end
225
227
 
228
+ def write_to_gemfile(gemfile_path, contents)
229
+ filesystem_access(gemfile_path) {|g| File.open(g, "w") {|file| file.puts contents } }
230
+ end
231
+
226
232
  private
227
233
 
228
234
  def validate_bundle_path
@@ -19,7 +19,7 @@ module Bundler
19
19
  # can't point to the actual gemspec or else the require paths will be wrong
20
20
  s.loaded_from = File.expand_path("..", __FILE__)
21
21
  end
22
- if loaded_spec = nil && Bundler.rubygems.loaded_specs("bundler")
22
+ if loaded_spec = Bundler.rubygems.loaded_specs("bundler")
23
23
  idx << loaded_spec # this has to come after the fake gemspec, to override it
24
24
  elsif local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION }
25
25
  idx << local_spec
@@ -23,6 +23,10 @@ Gem::Specification.new do |spec|
23
23
  # to allow pushing to a single host or delete this section to allow pushing to any host.
24
24
  if spec.respond_to?(:metadata)
25
25
  spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
26
+
27
+ spec.metadata["homepage_uri"] = spec.homepage
28
+ spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
29
+ spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
26
30
  else
27
31
  raise "RubyGems 2.0 or newer is required to protect against " \
28
32
  "public gem pushes."
@@ -7,7 +7,7 @@ module Bundler
7
7
  # We're doing this because we might write tests that deal
8
8
  # with other versions of bundler and we are unsure how to
9
9
  # handle this better.
10
- VERSION = "1.17.0.pre.1" unless defined?(::Bundler::VERSION)
10
+ VERSION = "1.17.0.pre.2" unless defined?(::Bundler::VERSION)
11
11
 
12
12
  def self.overwrite_loaded_gem_version
13
13
  begin
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-ADD" "1" "September 2018" "" ""
4
+ .TH "BUNDLE\-ADD" "1" "October 2018" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
@@ -49,4 +49,4 @@ OPTIONS
49
49
 
50
50
 
51
51
 
52
- September 2018 BUNDLE-ADD(1)
52
+ October 2018 BUNDLE-ADD(1)
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-BINSTUBS" "1" "September 2018" "" ""
4
+ .TH "BUNDLE\-BINSTUBS" "1" "October 2018" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
@@ -45,4 +45,4 @@ BUNDLE INSTALL --BINSTUBS
45
45
 
46
46
 
47
47
 
48
- September 2018 BUNDLE-BINSTUBS(1)
48
+ October 2018 BUNDLE-BINSTUBS(1)
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-CHECK" "1" "September 2018" "" ""
4
+ .TH "BUNDLE\-CHECK" "1" "October 2018" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems