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
@@ -29,9 +29,11 @@ module Bundler
29
29
  constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase }
30
30
  constant_array = constant_name.split("::")
31
31
 
32
- git_author_name = `git config user.name`.chomp
33
- github_username = `git config github.user`.chomp
34
- git_user_email = `git config user.email`.chomp
32
+ git_installed = Bundler.git_present?
33
+
34
+ git_author_name = git_installed ? `git config user.name`.chomp : ""
35
+ github_username = git_installed ? `git config github.user`.chomp : ""
36
+ git_user_email = git_installed ? `git config user.email`.chomp : ""
35
37
 
36
38
  config = {
37
39
  :name => name,
@@ -52,7 +54,6 @@ module Bundler
52
54
 
53
55
  templates = {
54
56
  "Gemfile.tt" => "Gemfile",
55
- "gitignore.tt" => ".gitignore",
56
57
  "lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb",
57
58
  "lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb",
58
59
  "newgem.gemspec.tt" => "#{name}.gemspec",
@@ -67,6 +68,8 @@ module Bundler
67
68
  bin/setup
68
69
  )
69
70
 
71
+ templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present?
72
+
70
73
  if test_framework = ask_and_set_test_framework
71
74
  config[:test] = test_framework
72
75
  config[:test_framework_version] = TEST_FRAMEWORK_VERSIONS[test_framework]
@@ -135,10 +138,12 @@ module Bundler
135
138
  path.chmod(executable)
136
139
  end
137
140
 
138
- Bundler.ui.info "Initializing git repo in #{target}"
139
- Dir.chdir(target) do
140
- `git init`
141
- `git add .`
141
+ if Bundler.git_present?
142
+ Bundler.ui.info "Initializing git repo in #{target}"
143
+ Dir.chdir(target) do
144
+ `git init`
145
+ `git add .`
146
+ end
142
147
  end
143
148
 
144
149
  # Open gemspec in editor
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/cli/common"
3
+
4
+ module Bundler
5
+ class CLI::Info
6
+ attr_reader :gem_name, :options
7
+ def initialize(options, gem_name)
8
+ @options = options
9
+ @gem_name = gem_name
10
+ end
11
+
12
+ def run
13
+ spec = spec_for_gem(gem_name)
14
+
15
+ spec_not_found(gem_name) unless spec
16
+ return print_gem_path(spec) if @options[:path]
17
+ print_gem_info(spec)
18
+ end
19
+
20
+ private
21
+
22
+ def spec_for_gem(gem_name)
23
+ spec = Bundler.definition.specs.find {|s| s.name == gem_name }
24
+ spec || default_gem_spec(gem_name)
25
+ end
26
+
27
+ def default_gem_spec(gem_name)
28
+ return unless Gem::Specification.respond_to?(:find_all_by_name)
29
+ gem_spec = Gem::Specification.find_all_by_name(gem_name).last
30
+ return gem_spec if gem_spec && gem_spec.respond_to?(:default_gem?) && gem_spec.default_gem?
31
+ end
32
+
33
+ def spec_not_found(gem_name)
34
+ raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies)
35
+ end
36
+
37
+ def print_gem_path(spec)
38
+ Bundler.ui.info spec.full_gem_path
39
+ end
40
+
41
+ def print_gem_info(spec)
42
+ gem_info = String.new
43
+ gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n"
44
+ gem_info << "\tSummary: #{spec.summary}\n" if spec.summary
45
+ gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage
46
+ gem_info << "\tPath: #{spec.full_gem_path}\n"
47
+ gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
48
+ Bundler.ui.info gem_info
49
+ end
50
+ end
51
+ end
@@ -6,7 +6,7 @@ module Bundler
6
6
  @options = options
7
7
  @name = name
8
8
  @version = version || last_version_number
9
- @group = options[:group]
9
+ @group = options[:group].split(",") unless options[:group].nil?
10
10
  @source = options[:source]
11
11
  @gems = []
12
12
  end
@@ -31,7 +31,13 @@ module Bundler
31
31
 
32
32
  if added.any?
33
33
  Bundler.ui.confirm "Added to Gemfile:"
