bundler 1.13.7 → 1.14.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop_todo.yml +100 -18
  4. data/.travis.yml +32 -18
  5. data/CHANGELOG.md +64 -2
  6. data/DEVELOPMENT.md +5 -3
  7. data/ISSUES.md +17 -0
  8. data/README.md +7 -0
  9. data/Rakefile +34 -23
  10. data/bin/rubocop +1 -1
  11. data/bundler.gemspec +2 -2
  12. data/exe/bundle +4 -6
  13. data/lib/bundler.rb +57 -5
  14. data/lib/bundler/cli.rb +51 -38
  15. data/lib/bundler/cli/binstubs.rb +1 -1
  16. data/lib/bundler/cli/cache.rb +1 -1
  17. data/lib/bundler/cli/check.rb +1 -1
  18. data/lib/bundler/cli/clean.rb +1 -1
  19. data/lib/bundler/cli/common.rb +30 -0
  20. data/lib/bundler/cli/doctor.rb +17 -19
  21. data/lib/bundler/cli/exec.rb +6 -0
  22. data/lib/bundler/cli/gem.rb +18 -4
  23. data/lib/bundler/cli/install.rb +9 -25
  24. data/lib/bundler/cli/lock.rb +8 -7
  25. data/lib/bundler/cli/outdated.rb +163 -56
  26. data/lib/bundler/cli/platform.rb +1 -1
  27. data/lib/bundler/cli/show.rb +1 -1
  28. data/lib/bundler/cli/update.rb +10 -23
  29. data/lib/bundler/compact_index_client.rb +108 -0
  30. data/lib/bundler/compact_index_client/cache.rb +119 -0
  31. data/lib/bundler/compact_index_client/updater.rb +88 -0
  32. data/lib/bundler/current_ruby.rb +4 -3
  33. data/lib/bundler/definition.rb +107 -17
  34. data/lib/bundler/dependency.rb +6 -0
  35. data/lib/bundler/dsl.rb +3 -2
  36. data/lib/bundler/env.rb +27 -18
  37. data/lib/bundler/errors.rb +22 -0
  38. data/lib/bundler/feature_flag.rb +32 -0
  39. data/lib/bundler/fetcher.rb +2 -2
  40. data/lib/bundler/fetcher/compact_index.rb +17 -5
  41. data/lib/bundler/fetcher/dependency.rb +1 -1
  42. data/lib/bundler/fetcher/downloader.rb +11 -0
  43. data/lib/bundler/friendly_errors.rb +28 -7
  44. data/lib/bundler/gem_helper.rb +1 -1
  45. data/lib/bundler/gem_helpers.rb +69 -1
  46. data/lib/bundler/gemdeps.rb +28 -0
  47. data/lib/bundler/index.rb +9 -4
  48. data/lib/bundler/inline.rb +3 -3
  49. data/lib/bundler/installer.rb +3 -2
  50. data/lib/bundler/installer/gem_installer.rb +2 -2
  51. data/lib/bundler/installer/parallel_installer.rb +40 -9
  52. data/lib/bundler/lazy_specification.rb +16 -1
  53. data/lib/bundler/lockfile_parser.rb +1 -2
  54. data/lib/bundler/match_platform.rb +12 -3
  55. data/lib/bundler/plugin.rb +4 -2
  56. data/lib/bundler/plugin/api.rb +2 -1
  57. data/lib/bundler/plugin/api/source.rb +1 -1
  58. data/lib/bundler/postit_trampoline.rb +12 -7
  59. data/lib/bundler/remote_specification.rb +5 -0
  60. data/lib/bundler/resolver.rb +59 -49
  61. data/lib/bundler/retry.rb +4 -1
  62. data/lib/bundler/ruby_version.rb +5 -0
  63. data/lib/bundler/rubygems_ext.rb +5 -0
  64. data/lib/bundler/rubygems_gem_installer.rb +60 -0
  65. data/lib/bundler/rubygems_integration.rb +28 -2
  66. data/lib/bundler/runtime.rb +2 -1
  67. data/lib/bundler/settings.rb +29 -5
  68. data/lib/bundler/setup.rb +1 -1
  69. data/lib/bundler/shared_helpers.rb +26 -15
  70. data/lib/bundler/source.rb +5 -0
  71. data/lib/bundler/source/git.rb +1 -1
  72. data/lib/bundler/source/git/git_proxy.rb +5 -0
  73. data/lib/bundler/source/path.rb +6 -1
  74. data/lib/bundler/source/rubygems.rb +11 -1
  75. data/lib/bundler/spec_set.rb +32 -13
  76. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  77. data/lib/bundler/templates/newgem/bin/console.tt +1 -1
  78. data/lib/bundler/templates/newgem/gitignore.tt +5 -0
  79. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  80. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +10 -1
  81. data/lib/bundler/ui/shell.rb +4 -0
  82. data/lib/bundler/ui/silent.rb +9 -0
  83. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +7 -0
  84. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -1
  85. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +2 -2
  86. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +2 -2
  87. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +62 -0
  88. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  89. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +12 -1
  90. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +2 -2
  91. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +2 -2
  92. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  93. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +22 -13
  94. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/faster.rb +1 -0
  95. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent.rb +24 -23
  96. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent/ssl_reuse.rb +2 -1
  97. data/lib/bundler/vendored_persistent.rb +9 -4
  98. data/lib/bundler/version.rb +1 -1
  99. data/lib/bundler/worker.rb +27 -5
  100. data/lib/bundler/yaml_serializer.rb +1 -1
  101. data/man/bundle-config.ronn +29 -2
  102. data/man/bundle-install.ronn +1 -1
  103. data/man/bundle-lock.ronn +47 -0
  104. data/man/bundle-outdated.ronn +107 -0
  105. data/man/bundle-update.ronn +152 -3
  106. data/man/bundle.ronn +27 -9
  107. data/man/gemfile.5.ronn +8 -0
  108. metadata +37 -31
  109. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client.rb +0 -79
  110. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/cache.rb +0 -112
  111. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/updater.rb +0 -80
  112. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/version.rb +0 -4
