bundler 1.13.0.rc.1 → 1.13.0.rc.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -0
  3. data/.rubocop.yml +8 -0
  4. data/.rubocop_todo.yml +21 -21
  5. data/.travis.yml +5 -1
  6. data/CHANGELOG.md +33 -1
  7. data/DEVELOPMENT.md +1 -1
  8. data/Rakefile +21 -12
  9. data/bin/rake +1 -1
  10. data/bin/rspec +1 -1
  11. data/bin/rubocop +2 -2
  12. data/bundler.gemspec +2 -2
  13. data/exe/bundler +1 -19
  14. data/lib/bundler.rb +43 -34
  15. data/lib/bundler/cli.rb +54 -5
  16. data/lib/bundler/cli/binstubs.rb +3 -2
  17. data/lib/bundler/cli/console.rb +3 -0
  18. data/lib/bundler/cli/doctor.rb +95 -0
  19. data/lib/bundler/cli/exec.rb +18 -2
  20. data/lib/bundler/cli/gem.rb +1 -1
  21. data/lib/bundler/cli/inject.rb +25 -7
  22. data/lib/bundler/cli/install.rb +23 -2
  23. data/lib/bundler/cli/lock.rb +14 -2
  24. data/lib/bundler/cli/update.rb +9 -0
  25. data/lib/bundler/definition.rb +86 -17
  26. data/lib/bundler/deployment.rb +6 -0
  27. data/lib/bundler/dsl.rb +67 -22
  28. data/lib/bundler/env.rb +1 -1
  29. data/lib/bundler/environment_preserver.rb +1 -1
  30. data/lib/bundler/errors.rb +11 -1
  31. data/lib/bundler/fetcher.rb +3 -2
  32. data/lib/bundler/fetcher/base.rb +10 -0
  33. data/lib/bundler/fetcher/compact_index.rb +27 -9
  34. data/lib/bundler/fetcher/dependency.rb +1 -12
  35. data/lib/bundler/fetcher/downloader.rb +1 -1
  36. data/lib/bundler/friendly_errors.rb +4 -2
  37. data/lib/bundler/gem_helper.rb +2 -2
  38. data/lib/bundler/gem_version_promoter.rb +175 -0
  39. data/lib/bundler/graph.rb +4 -25
  40. data/lib/bundler/index.rb +9 -1
  41. data/lib/bundler/injector.rb +12 -5
  42. data/lib/bundler/inline.rb +2 -2
  43. data/lib/bundler/installer.rb +23 -8
  44. data/lib/bundler/installer/gem_installer.rb +13 -15
  45. data/lib/bundler/installer/parallel_installer.rb +121 -99
  46. data/lib/bundler/lazy_specification.rb +8 -2
  47. data/lib/bundler/lockfile_parser.rb +20 -12
  48. data/lib/bundler/mirror.rb +2 -2
  49. data/lib/bundler/plugin.rb +153 -31
  50. data/lib/bundler/plugin/api.rb +29 -5
  51. data/lib/bundler/plugin/api/source.rb +293 -0
  52. data/lib/bundler/plugin/dsl.rb +25 -1
  53. data/lib/bundler/plugin/index.rb +80 -13
  54. data/lib/bundler/plugin/installer.rb +6 -10
  55. data/lib/bundler/plugin/source_list.rb +4 -0
  56. data/lib/bundler/postit_trampoline.rb +57 -40
  57. data/lib/bundler/resolver.rb +24 -12
  58. data/lib/bundler/retry.rb +2 -1
  59. data/lib/bundler/ruby_version.rb +4 -2
  60. data/lib/bundler/rubygems_ext.rb +10 -3
  61. data/lib/bundler/rubygems_gem_installer.rb +6 -0
  62. data/lib/bundler/rubygems_integration.rb +101 -66
  63. data/lib/bundler/runtime.rb +25 -2
  64. data/lib/bundler/settings.rb +30 -11
  65. data/lib/bundler/setup.rb +6 -3
  66. data/lib/bundler/shared_helpers.rb +11 -5
  67. data/lib/bundler/source/gemspec.rb +4 -0
  68. data/lib/bundler/source/git.rb +9 -6
  69. data/lib/bundler/source/git/git_proxy.rb +27 -3
  70. data/lib/bundler/source/path.rb +4 -26
  71. data/lib/bundler/source/path/installer.rb +39 -11
  72. data/lib/bundler/source/rubygems.rb +1 -1
  73. data/lib/bundler/source_list.rb +28 -8
  74. data/lib/bundler/spec_set.rb +1 -1
  75. data/lib/bundler/templates/Executable.standalone +4 -2
  76. data/lib/bundler/templates/Gemfile +0 -1
  77. data/lib/bundler/ui/shell.rb +11 -3
  78. data/lib/bundler/ui/silent.rb +1 -3
  79. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client.rb +1 -2
  80. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/cache.rb +16 -2
  81. data/lib/bundler/version.rb +1 -1
  82. data/lib/bundler/yaml_serializer.rb +34 -11
  83. data/man/bundle-binstubs.ronn +29 -0
  84. data/man/bundle-config.ronn +32 -0
  85. data/man/bundle-install.ronn +6 -41
  86. data/man/bundle-package.ronn +1 -1
  87. data/man/bundle.ronn +4 -3
  88. data/man/gemfile.5.ronn +1 -1
  89. metadata +13 -9
  90. data/lib/bundler/environment.rb +0 -42