34
- Bundler.ui.confirm added.map {|g| " #{g}" }.join("\n")
34
+ Bundler.ui.confirm(added.map do |d|
35
+ name = "'#{d.name}'"
36
+ requirement = ", '#{d.requirement}'"
37
+ group = ", :group => #{d.groups.inspect}" if d.groups != Array(:default)
38
+ source = ", :source => '#{d.source}'" unless d.source.nil?
39
+ %(gem #{name}#{requirement}#{group}#{source})
40
+ end.join("\n"))
35
41
  else
36
42
  Bundler.ui.confirm "All gems were already present in the Gemfile"
37
43
  end
@@ -78,7 +78,7 @@ module Bundler
78
78
  relative_path = absolute_path.sub(File.expand_path(".") + File::SEPARATOR, "." + File::SEPARATOR)
79
79
  Bundler.ui.confirm "Bundled gems are installed into #{relative_path}."
80
80
  else
81
- Bundler.ui.confirm "Use `bundle show [gemname]` to see where a bundled gem is installed."
81
+ Bundler.ui.confirm "Use `bundle info [gemname]` to see where a bundled gem is installed."
82
82
  end
83
83
 
84
84
  Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbconfig"
4
+
5
+ module Bundler
6
+ class CLI::Issue
7
+ def run
8
+ Bundler.ui.info <<-EOS.gsub(/^ {8}/, "")
9
+ Did you find an issue with Bundler? Before filing a new issue,
10
+ be sure to check out these resources:
11
+
12
+ 1. Check out our troubleshooting guide for quick fixes to common issues:
13
+ https://github.com/bundler/bundler/blob/master/doc/TROUBLESHOOTING.md
14
+
15
+ 2. Instructions for common Bundler uses can be found on the documentation
16
+ site: http://bundler.io/
17
+
18
+ 3. Information about each Bundler command can be found in the Bundler
19
+ man pages: http://bundler.io/man/bundle.1.html
20
+
21
+ Hopefully the troubleshooting steps above resolved your problem! If things
22
+ still aren't working the way you expect them to, please let us know so
23
+ that we can diagnose and help fix the problem you're having. Please
24
+ view the Filing Issues guide for more information:
25
+ https://github.com/bundler/bundler/blob/master/doc/contributing/ISSUES.md
26
+
27
+ EOS
28
+
29
+ Bundler.ui.info Bundler::Env.new.report
30
+
31
+ Bundler.ui.info "\n## Bundle Doctor"
32
+ doctor
33
+ end
34
+
35
+ def doctor
36
+ require "bundler/cli/doctor"
37
+ Bundler::CLI::Doctor.new({}).run
38
+ end
39
+ end
40
+ end
@@ -20,7 +20,7 @@ module Bundler
20
20
  end
21
21
 
22
22
  Bundler.definition.validate_runtime!
23
- current_specs = Bundler.ui.silence { Bundler.load.specs }
23
+ current_specs = Bundler.ui.silence { Bundler.definition.resolve }
24
24
  current_dependencies = {}
25
25
  Bundler.ui.silence do
26
26
  Bundler.load.dependencies.each do |dep|
@@ -80,25 +80,22 @@ module Bundler
80
80
  end
81
81
 
82
82
  gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version)
83
- if gem_outdated || (current_spec.git_version != active_spec.git_version)
84
- groups = nil
85
- if dependency && !options[:parseable]
86
- groups = dependency.groups.join(", ")
87
- end
88
-
89
- outdated_gems_list << { :active_spec => active_spec,
90
- :current_spec => current_spec,
91
- :dependency => dependency,
92
- :groups => groups }
93
-
94
- outdated_gems_by_groups[groups] ||= []
95
- outdated_gems_by_groups[groups] << { :active_spec => active_spec,
96
- :current_spec => current_spec,
97
- :dependency => dependency,
98
- :groups => groups }
83
+ next unless gem_outdated || (current_spec.git_version != active_spec.git_version)
84
+ groups = nil
85
+ if dependency && !options[:parseable]
86
+ groups = dependency.groups.join(", ")
99
87
  end
100
88
 
101
- Bundler.ui.debug "from #{active_spec.loaded_from}"
89
+ outdated_gems_list << { :active_spec => active_spec,
90
+ :current_spec => current_spec,
91
+ :dependency => dependency,
92
+ :groups => groups }
93
+
94
+ outdated_gems_by_groups[groups] ||= []
95
+ outdated_gems_by_groups[groups] << { :active_spec => active_spec,
96
+ :current_spec => current_spec,
97
+ :dependency => dependency,
98
+ :groups => groups }
102
99
  end