@@ -18,6 +18,7 @@ module Bundler
18
18
  :ruby_22 => Gem::Platform::RUBY,
19
19
  :ruby_23 => Gem::Platform::RUBY,
20
20
  :ruby_24 => Gem::Platform::RUBY,
21
+ :ruby_25 => Gem::Platform::RUBY,
21
22
  :mri => Gem::Platform::RUBY,
22
23
  :mri_18 => Gem::Platform::RUBY,
23
24
  :mri_19 => Gem::Platform::RUBY,
@@ -26,6 +27,7 @@ module Bundler
26
27
  :mri_22 => Gem::Platform::RUBY,
27
28
  :mri_23 => Gem::Platform::RUBY,
28
29
  :mri_24 => Gem::Platform::RUBY,
30
+ :mri_25 => Gem::Platform::RUBY,
29
31
  :rbx => Gem::Platform::RUBY,
30
32
  :jruby => Gem::Platform::JAVA,
31
33
  :jruby_18 => Gem::Platform::JAVA,
@@ -38,6 +40,7 @@ module Bundler
38
40
  :mswin_22 => Gem::Platform::MSWIN,
39
41
  :mswin_23 => Gem::Platform::MSWIN,
40
42
  :mswin_24 => Gem::Platform::MSWIN,
43
+ :mswin_25 => Gem::Platform::MSWIN,
41
44
  :mswin64 => Gem::Platform::MSWIN64,
42
45
  :mswin64_19 => Gem::Platform::MSWIN64,
43
46
  :mswin64_20 => Gem::Platform::MSWIN64,
@@ -45,6 +48,7 @@ module Bundler
45
48
  :mswin64_22 => Gem::Platform::MSWIN64,
46
49
  :mswin64_23 => Gem::Platform::MSWIN64,