@@ -10,6 +10,8 @@ module Bundler
10
10
  def run
11
11
  Bundler.ui.level = "error" if options[:quiet]
12
12
 
13
+ Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.settings[:plugins]
14
+
13
15
  sources = Array(options[:source])
14
16
  groups = Array(options[:group]).map(&:to_sym)
15
17
 
@@ -37,6 +39,13 @@ module Bundler
37
39
  Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby])
38
40
  end
39
41
 
42
+ patch_level = [:major, :minor, :patch].select {|v| options.keys.include?(v.to_s) }
43
+ raise ProductionError, "Provide only one of the following options: #{patch_level.join(", ")}" unless patch_level.length <= 1
44
+ Bundler.definition.gem_version_promoter.tap do |gvp|
45
+ gvp.level = patch_level.first || :major
46
+ gvp.strict = options[:strict]
47
+ end
48
+
40
49
  Bundler::Fetcher.disable_endpoint = options["full-index"]
41
50
 
42
51
  opts = options.dup
@@ -7,7 +7,15 @@ module Bundler
7
7
  class Definition
8
8
  include GemHelpers
9
9
 
10
- attr_reader :dependencies, :platforms, :ruby_version, :locked_deps
10
+ attr_reader(
11
+ :dependencies,
12
+ :gem_version_promoter,
13
+ :locked_deps,
14
+ :locked_gems,
15
+ :platforms,
16
+ :requires,
17
+ :ruby_version
18
+ )
11
19
 
12
20
  # Given a gemfile and lockfile creates a Bundler definition
13
21
  #
@@ -60,15 +68,15 @@ module Bundler
60
68
 
61
69
  if lockfile && File.exist?(lockfile)
62
70
  @lockfile_contents = Bundler.read_file(lockfile)
63
- locked = LockfileParser.new(@lockfile_contents)
64
- @platforms = locked.platforms
65
- @locked_bundler_version = locked.bundler_version
66
- @locked_ruby_version = locked.ruby_version
71
+ @locked_gems = LockfileParser.new(@lockfile_contents)
72
+ @platforms = @locked_gems.platforms
73
+ @locked_bundler_version = @locked_gems.bundler_version
74
+ @locked_ruby_version = @locked_gems.ruby_version
67
75
 
68
76
  if unlock != true
69
- @locked_deps = locked.dependencies
70
- @locked_specs = SpecSet.new(locked.specs)
71
- @locked_sources = locked.sources
77
+ @locked_deps = @locked_gems.dependencies
78
+ @locked_specs = SpecSet.new(@locked_gems.specs)
79
+ @locked_sources = @locked_gems.sources
72
80
  else
73
81
  @unlock = {}
74
82
  @locked_deps = []
@@ -78,6 +86,7 @@ module Bundler
78
86
  else
79
87
  @unlock = {}
80
88
  @platforms = []
89
+ @locked_gems = nil
81
90
  @locked_deps = []
82
91
  @locked_specs = SpecSet.new([])
83
92
  @locked_sources = []