103
100
 
104
101
  if outdated_gems_list.empty?
@@ -195,6 +192,7 @@ module Bundler
195
192
 
196
193
  def print_gem(current_spec, active_spec, dependency, groups, options_include_groups)
197
194
  spec_version = "#{active_spec.version}#{active_spec.git_version}"
195
+ spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from
198
196
  current_version = "#{current_spec.version}#{current_spec.git_version}"
199
197
 
200
198
  if dependency && dependency.specific?
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/cli/common"
3
+
4
+ module Bundler
5
+ class CLI::Pristine
6
+ def run
7
+ Bundler.load.specs.each do |spec|
8
+ next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
9
+
10
+ gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
11
+ gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
12
+
13
+ case spec.source
14
+ when Source::Rubygems
15
+ cached_gem = spec.cache_file
16
+ unless File.exist?(cached_gem)
17
+ Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
18
+ next
19
+ end
20
+
21
+ FileUtils.rm_rf spec.full_gem_path
22
+ spec.source.install(spec, :force => true)
23
+ when Source::Git
24
+ git_source = spec.source
25
+ git_source.remote!
26
+ git_source.install(spec, :force => true)
27
+ else
28
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -21,7 +21,7 @@ module Bundler
21
21
  rescue StandardError => e
22
22
  raise unless e.message =~ /GraphViz not installed or dot not in PATH/
23
23
  Bundler.ui.error e.message
24
- Bundler.ui.warn "Please install GraphViz. On a Mac with homebrew, you can run `brew install graphviz`."
24
+ Bundler.ui.warn "Please install GraphViz. On a Mac with Homebrew, you can run `brew install graphviz`."
25
25
  end
26
26
  end
27
27
  end
@@ -81,7 +81,7 @@ module Bundler
81
81
  @locked_sources = @locked_gems.sources
82
82
  else
83
83
  @unlock = {}
84
- @locked_deps = []
84
+ @locked_deps = {}
85
85
  @locked_specs = SpecSet.new([])
86
86
  @locked_sources = []
87
87
  end
@@ -89,7 +89,7 @@ module Bundler
89
89
  @unlock = {}
90
90
  @platforms = []
91
91
  @locked_gems = nil
92
- @locked_deps = []
92
+ @locked_deps = {}
93
93
  @locked_specs = SpecSet.new([])
94
94
  @locked_sources = []
95
95
  @locked_platforms = []
@@ -119,28 +119,11 @@ module Bundler
119
119
  @local_changes = converge_locals
120
120
 
121
121
  @requires = compute_requires
122
-
123
- fixup_dependency_types!
124
- end
125
-
126
- def fixup_dependency_types!
127
- # XXX This is a temporary workaround for a bug when using rubygems 1.8.15
128
- # where Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
129
- # doesn't carry a notion of the dependency type, if you use
130
- # add_development_dependency in a gemspec that's loaded with the gemspec
131
- # directive, the lockfile dependencies and resolved dependencies end up
132
- # with a mismatch on #type.
133
- # Test coverage to catch a regression on this is in gemspec_spec.rb
134
- @dependencies.each do |d|
135
- if ld = @locked_deps.find {|l| l.name == d.name }
136
- ld.instance_variable_set(:@type, d.type)
137
- end
138
- end
139
122
  end
140
123
 
141
124
  def create_gem_version_promoter
142
125
  locked_specs =
143
- if @unlocking && @locked_specs.empty? && !@lockfile_contents.empty?
126
+ if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
144
127
  # Definition uses an empty set of locked_specs to indicate all gems
145
128
  # are unlocked, but GemVersionPromoter needs the locked_specs
146
129
  # for conservative comparison.
@@ -243,7 +226,7 @@ module Bundler
243
226
  def resolve
244
227
  @resolve ||= begin
245
228
  last_resolve = converge_locked_specs
246
- if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
229
+ if Bundler.settings[:frozen] || (!unlocking? && nothing_changed?)
247
230
  Bundler.ui.debug("Found no changes, using resolution from the lockfile")
248
231
  last_resolve
249
232
  else
@@ -312,7 +295,7 @@ module Bundler
312
295
  end