47
50
  :mswin64_24 => Gem::Platform::MSWIN64,
51
+ :mswin64_25 => Gem::Platform::MSWIN64,
48
52
  :mingw => Gem::Platform::MINGW,
49
53
  :mingw_18 => Gem::Platform::MINGW,
50
54
  :mingw_19 => Gem::Platform::MINGW,
@@ -53,12 +57,14 @@ module Bundler
53
57
  :mingw_22 => Gem::Platform::MINGW,
54
58
  :mingw_23 => Gem::Platform::MINGW,
55
59
  :mingw_24 => Gem::Platform::MINGW,
60
+ :mingw_25 => Gem::Platform::MINGW,
56
61
  :x64_mingw => Gem::Platform::X64_MINGW,
57
62
  :x64_mingw_20 => Gem::Platform::X64_MINGW,
58
63
  :x64_mingw_21 => Gem::Platform::X64_MINGW,
59
64
  :x64_mingw_22 => Gem::Platform::X64_MINGW,
60
65
  :x64_mingw_23 => Gem::Platform::X64_MINGW,
61
66
  :x64_mingw_24 => Gem::Platform::X64_MINGW,
67
+ :x64_mingw_25 => Gem::Platform::X64_MINGW,
62
68
  }.freeze
63
69
 
64
70
  REVERSE_PLATFORM_MAP = {}.tap do |reverse_platform_map|
@@ -65,7 +65,7 @@ module Bundler
65
65
  case specs_by_name_and_version.size
66
66
  when 1
67
67
  specs = specs_by_name_and_version.values.first
68
- spec = specs.find {|s| s.match_platform(Gem::Platform.local) } || specs.first
68
+ spec = specs.find {|s| s.match_platform(Bundler.local_platform) } || specs.first
69
69
 
70
70
  @gemspecs << spec
71
71
 
@@ -393,7 +393,8 @@ module Bundler
393
393
  "as an option for #{command}, but it is invalid."
394
394
  end
395
395
 
396
- message << " Valid options are: #{valid_keys.join(", ")}"
396
+ message << " Valid options are: #{valid_keys.join(", ")}."
397
+ message << " You may be able to resolve this by upgrading Bundler to the newest version."
397
398
  raise InvalidOption, message
398
399
  end
399
400
  end
@@ -12,40 +12,49 @@ module Bundler
12
12
  print_gemfile = options.delete(:print_gemfile)
13
13
  print_gemspecs = options.delete(:print_gemspecs)
14
14
 
15
- out = String.new("Environment\n\n")
16
- out << " Bundler #{Bundler::VERSION}\n"
17
- out << " Rubygems #{Gem::VERSION}\n"
18
- out << " Ruby #{ruby_version}"
19
- out << " GEM_HOME #{ENV["GEM_HOME"]}\n" unless ENV["GEM_HOME"].nil? || ENV["GEM_HOME"].empty?
20
- out << " GEM_PATH #{ENV["GEM_PATH"]}\n" unless ENV["GEM_PATH"] == ENV["GEM_HOME"]
21
- out << " RVM #{ENV["rvm_version"]}\n" if ENV["rvm_version"]
22
- out << " Git #{git_version}\n"
15
+ out = String.new("## Environment\n\n```\n")
16
+ out << "Bundler #{Bundler::VERSION}\n"
17
+ out << "Rubygems #{Gem::VERSION}\n"
18
+ out << "Ruby #{ruby_version}"
19
+ out << "GEM_HOME #{ENV["GEM_HOME"]}\n" unless ENV["GEM_HOME"].nil? || ENV["GEM_HOME"].empty?
20
+ out << "GEM_PATH #{ENV["GEM_PATH"]}\n" unless ENV["GEM_PATH"] == ENV["GEM_HOME"]
21
+ out << "RVM #{ENV["rvm_version"]}\n" if ENV["rvm_version"]
22
+ out << "Git #{git_version}\n"
23
+ out << "Platform #{Gem::Platform.local}\n"
24
+ out << "OpenSSL #{OpenSSL::OPENSSL_VERSION}\n" if defined?(OpenSSL::OPENSSL_VERSION)
23
25
  %w(rubygems-bundler open_gem).each do |name|
