summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/playbooks/RELEASING.md (renamed from doc/development/RELEASING.md)4
-rw-r--r--doc/playbooks/TEAM_CHANGES.md42
-rw-r--r--lib/bundler.rb4
-rw-r--r--lib/bundler/definition.rb4
-rw-r--r--lib/bundler/env.rb2
-rw-r--r--lib/bundler/resolver.rb38
-rw-r--r--lib/bundler/resolver/spec_group.rb4
-rw-r--r--lib/bundler/source/metadata.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/base.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb2
-rw-r--r--lib/bundler/version_ranges.rb56
-rw-r--r--spec/bundler/version_ranges_spec.rb3
-rw-r--r--spec/install/gemfile_spec.rb29
-rw-r--r--spec/install/gems/resolving_spec.rb9
-rw-r--r--spec/resolver/basic_spec.rb4
-rw-r--r--spec/runtime/setup_spec.rb2
-rw-r--r--spec/support/indexes.rb4
17 files changed, 180 insertions, 35 deletions
diff --git a/doc/development/RELEASING.md b/doc/playbooks/RELEASING.md
index afa689eaad..58a6196fef 100644
--- a/doc/development/RELEASING.md
+++ b/doc/playbooks/RELEASING.md
@@ -1,6 +1,6 @@
# Releasing
-Bundler users [Semantic Versioning](https://semver.org/).
+Bundler uses [Semantic Versioning](https://semver.org/).
_Note: In the documentation listed below, the *current* minor version number is
1.11 and the *next* minor version number is 1.12_
@@ -55,7 +55,7 @@ The `rake release:patch` command will automatically handle cherry-picking, and i
Bundler maintains a list of changes present in each version in the `CHANGELOG.md` file.
Entries should not be added in pull requests, but are rather written by the Bundler
maintainers in the [bundler-changelog repo](https://github.com/bundler/bundler-changelog).
-That reposity tracks changes by pull requests, with each entry having an associated version,
+That repository tracks changes by pull requests, with each entry having an associated version,
PR, section, author(s), issue(s) closed, and message.
Ensure that repo has been updated with all new PRs before releasing a new version,
diff --git a/doc/playbooks/TEAM_CHANGES.md b/doc/playbooks/TEAM_CHANGES.md
new file mode 100644
index 0000000000..4fd86b5cd1
--- /dev/null
+++ b/doc/playbooks/TEAM_CHANGES.md
@@ -0,0 +1,42 @@
+# Team changes
+
+This file documents how to add and remove team members. For the rules governing adding and removing team members, see [POLICIES][policies].
+
+## Adding a new team member
+
+Interested in adding someone to the team? Here's the process.
+
+1. An existing team member nominates a potential team member to the rest of the team.
+2. The existing team reaches consensus about whether to invite the potential member.
+3. The nominator asks the potential member if they would like to join the team.
+4. The nominator also sends the candidate a link to [POLICIES][policies] as an orientation for being on the team.
+5. If the potential member accepts:
+ - Invite them to the maintainers Slack channel
+ - Add them to the [maintainers team][org_team] on GitHub
+ - Add them to the [Team page][team] on bundler.io, in the [maintainers list][maintainers]
+ - Add them to the [list of team members][list] in `contributors.rake`
+ - Add them to the authors list in `bundler.gemspec`
+ - Add them to the owners list on RubyGems.org by running
+ ```
+ $ gem owner -a EMAIL bundler
+ ```
+
+
+## Removing a team member
+
+When the conditions in [POLICIES](https://github.com/bundler/bundler/blob/master/doc/POLICIES.md#maintainer-team-guidelines) are met, or when team members choose to retire, here's how to remove someone from the team.
+
+- Remove them from the owners list on RubyGems.org by running
+ ```
+ $ gem owner -r EMAIL bundler
+ ```
+- Remove their entry on the [Team page][team] on bundler.io, in the [maintainers list][maintainers]
+- Remove them from the [list of team members][list] in `contributors.rake`
+- Remove them from the [maintainers team][org_team] on GitHub
+- Remove them from the maintainers Slack channel
+
+[policies]: https://github.com/bundler/bundler/blob/master/doc/POLICIES.md#bundler-policies
+[org_team]: https://github.com/orgs/bundler/teams/maintainers/members
+[team]: https://bundler.io/contributors.html
+[maintainers]: https://github.com/bundler/bundler-site/blob/02483d3f79f243774722b3fc18a471ca77b1c424/source/contributors.html.haml#L25
+[list]: https://github.com/bundler/bundler-site/blob/02483d3f79f243774722b3fc18a471ca77b1c424/lib/tasks/contributors.rake#L8
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 6b62ac9b1c..5da316ec4d 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -424,7 +424,7 @@ EOF
def read_file(file)
SharedHelpers.filesystem_access(file, :read) do
- File.open(file, "rb", &:read)
+ File.open(file, "r:UTF-8", &:read)
end
end
@@ -445,7 +445,7 @@ EOF
def load_gemspec_uncached(file, validate = false)
path = Pathname.new(file)
- contents = File.open(file, "r:UTF-8", &:read)
+ contents = read_file(file)
spec = if contents.start_with?("---") # YAML header
eval_yaml_gemspec(path, contents)
else
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index df8ee1f54b..3964c07fb5 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -855,8 +855,8 @@ module Bundler
concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
end
[
- Dependency.new("ruby\0", ruby_versions),
- Dependency.new("rubygems\0", Gem::VERSION),
+ Dependency.new("Ruby\0", ruby_versions),
+ Dependency.new("RubyGems\0", Gem::VERSION),
]
end
end
diff --git a/lib/bundler/env.rb b/lib/bundler/env.rb
index b91a345cee..923a14de0c 100644
--- a/lib/bundler/env.rb
+++ b/lib/bundler/env.rb
@@ -61,7 +61,7 @@ module Bundler
end
def self.read_file(filename)
- File.read(filename.to_s).strip
+ Bundler.read_file(filename.to_s).strip
rescue Errno::ENOENT
"<No #{filename} found>"
rescue RuntimeError => e
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 8872b861be..a6c26ffc6b 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -302,10 +302,23 @@ module Bundler
end
def version_conflict_message(e)
+ # only show essential conflicts, if possible
+ conflicts = e.conflicts.dup
+ conflicts.delete_if do |_name, conflict|
+ deps = conflict.requirement_trees.map(&:last).flatten(1)
+ !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
+ end
+ e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
+
+ solver_name = "Bundler"
+ possibility_type = "gem"
e.message_with_trees(
- :solver_name => "Bundler",
- :possibility_type => "gem",
+ :solver_name => solver_name,
+ :possibility_type => possibility_type,
:reduce_trees => lambda do |trees|
+ # called first, because we want to reduce the amount of work required to find maximal empty sets
+ trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
+
# bail out if tree size is too big for Array#combination to make any sense
return trees if trees.size > 15
maximal = 1.upto(trees.size).map do |size|
@@ -313,10 +326,8 @@ module Bundler
end.flatten(1).select do |deps|
Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end.min_by(&:size)
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
- trees = trees.sort_by {|t| t.flatten.map(&:to_s) }
- trees.uniq! {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
trees.sort_by {|t| t.reverse.map(&:name) }
end,
@@ -351,7 +362,11 @@ module Bundler
[]
end.compact.map(&:to_s).uniq.sort
- o << "Could not find gem '#{SharedHelpers.pretty_dependency(conflict.requirement)}'"
+ metadata_requirement = name.end_with?("\0")
+
+ o << "Could not find gem '" unless metadata_requirement
+ o << SharedHelpers.pretty_dependency(conflict.requirement)
+ o << "'" unless metadata_requirement
if conflict.requirement_trees.first.size > 1
o << ", which is required by "
o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
@@ -360,12 +375,21 @@ module Bundler
o << if relevant_sources.empty?
"in any of the sources.\n"
+ elsif metadata_requirement
+ "is not available in #{relevant_sources.join(" or ")}"
else
"in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
end
end
end,
- :version_for_spec => lambda {|spec| spec.version }
+ :version_for_spec => lambda {|spec| spec.version },
+ :incompatible_version_message_for_conflict => lambda do |name, _conflict|
+ if name.end_with?("\0")
+ %(#{solver_name} found conflicting requirements for the #{name} version:)
+ else
+ %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
+ end
+ end
)
end
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index 34d043aed7..119f63b5c8 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -94,10 +94,10 @@ module Bundler
return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
+ dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
+ dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
end
dependencies
end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 93909002c7..ff8861c710 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -5,8 +5,10 @@ module Bundler
class Metadata < Source
def specs
@specs ||= Index.build do |idx|
- idx << Gem::Specification.new("ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
- idx << Gem::Specification.new("rubygems\0", Gem::VERSION)
+ idx << Gem::Specification.new("Ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
+ idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
+ s.required_rubygems_version = Gem::Requirement.default
+ end
idx << Gem::Specification.new do |s|
s.name = "bundler"
diff --git a/lib/bundler/vendor/thor/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb
index 9bd1077170..7e41dc226b 100644
--- a/lib/bundler/vendor/thor/lib/thor/base.rb
+++ b/lib/bundler/vendor/thor/lib/thor/base.rb
@@ -113,7 +113,7 @@ class Bundler::Thor
end
# Whenever a class inherits from Bundler::Thor or Bundler::Thor::Group, we should track the
- # class and the file on Bundler::Thor::Base. This is the method responsable for it.
+ # class and the file on Bundler::Thor::Base. This is the method responsible for it.
#
def register_klass_file(klass) #:nodoc:
file = caller[1].match(/(.*):\d+/)[1]
diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb
index 5d03177a28..0fe7d4d859 100644
--- a/lib/bundler/vendor/thor/lib/thor/util.rb
+++ b/lib/bundler/vendor/thor/lib/thor/util.rb
@@ -27,7 +27,7 @@ class Bundler::Thor
end
# Receives a constant and converts it to a Bundler::Thor namespace. Since Bundler::Thor
- # commands can be added to a sandbox, this method is also responsable for
+ # commands can be added to a sandbox, this method is also responsible for
# removing the sandbox namespace.
#
# This method should not be used in general because it's used to deal with
diff --git a/lib/bundler/version_ranges.rb b/lib/bundler/version_ranges.rb
index ec25716cde..12a956d6a0 100644
--- a/lib/bundler/version_ranges.rb
+++ b/lib/bundler/version_ranges.rb
@@ -5,11 +5,42 @@ module Bundler
NEq = Struct.new(:version)
ReqR = Struct.new(:left, :right)
class ReqR
- Endpoint = Struct.new(:version, :inclusive)
+ Endpoint = Struct.new(:version, :inclusive) do
+ def <=>(other)
+ if version.equal?(INFINITY)
+ return 0 if other.version.equal?(INFINITY)
+ return 1
+ elsif other.version.equal?(INFINITY)
+ return -1
+ end
+
+ comp = version <=> other.version
+ return comp unless comp.zero?
+
+ if inclusive && !other.inclusive
+ 1
+ elsif !inclusive && other.inclusive
+ -1
+ else
+ 0
+ end
+ end
+ end
+
def to_s
"#{left.inclusive ? "[" : "("}#{left.version}, #{right.version}#{right.inclusive ? "]" : ")"}"
end
- INFINITY = Object.new.freeze
+ INFINITY = begin
+ inf = Object.new
+ def inf.to_s
+ "∞"
+ end
+ def inf.<=>(other)
+ return 0 if other.equal?(self)
+ 1
+ end
+ inf.freeze
+ end
ZERO = Gem::Version.new("0.a")
def cover?(v)
@@ -32,6 +63,15 @@ module Bundler
left.version == right.version
end
+ def <=>(other)
+ return -1 if other.equal?(INFINITY)
+
+ comp = left <=> other.left
+ return comp unless comp.zero?
+
+ right <=> other.right
+ end
+
UNIVERSAL = ReqR.new(ReqR::Endpoint.new(Gem::Version.new("0.a"), true), ReqR::Endpoint.new(ReqR::INFINITY, false)).freeze
end
@@ -57,7 +97,7 @@ module Bundler
end.uniq
ranges, neqs = ranges.partition {|r| !r.is_a?(NEq) }
- [ranges.sort_by {|range| [range.left.version, range.left.inclusive ? 0 : 1] }, neqs.map(&:version)]
+ [ranges.sort, neqs.map(&:version)]
end
def self.empty?(ranges, neqs)
@@ -66,8 +106,14 @@ module Bundler
next false if curr_range.single? && neqs.include?(curr_range.left.version)
next curr_range if last_range.right.version == ReqR::INFINITY
case last_range.right.version <=> curr_range.left.version
- when 1 then next curr_range
- when 0 then next(last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version) && curr_range)
+ # higher
+ when 1 then next ReqR.new(curr_range.left, last_range.right)
+ # equal
+ when 0
+ if last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version)
+ ReqR.new(curr_range.left, [curr_range.right, last_range.right].max)
+ end
+ # lower
when -1 then next false
end
end
diff --git a/spec/bundler/version_ranges_spec.rb b/spec/bundler/version_ranges_spec.rb
index ccbb9285d5..bca044b0c0 100644
--- a/spec/bundler/version_ranges_spec.rb
+++ b/spec/bundler/version_ranges_spec.rb
@@ -25,9 +25,12 @@ RSpec.describe Bundler::VersionRanges do
include_examples "empty?", false, ">= 1.0.0", "< 2.0.0"
include_examples "empty?", false, "~> 1"
include_examples "empty?", false, "~> 2.0", "~> 2.1"
+ include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1"
+ include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4"
include_examples "empty?", true, "!= 1", "< 2", "> 2"
include_examples "empty?", true, "!= 1", "<= 1", ">= 1"
include_examples "empty?", true, "< 2", "> 2"
+ include_examples "empty?", true, "< 2", "> 2", "= 2"
include_examples "empty?", true, "= 1", "!= 1"
include_examples "empty?", true, "= 1", "= 2"
include_examples "empty?", true, "= 1", "~> 2"
diff --git a/spec/install/gemfile_spec.rb b/spec/install/gemfile_spec.rb
index 45bc232901..ad254a87e9 100644
--- a/spec/install/gemfile_spec.rb
+++ b/spec/install/gemfile_spec.rb
@@ -112,4 +112,33 @@ RSpec.describe "bundle install" do
end
end
end
+
+ context "with a Gemfile containing non-US-ASCII characters" do
+ it "reads the Gemfile with the UTF-8 encoding by default" do
+ skip "Ruby 1.8 has no encodings" if RUBY_VERSION < "1.9"
+
+ install_gemfile <<-G
+ str = "Il était une fois ..."
+ puts "The source encoding is: " + str.encoding.name
+ G
+
+ expect(out).to include("The source encoding is: UTF-8")
+ expect(out).not_to include("The source encoding is: ASCII-8BIT")
+ expect(out).to include("Bundle complete!")
+ end
+
+ it "respects the magic encoding comment" do
+ skip "Ruby 1.8 has no encodings" if RUBY_VERSION < "1.9"
+
+ # NOTE: This works thanks to #eval interpreting the magic encoding comment
+ install_gemfile <<-G
+ # encoding: iso-8859-1
+ str = "Il #{"\xE9".b}tait une fois ..."
+ puts "The source encoding is: " + str.encoding.name
+ G
+
+ expect(out).to include("The source encoding is: ISO-8859-1")
+ expect(out).to include("Bundle complete!")
+ end
+ end
end
diff --git a/spec/install/gems/resolving_spec.rb b/spec/install/gems/resolving_spec.rb
index e58f32836c..f581522c71 100644
--- a/spec/install/gems/resolving_spec.rb
+++ b/spec/install/gems/resolving_spec.rb
@@ -142,15 +142,14 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
nice_error = strip_whitespace(<<-E).strip
- Bundler could not find compatible versions for gem "ruby\0":
+ Bundler found conflicting requirements for the Ruby\0 version:
In Gemfile:
- ruby\0 (#{error_message_requirement})
+ Ruby\0 (#{error_message_requirement})
require_ruby was resolved to 1.0, which depends on
- ruby\0 (> 9000)
+ Ruby\0 (> 9000)
- Could not find gem 'ruby\0 (> 9000)', which is required by gem 'require_ruby', in any of the relevant sources:
- the local ruby installation
+ Ruby\0 (> 9000), which is required by gem 'require_ruby', is not available in the local ruby installation
E
expect(last_command.bundler_err).to end_with(nice_error)
end
diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb
index 6d2dea2fb3..a2d5e13377 100644
--- a/spec/resolver/basic_spec.rb
+++ b/spec/resolver/basic_spec.rb
@@ -157,10 +157,10 @@ Bundler could not find compatible versions for gem "a":
s.required_ruby_version = "~> 2.0.0"
end
- gem "ruby\0", "1.8.7"
+ gem "Ruby\0", "1.8.7"
end
dep "foo"
- dep "ruby\0", "1.8.7"
+ dep "Ruby\0", "1.8.7"
deps = []
@deps.each do |d|
diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb
index cd87971238..7fec55c4c3 100644
--- a/spec/runtime/setup_spec.rb
+++ b/spec/runtime/setup_spec.rb
@@ -881,7 +881,7 @@ end
end
end
- it "should succesfully require 'bundler/setup'" do
+ it "should successfully require 'bundler/setup'" do
install_gemfile ""
ENV["GEM_PATH"] = symlinked_gem_home.path
diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb
index c56d6145a7..5f6c515735 100644
--- a/spec/support/indexes.rb
+++ b/spec/support/indexes.rb
@@ -76,7 +76,7 @@ module Spec
gem "rack-mount", %w[0.4 0.5 0.5.1 0.5.2 0.6]
# --- Pre-release support
- gem "rubygems\0", ["1.3.2"]
+ gem "RubyGems\0", ["1.3.2"]
# --- Rails
versions "1.2.3 2.2.3 2.3.5 3.0.0.beta 3.0.0.beta1" do |version|
@@ -413,7 +413,7 @@ module Spec
gem("b", %w[0.9.0 1.5.0 2.0.0.pre])
# --- Pre-release support
- gem "rubygems\0", ["1.3.2"]
+ gem "RubyGems\0", ["1.3.2"]
end
end
end