@@ -94,6 +103,8 @@ module Bundler
94
103
  end
95
104
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
96
105
 
106
+ @gem_version_promoter = create_gem_version_promoter
107
+
97
108
  current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
98
109
  add_platform(current_platform)
99
110
 
@@ -105,6 +116,8 @@ module Bundler
105
116
  @dependency_changes = converge_dependencies
106
117
  @local_changes = converge_locals
107
118
 
119
+ @requires = compute_requires
120
+
108
121
  fixup_dependency_types!
109
122
  end
110
123
 
@@ -123,6 +136,21 @@ module Bundler
123
136
  end
124
137
  end
125
138
 
139
+ def create_gem_version_promoter
140
+ locked_specs = begin
141
+ if @unlocking && @locked_specs.empty? && !@lockfile_contents.empty?
142
+ # Definition uses an empty set of locked_specs to indicate all gems
143
+ # are unlocked, but GemVersionPromoter needs the locked_specs
144
+ # for conservative comparison.
145
+ locked = Bundler::LockfileParser.new(@lockfile_contents)
146
+ Bundler::SpecSet.new(locked.specs)
147
+ else
148
+ @locked_specs
149
+ end
150
+ end
151
+ GemVersionPromoter.new(locked_specs, @unlock[:gems])
152
+ end
153
+
126
154
  def resolve_with_cache!
127
155
  raise "Specs already loaded" if @specs
128
156
  sources.cached!
@@ -198,7 +226,7 @@ module Bundler
198
226
  end
199
227
 
200
228
  def current_dependencies
201
- dependencies.reject {|d| !d.should_include? }
229
+ dependencies.select(&:should_include?)
202
230
  end
203
231
 
204
232
  def specs_for(groups)
@@ -221,7 +249,7 @@ module Bundler
221
249
  else
222
250
  # Run a resolve against the locally available gems
223
251
  Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
224
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, ruby_version)
252
+ last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, ruby_version, gem_version_promoter, additional_base_requirements_for_resolve)
225
253
  end
226
254
  end
227
255
  end
@@ -453,6 +481,11 @@ module Bundler
453
481
  @platforms |= [platform]
454
482
  end
455
483
 
484
+ def remove_platform(platform)
485
+ return if @platforms.delete(Gem::Platform.new(platform))
486
+ raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
487
+ end
488
+
456
489
  attr_reader :sources
457
490
  private :sources
458
491
 
@@ -493,14 +526,14 @@ module Bundler
493
526
  # Check if the specs of the given source changed
494
527
  # according to the locked source.
495
528
  def specs_changed?(source)
496
- locked = @locked_sources.find(source)
529
+ locked = @locked_sources.find {|s| s == source }
497
530
 
498
- !locked || dependencies_for_source_changed?(source) || specs_for_source_changed?(source)
531
+ !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
499
532
  end
500
533
 
501
- def dependencies_for_source_changed?(source)
534
+ def dependencies_for_source_changed?(source, locked_source = source)
502
535
  deps_for_source = @dependencies.select {|s| s.source == source }
503
- locked_deps_for_source = @locked_deps.select {|s| s.source == source }
536
+ locked_deps_for_source = @locked_deps.select {|s| s.source == locked_source }
504
537
 
505
538
  Set.new(deps_for_source) != Set.new(locked_deps_for_source)
506
539
  end
@@ -527,9 +560,10 @@ module Bundler
527
560
  end
528
561
  end
529
562
 
530
- locals.any? do |source, changed|
563
+ sources_with_changes = locals.select do |source, changed|
531
564
  changed || specs_changed?(source)
532
- end
565
+ end.map(&:first)
566
+ !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
533
567
  end
534
568
 
535
569
  def converge_paths
@@ -538,9 +572,22 @@ module Bundler
538
572
  end
539
573
  end
540
574
 
575
+ def converge_path_source_to_gemspec_source(source)
576
+ return source unless source.instance_of?(Source::Path)
577
+ gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
578
+ gemspec_source || source
579
+ end
580
+
541
581
  def converge_sources
542
582
  changes = false
543
583
 