24
26
  specs = Bundler.rubygems.find_name(name)
25
- out << " #{name} (#{specs.map(&:version).join(",")})\n" unless specs.empty?
27
+ out << "#{name} (#{specs.map(&:version).join(",")})\n" unless specs.empty?
26
28
  end
27
29
 
28
- out << "\nBundler settings\n\n" unless Bundler.settings.all.empty?
30
+ out << "```\n"
31
+
32
+ out << "\n## Bundler settings\n\n```\n" unless Bundler.settings.all.empty?
29
33
  Bundler.settings.all.each do |setting|
30
- out << " " << setting << "\n"
34
+ out << setting << "\n"
31
35
  Bundler.settings.pretty_values_for(setting).each do |line|
32
- out << " " << line << "\n"
36
+ out << " " << line << "\n"
33
37
  end
34
38
  end
39
+ out << "```\n"
40
+
41
+ return out unless SharedHelpers.in_bundle?
35
42
 
36
43
  if print_gemfile
37
- out << "\n#{Bundler.default_gemfile.relative_path_from(SharedHelpers.pwd)}\n\n"
38
- out << " " << read_file(Bundler.default_gemfile).gsub(/\n/, "\n ") << "\n"
44
+ out << "\n## Gemfile\n"
45
+ out << "\n### #{Bundler.default_gemfile.relative_path_from(SharedHelpers.pwd)}\n\n"
46
+ out << "```ruby\n" << read_file(Bundler.default_gemfile).chomp << "\n```\n"
39
47
 
40
- out << "\n#{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}\n\n"
41
- out << " " << read_file(Bundler.default_lockfile).gsub(/\n/, "\n ") << "\n"
48
+ out << "\n### #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}\n\n"
49
+ out << "```\n" << read_file(Bundler.default_lockfile).chomp << "\n```\n"
42
50
  end
43
51
 
44
52
  if print_gemspecs
45
53
  dsl = Dsl.new.tap {|d| d.eval_gemfile(Bundler.default_gemfile) }
54
+ out << "\n## Gemspecs\n" unless dsl.gemspecs.empty?
46
55
  dsl.gemspecs.each do |gs|
47
- out << "\n#{File.basename(gs.loaded_from)}"
48
- out << "\n\n " << read_file(gs.loaded_from).gsub(/\n/, "\n ") << "\n"
56
+ out << "\n### #{File.basename(gs.loaded_from)}"
57
+ out << "\n\n```ruby\n" << read_file(gs.loaded_from).chomp << "\n```\n"
49
58
  end
50
59
  end
51
60
 
@@ -52,6 +52,8 @@ module Bundler
52
52
  class CyclicDependencyError < BundlerError; status_code(21); end
53
53
  class GemfileLockNotFound < BundlerError; status_code(22); end
54
54
  class PluginError < BundlerError; status_code(29); end
55
+ class SudoNotPermittedError < BundlerError; status_code(30); end
56
+ class ThreadCreationError < BundlerError; status_code(33); end
55
57
  class GemfileEvalError < GemfileError; end
56
58
  class MarshalError < StandardError; end
57
59
 
@@ -131,4 +133,24 @@ module Bundler
131
133
 
132
134
  status_code(28)
133
135
  end
