bundler 1.12.6 → 1.13.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +15 -13
  3. data/.travis.yml +2 -2
  4. data/CHANGELOG.md +40 -3
  5. data/CONTRIBUTING.md +9 -5
  6. data/DEVELOPMENT.md +30 -18
  7. data/ISSUES.md +26 -22
  8. data/Rakefile +15 -4
  9. data/bin/rubocop +1 -1
  10. data/bundler.gemspec +2 -2
  11. data/exe/bundle +7 -0
  12. data/lib/bundler.rb +6 -3
  13. data/lib/bundler/capistrano.rb +1 -1
  14. data/lib/bundler/cli.rb +27 -10
  15. data/lib/bundler/cli/binstubs.rb +2 -0
  16. data/lib/bundler/cli/exec.rb +1 -1
  17. data/lib/bundler/cli/install.rb +87 -56
  18. data/lib/bundler/cli/lock.rb +5 -0
  19. data/lib/bundler/cli/open.rb +3 -1
  20. data/lib/bundler/cli/outdated.rb +8 -8
  21. data/lib/bundler/cli/plugin.rb +23 -0
  22. data/lib/bundler/cli/update.rb +2 -2
  23. data/lib/bundler/cli/viz.rb +3 -0
  24. data/lib/bundler/definition.rb +72 -16
  25. data/lib/bundler/dsl.rb +19 -7
  26. data/lib/bundler/endpoint_specification.rb +2 -2
  27. data/lib/bundler/env.rb +2 -2
  28. data/lib/bundler/errors.rb +15 -1
  29. data/lib/bundler/fetcher.rb +5 -2
  30. data/lib/bundler/fetcher/compact_index.rb +2 -2
  31. data/lib/bundler/fetcher/dependency.rb +8 -4
  32. data/lib/bundler/fetcher/downloader.rb +1 -1
  33. data/lib/bundler/friendly_errors.rb +1 -1
  34. data/lib/bundler/index.rb +29 -36
  35. data/lib/bundler/inline.rb +14 -4
  36. data/lib/bundler/installer.rb +22 -3
  37. data/lib/bundler/installer/gem_installer.rb +1 -1
  38. data/lib/bundler/installer/standalone.rb +1 -1
  39. data/lib/bundler/mirror.rb +4 -4
  40. data/lib/bundler/plugin.rb +156 -0
  41. data/lib/bundler/plugin/api.rb +56 -0
  42. data/lib/bundler/plugin/dsl.rb +29 -0
  43. data/lib/bundler/plugin/index.rb +88 -0
  44. data/lib/bundler/plugin/installer.rb +99 -0
  45. data/lib/bundler/plugin/installer/git.rb +38 -0
  46. data/lib/bundler/plugin/installer/rubygems.rb +27 -0
  47. data/lib/bundler/plugin/source_list.rb +24 -0
  48. data/lib/bundler/postit_trampoline.rb +54 -0
  49. data/lib/bundler/psyched_yaml.rb +1 -1
  50. data/lib/bundler/remote_specification.rb +5 -5
  51. data/lib/bundler/resolver.rb +27 -29
  52. data/lib/bundler/ruby_version.rb +29 -3
  53. data/lib/bundler/rubygems_ext.rb +3 -1
  54. data/lib/bundler/rubygems_integration.rb +10 -4
  55. data/lib/bundler/runtime.rb +1 -16
  56. data/lib/bundler/settings.rb +19 -15
  57. data/lib/bundler/setup.rb +1 -0
  58. data/lib/bundler/shared_helpers.rb +3 -0
  59. data/lib/bundler/source.rb +4 -3
  60. data/lib/bundler/source/gemspec.rb +13 -0
  61. data/lib/bundler/source/git.rb +4 -3
  62. data/lib/bundler/source/git/git_proxy.rb +9 -5
  63. data/lib/bundler/source/path.rb +11 -2
  64. data/lib/bundler/source/rubygems.rb +28 -15
  65. data/lib/bundler/source_list.rb +5 -1
  66. data/lib/bundler/spec_set.rb +3 -3
  67. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
  68. data/lib/bundler/ssl_certs/rubygems.org/{AddTrustExternalCARoot-2048.pem → AddTrustExternalCARoot.pem} +0 -0
  69. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +54 -29
  70. data/lib/bundler/templates/newgem/newgem.gemspec.tt +5 -2
  71. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +3 -3
  72. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -2
  73. data/lib/bundler/ui/shell.rb +4 -0
  74. data/lib/bundler/ui/silent.rb +3 -0
  75. data/lib/bundler/uri_credentials_filter.rb +36 -0
  76. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/updater.rb +1 -1
  77. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +50 -0
  78. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +80 -0
  79. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +56 -144
  80. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +35 -0
  81. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +58 -0
  82. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +61 -0
  83. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +53 -0
  84. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +114 -0
  85. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +45 -0
  86. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +35 -0
  87. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +123 -0
  88. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  89. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +46 -51
  90. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +4 -2
  91. data/lib/bundler/vendor/postit/lib/postit.rb +15 -0
  92. data/lib/bundler/vendor/postit/lib/postit/environment.rb +44 -0
  93. data/lib/bundler/vendor/postit/lib/postit/installer.rb +28 -0
  94. data/lib/bundler/vendor/postit/lib/postit/parser.rb +21 -0
  95. data/lib/bundler/vendor/postit/lib/postit/setup.rb +12 -0
  96. data/lib/bundler/vendor/postit/lib/postit/version.rb +3 -0
  97. data/lib/bundler/version.rb +1 -1
  98. data/lib/bundler/vlad.rb +1 -1
  99. data/lib/bundler/yaml_serializer.rb +67 -0
  100. data/man/bundle-install.ronn +10 -5
  101. data/man/bundle-package.ronn +7 -6
  102. data/man/bundle-platform.ronn +1 -1
  103. data/man/bundle-update.ronn +5 -2
  104. data/man/bundle.ronn +5 -5
  105. data/man/gemfile.5.ronn +32 -28
  106. metadata +37 -12
  107. data/lib/bundler/ssl_certs/Fastly.pem +0 -82
  108. data/lib/bundler/ssl_certs/GlobalSignOrganizationValidationCA.pem +0 -26
  109. data/lib/bundler/ssl_certs/GlobalSignRoot.pem +0 -18
  110. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRoot.pem +0 -18
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # This is the interfacing class represents the API that we intend to provide
5
+ # the plugins to use.
6
+ #
7
+ # For plugins to be independent of the Bundler internals they shall limit their
8
+ # interactions to methods of this class only. This will save them from breaking
9
+ # when some internal change.
10
+ #
11
+ # Currently we are delegating the methods defined in Bundler class to
12
+ # itself. So, this class acts as a buffer.
13
+ #
14
+ # If there is some change in the Bundler class that is incompatible to its
15
+ # previous behavior or if otherwise desired, we can reimplement(or implement)
16
+ # the method to preserve compatibility.
17
+ #
18
+ # To use this, either the class can inherit this class or use it directly.
19
+ # For example of both types of use, refer the file `spec/plugins/command.rb`
20
+ #
21
+ # To use it without inheriting, you will have to create an object of this
22
+ # to use the functions (except for declaration functions like command, source,
23
+ # and hooks).
24
+ module Plugin
25
+ class API
26
+ # The plugins should declare that they handle a command through this helper.
27
+ #
28
+ # @param [String] command being handled by them
29
+ # @param [Class] (optional) class that shall handle the command. If not
30
+ # provided, the `self` class will be used.
31
+ def self.command(command, cls = self)
32
+ Plugin.add_command command, cls
33
+ end
34
+
35
+ # The cache dir to be used by the plugins for persistance storage
36
+ #
37
+ # @return [Pathname] path of the cache dir
38
+ def cache
39
+ Plugin.cache.join("plugins")
40
+ end
41
+
42
+ # A tmp dir to be used by plugins
43
+ # Accepts names that get concatenated as suffix
44
+ #
45
+ # @return [Pathname] object for the new directory created
46
+ def tmp(*names)
47
+ Bundler.tmp(["plugin", *names].join("-"))
48
+ end
49
+
50
+ def method_missing(name, *args, &blk)
51
+ super unless Bundler.respond_to?(name)
52
+ Bundler.send(name, *args, &blk)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # Dsl to parse the Gemfile looking for plugins to install
5
+ module Plugin
6
+ class DSL < Bundler::Dsl
7
+ class PluginGemfileError < PluginError; end
8
+ alias_method :_gem, :gem # To use for plugin installation as gem
9
+
10
+ # So that we don't have to override all there methods to dummy ones
11
+ # explicitly.
12
+ # They will be handled by method_missing
13
+ [:gemspec, :gem, :path, :install_if, :platforms, :env].each {|m| undef_method m }
14
+
15
+ def initialize
16
+ super
17
+ @sources = Plugin::SourceList.new
18
+ end
19
+
20
+ def plugin(name, *args)
21
+ _gem(name, *args)
22
+ end
23
+
24
+ def method_missing(name, *args)
25
+ raise PluginGemfileError, "Undefined local variable or method `#{name}' for Gemfile" unless Bundler::Dsl.method_defined? name
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # Manages which plugins are installed and their sources. This also is supposed to map
5
+ # which plugin does what (currently the features are not implemented so this class is
6
+ # now a stub class).
7
+ module Plugin
8
+ class Index
9
+ class CommandConflict < PluginError
10
+ def initialize(plugin, commands)
11
+ msg = "Command(s) `#{commands.join("`, `")}` declared by #{plugin} are already registered."
12
+ super msg
13
+ end
14
+ end
15
+
16
+ def initialize
17
+ @plugin_paths = {}
18
+ @commands = {}
19
+
20
+ load_index
21
+ end
22
+
23
+ # This function is to be called when a new plugin is installed. This function shall add
24
+ # the functions of the plugin to existing maps and also the name to source location.
25
+ #
26
+ # @param [String] name of the plugin to be registered
27
+ # @param [String] path where the plugin is installed
28
+ # @param [Array<String>] commands that are handled by the plugin
29
+ def register_plugin(name, path, commands)
30
+ @plugin_paths[name] = path
31
+
32
+ common = commands & @commands.keys
33
+ raise CommandConflict.new(name, common) unless common.empty?
34
+ commands.each {|c| @commands[c] = name }
35
+
36
+ save_index
37
+ end
38
+
39
+ # Path where the index file is stored
40
+ def index_file
41
+ Plugin.root.join("index")
42
+ end
43
+
44
+ def plugin_path(name)
45
+ Pathname.new @plugin_paths[name]
46
+ end
47
+
48
+ # Fetch the name of plugin handling the command
49
+ def command_plugin(command)
50
+ @commands[command]
51
+ end
52
+
53
+ def installed?(name)
54
+ @plugin_paths[name]
55
+ end
56
+
57
+ private
58
+
59
+ # Reads the index file from the directory and initializes the instance variables.
60
+ def load_index
61
+ SharedHelpers.filesystem_access(index_file, :read) do |index_f|
62
+ valid_file = index_f && index_f.exist? && !index_f.size.zero?
63
+ break unless valid_file
64
+ data = index_f.read
65
+ require "bundler/yaml_serializer"
66
+ index = YAMLSerializer.load(data)
67
+ @plugin_paths = index["plugin_paths"] || {}
68
+ @commands = index["commands"] || {}
69
+ end
70
+ end
71
+
72
+ # Should be called when any of the instance variables change. Stores the instance
73
+ # variables in YAML format. (The instance variables are supposed to be only String key value pairs)
74
+ def save_index
75
+ index = {
76
+ "plugin_paths" => @plugin_paths,
77
+ "commands" => @commands,
78
+ }
79
+
80
+ require "bundler/yaml_serializer"
81
+ SharedHelpers.filesystem_access(index_file) do |index_f|
82
+ FileUtils.mkdir_p(index_f.dirname)
83
+ File.open(index_f, "w") {|f| f.puts YAMLSerializer.dump(index) }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # Handles the installation of plugin in appropriate directories.
5
+ #
6
+ # This class is supposed to be wrapper over the existing gem installation infra
7
+ # but currently it itself handles everything as the Source's subclasses (e.g. Source::RubyGems)
8
+ # are heavily dependent on the Gemfile.
9
+ module Plugin
10
+ class Installer
11
+ autoload :Rubygems, "bundler/plugin/installer/rubygems"
12
+ autoload :Git, "bundler/plugin/installer/git"
13
+
14
+ def install(names, options)
15
+ version = options[:version] || [">= 0"]
16
+
17
+ if options[:git]
18
+ install_git(names, version, options)
19
+ else
20
+ sources = options[:source] || Bundler.rubygems.sources
21
+ install_rubygems(names, version, sources)
22
+ end
23
+ end
24
+
25
+ # Installs the plugin from Definition object created by limited parsing of
26
+ # Gemfile searching for plugins to be installed
27
+ #
28
+ # @param [Definition] definiton object
29
+ # @return [Hash] map of plugin names to thier paths
30
+ def install_definition(definition)
31
+ plugins = definition.dependencies.map(&:name)
32
+
33
+ def definition.lock(*); end
34
+ definition.resolve_remotely!
35
+ specs = definition.specs
36
+
37
+ paths = install_from_specs specs
38
+
39
+ Hash[paths.select {|name, _| plugins.include? name }]
40
+ end
41
+
42
+ private
43
+
44
+ def install_git(names, version, options)
45
+ uri = options.delete(:git)
46
+ options["uri"] = uri
47
+
48
+ source_list = SourceList.new
49
+ source_list.add_git_source(options)
50
+
51
+ # To support both sources
52
+ if options[:source]
53
+ source_list.add_rubygems_source("remotes" => options[:source])
54
+ end
55
+
56
+ deps = names.map {|name| Dependency.new name, version }
57
+
58
+ definition = Definition.new(nil, deps, source_list, true)
59
+ install_definition(definition)
60
+ end
61
+
62
+ # Installs the plugin from rubygems source and returns the path where the
63
+ # plugin was installed
64
+ #
65
+ # @param [String] name of the plugin gem to search in the source
66
+ # @param [Array] version of the gem to install
67
+ # @param [String, Array<String>] source(s) to resolve the gem
68
+ #
69
+ # @return [String] the path where the plugin was installed
70
+ def install_rubygems(names, version, sources)
71
+ deps = names.map {|name| Dependency.new name, version }
72
+
73
+ source_list = SourceList.new
74
+ source_list.add_rubygems_source("remotes" => sources)
75
+
76
+ definition = Definition.new(nil, deps, source_list, true)
77
+ install_definition(definition)
78
+ end
79
+
80
+ # Installs the plugins and deps from the provided specs and returns map of
81
+ # gems to their paths
82
+ #
83
+ # @param specs to install
84
+ #
85
+ # @return [Hash] map of names to path where the plugin was installed
86
+ def install_from_specs(specs)
87
+ paths = {}
88
+
89
+ specs.each do |spec|
90
+ spec.source.install spec
91
+
92
+ paths[spec.name] = spec.full_gem_path
93
+ end
94
+
95
+ paths
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ module Plugin
5
+ class Installer
6
+ class Git < Bundler::Source::Git
7
+ def cache_path
8
+ @cache_path ||= begin
9
+ git_scope = "#{base_name}-#{uri_hash}"
10
+
11
+ Plugin.cache.join("bundler", "git", git_scope)
12
+ end
13
+ end
14
+
15
+ def install_path
16
+ @install_path ||= begin
17
+ git_scope = "#{base_name}-#{shortref_for_path(revision)}"
18
+
19
+ Plugin.root.join("bundler", "gems", git_scope)
20
+ end
21
+ end
22
+
23
+ def version_message(spec)
24
+ "#{spec.name} #{spec.version}"
25
+ end
26
+
27
+ def root
28
+ Plugin.root
29
+ end
30
+
31
+ def generate_bin(spec, disable_extensions = false)
32
+ # Need to find a way without code duplication
33
+ # For now, we can ignore this
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ module Plugin
5
+ class Installer
6
+ class Rubygems < Bundler::Source::Rubygems
7
+ def version_message(spec)
8
+ "#{spec.name} #{spec.version}"
9
+ end
10
+
11
+ private
12
+
13
+ def requires_sudo?
14
+ false # Will change on implementation of project level plugins
15
+ end
16
+
17
+ def rubygems_dir
18
+ Plugin.root
19
+ end
20
+
21
+ def cache_path
22
+ Plugin.cache
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # SourceList object to be used while parsing the Gemfile, setting the
5
+ # approptiate options to be used with Source classes for plugin installation
6
+ module Plugin
7
+ class SourceList < Bundler::SourceList
8
+ def initialize
9
+ @path_sources = []
10
+ @git_sources = []
11
+ @rubygems_aggregate = Plugin::Installer::Rubygems.new
12
+ @rubygems_sources = []
13
+ end
14
+
15
+ def add_git_source(options = {})
16
+ add_source_to_list Plugin::Installer::Git.new(options), git_sources
17
+ end
18
+
19
+ def add_rubygems_source(options = {})
20
+ add_source_to_list Plugin::Installer::Rubygems.new(options), @rubygems_sources
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ postit_lib = File.expand_path("../vendor/postit/lib", __FILE__)
4
+ $:.unshift(postit_lib)
5
+ require "postit"
6
+ require "rubygems"
7
+
8
+ environment = BundlerVendoredPostIt::Environment.new([])
9
+ version = Gem::Requirement.new(environment.bundler_version)
10
+
11
+ installed_version =
12
+ if defined?(Bundler::VERSION)
13
+ Bundler::VERSION
14
+ else
15
+ File.read(File.expand_path("../version.rb", __FILE__)) =~ /VERSION = "(.+)"/
16
+ $1
17
+ end
18
+ installed_version &&= Gem::Version.new(installed_version)
19
+
20
+ if !version.satisfied_by?(installed_version)
21
+ begin
22
+ installer = BundlerVendoredPostIt::Installer.new(version)
23
+ installer.install!
24
+ rescue => e
25
+ abort <<-EOS.strip
26
+ Installing the inferred bundler version (#{version}) failed.
27
+ If you'd like to update to the current bundler version (#{installed_version}) in this project, run `bundle update --bundler`.
28
+ The error was: #{e}
29
+ EOS
30
+ end
31
+
32
+ Gem.loaded_specs.delete("bundler") unless defined?(Bundler)
33
+ gem "bundler", version
34
+ $:.delete(File.expand_path("../..", __FILE__))
35
+ else
36
+ begin
37
+ gem "bundler", version
38
+ rescue LoadError
39
+ $:.unshift(File.expand_path("../..", __FILE__))
40
+ end
41
+ end
42
+
43
+ running_version = begin
44
+ require "bundler/version"
45
+ Bundler::VERSION
46
+ rescue LoadError, NameError
47
+ nil
48
+ end
49
+
50
+ if !Gem::Version.correct?(running_version.to_s) || !version.satisfied_by?(Gem::Version.create(running_version))
51
+ abort "The running bundler (#{running_version}) does not match the required `#{version}`"
52
+ end
53
+
54
+ $:.delete_at($:.find_index(postit_lib))
@@ -5,7 +5,7 @@ begin
5
5
  rescue LoadError
6
6
  end if defined?(gem)
7
7
 
8
- # Psych could just be in the stdlib
8
+ # Psych could be in the stdlib
9
9
  # but it's too late if Syck is already loaded
10
10
  begin
11
11
  require "psych" unless defined?(Syck)
@@ -66,6 +66,10 @@ module Bundler
66
66
  [@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1]
67
67
  end
68
68
 
69
+ def to_s
70
+ "#<#{self.class} name=#{name} version=#{version} platform=#{platform}>"
71
+ end
72
+
69
73
  private
70
74
 
71
75
  def _remote_specification
@@ -75,11 +79,7 @@ module Bundler
75
79
  end
76
80
 
77
81
  def method_missing(method, *args, &blk)
78
- if Gem::Specification.new.respond_to?(method)
79
- _remote_specification.send(method, *args, &blk)
80
- else
81
- super
82
- end
82
+ _remote_specification.send(method, *args, &blk)
83
83
  end
84
84
  end
85
85
  end