584
+ @locked_sources.map! do |source|
585
+ converge_path_source_to_gemspec_source(source)
586
+ end
587
+ @locked_specs.each do |spec|
588
+ spec.source &&= converge_path_source_to_gemspec_source(spec.source)
589
+ end
590
+
544
591
  # Get the Rubygems sources from the Gemfile.lock
545
592
  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
546
593
  # Get the Rubygems remotes from the Gemfile
@@ -585,6 +632,9 @@ module Bundler
585
632
  elsif dep.source
586
633
  dep.source = sources.get(dep.source)
587
634
  end
635
+ if dep.source.is_a?(Source::Gemspec)
636
+ dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq!
637
+ end
588
638
  end
589
639
  Set.new(@dependencies) != Set.new(@locked_deps)
590
640
  end
@@ -636,7 +686,7 @@ module Bundler
636
686
  # then we unlock it.
637
687
 
638
688
  # Path sources have special logic
639
- if s.source.instance_of?(Source::Path)
689
+ if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
640
690
  other = s.source.specs[s].first
641
691
 
642
692
  # If the spec is no longer in the path source, unlock it. This
@@ -751,5 +801,24 @@ module Bundler
751
801
  # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
752
802
  error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
753
803
  end
804
+
805
+ def compute_requires
806
+ dependencies.reduce({}) do |requires, dep|
807
+ next requires unless dep.should_include?
808
+ requires[dep.name] = Array(dep.autorequire || dep.name).map do |file|
809
+ # Allow `require: true` as an alias for `require: <name>`
810
+ file == true ? dep.name : file
811
+ end
812
+ requires
813
+ end
814
+ end
815
+
816
+ def additional_base_requirements_for_resolve
817
+ return [] unless @locked_gems && Bundler.settings[:only_update_to_newer_versions]
818
+ @locked_gems.specs.reduce({}) do |requirements, locked_spec|
819
+ requirements[locked_spec.name] = Gem::Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
820
+ requirements
821
+ end.values
822
+ end
754
823
  end
755
824
  end
@@ -1,4 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require "bundler/shared_helpers"
4
+ Bundler::SharedHelpers.major_deprecation "Bundler no longer integrates with " \
5
+ "Capistrano, but Capistrano provides its own integration with " \
6
+ "Bundler via the capistrano-bundler gem. Use it instead."
7
+
2
8
  module Bundler
3
9
  class Deployment
4
10
  def self.define_task(context, task_method = :task, opts = {})
@@ -38,7 +38,7 @@ module Bundler
38
38
  original_gemfile = @gemfile
39
39
  @gemfile = expanded_gemfile_path
40
40
  contents ||= Bundler.read_file(gemfile.to_s)
41
- instance_eval(contents, gemfile.to_s, 1)
41
+ instance_eval(contents.dup.untaint, gemfile.to_s, 1)
42
42
  rescue Exception => e
43
43
  message = "There was an error " \
44
44
  "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -50,22 +50,22 @@ module Bundler
50
50
  end
51
51
 
52
52
  def gemspec(opts = nil)
53
- path = opts && opts[:path] || "."
54
- glob = opts && opts[:glob]
55
- name = opts && opts[:name] || "{,*}"
56
- development_group = opts && opts[:development_group] || :development
53
+ opts ||= {}
54
+ path = opts[:path] || "."
55
+ glob = opts[:glob]
56
+ name = opts[:name]
57
+ development_group = opts[:development_group] || :development
57
58
  expanded_path = gemfile_root.join(path)
58
59
 
59
- gemspecs = Dir[File.join(expanded_path, "#{name}.gemspec")]
60
+ gemspecs = Dir[File.join(expanded_path, "{,*}.gemspec")].map {|g| Bundler.load_gemspec(g) }.compact
61
+ gemspecs.reject! {|s| s.name != name } if name
62
+ Index.sort_specs(gemspecs)
63
+ specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] }
60
64
 
61
- case gemspecs.size
65
+ case specs_by_name_and_version.size
62
66
  when 1
63
- spec = Bundler.load_gemspec(gemspecs.first)
64
-
65
- unless spec
66
- raise InvalidOption, "There was an error loading the gemspec at " \
67
- "#{file}. Make sure you can build the gem, then try again"
68
- end
67
+ specs = specs_by_name_and_version.values.first
68
+ spec = specs.find {|s| s.match_platform(Gem::Platform.local) } || specs.first
69
69
 