136
+
137
+ class NoSpaceOnDeviceError < PermissionError
138
+ def message
139
+ "There was an error while trying to #{action} `#{@path}`. " \
140
+ "There was insufficent space remaining on the device."
141
+ end
142
+
143
+ status_code(31)
144
+ end
145
+
146
+ class GenericSystemCallError < BundlerError
147
+ attr_reader :underlying_error
148
+
149
+ def initialize(underlying_error, message)
150
+ @underlying_error = underlying_error
151
+ super("#{message}\nThe underlying system error is #{@underlying_error.class}: #{@underlying_error}")
152
+ end
153
+
154
+ status_code(32)
155
+ end
134
156
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Bundler
3
+ class FeatureFlag
4
+ def self.settings_flag(flag, &default)
5
+ unless Bundler::Settings::BOOL_KEYS.include?(flag.to_s)
6
+ raise "Cannot use `#{flag}` as a settings feature flag since it isn't a bool key"
7
+ end
8
+ define_method("#{flag}?") do
9
+ value = Bundler.settings[flag]
10
+ value = instance_eval(&default) if value.nil? && !default.nil?
11
+ value
12
+ end
13
+ end
14
+
15
+ (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
16
+
17
+ settings_flag(:allow_offline_install) { bundler_2_mode? }
18
+ settings_flag(:only_update_to_newer_versions) { bundler_2_mode? }
19
+ settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
20
+
21
+ def initialize(bundler_version)
22
+ @bundler_version = Gem::Version.create(bundler_version)
23
+ end
24
+
25
+ def major_version
26
+ @bundler_version.segments.first
27
+ end
28
+ private :major_version
29
+
30
+ class << self; private :settings_flag; end
31
+ end
32
+ end
@@ -237,7 +237,7 @@ module Bundler
237
237
  Bundler.settings[:ssl_client_cert]
238
238
  raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
239
239
 
240
- con = Net::HTTP::Persistent.new "bundler", :ENV
240
+ con = Bundler::Persistent::Net::HTTP::Persistent.new "bundler", :ENV
241
241
  if gem_proxy = Bundler.rubygems.configuration[:http_proxy]
242
242
  con.proxy = URI.parse(gem_proxy) if gem_proxy != :no_proxy
243
243
  end
@@ -273,7 +273,7 @@ module Bundler
273
273
  Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
274
274
  Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
275
275
  Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
276
- Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
276
+ Bundler::Persistent::Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
277
277
  ].freeze
278
278
 
279
279
  def bundler_cert_store
@@ -3,10 +3,10 @@ require "bundler/fetcher/base"
3
3
  require "bundler/worker"
4
4
 
5
5
  module Bundler
6
+ autoload :CompactIndexClient, "bundler/compact_index_client"
7
+
6
8
  class Fetcher
7
9
  class CompactIndex < Base
8
- require "bundler/vendor/compact_index_client/lib/compact_index_client"
9
-
10
10
  def self.compact_index_request(method_name)
11
11
  method = instance_method(method_name)
12
12
  undef_method(method_name)
@@ -61,7 +61,8 @@ module Bundler
61
61
  compact_index_request :fetch_spec
62
62
 
63
63
  def available?
64
- user_home = Pathname.new(Bundler.rubygems.user_home)
64
+ return nil unless md5_available?
65
+ user_home = Bundler.user_home
65
66
  return nil unless user_home.directory? && user_home.writable?
66
67
  # Read info file checksums out of /versions, so we can know if gems are up to date
67
68
  fetch_uri.scheme != "file" && compact_index_client.update_and_parse_checksums!
@@ -95,7 +96,7 @@ module Bundler
95
96
  def bundle_worker(func = nil)
96
97
  @bundle_worker ||= begin
97
98
  worker_name = "Compact Index (#{display_uri.host})"
98
- Bundler::Worker.new(25, worker_name, func)
99
+ Bundler::Worker.new(Bundler.current_ruby.rbx? ? 1 : 25, worker_name, func)
99
100
  end
100
101
  @bundle_worker.tap do |worker|
101
102
  worker.instance_variable_set(:@func, func) if func
@@ -114,11 +115,22 @@ module Bundler
114
115
  def call(path, headers)
115
116
  fetcher.downloader.fetch(fetcher.fetch_uri + path, headers)
116
117
  rescue NetworkDownError => e
