summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-08 01:22:39 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-08 01:22:39 +0000
commit7ed9b794b4e3f3f9874f2ce19401461596d8a2c0 ()
tree5caaf13685de34b09d2949709a77b4c650b62741 /lib
parent866b438c21ff05dfeabba8bc9aa9850e415be607 (diff)
* lib/rubygems: Update to RubyGems master 14749ce. This fixes bugs
handling of gem dependencies lockfiles (Gemfile.lock). * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44054 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--lib/rubygems/request_set.rb10
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb42
-rw-r--r--lib/rubygems/request_set/lockfile.rb220
-rw-r--r--lib/rubygems/requirement.rb18
-rw-r--r--lib/rubygems/resolver.rb40
-rw-r--r--lib/rubygems/resolver/git_set.rb26
-rw-r--r--lib/rubygems/resolver/lock_set.rb6
-rw-r--r--lib/rubygems/resolver/lock_specification.rb58
-rw-r--r--lib/rubygems/resolver/requirement_list.rb25
-rw-r--r--lib/rubygems/resolver/stats.rb44
-rw-r--r--lib/rubygems/source.rb3
-rw-r--r--lib/rubygems/source/git.rb10
-rw-r--r--lib/rubygems/source/lock.rb4
-rw-r--r--lib/rubygems/test_case.rb8
-rw-r--r--lib/rubygems/test_utilities.rb27
15 files changed, 473 insertions, 68 deletions
@@ -158,6 +158,10 @@ class Gem::RequestSet
specs.map { |s| s.full_name }.sort.each do |s|
puts " #{s}"
end
else
installed = install options, &block
@@ -169,6 +173,8 @@ class Gem::RequestSet
end
def install_into dir, force = true, options = {}
existing = force ? [] : specs_in(dir)
existing.delete_if { |s| @always_install.include? s }
@@ -195,6 +201,8 @@ class Gem::RequestSet
end
installed
end
##
@@ -229,6 +237,8 @@ class Gem::RequestSet
resolver.development = @development
resolver.soft_missing = @soft_missing
@requests = resolver.resolve
end
@@ -221,13 +221,7 @@ class Gem::RequestSet::GemDependencyAPI
return unless (groups & @without_groups).empty?
- unless source_set then
- raise ArgumentError,
- "duplicate source (default) for gem #{name}" if
- @gem_sources.include? name
-
- @gem_sources[name] = :default
- end
gem_requires name, options
@@ -246,9 +240,7 @@ class Gem::RequestSet::GemDependencyAPI
return unless repository = options.delete(:git)
- raise ArgumentError,
- "duplicate source git: #{repository} for gem #{name}" if
- @gem_sources.include? name
reference = nil
reference ||= options.delete :ref
@@ -260,8 +252,6 @@ class Gem::RequestSet::GemDependencyAPI
@git_set.add_git_gem name, repository, reference, submodules
- @gem_sources[name] = repository
-
true
end
@@ -310,14 +300,10 @@ class Gem::RequestSet::GemDependencyAPI
def gem_path name, options # :nodoc:
return unless directory = options.delete(:path)
- raise ArgumentError,
- "duplicate source path: #{directory} for gem #{name}" if
- @gem_sources.include? name
@vendor_set.add_vendor_gem name, directory
- @gem_sources[name] = directory
-
true
end
@@ -430,6 +416,28 @@ class Gem::RequestSet::GemDependencyAPI
end
##
# :category: Gem Dependencies DSL
#
# Block form for restricting gems to a particular platform.
@@ -1,3 +1,5 @@
##
# Parses a gem.deps.rb.lock file and constructs a LockSet containing the
# dependencies found inside. If the lock file is missing no LockSet is
@@ -29,11 +31,11 @@ class Gem::RequestSet::Lockfile
# Raises a ParseError with the given +message+ which was encountered at a
# +line+ and +column+ while parsing.
- def initialize message, line, column, path
@line = line
@column = column
@path = path
- super "#{message} (at #{line}:#{column})"
end
end
@@ -62,30 +64,31 @@ class Gem::RequestSet::Lockfile
def add_DEPENDENCIES out # :nodoc:
out << "DEPENDENCIES"
- @set.dependencies.sort.map do |dependency|
- source = @requests.find do |req|
- req.name == dependency.name and
- req.spec.class == Gem::Resolver::VendorSpecification
- end
-
- source_dep = '!' if source
- requirement = dependency.requirement
- out << " #{dependency.name}#{source_dep}#{requirement.for_lockfile}"
end
out << nil
end
def add_GEM out # :nodoc:
- out << "GEM"
source_groups = @spec_groups.values.flatten.group_by do |request|
request.spec.source.uri
end
- source_groups.map do |group, requests|
out << " remote: #{group}"
out << " specs:"
@@ -100,6 +103,33 @@ class Gem::RequestSet::Lockfile
out << " #{dependency.name}#{requirement.for_lockfile}"
end
end
end
out << nil
@@ -148,27 +178,28 @@ class Gem::RequestSet::Lockfile
##
# Gets the next token for a Lockfile
- def get expected_type = nil, expected_value = nil # :nodoc:
@current_token = @tokens.shift
- type, value, line, column = @current_token
- if expected_type and expected_type != type then
unget
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
- "expected #{expected_type.inspect}"
- raise ParseError.new message, line, column, "#{@gem_deps_file}.lock"
end
if expected_value and expected_value != value then
unget
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
- "expected [#{expected_type.inspect}, #{expected_value.inspect}]"
- raise ParseError.new message, line, column, "#{@gem_deps_file}.lock"
end
@current_token
@@ -187,6 +218,8 @@ class Gem::RequestSet::Lockfile
case data
when 'DEPENDENCIES' then
parse_DEPENDENCIES
when 'GEM' then
parse_GEM
when 'PLATFORMS' then
@@ -195,7 +228,7 @@ class Gem::RequestSet::Lockfile
type, = get until @tokens.empty? or peek.first == :section
end
else
- raise "BUG: unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
end
end
end
@@ -204,7 +237,37 @@ class Gem::RequestSet::Lockfile
while not @tokens.empty? and :text == peek.first do
_, name, = get :text
- @set.gem name
skip :newline
end
@@ -223,20 +286,76 @@ class Gem::RequestSet::Lockfile
skip :newline
set = Gem::Resolver::LockSet.new source
while not @tokens.empty? and :text == peek.first do
- _, name, = get :text
case peek[0]
- when :newline then # ignore
when :l_paren then
get :l_paren
- _, version, = get :text
get :r_paren
- set.add name, version, Gem::Platform::RUBY
else
raise "BUG: unknown token #{peek}"
end
@@ -258,10 +377,32 @@ class Gem::RequestSet::Lockfile
end
##
# Peeks at the next token for Lockfile
def peek # :nodoc:
- @tokens.first
end
def skip type # :nodoc:
@@ -284,6 +425,8 @@ class Gem::RequestSet::Lockfile
add_PATH out
add_GEM out
add_PLATFORMS out
@@ -321,14 +464,13 @@ class Gem::RequestSet::Lockfile
until s.eos? do
pos = s.pos
- # leading whitespace is for the user's convenience
- next if s.scan(/ +/)
if s.scan(/[<|=>]{7}/) then
message = "your #{lock_file} contains merge conflict markers"
- line, column = token_pos pos
- raise ParseError.new message, line, column, lock_file
end
@tokens <<
@@ -339,7 +481,13 @@ class Gem::RequestSet::Lockfile
@line += 1
token
when s.scan(/[A-Z]+/) then
- [:section, s.matched, *token_pos(pos)]
when s.scan(/([a-z]+):\s/) then
s.pos -= 1 # rewind for possible newline
[:entry, s[1], *token_pos(pos)]
@@ -347,7 +495,13 @@ class Gem::RequestSet::Lockfile
[:l_paren, nil, *token_pos(pos)]
when s.scan(/\)/) then
[:r_paren, nil, *token_pos(pos)]
- when s.scan(/[^\s)]*/) then
[:text, s.matched, *token_pos(pos)]
else
raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}"
@@ -133,7 +133,15 @@ class Gem::Requirement
# Formats this requirement for use in a Gem::RequestSet::Lockfile.
def for_lockfile # :nodoc:
- " (#{to_s})" unless [DefaultRequirement] == @requirements
end
##
@@ -147,6 +155,14 @@ class Gem::Requirement
end
end
def as_list # :nodoc:
requirements.map { |op, version| "#{op} #{version}" }.sort
end
@@ -36,6 +36,8 @@ class Gem::Resolver
attr_reader :missing
##
# When a missing dependency, don't stop. Just go on and record what was
# missing.
@@ -93,6 +95,7 @@ class Gem::Resolver
@development = false
@missing = []
@soft_missing = false
end
def explain stage, *data # :nodoc:
@@ -132,10 +135,13 @@ class Gem::Resolver
s.dependencies.reverse_each do |d|
next if d.type == :development and not @development
reqs.add Gem::Resolver::DependencyRequest.new(d, act)
end
@set.prefetch reqs
reqs
end
@@ -151,8 +157,11 @@ class Gem::Resolver
request = Gem::Resolver::DependencyRequest.new n, nil
needed.add request
end
res = resolve_for needed, nil
raise Gem::DependencyResolutionError, res if
@@ -268,6 +277,8 @@ class Gem::Resolver
states = []
while !needed.empty?
dep = needed.remove
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
explain_list :next5, needed.next5
@@ -279,12 +290,33 @@ class Gem::Resolver
next if dep.matches_spec? existing
conflict = handle_conflict dep, existing
- explain :conflict, conflict.explain
- state = find_conflict_state conflict, states
return conflict unless state
needed, specs = resolve_for_conflict needed, specs, state
states << state unless state.possibles.empty?
@@ -346,6 +378,8 @@ class Gem::Resolver
# what makes conflict resolution possible.
states << State.new(needed.dup, specs, dep, spec, possible, [])
explain :states, states.map { |s| s.dep }
needed = requests spec, act, needed
@@ -404,6 +438,7 @@ require 'rubygems/resolver/activation_request'
require 'rubygems/resolver/conflict'
require 'rubygems/resolver/dependency_request'
require 'rubygems/resolver/requirement_list'
require 'rubygems/resolver/set'
require 'rubygems/resolver/api_set'
@@ -423,5 +458,6 @@ require 'rubygems/resolver/git_specification'
require 'rubygems/resolver/index_specification'
require 'rubygems/resolver/installed_specification'
require 'rubygems/resolver/local_specification'
require 'rubygems/resolver/vendor_specification'
@@ -46,6 +46,32 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
end
##
# Finds all git gems matching +req+
def find_all req
@@ -24,10 +24,12 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
version = Gem::Version.new version
spec =
- Gem::Resolver::IndexSpecification.new self, name, version, @source,
- platform
@specs << spec
end
##
@@ -0,0 +1,58 @@
@@ -13,10 +13,12 @@ class Gem::Resolver::RequirementList
# Creates a new RequirementList.
def initialize
@list = []
end
def initialize_copy other # :nodoc:
@list = @list.dup
end
@@ -24,7 +26,11 @@ class Gem::Resolver::RequirementList
# Adds Resolver::DependencyRequest +req+ to this requirements list.
def add(req)
- @list.push req
req
end
@@ -34,22 +40,34 @@ class Gem::Resolver::RequirementList
def each # :nodoc:
return enum_for __method__ unless block_given?
@list.each do |requirement|
yield requirement
end
end
##
# Is the list empty?
def empty?
- @list.empty?
end
##
# Remove the oldest DependencyRequest from the list.
def remove
@list.shift
end
@@ -57,6 +75,7 @@ class Gem::Resolver::RequirementList
# Returns the oldest five entries from the list.
def next5
- @list[0,5]
end
end
@@ -0,0 +1,44 @@
@@ -202,7 +202,10 @@ class Gem::Source
q.group 2, '[Remote:', ']' do
q.breakable
q.text @uri.to_s
if api = api_uri
q.text api.to_s
end
end
@@ -147,6 +147,16 @@ class Gem::Source::Git < Gem::Source
File.join base_dir, 'gems', "#{@name}-#{dir_shortref}"
end
##
# The directory where the git gem's repository will be cached.
@@ -40,5 +40,9 @@ class Gem::Source::Lock < Gem::Source
@wrapped.fetch_spec name_tuple
end
end
@@ -85,6 +85,10 @@ class Gem::TestCase < MiniTest::Unit::TestCase
attr_accessor :fetcher # :nodoc:
def assert_activate expected, *specs
specs.each do |spec|
case spec
@@ -1196,8 +1200,8 @@ Also, a list:
# end
# end
- def spec_fetcher
- Gem::TestCase::SpecFetcherSetup.declare self do |spec_fetcher_setup|
yield spec_fetcher_setup if block_given?
end
end
@@ -199,16 +199,17 @@ class Gem::TestCase::SpecFetcherSetup
# Executes a SpecFetcher setup block. Yields an instance then creates the
# gems and specifications defined in the instance.
- def self.declare test
- setup = new test
yield setup
setup.execute
end
- def initialize test # :nodoc:
- @test = test
@gems = {}
@installed = []
@@ -298,12 +299,22 @@ class Gem::TestCase::SpecFetcherSetup
require 'socket'
require 'rubygems/remote_fetcher'
- @test.fetcher = Gem::FakeFetcher.new
- Gem::RemoteFetcher.fetcher = @test.fetcher
Gem::Specification.reset
- @test.util_setup_spec_fetcher(*@gems.keys)
# This works around util_setup_spec_fetcher adding all created gems to the
# installed set.
@@ -313,7 +324,7 @@ class Gem::TestCase::SpecFetcherSetup
@gems.each do |spec, gem|
next unless gem
- @test.fetcher.data["http://gems.example.com/gems/#{spec.file_name}"] =
Gem.read_binary(gem)
FileUtils.cp gem, spec.cache_file