313
296
  end
314
297
 
315
- preserve_unknown_sections ||= !updating_major && (Bundler.settings[:frozen] || !@unlocking)
298
+ preserve_unknown_sections ||= !updating_major && (Bundler.settings[:frozen] || !unlocking?)
316
299
  return if lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
317
300
 
318
301
  if Bundler.settings[:frozen]
@@ -409,8 +392,10 @@ module Bundler
409
392
  "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
410
393
 
411
394
  unless explicit_flag
395
+
396
+ suggested_command = Bundler.settings.locations("frozen")[:global] == "1" ? "bundle config --delete frozen" : "bundle install --no-deployment"
412
397
  msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
413
- "freeze \nby running `bundle install --no-deployment`."
398
+ "freeze \nby running `#{suggested_command}`."
414
399
  end
415
400
 
416
401
  added = []
@@ -427,8 +412,8 @@ module Bundler
427
412
  new_sources = gemfile_sources - @locked_sources
428
413
  deleted_sources = @locked_sources - gemfile_sources
429
414
 
430
- new_deps = @dependencies - @locked_deps
431
- deleted_deps = @locked_deps - @dependencies
415
+ new_deps = @dependencies - @locked_deps.values
416
+ deleted_deps = @locked_deps.values - @dependencies
432
417
 
433
418
  # Check if it is possible that the source is only changed thing
434
419
  if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
@@ -453,7 +438,7 @@ module Bundler
453
438
 
454
439
  both_sources = Hash.new {|h, k| h[k] = [] }
455
440
  @dependencies.each {|d| both_sources[d.name][0] = d }
456
- @locked_deps.each {|d| both_sources[d.name][1] = d.source }
441
+ @locked_deps.each {|name, d| both_sources[name][1] = d.source }
457
442
 
458
443
  both_sources.each do |name, (dep, lock_source)|
459
444
  next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
@@ -462,7 +447,8 @@ module Bundler
462
447
  changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
463
448
  end
464
449
 
465
- msg << "\n\n#{change_reason.split(", ").join("\n")}\n"
450
+ reason = change_reason
451
+ msg << "\n\n#{reason.split(", ").map(&:capitalize).join("\n")}" unless reason.strip.empty?
466
452
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
467
453
  msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
468
454
  msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
@@ -540,14 +526,18 @@ module Bundler
540
526
  attr_reader :sources
541
527
  private :sources
542
528
 
543
- private
544
-
545
529
  def nothing_changed?
546
530
  !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
547
531
  end
548
532
 
533
+ def unlocking?
534
+ @unlocking
535
+ end
536
+
537
+ private
538
+
549
539
  def change_reason
550
- if @unlocking
540
+ if unlocking?
551
541
  unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
552
542
  if v == true
553
543
  k.to_s
@@ -584,7 +574,7 @@ module Bundler
584
574
 
585
575
  def dependencies_for_source_changed?(source, locked_source = source)
586
576
  deps_for_source = @dependencies.select {|s| s.source == source }
587
- locked_deps_for_source = @locked_deps.select {|s| s.source == locked_source }
577
+ locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
588
578
 
589
579
  Set.new(deps_for_source) != Set.new(locked_deps_for_source)
590
580
  end
@@ -637,7 +627,7 @@ module Bundler
637
627
  @locked_specs.each do |spec|
638
628
  spec.source &&= converge_path_source_to_gemspec_source(spec.source)
639
629
  end
640
- @locked_deps.each do |dep|
630
+ @locked_deps.each do |_, dep|
641
631
  dep.source &&= converge_path_source_to_gemspec_source(dep.source)
642
632
  end
643
633
  end
@@ -679,11 +669,12 @@ module Bundler
679
669
  end
680
670
 
681
671
  def converge_dependencies
682
- (@dependencies + @locked_deps).each do |dep|
683
- locked_source = @locked_deps.select {|d| d.name == dep.name }.last
672
+ frozen = Bundler.settings[:frozen]
673
+ (@dependencies + @locked_deps.values).each do |dep|
674
+ locked_source = @locked_deps[dep.name]
684
675
  # This is to make sure that if bundler is installing in deployment mode and
685
676
  # after locked_source and sources don't match, we still use locked_source.