117
- raise unless Bundler.settings[:allow_offline_install] && headers["If-None-Match"]
118
+ raise unless Bundler.feature_flag.allow_offline_install? && headers["If-None-Match"]
118
119
  ui.warn "Using the cached data for the new index because of a network error: #{e}"
119
120
  Net::HTTPNotModified.new(nil, nil, nil)
120
121
  end
121
122
  end
123
+
124
+ def md5_available?
125
+ begin
126
+ require "openssl"
127
+ return false if defined?(OpenSSL::OPENSSL_FIPS) && OpenSSL::OPENSSL_FIPS
128
+ rescue LoadError
129
+ nil
130
+ end
131
+
132
+ true
133
+ end
122
134
  end
123
135
  end
124
136
  end
@@ -73,7 +73,7 @@ module Bundler
73
73
 
74
74
  def dependency_api_uri(gem_names = [])
75
75
  uri = fetch_uri + "api/v1/dependencies"
76
- uri.query = "gems=#{CGI.escape(gem_names.join(","))}" if gem_names.any?
76
+ uri.query = "gems=#{CGI.escape(gem_names.sort.join(","))}" if gem_names.any?
77
77
  uri
78
78
  end
79
79
  end
@@ -38,6 +38,8 @@ module Bundler
38
38
  end
39
39
 
40
40
  def request(uri, options)
41
+ validate_uri_scheme!(uri)
42
+
41
43
  Bundler.ui.debug "HTTP GET #{uri}"
42
44
  req = Net::HTTP::Get.new uri.request_uri, options
43
45
  if uri.user
@@ -61,6 +63,15 @@ module Bundler
61
63
  raise HTTPError, "Network error while fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
62
64
  end
63
65
  end
66
+
67
+ private
68
+
69
+ def validate_uri_scheme!(uri)
70
+ return if uri.scheme =~ /\Ahttps?\z/
71
+ raise InvalidOption,
72
+ "The request uri `#{uri}` has an invalid scheme (`#{uri.scheme}`). " \
73
+ "Did you mean `http` or `https`?"
74
+ end
64
75
  end
65
76
  end
66
77
  end
@@ -37,6 +37,11 @@ module Bundler
37
37
  when Gem::InvalidSpecificationException
38
38
  Bundler.ui.error error.message, :wrap => true
39
39
  when SystemExit
40
+ when *[defined?(Java::JavaLang::OutOfMemoryError) && Java::JavaLang::OutOfMemoryError].compact
41
+ Bundler.ui.error "\nYour JVM has run out of memory, and Bundler cannot continue. " \
42
+ "You can decrease the amount of memory Bundler needs by removing gems from your Gemfile, " \
43
+ "especially large gems. (Gems can be as large as hundreds of megabytes, and Bundler has to read those files!). " \
44
+ "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)."
40
45
  else request_issue_report_for(error)
41
46
  end
42
47
  end
@@ -53,25 +58,41 @@ module Bundler
53
58
  def request_issue_report_for(e)
54
59
  Bundler.ui.info <<-EOS.gsub(/^ {8}/, "")
55
60
  --- ERROR REPORT TEMPLATE -------------------------------------------------------
56
- - What did you do?
61
+ # Error Report
62
+
63
+ ## Questions
64
+
65
+ Please fill out answers to these questions, it'll help us figure out
66
+ why things are going wrong.
67
+
68
+ - **What did you do?**
57
69
 
58
70
  I ran the command `#{$PROGRAM_NAME} #{ARGV.join(" ")}`
59
71
 
60
- - What did you expect to happen?
72
+ - **What did you expect to happen?**
61
73
 
62
74
  I expected Bundler to...
63
75
 
64
- - What happened instead?
76
+ - **What happened instead?**
65
77
 
66
78
  Instead, what happened was...
67
79
 
80
+ - **Have you tried any solutions posted on similar issues in our issue tracker, stack overflow, or google?**
81
+
82
+ I tried...
83
+
84
+ - **Have you read our issues document, https://github.com/bundler/bundler/blob/master/ISSUES.md?**
85
+
86
+ ...
68
87
 
