bundler 1.14.6 → 1.15.0.pre.1

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 (131) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +131 -43
  4. data/.travis.yml +5 -5
  5. data/CHANGELOG.md +52 -8
  6. data/CONTRIBUTING.md +10 -29
  7. data/README.md +13 -6
  8. data/Rakefile +4 -2
  9. data/bin/rubocop +1 -1
  10. data/doc/README.md +30 -0
  11. data/doc/TROUBLESHOOTING.md +64 -0
  12. data/doc/contributing/BUG_TRIAGE.md +36 -0
  13. data/doc/contributing/COMMUNITY.md +13 -0
  14. data/doc/contributing/GETTING_HELP.md +11 -0
  15. data/doc/contributing/HOW_YOU_CAN_HELP.md +27 -0
  16. data/doc/contributing/ISSUES.md +51 -0
  17. data/doc/contributing/README.md +38 -0
  18. data/doc/development/NEW_FEATURES.md +10 -0
  19. data/doc/development/PULL_REQUESTS.md +40 -0
  20. data/doc/development/README.md +19 -0
  21. data/doc/development/RELEASING.md +9 -0
  22. data/doc/development/SETUP.md +29 -0
  23. data/doc/documentation/README.md +29 -0
  24. data/doc/documentation/VISION.md +26 -0
  25. data/doc/documentation/WRITING.md +54 -0
  26. data/exe/bundle +4 -1
  27. data/lib/bundler.rb +20 -13
  28. data/lib/bundler/cli.rb +67 -3
  29. data/lib/bundler/cli/add.rb +26 -0
  30. data/lib/bundler/cli/config.rb +24 -6
  31. data/lib/bundler/cli/gem.rb +13 -8
  32. data/lib/bundler/cli/info.rb +51 -0
  33. data/lib/bundler/cli/inject.rb +8 -2
  34. data/lib/bundler/cli/install.rb +1 -1
  35. data/lib/bundler/cli/issue.rb +40 -0
  36. data/lib/bundler/cli/outdated.rb +16 -18
  37. data/lib/bundler/cli/pristine.rb +33 -0
  38. data/lib/bundler/cli/viz.rb +1 -1
  39. data/lib/bundler/definition.rb +64 -48
  40. data/lib/bundler/dsl.rb +6 -0
  41. data/lib/bundler/endpoint_specification.rb +3 -9
  42. data/lib/bundler/env.rb +3 -3
  43. data/lib/bundler/errors.rb +1 -1
  44. data/lib/bundler/fetcher/downloader.rb +3 -2
  45. data/lib/bundler/gem_helper.rb +5 -0
  46. data/lib/bundler/index.rb +9 -3
  47. data/lib/bundler/injector.rb +32 -11
  48. data/lib/bundler/installer.rb +1 -1
  49. data/lib/bundler/installer/parallel_installer.rb +15 -1
  50. data/lib/bundler/lazy_specification.rb +6 -0
  51. data/lib/bundler/lockfile_parser.rb +42 -34
  52. data/lib/bundler/mirror.rb +2 -0
  53. data/lib/bundler/plugin.rb +5 -1
  54. data/lib/bundler/plugin/api/source.rb +1 -1
  55. data/lib/bundler/plugin/index.rb +2 -0
  56. data/lib/bundler/remote_specification.rb +16 -7
  57. data/lib/bundler/resolver.rb +13 -3
  58. data/lib/bundler/rubygems_ext.rb +8 -3
  59. data/lib/bundler/rubygems_integration.rb +85 -36
  60. data/lib/bundler/runtime.rb +4 -1
  61. data/lib/bundler/settings.rb +2 -1
  62. data/lib/bundler/setup.rb +1 -1
  63. data/lib/bundler/shared_helpers.rb +26 -1
  64. data/lib/bundler/source.rb +17 -1
  65. data/lib/bundler/source/git.rb +16 -0
  66. data/lib/bundler/source/path.rb +13 -3
  67. data/lib/bundler/source/path/installer.rb +2 -2
  68. data/lib/bundler/source/rubygems.rb +5 -2
  69. data/lib/bundler/spec_set.rb +22 -13
  70. data/lib/bundler/stub_specification.rb +64 -2
  71. data/lib/bundler/templates/Executable +1 -1
  72. data/lib/bundler/templates/Executable.standalone +5 -5
  73. data/lib/bundler/templates/newgem/Gemfile.tt +2 -2
  74. data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
  75. data/lib/bundler/templates/newgem/README.md.tt +12 -6
  76. data/lib/bundler/templates/newgem/Rakefile.tt +5 -5
  77. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
  78. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
  79. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +6 -6
  80. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +4 -4
  81. data/lib/bundler/templates/newgem/newgem.gemspec.tt +9 -9
  82. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +3 -0
  83. data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +1 -1
  84. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +3 -3
  85. data/lib/bundler/ui/shell.rb +9 -6
  86. data/lib/bundler/vendor/thor/lib/thor.rb +31 -23
  87. data/lib/bundler/vendor/thor/lib/thor/actions.rb +21 -22
  88. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -1
  89. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -1
  90. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +2 -2
  91. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +8 -8
  92. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +23 -12
  93. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +10 -14
  94. data/lib/bundler/vendor/thor/lib/thor/base.rb +30 -30
  95. data/lib/bundler/vendor/thor/lib/thor/command.rb +9 -9
  96. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
  97. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +7 -5
  98. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +94 -63
  99. data/lib/bundler/vendor/thor/lib/thor/error.rb +3 -3
  100. data/lib/bundler/vendor/thor/lib/thor/group.rb +12 -12
  101. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +4 -5
  102. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +4 -7
  103. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +16 -16
  104. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +40 -19
  105. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +7 -5
  106. data/lib/bundler/vendor/thor/lib/thor/runner.rb +25 -25
  107. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  108. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +41 -26
  109. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +1 -1
  110. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +4 -4
  111. data/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
  112. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  113. data/lib/bundler/version.rb +14 -1
  114. data/lib/bundler/version_ranges.rb +75 -0
  115. data/lib/bundler/worker.rb +2 -1
  116. data/man/bundle-check.ronn +26 -0
  117. data/man/bundle-clean.ronn +18 -0
  118. data/man/bundle-config.ronn +4 -1
  119. data/man/bundle-info.ronn +17 -0
  120. data/man/bundle-init.ronn +18 -0
  121. data/man/bundle-inject.ronn +22 -0
  122. data/man/bundle-open.ronn +19 -0
  123. data/man/bundle-show.ronn +20 -0
  124. data/man/bundle-update.ronn +5 -2
  125. data/man/bundle-viz.ronn +30 -0
  126. data/man/bundle.ronn +3 -0
  127. data/man/gemfile.5.ronn +24 -64
  128. data/task/release.rake +115 -0
  129. metadata +49 -5
  130. data/DEVELOPMENT.md +0 -150
  131. data/ISSUES.md +0 -117