686
- if Bundler.settings[:frozen] && !locked_source.nil? &&
677
+ if frozen && !locked_source.nil? &&
687
678
  locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
688
679
  dep.source = locked_source.source
689
680
  elsif dep.source
@@ -693,8 +684,31 @@ module Bundler
693
684
  dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq!
694
685
  end
695
686
  end
696
- dependency_without_type = proc {|d| Gem::Dependency.new(d.name, *d.requirement.as_list) }
697
- Set.new(@dependencies.map(&dependency_without_type)) != Set.new(@locked_deps.map(&dependency_without_type))
687
+
688
+ changes = false
689
+ # We want to know if all match, but don't want to check all entries
690
+ # This means we need to return false if any dependency doesn't match
691
+ # the lock or doesn't exist in the lock.
692
+ @dependencies.each do |dependency|
693
+ unless locked_dep = @locked_deps[dependency.name]
694
+ changes = true
695
+ next
696
+ end
697
+
698
+ # Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
699
+ # doesn't carry a notion of the dependency type, if you use
700
+ # add_development_dependency in a gemspec that's loaded with the gemspec
701
+ # directive, the lockfile dependencies and resolved dependencies end up
702
+ # with a mismatch on #type. Work around that by setting the type on the
703
+ # dep from the lockfile.
704
+ locked_dep.instance_variable_set(:@type, dependency.type)
705
+
706
+ # We already know the name matches from the hash lookup
707
+ # so we only need to check the requirement now
708
+ changes ||= dependency.requirement != locked_dep.requirement
709
+ end
710
+
711
+ changes
698
712
  end
699
713
 
700
714
  # Remove elements from the locked specs that are expired. This will most
@@ -707,12 +721,11 @@ module Bundler
707
721
  # and Gemfile.lock. If the Gemfile modified a dependency, but
708
722
  # the gem in the Gemfile.lock still satisfies it, this is fine
709
723
  # too.
710
- locked_deps_hash = @locked_deps.inject({}) do |hsh, dep|
711
- hsh[dep] = dep
712
- hsh
713
- end
714
724
  @dependencies.each do |dep|
715
- locked_dep = locked_deps_hash[dep]
725
+ locked_dep = @locked_deps[dep.name]
726
+
727
+ # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
728
+ locked_dep = nil unless locked_dep == dep
716
729
 
717
730
  if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
718
731
  deps << dep
@@ -734,11 +747,13 @@ module Bundler
734
747
 
735
748
  # Don't add a spec to the list if its source is expired. For example,
736
749
  # if you change a Git gem to Rubygems.
737
- next if s.source.nil? || @unlock[:sources].include?(s.source.name)
750
+ next if s.source.nil?
751
+ next if @unlock[:sources].include?(s.source.name)
738
752
 
739
753
  # XXX This is a backwards-compatibility fix to preserve the ability to
740
754
  # unlock a single gem by passing its name via `--source`. See issue #3759
741
- next if s.source.nil? || @unlock[:sources].include?(s.name)
755
+ # TODO: delete in Bundler 2
756
+ next if @unlock[:sources].include?(s.name)
742
757
 
743
758
  # If the spec is from a path source and it doesn't exist anymore
744
759
  # then we unlock it.
@@ -761,15 +776,16 @@ module Bundler
761
776
  end
762
777
 
763
778
  resolve = SpecSet.new(converged)
764
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems])
765
- diff = @locked_specs.to_a - resolve.to_a
779
+ resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
780
+ diff = nil
766
781
 
767
782
  # Now, we unlock any sources that do not have anymore gems pinned to it
768
783
  sources.all_sources.each do |source|
769
784
  next unless source.respond_to?(:unlock!)
770
785
 
771
786
  unless resolve.any? {|s| s.source == source }
772
- source.unlock! if !diff.empty? && diff.any? {|s| s.source == source }
787
+ diff ||= @locked_specs.to_a - resolve.to_a
788
+ source.unlock! if diff.any? {|s| s.source == source }
773
789
  end
774
790
  end
775
791
 
@@ -784,7 +800,7 @@ module Bundler
784
800
  end
785
801
 
786
802
  def satisfies_locked_spec?(dep)
787
- @locked_specs.any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
803
+ @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
788
804
  end
789
805
 
790
806
  # This list of dependencies is only used in #resolve, so it's OK to add