69
- Error details
88
+ ## Backtrace
70
89
 
71
- #{e.class}: #{e.message}
72
- #{e.backtrace && e.backtrace.join("\n ")}
90
+ ```
91
+ #{e.class}: #{e.message}
92
+ #{e.backtrace && e.backtrace.join("\n ").chomp}
93
+ ```
73
94
 
74
- #{Bundler::Env.new.report(:print_gemfile => false, :print_gemspecs => false).gsub(/\n/, "\n ").strip}
95
+ #{Bundler::Env.new.report(:print_gemfile => false, :print_gemspecs => false)}
75
96
  --- TEMPLATE END ----------------------------------------------------------------
76
97
 
77
98
  EOS
@@ -98,7 +98,7 @@ module Bundler
98
98
  allowed_push_host = @gemspec.metadata["allowed_push_host"]
99
99
  gem_command += " --host #{allowed_push_host}" if allowed_push_host
100
100
  end
101
- unless allowed_push_host || Pathname.new("~/.gem/credentials").expand_path.file?
101
+ unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file?
102
102
  raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
103
103
  end
104
104
  sh(gem_command)
@@ -25,8 +25,76 @@ module Bundler
25
25
  module_function :generic
26
26
 
27
27
  def generic_local_platform
28
- generic(Gem::Platform.local)
28
+ generic(Bundler.local_platform)
29
29
  end
30
30
  module_function :generic_local_platform
31
+
32
+ def platform_specificity_match(spec_platform, user_platform)
33
+ spec_platform = Gem::Platform.new(spec_platform)
34
+ return PlatformMatch::EXACT_MATCH if spec_platform == user_platform
35
+ return PlatformMatch::WORST_MATCH if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
36
+
37
+ PlatformMatch.new(
38
+ PlatformMatch.os_match(spec_platform, user_platform),
39
+ PlatformMatch.cpu_match(spec_platform, user_platform),
40
+ PlatformMatch.platform_version_match(spec_platform, user_platform)
41
+ )
42
+ end
43
+ module_function :platform_specificity_match
44
+
45
+ def select_best_platform_match(specs, platform)
46
+ specs.select {|spec| spec.match_platform(platform) }.
47
+ min_by {|spec| platform_specificity_match(spec.platform, platform) }
48
+ end
49
+ module_function :select_best_platform_match
50
+
51
+ PlatformMatch = Struct.new(:os_match, :cpu_match, :platform_version_match)
52
+ class PlatformMatch
53
+ def <=>(other)
54
+ return nil unless other.is_a?(PlatformMatch)
55
+
56
+ m = os_match <=> other.os_match
57
+ return m unless m.zero?
58
+
59
+ m = cpu_match <=> other.cpu_match
60
+ return m unless m.zero?
61
+
62
+ m = platform_version_match <=> other.platform_version_match
63
+ m
64
+ end
65
+
66
+ EXACT_MATCH = new(-1, -1, -1).freeze
67
+ WORST_MATCH = new(1_000_000, 1_000_000, 1_000_000).freeze
68
+
69
+ def self.os_match(spec_platform, user_platform)
70
+ if spec_platform.os == user_platform.os
71
+ 0
72
+ else
73
+ 1
74
+ end
75
+ end
76
+
77
+ def self.cpu_match(spec_platform, user_platform)
78
+ if spec_platform.cpu == user_platform.cpu
79
+ 0
80
+ elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
81
+ 0
82
+ elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
83
+ 1
84
+ else
85
+ 2
86
+ end
87
+ end
88
+
89
+ def self.platform_version_match(spec_platform, user_platform)
90
+ if spec_platform.version == user_platform.version
91
+ 0
92
+ elsif spec_platform.version.nil?
93
+ 1
94
+ else
95
+ 2
96
+ end
97
+ end
98
+ end
31
99
  end
32
100
  end