@@ -14,14 +14,23 @@ module Bundler
14
14
 
15
15
  def message
16
16
  conflicts.sort.reduce(String.new) do |o, (name, conflict)|
17
- o << %(Bundler could not find compatible versions for gem "#{name}":\n)
17
+ o << %(\nBundler could not find compatible versions for gem "#{name}":\n)
18
18
  if conflict.locked_requirement
19
19
  o << %( In snapshot (#{Bundler.default_lockfile.basename}):\n)
20
20
  o << %( #{printable_dep(conflict.locked_requirement)}\n)
21
21
  o << %(\n)
22
22
  end
23
23
  o << %( In Gemfile:\n)
24
- o << conflict.requirement_trees.sort_by {|t| t.reverse.map(&:name) }.map do |tree|
24
+ trees = conflict.requirement_trees
25
+
26
+ maximal = 1.upto(trees.size).map do |size|
27
+ trees.map(&:last).flatten(1).combination(size).to_a
28
+ end.flatten(1).select do |deps|
29
+ Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
30
+ end.min_by(&:size)
31
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
32
+
33
+ o << trees.sort_by {|t| t.reverse.map(&:name) }.map do |tree|
25
34
  t = String.new
26
35
  depth = 2
27
36
  tree.each do |req|
@@ -62,7 +71,7 @@ module Bundler
62
71
  end
63
72
  end
64
73
  o
65
- end
74
+ end.strip
66
75
  end
67
76
  end
68
77
 
@@ -318,6 +327,7 @@ module Bundler
318
327
  dependencies.sort_by do |dependency|
319
328
  name = name_for(dependency)
320
329
  [
330
+ @base_dg.vertex_named(name) ? 0 : 1,
321
331
  activated.vertex_named(name).payload ? 0 : 1,
322
332
  amount_constrained(dependency),
323
333
  conflicts[name] ? 0 : 1,
@@ -151,7 +151,7 @@ module Gem
151
151
 
152
152
  def to_lock
153
153
  out = String.new(" #{name}")
154
- unless requirement == Gem::Requirement.default
154
+ unless requirement.none?
155
155
  reqs = requirement.requirements.map {|o, v| "#{o} #{v}" }.sort.reverse
156
156
  out << " (#{reqs.join(", ")})"
157
157
  end
@@ -169,11 +169,16 @@ module Gem
169
169
  end
170
170
 
171
171
  class Requirement
172
- # Backport of performance enhancement added to Rubygems 1.4
172
+ # Backport of performance enhancement added to RubyGems 1.4
173
173
  def none?
174
- @none ||= (to_s == ">= 0")
174
+ # note that it might be tempting to replace with with RubyGems 2.0's
175
+ # improved implementation. Don't. It requires `DefaultRequirement` to be
176
+ # defined, and more importantantly, these overrides are not used when the
177
+ # running RubyGems defines these methods
178
+ to_s == ">= 0"
175
179
  end unless allocate.respond_to?(:none?)
176
180
 
181
+ # Backport of performance enhancement added to RubyGems 2.2
177
182
  def exact?
178
183
  return false unless @requirements.size == 1
179
184
  @requirements[0][0] == "="
@@ -80,6 +80,10 @@ module Bundler
80
80
  default
81
81
  end
82
82
 
83
+ def stub_set_spec(stub, spec)
84
+ stub.instance_variable_set(:@spec, spec)
85
+ end
86
+
83
87
  def path(obj)
84
88
  obj.to_s
85
89
  end
@@ -320,48 +324,53 @@ module Bundler
320
324
  end
321
325
  end
322
326
 
323
- def replace_gem(specs)
327
+ def binstubs_call_gem?
328
+ true
329
+ end
330
+
331
+ def stubs_provide_full_functionality?
332
+ false
333
+ end
334
+
335
+ def replace_gem(specs, specs_by_name)
324
336
  reverse_rubygems_kernel_mixin
325
337
 
326
- executables = specs.map(&:executables).flatten
338
+ executables = nil
327
339
 
328
340
  kernel = (class << ::Kernel; self; end)
329
341
  [kernel, ::Kernel].each do |kernel_class|
330
342
  redefine_method(kernel_class, :gem) do |dep, *reqs|
331
- if executables.include? File.basename(caller.first.split(":").first)
343
+ executables ||= specs.map(&:executables).flatten if ::Bundler.rubygems.binstubs_call_gem?
344
+ if executables && executables.include?(File.basename(caller.first.split(":").first))
332
345
  break
333
346
  end
347
+
334
348
  reqs.pop if reqs.last.is_a?(Hash)
335
349
 
336
350
  unless dep.respond_to?(:name) && dep.respond_to?(:requirement)
337
351
  dep = Gem::Dependency.new(dep, reqs)
338
352
  end
339
353
 
340
- spec = specs.find {|s| s.name == dep.name }
341
-
342
- if spec.nil?
343
-
344
- e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile."
345
- e.name = dep.name
346
- if e.respond_to?(:requirement=)
347
- e.requirement = dep.requirement
348
- else
349
- e.version_requirement = dep.requirement
350
- end
351
- raise e
352
- elsif dep !~ spec
353
- e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
354
- "Make sure all dependencies are added to Gemfile."
355
- e.name = dep.name
356
- if e.respond_to?(:requirement=)
357
- e.requirement = dep.requirement
358
- else
359
- e.version_requirement = dep.requirement
360
- end
361
- raise e
354
+ if spec = specs_by_name[dep.name]
355
+ return true if dep.matches_spec?(spec)
362
356
  end
363
357
 
364
- true
358
+ message = if spec.nil?
359
+ "#{dep.name} is not part of the bundle." \
360
+ " Add it to your #{Bundler.default_gemfile.basename}."
361
+ else
362
+ "can't activate #{dep}, already activated #{spec.full_name}. " \
363
+ "Make sure all dependencies are added to Gemfile."
364
+ end
365
+
366
+ e = Gem::LoadError.new(message)
367
+ e.name = dep.name
368
+ if e.respond_to?(:requirement=)
369
+ e.requirement = dep.requirement
370
+ elsif e.respond_to?(:version_requirement=)
371
+ e.version_requirement = dep.requirement
372
+ end
373
+ raise e
365
374
  end
366
375
 
367
376
  # TODO: delete this in 2.0, it's a backwards compatibility shim
@@ -393,20 +402,34 @@ module Bundler
393
402
  # Used to make bin stubs that are not created by bundler work
394
403
  # under bundler. The new Gem.bin_path only considers gems in
395
404
  # +specs+
396
- def replace_bin_path(specs)
405
+ def replace_bin_path(specs, specs_by_name)
397
406
  gem_class = (class << Gem; self; end)
398
407
 
399
408
  redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args|
400
409
  exec_name = args.first
401
410
 
411
+ spec_with_name = specs_by_name[gem_name]
402
412
  spec = if exec_name
403
- specs.find {|s| s.name == gem_name && s.executables.include?(exec_name) } ||
413
+ if spec_with_name && spec_with_name.executables.include?(exec_name)
414
+ spec_with_name
415
+ else
404
416
  specs.find {|s| s.executables.include?(exec_name) }
417
+ end
405
418
  else
406
- specs.find {|s| s.name == gem_name }
419
+ spec_with_name
407
420
  end
408
- raise(Gem::Exception, "can't find executable #{exec_name}") unless spec
421
+
422
+ unless spec
423
+ message = "can't find executable #{exec_name} for gem #{gem_name}"
424
+ if !exec_name || spec_with_name.nil?
425
+ message += ". #{gem_name} is not currently included in the bundle, " \
426
+ "perhaps you meant to add it to your #{Bundler.default_gemfile.basename}?"
427
+ end
428
+ raise Gem::Exception, message
429
+ end
430
+
409
431
  raise Gem::Exception, "no default executable for #{spec.full_name}" unless exec_name ||= spec.default_executable
432
+
410
433
  unless spec.name == name
411
434
  Bundler::SharedHelpers.major_deprecation \
412
435
  "Bundler is using a binstub that was created for a different gem.\n" \
@@ -423,8 +446,10 @@ module Bundler
423
446
  # Copy of Rubygems activate_bin_path impl
424
447
  requirement = args.last
425
448
  spec = find_spec_for_exe name, exec_name, [requirement]
426
- Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate }
427
- spec.bin_file exec_name
449
+
450
+ gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
451
+ gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
452
+ File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
428
453
  end
429
454
 
430
455
  redefine_method(gem_class, :bin_path) do |name, *args|
@@ -450,11 +475,14 @@ module Bundler
450
475
  # Replace or hook into Rubygems to provide a bundlerized view
451
476
  # of the world.
452
477
  def replace_entrypoints(specs)
453
- replace_gem(specs)
478
+ specs_by_name = specs.reduce({}) do |h, s|
479
+ h[s.name] = s
480
+ h
481
+ end
454
482
 
483
+ replace_gem(specs, specs_by_name)
455
484
  stub_rubygems(specs)
456
-
457
- replace_bin_path(specs)
485
+ replace_bin_path(specs, specs_by_name)
458
486
  replace_refresh
459
487
 
460
488
  Gem.clear_paths
@@ -746,7 +774,13 @@ module Bundler
746
774
  end
747
775
 
748
776
  def backport_ext_builder_monitor
749
- require "rubygems/ext"
777
+ # So we can avoid requiring "rubygems/ext" in its entirety
778
+ Gem.module_eval <<-RB, __FILE__, __LINE__ + 1
779
+ module Ext
780
+ end
781
+ RB
782
+
783
+ require "rubygems/ext/builder"
750
784
 
751
785
  Gem::Ext::Builder.class_eval do
752
786
  unless const_defined?(:CHDIR_MONITOR)
@@ -777,6 +811,21 @@ module Bundler
777
811
  activated_spec_names = runtime.requested_specs.map(&:to_spec).sort_by(&:name)
778
812
  [Gemdeps.new(runtime), activated_spec_names]
779
813
  end
814
+
815
+ if provides?(">= 2.5.2")
816
+ # RubyGems-generated binstubs call Kernel#gem
817
+ def binstubs_call_gem?
818
+ false
819
+ end
820
+
821
+ # only 2.5.2+ has all of the stub methods we want to use, and since this
822
+ # is a performance optimization _only_,
823
+ # we'll restrict ourselves to the most
824
+ # recent RG versions instead of all versions that have stubs
825
+ def stubs_provide_full_functionality?
826
+ true
827
+ end
828
+ end
780
829
  end
781
830
  end
782
831
 
@@ -11,6 +11,8 @@ module Bundler
11
11
  end
12
12
 
13
13
  def setup(*groups)
14
+ @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.settings[:frozen]
15
+
14
16
  groups.map!(&:to_sym)
15
17
 
16
18
  # Has to happen first
@@ -24,7 +26,7 @@ module Bundler
24
26
  # Activate the specs
25
27
  load_paths = specs.map do |spec|
26
28
  unless spec.loaded_from
27
- raise GemNotFound, "#{spec.full_name} is missing. Run `bundle` to get it."
29
+ raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it."
28
30
  end
29
31
 
30
32
  if (activated_spec = Bundler.rubygems.loaded_specs(spec.name)) && activated_spec.version != spec.version
@@ -127,6 +129,7 @@ module Bundler
127
129
  definition_method :requires
128
130
 
129
131
  def lock(opts = {})
132
+ return if @definition.nothing_changed? && !@definition.unlocking?
130
133
  @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
131
134
  end
132
135
 
@@ -15,6 +15,8 @@ module Bundler
15
15
  disable_exec_load
16
16
  disable_local_branch_check
17
17
  disable_shared_gems
18
+ disable_version_check
19
+ force_ruby_platform
18
20
  frozen
19
21
  gem.coc
20
22
  gem.mit
@@ -22,7 +24,6 @@ module Bundler
22
24
  major_deprecations
23
25
  no_install
24
26
  no_prune
25
- force_ruby_platform
26
27
  only_update_to_newer_versions
27
28
  plugins
28
29
  silence_root_warning
@@ -22,7 +22,7 @@ if Bundler::SharedHelpers.in_bundle?
22
22
 
23
23
  unless ENV["BUNDLE_POSTIT_TRAMPOLINING_VERSION"]
24
24
  # Add bundler to the load path after disabling system gems
25
- # This is guarenteed to be done already if we've trampolined
25
+ # This is guaranteed to be done already if we've trampolined
26
26
  bundler_lib = File.expand_path("../..", __FILE__)
27
27
  $LOAD_PATH.unshift(bundler_lib) unless $LOAD_PATH.include?(bundler_lib)
28
28
  end
@@ -145,6 +145,31 @@ module Bundler
145
145
  major_deprecation("Bundler will only support rubygems >= 2.0, you are running #{Bundler.rubygems.version}")
146
146
  end
147
147
 
148
+ def trap(signal, override = false, &block)
149
+ prior = Signal.trap(signal) do
150
+ block.call
151
+ prior.call unless override
152
+ end
153
+ end
154
+
155
+ def ensure_same_dependencies(spec, old_deps, new_deps)
156
+ new_deps = new_deps.reject {|d| d.type == :development }
157
+ old_deps = old_deps.reject {|d| d.type == :development }
158
+
159
+ without_type = proc {|d| Gem::Dependency.new(d.name, d.requirements_list.sort) }
160
+ new_deps.map!(&without_type)
161
+ old_deps.map!(&without_type)
162
+
163
+ extra_deps = new_deps - old_deps
164
+ return if extra_deps.empty?
165
+
166
+ Bundler.ui.debug "#{spec.full_name} from #{spec.remote} has either corrupted API or lockfile dependencies" \
167
+ " (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})"
168
+ raise APIResponseMismatchError,
169
+ "Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \
170
+ "\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem."
171
+ end
172
+
148
173
  private
149
174
 
150
175
  def find_gemfile
@@ -246,7 +271,7 @@ module Bundler
246
271
  def deprecate_gemfile(gemfile)
247
272
  return unless gemfile && File.basename(gemfile) == "Gemfile"
248
273
  Bundler::SharedHelpers.major_deprecation \
249
- "gems.rb and gems.locked will be prefered to Gemfile and Gemfile.lock."
274
+ "gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock."
250
275
  end
251
276
 
252
277
  extend self
@@ -20,7 +20,7 @@ module Bundler
20
20
  locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name }
21
21
  locked_spec_version = locked_spec.version if locked_spec
22
22
  if locked_spec_version && spec.version != locked_spec_version
23
- message += Bundler.ui.add_color(" (was #{locked_spec_version})", :green)
23
+ message += Bundler.ui.add_color(" (was #{locked_spec_version})", version_color(spec.version, locked_spec_version))
24
24
  end
25
25
  end
26
26
 
@@ -38,5 +38,21 @@ module Bundler
38
38
  def inspect
39
39
  "#<#{self.class}:0x#{object_id} #{self}>"
40
40
  end
41
+
42
+ private
43
+
44
+ def version_color(spec_version, locked_spec_version)
45
+ if Gem::Version.correct?(spec_version) && Gem::Version.correct?(locked_spec_version)
46
+ # display yellow if there appears to be a regression
47
+ earlier_version?(spec_version, locked_spec_version) ? :yellow : :green
48
+ else
49
+ # default to green if the versions cannot be directly compared
50
+ :green
51
+ end
52
+ end
53
+
54
+ def earlier_version?(spec_version, locked_spec_version)
55
+ Gem::Version.new(spec_version) < Gem::Version.new(locked_spec_version)
56
+ end
41
57
  end
42
58
  end
@@ -171,7 +171,10 @@ module Bundler
171
171
  git_proxy.copy_to(install_path, submodules)
172
172
  serialize_gemspecs_in(install_path)
173
173
  @copied = true
174
+ elsif force
175
+ git_proxy.copy_to(install_path, submodules)
174
176
  end
177
+
175
178
  generate_bin_options = { :disable_extensions => !Bundler.rubygems.spec_missing_extensions?(spec), :build_args => options[:build_args] }
176
179
  generate_bin(spec, generate_bin_options)
177
180
 
@@ -234,6 +237,8 @@ module Bundler
234
237
  # The gemspecs we cache should already be evaluated.
235
238
  spec = Bundler.load_gemspec(spec_path)
236
239
  next unless spec
240
+ Bundler.rubygems.set_installed_by_version(spec)
241
+ Bundler.rubygems.validate(spec)
237
242
  File.open(spec_path, "wb") {|file| file.write(spec.to_ruby) }
238
243
  end
239
244
  end
@@ -298,6 +303,17 @@ module Bundler
298
303
  raise unless Bundler.feature_flag.allow_offline_install?
299
304
  Bundler.ui.warn "Using cached git data because of network errors"
300
305
  end
306
+
307
+ # no-op, since we validate when re-serializing the gemspec
308
+ def validate_spec(_spec); end
309
+
310
+ if Bundler.rubygems.stubs_provide_full_functionality?
311
+ def load_gemspec(file)
312
+ stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent)
313
+ stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s.untaint
314
+ StubSpecification.from_stub(stub)
315
+ end
316
+ end
301
317
  end
302
318
  end
303
319
  end
@@ -144,18 +144,28 @@ module Bundler
144
144
  SharedHelpers.in_bundle? && app_cache_path.exist?
145
145
  end
146
146
 
147
+ def load_gemspec(file)
148
+ return unless spec = Bundler.load_gemspec(file)
149
+ Bundler.rubygems.set_installed_by_version(spec)
150
+ spec
151
+ end
152
+
153
+ def validate_spec(spec)
154
+ Bundler.rubygems.validate(spec)
155
+ end
156
+
147
157
  def load_spec_files
148
158
  index = Index.new
149
159
 
150
160
  if File.directory?(expanded_path)
151
161
  # We sort depth-first since `<<` will override the earlier-found specs
152
162
  Dir["#{expanded_path}/#{@glob}"].sort_by {|p| -p.split(File::SEPARATOR).size }.each do |file|
153
- next unless spec = Bundler.load_gemspec(file)
163
+ next unless spec = load_gemspec(file)
154
164
  spec.source = self
155
- Bundler.rubygems.set_installed_by_version(spec)
165
+
156
166
  # Validation causes extension_dir to be calculated, which depends
157
167
  # on #source, so we validate here instead of load_gemspec
158
- Bundler.rubygems.validate(spec)
168
+ validate_spec(spec)
159
169
  index << spec
160
170
  end
161
171