70
70
  @gemspecs << spec
71
71
 
@@ -74,7 +74,7 @@ module Bundler
74
74
 
75
75
  group(development_group) do
76
76
  spec.development_dependencies.each do |dep|
77
- gem dep.name, *(dep.requirement.as_list + [:type => :development, :platforms => gem_platforms])
77
+ gem dep.name, *(dep.requirement.as_list + [:type => :development])
78
78
  end
79
79
  end
80
80
  when 0
@@ -125,11 +125,26 @@ module Bundler
125
125
  @dependencies << dep
126
126
  end
127
127
 
128
- def source(source, &blk)
129
- source = normalize_source(source)
130
- if block_given?
128
+ def source(source, *args, &blk)
129
+ options = args.last.is_a?(Hash) ? args.pop.dup : {}
130
+ options = normalize_hash(options)
131
+ if options.key?("type")
132
+ options["type"] = options["type"].to_s
133
+ unless Plugin.source?(options["type"])
134
+ raise "No sources available for #{options["type"]}"
135
+ end
136
+
137
+ unless block_given?
138
+ raise InvalidOption, "You need to pass a block to #source with :type option"
139
+ end
140
+
141
+ source_opts = options.merge("uri" => source)
142
+ with_source(@sources.add_plugin_source(options["type"], source_opts), &blk)
143
+ elsif block_given?
144
+ source = normalize_source(source)
131
145
  with_source(@sources.add_rubygems_source("remotes" => source), &blk)
132
146
  else
147
+ source = normalize_source(source)
133
148
  check_primary_source_safety(@sources)
134
149
  @sources.add_rubygems_remote(source)
135
150
  end
@@ -250,13 +265,25 @@ module Bundler
250
265
  # "https://github.com/#{repo_name}.git"
251
266
  # end
252
267
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
253
- "git://github.com/#{repo_name}.git"
268
+ # TODO: 2.0 upgrade this setting to the default
269
+ if Bundler.settings["github.https"]
270
+ "https://github.com/#{repo_name}.git"
271
+ else
272
+ warn_github_source_change(repo_name)
273
+ "git://github.com/#{repo_name}.git"
274
+ end
254
275
  end
255
276
 
256
- git_source(:gist) {|repo_name| "https://gist.github.com/#{repo_name}.git" }
277
+ # TODO: 2.0 remove this deprecated git source
278
+ git_source(:gist) do |repo_name|
279
+ warn_deprecated_git_source(:gist, 'https://gist.github.com/#{repo_name}.git')
280
+ "https://gist.github.com/#{repo_name}.git"
281
+ end
257
282
 
283
+ # TODO: 2.0 remove this deprecated git source
258
284
  git_source(:bitbucket) do |repo_name|
259
285
  user_name, repo_name = repo_name.split "/"
286
+ warn_deprecated_git_source(:bitbucket, 'https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git')
260
287
  repo_name ||= user_name
261
288
  "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
262
289
  end
@@ -388,13 +415,14 @@ module Bundler
388
415
  def check_primary_source_safety(source)
389
416
  return unless source.rubygems_primary_remotes.any?
390
417
 
418
+ # TODO: 2.0 upgrade from setting to default
391
419
  if Bundler.settings[:disable_multisource]
392
- raise GemspecError, "Warning: this Gemfile contains multiple primary sources. " \
420
+ raise GemfileError, "Warning: this Gemfile contains multiple primary sources. " \
393
421
  "Each source after the first must include a block to indicate which gems " \
394
422
  "should come from that source. To downgrade this error to a warning, run " \
395
423
  "`bundle config --delete disable_multisource`"
396
424
  else
397
- Bundler.ui.warn "Warning: this Gemfile contains multiple primary sources. " \
425
+ Bundler::SharedHelpers.major_deprecation "Your Gemfile contains multiple primary sources. " \
398
426
  "Using `source` more than once without a block is a security risk, and " \
399
427
  "may result in installing unexpected gems. To resolve this warning, use " \
400
428
  "a block to indicate which gems should come from the secondary source. " \
@@ -403,6 +431,23 @@ module Bundler
403
431
  end
404
432
  end
405
433
 
434
+ def warn_github_source_change(repo_name)
435
+ # TODO: 2.0 remove deprecation
436
+ Bundler::SharedHelpers.major_deprecation "The :github option uses the git: protocol, which is not secure. " \
437
+ "Bundler 2.0 will use the https: protocol, which is secure. Enable this change now by " \
438
+ "running `bundle config github.https true`."
439
+ end
440
+
441
+ def warn_deprecated_git_source(name, repo_string)
442
+ # TODO: 2.0 remove deprecation
443
+ Bundler::SharedHelpers.major_deprecation <<-EOS
444
+ The :#{name} git source is deprecated, and will be removed in Bundler 2.0. Add this code to your Gemfile to ensure it continues to work:
445
+ git_source(:#{name}) do |repo_name|
446
+ "#{repo_string}"
447
+ end
448
+ EOS
449
+ end
450
+
406
451
  class DSLError < GemfileError
407
452
  # @return [String] the description that should be presented to the user.
408
453
  #
@@ -477,7 +522,7 @@ module Bundler
477
522
 
478
523
  lines = contents.lines.to_a
479
524
  indent = " # "
480
- indicator = indent.tr('#', ">")
525
+ indicator = indent.tr("#", ">")
481
526
  first_line = (line_numer.zero?)
482
527
  last_line = (line_numer == (lines.count - 1))
483
528
 
@@ -75,7 +75,7 @@ module Bundler
75
75
  end
76
76
 
77
77
  def git_version
78
- Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
78
+ Bundler::Source::Git::GitProxy.new(nil, nil, nil).full_version
79
79
  rescue Bundler::Source::Git::GitNotInstalledError
80
80
  "not installed"
81
81
  end
@@ -6,7 +6,7 @@ module Bundler
6
6
  def initialize(env, keys)
7
7
  @original = env.to_hash
8
8
  @keys = keys
9
- @prefix = "BUNDLE_ORIG_"
9
+ @prefix = "BUNDLER_ORIG_"
10
10
  end
11
11
 
12
12
  # @return [Hash]
@@ -3,6 +3,16 @@ module Bundler
3
3
  class BundlerError < StandardError
4
4
  def self.status_code(code)
5
5
  define_method(:status_code) { code }
6
+ if match = BundlerError.all_errors.find {|_k, v| v == code }
7
+ error, _ = match
8
+ raise ArgumentError,
9
+ "Trying to register #{self} for status code #{code} but #{error} is already registered"
10
+ end
11
+ BundlerError.all_errors[self] = code
12
+ end
13
+
14
+ def self.all_errors
15
+ @all_errors ||= {}
6
16
  end
7
17
  end
8
18
 
@@ -41,7 +51,7 @@ module Bundler
41
51
  class LockfileError < BundlerError; status_code(20); end
42
52
  class CyclicDependencyError < BundlerError; status_code(21); end
43
53
  class GemfileLockNotFound < BundlerError; status_code(22); end
44
- class PluginError < BundlerError; status_code(23); end
54
+ class PluginError < BundlerError; status_code(29); end
45
55
  class GemfileEvalError < GemfileError; end
46
56
  class MarshalError < StandardError; end
47
57
 
@@ -131,10 +131,10 @@ module Bundler
131
131
  @use_api = false if fetchers.none?(&:api_fetcher?)
132
132
  end
133
133
 
134
- specs.each do |name, version, platform, dependencies|
134
+ specs.each do |name, version, platform, dependencies, metadata|
135
135
  next if name == "bundler"
136
136
  spec = if dependencies
137
- EndpointSpecification.new(name, version, platform, dependencies)
137
+ EndpointSpecification.new(name, version, platform, dependencies, metadata)
138
138
  else
139
139
  RemoteSpecification.new(name, version, platform, self)
140
140
  end
@@ -255,6 +255,7 @@ module Bundler
255
255
  end
256
256
 
257
257
  con.read_timeout = Fetcher.api_timeout
258
+ con.open_timeout = Fetcher.api_timeout
258
259
  con.override_headers["User-Agent"] = user_agent
259
260
  con.override_headers["X-Gemfile-Source"] = @remote.original_uri.to_s if @remote.original_uri
260
261
  con