* 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
This commit is contained in:
parent
866b438c21
commit
7ed9b794b4
@ -1,3 +1,10 @@
|
|||||||
|
Sun Dec 8 10:21:36 2013 Eric Hodel <drbrain@segment7.net>
|
||||||
|
|
||||||
|
* lib/rubygems: Update to RubyGems master 14749ce. This fixes bugs
|
||||||
|
handling of gem dependencies lockfiles (Gemfile.lock).
|
||||||
|
|
||||||
|
* test/rubygems: ditto.
|
||||||
|
|
||||||
Sun Dec 8 09:40:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
|
Sun Dec 8 09:40:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
|
||||||
|
|
||||||
* array.c (rb_ary_or): use RHASH_TBL_RAW instead of RHASH_TBL
|
* array.c (rb_ary_or): use RHASH_TBL_RAW instead of RHASH_TBL
|
||||||
|
@ -158,6 +158,10 @@ class Gem::RequestSet
|
|||||||
specs.map { |s| s.full_name }.sort.each do |s|
|
specs.map { |s| s.full_name }.sort.each do |s|
|
||||||
puts " #{s}"
|
puts " #{s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Gem.configuration.really_verbose
|
||||||
|
@resolver.stats.display
|
||||||
|
end
|
||||||
else
|
else
|
||||||
installed = install options, &block
|
installed = install options, &block
|
||||||
|
|
||||||
@ -169,6 +173,8 @@ class Gem::RequestSet
|
|||||||
end
|
end
|
||||||
|
|
||||||
def install_into dir, force = true, options = {}
|
def install_into dir, force = true, options = {}
|
||||||
|
gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir
|
||||||
|
|
||||||
existing = force ? [] : specs_in(dir)
|
existing = force ? [] : specs_in(dir)
|
||||||
existing.delete_if { |s| @always_install.include? s }
|
existing.delete_if { |s| @always_install.include? s }
|
||||||
|
|
||||||
@ -195,6 +201,8 @@ class Gem::RequestSet
|
|||||||
end
|
end
|
||||||
|
|
||||||
installed
|
installed
|
||||||
|
ensure
|
||||||
|
ENV['GEM_HOME'] = gem_home
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -229,6 +237,8 @@ class Gem::RequestSet
|
|||||||
resolver.development = @development
|
resolver.development = @development
|
||||||
resolver.soft_missing = @soft_missing
|
resolver.soft_missing = @soft_missing
|
||||||
|
|
||||||
|
@resolver = resolver
|
||||||
|
|
||||||
@requests = resolver.resolve
|
@requests = resolver.resolve
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -221,13 +221,7 @@ class Gem::RequestSet::GemDependencyAPI
|
|||||||
|
|
||||||
return unless (groups & @without_groups).empty?
|
return unless (groups & @without_groups).empty?
|
||||||
|
|
||||||
unless source_set then
|
pin_gem_source name, :default unless source_set
|
||||||
raise ArgumentError,
|
|
||||||
"duplicate source (default) for gem #{name}" if
|
|
||||||
@gem_sources.include? name
|
|
||||||
|
|
||||||
@gem_sources[name] = :default
|
|
||||||
end
|
|
||||||
|
|
||||||
gem_requires name, options
|
gem_requires name, options
|
||||||
|
|
||||||
@ -246,9 +240,7 @@ class Gem::RequestSet::GemDependencyAPI
|
|||||||
|
|
||||||
return unless repository = options.delete(:git)
|
return unless repository = options.delete(:git)
|
||||||
|
|
||||||
raise ArgumentError,
|
pin_gem_source name, :git, repository
|
||||||
"duplicate source git: #{repository} for gem #{name}" if
|
|
||||||
@gem_sources.include? name
|
|
||||||
|
|
||||||
reference = nil
|
reference = nil
|
||||||
reference ||= options.delete :ref
|
reference ||= options.delete :ref
|
||||||
@ -260,8 +252,6 @@ class Gem::RequestSet::GemDependencyAPI
|
|||||||
|
|
||||||
@git_set.add_git_gem name, repository, reference, submodules
|
@git_set.add_git_gem name, repository, reference, submodules
|
||||||
|
|
||||||
@gem_sources[name] = repository
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -310,14 +300,10 @@ class Gem::RequestSet::GemDependencyAPI
|
|||||||
def gem_path name, options # :nodoc:
|
def gem_path name, options # :nodoc:
|
||||||
return unless directory = options.delete(:path)
|
return unless directory = options.delete(:path)
|
||||||
|
|
||||||
raise ArgumentError,
|
pin_gem_source name, :path, directory
|
||||||
"duplicate source path: #{directory} for gem #{name}" if
|
|
||||||
@gem_sources.include? name
|
|
||||||
|
|
||||||
@vendor_set.add_vendor_gem name, directory
|
@vendor_set.add_vendor_gem name, directory
|
||||||
|
|
||||||
@gem_sources[name] = directory
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -429,6 +415,28 @@ class Gem::RequestSet::GemDependencyAPI
|
|||||||
@current_groups = nil
|
@current_groups = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Pins the gem +name+ to the given +source+. Adding a gem with the same
|
||||||
|
# name from a different +source+ will raise an exception.
|
||||||
|
|
||||||
|
def pin_gem_source name, type = :default, source = nil
|
||||||
|
source_description =
|
||||||
|
case type
|
||||||
|
when :default then '(default)'
|
||||||
|
when :path then "path: #{source}"
|
||||||
|
when :git then "git: #{source}"
|
||||||
|
else '(unknown)'
|
||||||
|
end
|
||||||
|
|
||||||
|
raise ArgumentError,
|
||||||
|
"duplicate source #{source_description} for gem #{name}" if
|
||||||
|
@gem_sources.fetch(name, source) != source
|
||||||
|
|
||||||
|
@gem_sources[name] = source
|
||||||
|
end
|
||||||
|
|
||||||
|
private :pin_gem_source
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
require 'strscan'
|
||||||
|
|
||||||
##
|
##
|
||||||
# Parses a gem.deps.rb.lock file and constructs a LockSet containing the
|
# 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
|
# 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
|
# Raises a ParseError with the given +message+ which was encountered at a
|
||||||
# +line+ and +column+ while parsing.
|
# +line+ and +column+ while parsing.
|
||||||
|
|
||||||
def initialize message, line, column, path
|
def initialize message, column, line, path
|
||||||
@line = line
|
@line = line
|
||||||
@column = column
|
@column = column
|
||||||
@path = path
|
@path = path
|
||||||
super "#{message} (at #{line}:#{column})"
|
super "#{message} (at line #{line} column #{column})"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -62,30 +64,31 @@ class Gem::RequestSet::Lockfile
|
|||||||
def add_DEPENDENCIES out # :nodoc:
|
def add_DEPENDENCIES out # :nodoc:
|
||||||
out << "DEPENDENCIES"
|
out << "DEPENDENCIES"
|
||||||
|
|
||||||
@set.dependencies.sort.map do |dependency|
|
@requests.sort_by { |r| r.name }.each do |request|
|
||||||
source = @requests.find do |req|
|
spec = request.spec
|
||||||
req.name == dependency.name and
|
|
||||||
req.spec.class == Gem::Resolver::VendorSpecification
|
if [Gem::Resolver::VendorSpecification,
|
||||||
|
Gem::Resolver::GitSpecification].include? spec.class then
|
||||||
|
out << " #{request.name}!"
|
||||||
|
else
|
||||||
|
requirement = request.request.dependency.requirement
|
||||||
|
|
||||||
|
out << " #{request.name}#{requirement.for_lockfile}"
|
||||||
end
|
end
|
||||||
|
|
||||||
source_dep = '!' if source
|
|
||||||
|
|
||||||
requirement = dependency.requirement
|
|
||||||
|
|
||||||
out << " #{dependency.name}#{source_dep}#{requirement.for_lockfile}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
out << nil
|
out << nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_GEM out # :nodoc:
|
def add_GEM out # :nodoc:
|
||||||
out << "GEM"
|
return if @spec_groups.empty?
|
||||||
|
|
||||||
source_groups = @spec_groups.values.flatten.group_by do |request|
|
source_groups = @spec_groups.values.flatten.group_by do |request|
|
||||||
request.spec.source.uri
|
request.spec.source.uri
|
||||||
end
|
end
|
||||||
|
|
||||||
source_groups.map do |group, requests|
|
source_groups.sort_by { |group,| group.to_s }.map do |group, requests|
|
||||||
|
out << "GEM"
|
||||||
out << " remote: #{group}"
|
out << " remote: #{group}"
|
||||||
out << " specs:"
|
out << " specs:"
|
||||||
|
|
||||||
@ -100,6 +103,33 @@ class Gem::RequestSet::Lockfile
|
|||||||
out << " #{dependency.name}#{requirement.for_lockfile}"
|
out << " #{dependency.name}#{requirement.for_lockfile}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
out << nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_GIT out
|
||||||
|
return unless git_requests =
|
||||||
|
@spec_groups.delete(Gem::Resolver::GitSpecification)
|
||||||
|
|
||||||
|
by_repository_revision = git_requests.group_by do |request|
|
||||||
|
source = request.spec.source
|
||||||
|
[source.repository, source.rev_parse]
|
||||||
|
end
|
||||||
|
|
||||||
|
out << "GIT"
|
||||||
|
by_repository_revision.each do |(repository, revision), requests|
|
||||||
|
out << " remote: #{repository}"
|
||||||
|
out << " revision: #{revision}"
|
||||||
|
out << " specs:"
|
||||||
|
|
||||||
|
requests.sort_by { |request| request.name }.each do |request|
|
||||||
|
out << " #{request.name} (#{request.version})"
|
||||||
|
|
||||||
|
dependencies = request.spec.dependencies.sort_by { |dep| dep.name }
|
||||||
|
dependencies.each do |dep|
|
||||||
|
out << " #{dep.name}#{dep.requirement.for_lockfile}"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
out << nil
|
out << nil
|
||||||
@ -148,27 +178,28 @@ class Gem::RequestSet::Lockfile
|
|||||||
##
|
##
|
||||||
# Gets the next token for a Lockfile
|
# Gets the next token for a Lockfile
|
||||||
|
|
||||||
def get expected_type = nil, expected_value = nil # :nodoc:
|
def get expected_types = nil, expected_value = nil # :nodoc:
|
||||||
@current_token = @tokens.shift
|
@current_token = @tokens.shift
|
||||||
|
|
||||||
type, value, line, column = @current_token
|
type, value, column, line = @current_token
|
||||||
|
|
||||||
if expected_type and expected_type != type then
|
if expected_types and not Array(expected_types).include? type then
|
||||||
unget
|
unget
|
||||||
|
|
||||||
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
|
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
|
||||||
"expected #{expected_type.inspect}"
|
"expected #{expected_types.inspect}"
|
||||||
|
|
||||||
raise ParseError.new message, line, column, "#{@gem_deps_file}.lock"
|
raise ParseError.new message, column, line, "#{@gem_deps_file}.lock"
|
||||||
end
|
end
|
||||||
|
|
||||||
if expected_value and expected_value != value then
|
if expected_value and expected_value != value then
|
||||||
unget
|
unget
|
||||||
|
|
||||||
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
|
message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
|
||||||
"expected [#{expected_type.inspect}, #{expected_value.inspect}]"
|
"expected [#{expected_types.inspect}, " +
|
||||||
|
"#{expected_value.inspect}]"
|
||||||
|
|
||||||
raise ParseError.new message, line, column, "#{@gem_deps_file}.lock"
|
raise ParseError.new message, column, line, "#{@gem_deps_file}.lock"
|
||||||
end
|
end
|
||||||
|
|
||||||
@current_token
|
@current_token
|
||||||
@ -187,6 +218,8 @@ class Gem::RequestSet::Lockfile
|
|||||||
case data
|
case data
|
||||||
when 'DEPENDENCIES' then
|
when 'DEPENDENCIES' then
|
||||||
parse_DEPENDENCIES
|
parse_DEPENDENCIES
|
||||||
|
when 'GIT' then
|
||||||
|
parse_GIT
|
||||||
when 'GEM' then
|
when 'GEM' then
|
||||||
parse_GEM
|
parse_GEM
|
||||||
when 'PLATFORMS' then
|
when 'PLATFORMS' then
|
||||||
@ -195,7 +228,7 @@ class Gem::RequestSet::Lockfile
|
|||||||
type, = get until @tokens.empty? or peek.first == :section
|
type, = get until @tokens.empty? or peek.first == :section
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise "BUG: unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
|
raise "BUG: unhandled token #{type} (#{data.inspect}) at line #{line} column #{column}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -204,7 +237,37 @@ class Gem::RequestSet::Lockfile
|
|||||||
while not @tokens.empty? and :text == peek.first do
|
while not @tokens.empty? and :text == peek.first do
|
||||||
_, name, = get :text
|
_, name, = get :text
|
||||||
|
|
||||||
@set.gem name
|
requirements = []
|
||||||
|
|
||||||
|
case peek[0]
|
||||||
|
when :bang then
|
||||||
|
get :bang
|
||||||
|
|
||||||
|
git_spec = @set.sets.select { |set|
|
||||||
|
Gem::Resolver::GitSet === set
|
||||||
|
}.map { |set|
|
||||||
|
set.specs[name]
|
||||||
|
}.first
|
||||||
|
|
||||||
|
requirements << git_spec.version
|
||||||
|
when :l_paren then
|
||||||
|
get :l_paren
|
||||||
|
|
||||||
|
loop do
|
||||||
|
_, op, = get :requirement
|
||||||
|
_, version, = get :text
|
||||||
|
|
||||||
|
requirements << "#{op} #{version}"
|
||||||
|
|
||||||
|
break unless peek[0] == :comma
|
||||||
|
|
||||||
|
get :comma
|
||||||
|
end
|
||||||
|
|
||||||
|
get :r_paren
|
||||||
|
end
|
||||||
|
|
||||||
|
@set.gem name, *requirements
|
||||||
|
|
||||||
skip :newline
|
skip :newline
|
||||||
end
|
end
|
||||||
@ -223,20 +286,76 @@ class Gem::RequestSet::Lockfile
|
|||||||
skip :newline
|
skip :newline
|
||||||
|
|
||||||
set = Gem::Resolver::LockSet.new source
|
set = Gem::Resolver::LockSet.new source
|
||||||
|
last_spec = nil
|
||||||
|
|
||||||
while not @tokens.empty? and :text == peek.first do
|
while not @tokens.empty? and :text == peek.first do
|
||||||
_, name, = get :text
|
_, name, column, = get :text
|
||||||
|
|
||||||
case peek[0]
|
case peek[0]
|
||||||
when :newline then # ignore
|
when :newline then
|
||||||
|
last_spec.add_dependency Gem::Dependency.new name if column == 6
|
||||||
when :l_paren then
|
when :l_paren then
|
||||||
get :l_paren
|
get :l_paren
|
||||||
|
|
||||||
_, version, = get :text
|
type, data, = get [:text, :requirement]
|
||||||
|
|
||||||
|
if type == :text and column == 4 then
|
||||||
|
last_spec = set.add name, data, Gem::Platform::RUBY
|
||||||
|
else
|
||||||
|
dependency = parse_dependency name, data
|
||||||
|
|
||||||
|
last_spec.add_dependency dependency
|
||||||
|
end
|
||||||
|
|
||||||
get :r_paren
|
get :r_paren
|
||||||
|
else
|
||||||
|
raise "BUG: unknown token #{peek}"
|
||||||
|
end
|
||||||
|
|
||||||
set.add name, version, Gem::Platform::RUBY
|
skip :newline
|
||||||
|
end
|
||||||
|
|
||||||
|
@set.sets << set
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_GIT # :nodoc:
|
||||||
|
get :entry, 'remote'
|
||||||
|
_, repository, = get :text
|
||||||
|
|
||||||
|
skip :newline
|
||||||
|
|
||||||
|
get :entry, 'revision'
|
||||||
|
_, revision, = get :text
|
||||||
|
|
||||||
|
skip :newline
|
||||||
|
|
||||||
|
get :entry, 'specs'
|
||||||
|
|
||||||
|
skip :newline
|
||||||
|
|
||||||
|
set = Gem::Resolver::GitSet.new
|
||||||
|
last_spec = nil
|
||||||
|
|
||||||
|
while not @tokens.empty? and :text == peek.first do
|
||||||
|
_, name, column, = get :text
|
||||||
|
|
||||||
|
case peek[0]
|
||||||
|
when :newline then
|
||||||
|
last_spec.add_dependency Gem::Dependency.new name if column == 6
|
||||||
|
when :l_paren then
|
||||||
|
get :l_paren
|
||||||
|
|
||||||
|
type, data, = get [:text, :requirement]
|
||||||
|
|
||||||
|
if type == :text and column == 4 then
|
||||||
|
last_spec = set.add_git_spec name, data, repository, revision, true
|
||||||
|
else
|
||||||
|
dependency = parse_dependency name, data
|
||||||
|
|
||||||
|
last_spec.spec.dependencies << dependency
|
||||||
|
end
|
||||||
|
|
||||||
|
get :r_paren
|
||||||
else
|
else
|
||||||
raise "BUG: unknown token #{peek}"
|
raise "BUG: unknown token #{peek}"
|
||||||
end
|
end
|
||||||
@ -257,11 +376,33 @@ class Gem::RequestSet::Lockfile
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses the requirements following the dependency +name+ and the +op+ for
|
||||||
|
# the first token of the requirements and returns a Gem::Dependency object.
|
||||||
|
|
||||||
|
def parse_dependency name, op # :nodoc:
|
||||||
|
return Gem::Dependency.new name unless peek[0] == :text
|
||||||
|
|
||||||
|
_, version, = get :text
|
||||||
|
|
||||||
|
requirements = ["#{op} #{version}"]
|
||||||
|
|
||||||
|
while peek[0] == :comma do
|
||||||
|
get :comma
|
||||||
|
_, op, = get :requirement
|
||||||
|
_, version, = get :text
|
||||||
|
|
||||||
|
requirements << "#{op} #{version}"
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem::Dependency.new name, requirements
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Peeks at the next token for Lockfile
|
# Peeks at the next token for Lockfile
|
||||||
|
|
||||||
def peek # :nodoc:
|
def peek # :nodoc:
|
||||||
@tokens.first
|
@tokens.first || :EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip type # :nodoc:
|
def skip type # :nodoc:
|
||||||
@ -284,6 +425,8 @@ class Gem::RequestSet::Lockfile
|
|||||||
|
|
||||||
add_PATH out
|
add_PATH out
|
||||||
|
|
||||||
|
add_GIT out
|
||||||
|
|
||||||
add_GEM out
|
add_GEM out
|
||||||
|
|
||||||
add_PLATFORMS out
|
add_PLATFORMS out
|
||||||
@ -321,14 +464,13 @@ class Gem::RequestSet::Lockfile
|
|||||||
until s.eos? do
|
until s.eos? do
|
||||||
pos = s.pos
|
pos = s.pos
|
||||||
|
|
||||||
# leading whitespace is for the user's convenience
|
pos = s.pos if leading_whitespace = s.scan(/ +/)
|
||||||
next if s.scan(/ +/)
|
|
||||||
|
|
||||||
if s.scan(/[<|=>]{7}/) then
|
if s.scan(/[<|=>]{7}/) then
|
||||||
message = "your #{lock_file} contains merge conflict markers"
|
message = "your #{lock_file} contains merge conflict markers"
|
||||||
line, column = token_pos pos
|
column, line = token_pos pos
|
||||||
|
|
||||||
raise ParseError.new message, line, column, lock_file
|
raise ParseError.new message, column, line, lock_file
|
||||||
end
|
end
|
||||||
|
|
||||||
@tokens <<
|
@tokens <<
|
||||||
@ -339,7 +481,13 @@ class Gem::RequestSet::Lockfile
|
|||||||
@line += 1
|
@line += 1
|
||||||
token
|
token
|
||||||
when s.scan(/[A-Z]+/) then
|
when s.scan(/[A-Z]+/) then
|
||||||
[:section, s.matched, *token_pos(pos)]
|
if leading_whitespace then
|
||||||
|
text = s.matched
|
||||||
|
text += s.scan(/[^\s)]*/).to_s # in case of no match
|
||||||
|
[:text, text, *token_pos(pos)]
|
||||||
|
else
|
||||||
|
[:section, s.matched, *token_pos(pos)]
|
||||||
|
end
|
||||||
when s.scan(/([a-z]+):\s/) then
|
when s.scan(/([a-z]+):\s/) then
|
||||||
s.pos -= 1 # rewind for possible newline
|
s.pos -= 1 # rewind for possible newline
|
||||||
[:entry, s[1], *token_pos(pos)]
|
[:entry, s[1], *token_pos(pos)]
|
||||||
@ -347,7 +495,13 @@ class Gem::RequestSet::Lockfile
|
|||||||
[:l_paren, nil, *token_pos(pos)]
|
[:l_paren, nil, *token_pos(pos)]
|
||||||
when s.scan(/\)/) then
|
when s.scan(/\)/) then
|
||||||
[:r_paren, nil, *token_pos(pos)]
|
[:r_paren, nil, *token_pos(pos)]
|
||||||
when s.scan(/[^\s)]*/) then
|
when s.scan(/<=|>=|=|~>|<|>|!=/) then
|
||||||
|
[:requirement, s.matched, *token_pos(pos)]
|
||||||
|
when s.scan(/,/) then
|
||||||
|
[:comma, nil, *token_pos(pos)]
|
||||||
|
when s.scan(/!/) then
|
||||||
|
[:bang, nil, *token_pos(pos)]
|
||||||
|
when s.scan(/[^\s),!]*/) then
|
||||||
[:text, s.matched, *token_pos(pos)]
|
[:text, s.matched, *token_pos(pos)]
|
||||||
else
|
else
|
||||||
raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}"
|
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.
|
# Formats this requirement for use in a Gem::RequestSet::Lockfile.
|
||||||
|
|
||||||
def for_lockfile # :nodoc:
|
def for_lockfile # :nodoc:
|
||||||
" (#{to_s})" unless [DefaultRequirement] == @requirements
|
return if [DefaultRequirement] == @requirements
|
||||||
|
|
||||||
|
list = requirements.sort_by { |_, version|
|
||||||
|
version
|
||||||
|
}.map { |op, version|
|
||||||
|
"#{op} #{version}"
|
||||||
|
}.uniq
|
||||||
|
|
||||||
|
" (#{list.join ', '})"
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -147,6 +155,14 @@ class Gem::Requirement
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# true if the requirement is for only an exact version
|
||||||
|
|
||||||
|
def exact?
|
||||||
|
return false unless @requirements.size == 1
|
||||||
|
@requirements[0][0] == "="
|
||||||
|
end
|
||||||
|
|
||||||
def as_list # :nodoc:
|
def as_list # :nodoc:
|
||||||
requirements.map { |op, version| "#{op} #{version}" }.sort
|
requirements.map { |op, version| "#{op} #{version}" }.sort
|
||||||
end
|
end
|
||||||
|
@ -36,6 +36,8 @@ class Gem::Resolver
|
|||||||
|
|
||||||
attr_reader :missing
|
attr_reader :missing
|
||||||
|
|
||||||
|
attr_reader :stats
|
||||||
|
|
||||||
##
|
##
|
||||||
# When a missing dependency, don't stop. Just go on and record what was
|
# When a missing dependency, don't stop. Just go on and record what was
|
||||||
# missing.
|
# missing.
|
||||||
@ -93,6 +95,7 @@ class Gem::Resolver
|
|||||||
@development = false
|
@development = false
|
||||||
@missing = []
|
@missing = []
|
||||||
@soft_missing = false
|
@soft_missing = false
|
||||||
|
@stats = Gem::Resolver::Stats.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def explain stage, *data # :nodoc:
|
def explain stage, *data # :nodoc:
|
||||||
@ -132,10 +135,13 @@ class Gem::Resolver
|
|||||||
s.dependencies.reverse_each do |d|
|
s.dependencies.reverse_each do |d|
|
||||||
next if d.type == :development and not @development
|
next if d.type == :development and not @development
|
||||||
reqs.add Gem::Resolver::DependencyRequest.new(d, act)
|
reqs.add Gem::Resolver::DependencyRequest.new(d, act)
|
||||||
|
@stats.requirement!
|
||||||
end
|
end
|
||||||
|
|
||||||
@set.prefetch reqs
|
@set.prefetch reqs
|
||||||
|
|
||||||
|
@stats.record_requirements reqs
|
||||||
|
|
||||||
reqs
|
reqs
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -151,8 +157,11 @@ class Gem::Resolver
|
|||||||
request = Gem::Resolver::DependencyRequest.new n, nil
|
request = Gem::Resolver::DependencyRequest.new n, nil
|
||||||
|
|
||||||
needed.add request
|
needed.add request
|
||||||
|
@stats.requirement!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@stats.record_requirements needed
|
||||||
|
|
||||||
res = resolve_for needed, nil
|
res = resolve_for needed, nil
|
||||||
|
|
||||||
raise Gem::DependencyResolutionError, res if
|
raise Gem::DependencyResolutionError, res if
|
||||||
@ -268,6 +277,8 @@ class Gem::Resolver
|
|||||||
states = []
|
states = []
|
||||||
|
|
||||||
while !needed.empty?
|
while !needed.empty?
|
||||||
|
@stats.iteration!
|
||||||
|
|
||||||
dep = needed.remove
|
dep = needed.remove
|
||||||
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
|
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
|
||||||
explain_list :next5, needed.next5
|
explain_list :next5, needed.next5
|
||||||
@ -279,12 +290,33 @@ class Gem::Resolver
|
|||||||
next if dep.matches_spec? existing
|
next if dep.matches_spec? existing
|
||||||
|
|
||||||
conflict = handle_conflict dep, existing
|
conflict = handle_conflict dep, existing
|
||||||
explain :conflict, conflict.explain
|
|
||||||
|
|
||||||
state = find_conflict_state conflict, states
|
return conflict unless dep.requester
|
||||||
|
|
||||||
|
explain :conflict, dep, :existing, existing.full_name
|
||||||
|
|
||||||
|
depreq = dep.requester.request
|
||||||
|
|
||||||
|
state = nil
|
||||||
|
until states.empty?
|
||||||
|
x = states.pop
|
||||||
|
|
||||||
|
i = existing.request.requester
|
||||||
|
explain :consider, x.spec.full_name, [depreq.name, dep.name, i ? i.name : :top]
|
||||||
|
|
||||||
|
if x.spec.name == depreq.name or
|
||||||
|
x.spec.name == dep.name or
|
||||||
|
(i && (i.name == x.spec.name))
|
||||||
|
explain :found, x.spec.full_name
|
||||||
|
state = x
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return conflict unless state
|
return conflict unless state
|
||||||
|
|
||||||
|
@stats.backtracking!
|
||||||
|
|
||||||
needed, specs = resolve_for_conflict needed, specs, state
|
needed, specs = resolve_for_conflict needed, specs, state
|
||||||
|
|
||||||
states << state unless state.possibles.empty?
|
states << state unless state.possibles.empty?
|
||||||
@ -346,6 +378,8 @@ class Gem::Resolver
|
|||||||
# what makes conflict resolution possible.
|
# what makes conflict resolution possible.
|
||||||
states << State.new(needed.dup, specs, dep, spec, possible, [])
|
states << State.new(needed.dup, specs, dep, spec, possible, [])
|
||||||
|
|
||||||
|
@stats.record_depth states
|
||||||
|
|
||||||
explain :states, states.map { |s| s.dep }
|
explain :states, states.map { |s| s.dep }
|
||||||
|
|
||||||
needed = requests spec, act, needed
|
needed = requests spec, act, needed
|
||||||
@ -404,6 +438,7 @@ require 'rubygems/resolver/activation_request'
|
|||||||
require 'rubygems/resolver/conflict'
|
require 'rubygems/resolver/conflict'
|
||||||
require 'rubygems/resolver/dependency_request'
|
require 'rubygems/resolver/dependency_request'
|
||||||
require 'rubygems/resolver/requirement_list'
|
require 'rubygems/resolver/requirement_list'
|
||||||
|
require 'rubygems/resolver/stats'
|
||||||
|
|
||||||
require 'rubygems/resolver/set'
|
require 'rubygems/resolver/set'
|
||||||
require 'rubygems/resolver/api_set'
|
require 'rubygems/resolver/api_set'
|
||||||
@ -423,5 +458,6 @@ require 'rubygems/resolver/git_specification'
|
|||||||
require 'rubygems/resolver/index_specification'
|
require 'rubygems/resolver/index_specification'
|
||||||
require 'rubygems/resolver/installed_specification'
|
require 'rubygems/resolver/installed_specification'
|
||||||
require 'rubygems/resolver/local_specification'
|
require 'rubygems/resolver/local_specification'
|
||||||
|
require 'rubygems/resolver/lock_specification'
|
||||||
require 'rubygems/resolver/vendor_specification'
|
require 'rubygems/resolver/vendor_specification'
|
||||||
|
|
||||||
|
@ -45,6 +45,32 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
|
|||||||
@need_submodules[repository] = submodules
|
@need_submodules[repository] = submodules
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Adds and returns a GitSpecification with the given +name+ and +version+
|
||||||
|
# which came from a +repository+ at the given +reference+. If +submodules+
|
||||||
|
# is true they are checked out along with the repository.
|
||||||
|
#
|
||||||
|
# This fills in the prefetch information as enough information about the gem
|
||||||
|
# is present in the arguments.
|
||||||
|
|
||||||
|
def add_git_spec name, version, repository, reference, submodules # :nodoc:
|
||||||
|
add_git_gem name, repository, reference, submodules
|
||||||
|
|
||||||
|
source = Gem::Source::Git.new name, repository, reference
|
||||||
|
source.root_dir = @root_dir
|
||||||
|
|
||||||
|
spec = Gem::Specification.new do |s|
|
||||||
|
s.name = name
|
||||||
|
s.version = version
|
||||||
|
end
|
||||||
|
|
||||||
|
git_spec = Gem::Resolver::GitSpecification.new self, spec, source
|
||||||
|
|
||||||
|
@specs[spec.name] = git_spec
|
||||||
|
|
||||||
|
git_spec
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Finds all git gems matching +req+
|
# Finds all git gems matching +req+
|
||||||
|
|
||||||
|
@ -24,10 +24,12 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
|
|||||||
version = Gem::Version.new version
|
version = Gem::Version.new version
|
||||||
|
|
||||||
spec =
|
spec =
|
||||||
Gem::Resolver::IndexSpecification.new self, name, version, @source,
|
Gem::Resolver::LockSpecification.new self, name, version, @source,
|
||||||
platform
|
platform
|
||||||
|
|
||||||
@specs << spec
|
@specs << spec
|
||||||
|
|
||||||
|
spec
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
58
lib/rubygems/resolver/lock_specification.rb
Normal file
58
lib/rubygems/resolver/lock_specification.rb
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
##
|
||||||
|
# The LockSpecification comes from a lockfile (Gem::RequestSet::Lockfile).
|
||||||
|
#
|
||||||
|
# A LockSpecification's dependency information is pre-filled from the
|
||||||
|
# lockfile.
|
||||||
|
|
||||||
|
class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
|
||||||
|
|
||||||
|
def initialize set, name, version, source, platform
|
||||||
|
super()
|
||||||
|
|
||||||
|
@name = name
|
||||||
|
@platform = platform
|
||||||
|
@set = set
|
||||||
|
@source = source
|
||||||
|
@version = version
|
||||||
|
|
||||||
|
@dependencies = []
|
||||||
|
@spec = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# This is a null install as a locked specification is considered installed.
|
||||||
|
# +options+ are ignored.
|
||||||
|
|
||||||
|
def install options
|
||||||
|
destination = options[:install_dir] || Gem.dir
|
||||||
|
|
||||||
|
if File.exist? File.join(destination, 'specifications', spec.spec_name) then
|
||||||
|
yield nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Adds +dependency+ from the lockfile to this specification
|
||||||
|
|
||||||
|
def add_dependency dependency # :nodoc:
|
||||||
|
@dependencies << dependency
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# A specification constructed from the lockfile is returned
|
||||||
|
|
||||||
|
def spec
|
||||||
|
@spec ||= Gem::Specification.new do |s|
|
||||||
|
s.name = @name
|
||||||
|
s.version = @version
|
||||||
|
s.platform = @platform
|
||||||
|
|
||||||
|
s.dependencies.concat @dependencies
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -13,10 +13,12 @@ class Gem::Resolver::RequirementList
|
|||||||
# Creates a new RequirementList.
|
# Creates a new RequirementList.
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@exact = []
|
||||||
@list = []
|
@list = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_copy other # :nodoc:
|
def initialize_copy other # :nodoc:
|
||||||
|
@exact = @exact.dup
|
||||||
@list = @list.dup
|
@list = @list.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,7 +26,11 @@ class Gem::Resolver::RequirementList
|
|||||||
# Adds Resolver::DependencyRequest +req+ to this requirements list.
|
# Adds Resolver::DependencyRequest +req+ to this requirements list.
|
||||||
|
|
||||||
def add(req)
|
def add(req)
|
||||||
@list.push req
|
if req.requirement.exact?
|
||||||
|
@exact.push req
|
||||||
|
else
|
||||||
|
@list.push req
|
||||||
|
end
|
||||||
req
|
req
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -34,22 +40,34 @@ class Gem::Resolver::RequirementList
|
|||||||
def each # :nodoc:
|
def each # :nodoc:
|
||||||
return enum_for __method__ unless block_given?
|
return enum_for __method__ unless block_given?
|
||||||
|
|
||||||
|
@exact.each do |requirement|
|
||||||
|
yield requirement
|
||||||
|
end
|
||||||
|
|
||||||
@list.each do |requirement|
|
@list.each do |requirement|
|
||||||
yield requirement
|
yield requirement
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# How many elements are in the list
|
||||||
|
|
||||||
|
def size
|
||||||
|
@exact.size + @list.size
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Is the list empty?
|
# Is the list empty?
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
@list.empty?
|
@exact.empty? && @list.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Remove the oldest DependencyRequest from the list.
|
# Remove the oldest DependencyRequest from the list.
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
|
return @exact.shift unless @exact.empty?
|
||||||
@list.shift
|
@list.shift
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -57,6 +75,7 @@ class Gem::Resolver::RequirementList
|
|||||||
# Returns the oldest five entries from the list.
|
# Returns the oldest five entries from the list.
|
||||||
|
|
||||||
def next5
|
def next5
|
||||||
@list[0,5]
|
x = @exact[0,5]
|
||||||
|
x + @list[0,5 - x.size]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
44
lib/rubygems/resolver/stats.rb
Normal file
44
lib/rubygems/resolver/stats.rb
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
class Gem::Resolver::Stats
|
||||||
|
def initialize
|
||||||
|
@max_depth = 0
|
||||||
|
@max_requirements = 0
|
||||||
|
@requirements = 0
|
||||||
|
@backtracking = 0
|
||||||
|
@iterations = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def record_depth(stack)
|
||||||
|
if stack.size > @max_depth
|
||||||
|
@max_depth = stack.size
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def record_requirements(reqs)
|
||||||
|
if reqs.size > @max_requirements
|
||||||
|
@max_requirements = reqs.size
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def requirement!
|
||||||
|
@requirements += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def backtracking!
|
||||||
|
@backtracking += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def iteration!
|
||||||
|
@iterations += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
PATTERN = "%20s: %d\n"
|
||||||
|
|
||||||
|
def display
|
||||||
|
$stdout.puts "=== Resolver Statistics ==="
|
||||||
|
$stdout.printf PATTERN, "Max Depth", @max_depth
|
||||||
|
$stdout.printf PATTERN, "Total Requirements", @requirements
|
||||||
|
$stdout.printf PATTERN, "Max Requirements", @max_requirements
|
||||||
|
$stdout.printf PATTERN, "Backtracking #", @backtracking
|
||||||
|
$stdout.printf PATTERN, "Iteration #", @iterations
|
||||||
|
end
|
||||||
|
end
|
@ -202,7 +202,10 @@ class Gem::Source
|
|||||||
q.group 2, '[Remote:', ']' do
|
q.group 2, '[Remote:', ']' do
|
||||||
q.breakable
|
q.breakable
|
||||||
q.text @uri.to_s
|
q.text @uri.to_s
|
||||||
|
|
||||||
if api = api_uri
|
if api = api_uri
|
||||||
|
q.breakable
|
||||||
|
q.text 'API URI: '
|
||||||
q.text api.to_s
|
q.text api.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -147,6 +147,16 @@ class Gem::Source::Git < Gem::Source
|
|||||||
File.join base_dir, 'gems', "#{@name}-#{dir_shortref}"
|
File.join base_dir, 'gems', "#{@name}-#{dir_shortref}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.group 2, '[Git: ', ']' do
|
||||||
|
q.breakable
|
||||||
|
q.text @repository
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text @reference
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The directory where the git gem's repository will be cached.
|
# 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
|
@wrapped.fetch_spec name_tuple
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uri # :nodoc:
|
||||||
|
@wrapped.uri
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ class Gem::TestCase < MiniTest::Unit::TestCase
|
|||||||
|
|
||||||
attr_accessor :fetcher # :nodoc:
|
attr_accessor :fetcher # :nodoc:
|
||||||
|
|
||||||
|
attr_accessor :gem_repo # :nodoc:
|
||||||
|
|
||||||
|
attr_accessor :uri # :nodoc:
|
||||||
|
|
||||||
def assert_activate expected, *specs
|
def assert_activate expected, *specs
|
||||||
specs.each do |spec|
|
specs.each do |spec|
|
||||||
case spec
|
case spec
|
||||||
@ -1196,8 +1200,8 @@ Also, a list:
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
|
||||||
def spec_fetcher
|
def spec_fetcher repository = @gem_repo
|
||||||
Gem::TestCase::SpecFetcherSetup.declare self do |spec_fetcher_setup|
|
Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup|
|
||||||
yield spec_fetcher_setup if block_given?
|
yield spec_fetcher_setup if block_given?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -199,16 +199,17 @@ class Gem::TestCase::SpecFetcherSetup
|
|||||||
# Executes a SpecFetcher setup block. Yields an instance then creates the
|
# Executes a SpecFetcher setup block. Yields an instance then creates the
|
||||||
# gems and specifications defined in the instance.
|
# gems and specifications defined in the instance.
|
||||||
|
|
||||||
def self.declare test
|
def self.declare test, repository
|
||||||
setup = new test
|
setup = new test, repository
|
||||||
|
|
||||||
yield setup
|
yield setup
|
||||||
|
|
||||||
setup.execute
|
setup.execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize test # :nodoc:
|
def initialize test, repository # :nodoc:
|
||||||
@test = test
|
@test = test
|
||||||
|
@repository = repository
|
||||||
|
|
||||||
@gems = {}
|
@gems = {}
|
||||||
@installed = []
|
@installed = []
|
||||||
@ -298,12 +299,22 @@ class Gem::TestCase::SpecFetcherSetup
|
|||||||
require 'socket'
|
require 'socket'
|
||||||
require 'rubygems/remote_fetcher'
|
require 'rubygems/remote_fetcher'
|
||||||
|
|
||||||
@test.fetcher = Gem::FakeFetcher.new
|
unless @test.fetcher then
|
||||||
Gem::RemoteFetcher.fetcher = @test.fetcher
|
@test.fetcher = Gem::FakeFetcher.new
|
||||||
|
Gem::RemoteFetcher.fetcher = @test.fetcher
|
||||||
|
end
|
||||||
|
|
||||||
Gem::Specification.reset
|
Gem::Specification.reset
|
||||||
|
|
||||||
@test.util_setup_spec_fetcher(*@gems.keys)
|
begin
|
||||||
|
gem_repo, @test.gem_repo = @test.gem_repo, @repository
|
||||||
|
@test.uri = URI @repository
|
||||||
|
|
||||||
|
@test.util_setup_spec_fetcher(*@gems.keys)
|
||||||
|
ensure
|
||||||
|
@test.gem_repo = gem_repo
|
||||||
|
@test.uri = URI gem_repo
|
||||||
|
end
|
||||||
|
|
||||||
# This works around util_setup_spec_fetcher adding all created gems to the
|
# This works around util_setup_spec_fetcher adding all created gems to the
|
||||||
# installed set.
|
# installed set.
|
||||||
@ -313,7 +324,7 @@ class Gem::TestCase::SpecFetcherSetup
|
|||||||
@gems.each do |spec, gem|
|
@gems.each do |spec, gem|
|
||||||
next unless gem
|
next unless gem
|
||||||
|
|
||||||
@test.fetcher.data["http://gems.example.com/gems/#{spec.file_name}"] =
|
@test.fetcher.data["#{@repository}gems/#{spec.file_name}"] =
|
||||||
Gem.read_binary(gem)
|
Gem.read_binary(gem)
|
||||||
|
|
||||||
FileUtils.cp gem, spec.cache_file
|
FileUtils.cp gem, spec.cache_file
|
||||||
|
@ -95,6 +95,7 @@ class TestGemRequestSet < Gem::TestCase
|
|||||||
fetcher.gem 'a', 1
|
fetcher.gem 'a', 1
|
||||||
fetcher.gem 'a', 2
|
fetcher.gem 'a', 2
|
||||||
fetcher.gem 'b', 1, 'a' => '>= 0'
|
fetcher.gem 'b', 1, 'a' => '>= 0'
|
||||||
|
fetcher.clear
|
||||||
end
|
end
|
||||||
|
|
||||||
rs = Gem::RequestSet.new
|
rs = Gem::RequestSet.new
|
||||||
@ -107,7 +108,7 @@ GEM
|
|||||||
specs:
|
specs:
|
||||||
a (1)
|
a (1)
|
||||||
b (1)
|
b (1)
|
||||||
a
|
a (~> 1.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
#{Gem::Platform::RUBY}
|
#{Gem::Platform::RUBY}
|
||||||
@ -127,6 +128,9 @@ DEPENDENCIES
|
|||||||
|
|
||||||
assert_includes installed, 'b-1'
|
assert_includes installed, 'b-1'
|
||||||
assert_includes installed, 'a-1'
|
assert_includes installed, 'a-1'
|
||||||
|
|
||||||
|
assert_path_exists File.join @gemhome, 'specifications', 'a-1.gemspec'
|
||||||
|
assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_load_gemdeps
|
def test_load_gemdeps
|
||||||
@ -301,7 +305,9 @@ DEPENDENCIES
|
|||||||
|
|
||||||
rs.resolve
|
rs.resolve
|
||||||
|
|
||||||
installed = rs.install_into @tempdir
|
installed = rs.install_into @tempdir do
|
||||||
|
assert_equal @tempdir, ENV['GEM_HOME']
|
||||||
|
end
|
||||||
|
|
||||||
assert_path_exists File.join @tempdir, 'specifications', 'a-1.gemspec'
|
assert_path_exists File.join @tempdir, 'specifications', 'a-1.gemspec'
|
||||||
assert_path_exists File.join @tempdir, 'specifications', 'b-1.gemspec'
|
assert_path_exists File.join @tempdir, 'specifications', 'b-1.gemspec'
|
||||||
|
@ -514,6 +514,27 @@ end
|
|||||||
assert_same @GDA, Gem::RequestSet::GemDepedencyAPI
|
assert_same @GDA, Gem::RequestSet::GemDepedencyAPI
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_pin_gem_source
|
||||||
|
gda = @GDA.new @set, nil
|
||||||
|
|
||||||
|
gda.send :pin_gem_source, 'a'
|
||||||
|
gda.send :pin_gem_source, 'a'
|
||||||
|
|
||||||
|
e = assert_raises ArgumentError do
|
||||||
|
gda.send :pin_gem_source, 'a', :path, 'vendor/a'
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal "duplicate source path: vendor/a for gem a",
|
||||||
|
e.message
|
||||||
|
|
||||||
|
e = assert_raises ArgumentError do
|
||||||
|
gda.send :pin_gem_source, 'a', :git, 'git://example/repo.git'
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal "duplicate source git: git://example/repo.git for gem a",
|
||||||
|
e.message
|
||||||
|
end
|
||||||
|
|
||||||
def test_platform_mswin
|
def test_platform_mswin
|
||||||
win_platform, Gem.win_platform = Gem.win_platform?, false
|
win_platform, Gem.win_platform = Gem.win_platform?, false
|
||||||
|
|
||||||
|
@ -13,8 +13,10 @@ class TestGemRequestSetLockfile < Gem::TestCase
|
|||||||
|
|
||||||
@set = Gem::RequestSet.new
|
@set = Gem::RequestSet.new
|
||||||
|
|
||||||
|
@git_set = Gem::Resolver::GitSet.new
|
||||||
@vendor_set = Gem::Resolver::VendorSet.new
|
@vendor_set = Gem::Resolver::VendorSet.new
|
||||||
|
|
||||||
|
@set.instance_variable_set :@git_set, @git_set
|
||||||
@set.instance_variable_set :@vendor_set, @vendor_set
|
@set.instance_variable_set :@vendor_set, @vendor_set
|
||||||
|
|
||||||
@gem_deps_file = 'gem.deps.rb'
|
@gem_deps_file = 'gem.deps.rb'
|
||||||
@ -49,15 +51,22 @@ class TestGemRequestSetLockfile < Gem::TestCase
|
|||||||
@lockfile.get :text
|
@lockfile.get :text
|
||||||
end
|
end
|
||||||
|
|
||||||
expected = 'unexpected token [:section, "x"], expected :text (at 5:1)'
|
expected =
|
||||||
|
'unexpected token [:section, "x"], expected :text (at line 1 column 5)'
|
||||||
|
|
||||||
assert_equal expected, e.message
|
assert_equal expected, e.message
|
||||||
|
|
||||||
assert_equal 5, e.line
|
assert_equal 1, e.line
|
||||||
assert_equal 1, e.column
|
assert_equal 5, e.column
|
||||||
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_get_type_multiple
|
||||||
|
@lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
|
||||||
|
|
||||||
|
assert @lockfile.get [:text, :section]
|
||||||
|
end
|
||||||
|
|
||||||
def test_get_type_value_mismatch
|
def test_get_type_value_mismatch
|
||||||
@lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
|
@lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
|
||||||
|
|
||||||
@ -66,17 +75,17 @@ class TestGemRequestSetLockfile < Gem::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
expected =
|
expected =
|
||||||
'unexpected token [:section, "x"], expected [:section, "y"] (at 5:1)'
|
'unexpected token [:section, "x"], expected [:section, "y"] (at line 1 column 5)'
|
||||||
|
|
||||||
assert_equal expected, e.message
|
assert_equal expected, e.message
|
||||||
|
|
||||||
assert_equal 5, e.line
|
assert_equal 1, e.line
|
||||||
assert_equal 1, e.column
|
assert_equal 5, e.column
|
||||||
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_parse
|
def test_parse
|
||||||
write_lockfile <<-LOCKFILE
|
write_lockfile <<-LOCKFILE.strip
|
||||||
GEM
|
GEM
|
||||||
remote: #{@gem_repo}
|
remote: #{@gem_repo}
|
||||||
specs:
|
specs:
|
||||||
@ -104,6 +113,113 @@ DEPENDENCIES
|
|||||||
assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
|
assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_parse_dependencies
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
GEM
|
||||||
|
remote: #{@gem_repo}
|
||||||
|
specs:
|
||||||
|
a (2)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
a (>= 1, <= 2)
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
@lockfile.parse
|
||||||
|
|
||||||
|
assert_equal [dep('a', '>= 1', '<= 2')], @set.dependencies
|
||||||
|
|
||||||
|
assert_equal [Gem::Platform::RUBY], @lockfile.platforms
|
||||||
|
|
||||||
|
lockfile_set = @set.sets.find do |set|
|
||||||
|
Gem::Resolver::LockSet === set
|
||||||
|
end
|
||||||
|
|
||||||
|
assert lockfile_set, 'could not find a LockSet'
|
||||||
|
|
||||||
|
assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_GIT
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
GIT
|
||||||
|
remote: git://example/a.git
|
||||||
|
revision: master
|
||||||
|
specs:
|
||||||
|
a (2)
|
||||||
|
b (>= 3)
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
a!
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
@lockfile.parse
|
||||||
|
|
||||||
|
assert_equal [dep('a', '= 2')], @set.dependencies
|
||||||
|
|
||||||
|
lockfile_set = @set.sets.find do |set|
|
||||||
|
Gem::Resolver::LockSet === set
|
||||||
|
end
|
||||||
|
|
||||||
|
refute lockfile_set, 'fount a LockSet'
|
||||||
|
|
||||||
|
git_set = @set.sets.find do |set|
|
||||||
|
Gem::Resolver::GitSet === set
|
||||||
|
end
|
||||||
|
|
||||||
|
assert git_set, 'could not find a GitSet'
|
||||||
|
|
||||||
|
assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name }
|
||||||
|
|
||||||
|
assert_equal [dep('b', '>= 3')], git_set.specs.values.first.dependencies
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_gem_specs_dependency
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
GEM
|
||||||
|
remote: #{@gem_repo}
|
||||||
|
specs:
|
||||||
|
a (2)
|
||||||
|
b (= 3)
|
||||||
|
c (~> 4)
|
||||||
|
d
|
||||||
|
e (~> 5.0, >= 5.0.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
a
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
@lockfile.parse
|
||||||
|
|
||||||
|
assert_equal [dep('a')], @set.dependencies
|
||||||
|
|
||||||
|
assert_equal [Gem::Platform::RUBY], @lockfile.platforms
|
||||||
|
|
||||||
|
lockfile_set = @set.sets.find do |set|
|
||||||
|
Gem::Resolver::LockSet === set
|
||||||
|
end
|
||||||
|
|
||||||
|
assert lockfile_set, 'could not find a LockSet'
|
||||||
|
|
||||||
|
assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
|
||||||
|
|
||||||
|
spec = lockfile_set.specs.first
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
dep('b', '= 3'),
|
||||||
|
dep('c', '~> 4'),
|
||||||
|
dep('d'),
|
||||||
|
dep('e', '~> 5.0', '>= 5.0.1'),
|
||||||
|
]
|
||||||
|
|
||||||
|
assert_equal expected, spec.dependencies
|
||||||
|
end
|
||||||
|
|
||||||
def test_parse_missing
|
def test_parse_missing
|
||||||
@lockfile.parse
|
@lockfile.parse
|
||||||
|
|
||||||
@ -120,6 +236,8 @@ DEPENDENCIES
|
|||||||
assert_equal :token, @lockfile.peek
|
assert_equal :token, @lockfile.peek
|
||||||
|
|
||||||
assert_equal :token, @lockfile.get
|
assert_equal :token, @lockfile.get
|
||||||
|
|
||||||
|
assert_equal :EOF, @lockfile.peek
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_skip
|
def test_skip
|
||||||
@ -147,6 +265,13 @@ GEM
|
|||||||
remote: #{@gem_repo}
|
remote: #{@gem_repo}
|
||||||
specs:
|
specs:
|
||||||
a (2)
|
a (2)
|
||||||
|
b (= 2)
|
||||||
|
c (!= 3)
|
||||||
|
d (> 4)
|
||||||
|
e (< 5)
|
||||||
|
f (>= 6)
|
||||||
|
g (<= 7)
|
||||||
|
h (~> 8)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
#{Gem::Platform::RUBY}
|
#{Gem::Platform::RUBY}
|
||||||
@ -155,6 +280,106 @@ DEPENDENCIES
|
|||||||
a
|
a
|
||||||
LOCKFILE
|
LOCKFILE
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
[:section, 'GEM', 0, 0],
|
||||||
|
[:newline, nil, 3, 0],
|
||||||
|
|
||||||
|
[:entry, 'remote', 2, 1],
|
||||||
|
[:text, @gem_repo, 10, 1],
|
||||||
|
[:newline, nil, 34, 1],
|
||||||
|
|
||||||
|
[:entry, 'specs', 2, 2],
|
||||||
|
[:newline, nil, 8, 2],
|
||||||
|
|
||||||
|
[:text, 'a', 4, 3],
|
||||||
|
[:l_paren, nil, 6, 3],
|
||||||
|
[:text, '2', 7, 3],
|
||||||
|
[:r_paren, nil, 8, 3],
|
||||||
|
[:newline, nil, 9, 3],
|
||||||
|
|
||||||
|
[:text, 'b', 6, 4],
|
||||||
|
[:l_paren, nil, 8, 4],
|
||||||
|
[:requirement, '=', 9, 4],
|
||||||
|
[:text, '2', 11, 4],
|
||||||
|
[:r_paren, nil, 12, 4],
|
||||||
|
[:newline, nil, 13, 4],
|
||||||
|
|
||||||
|
[:text, 'c', 6, 5],
|
||||||
|
[:l_paren, nil, 8, 5],
|
||||||
|
[:requirement, '!=', 9, 5],
|
||||||
|
[:text, '3', 12, 5],
|
||||||
|
[:r_paren, nil, 13, 5],
|
||||||
|
[:newline, nil, 14, 5],
|
||||||
|
|
||||||
|
[:text, 'd', 6, 6],
|
||||||
|
[:l_paren, nil, 8, 6],
|
||||||
|
[:requirement, '>', 9, 6],
|
||||||
|
[:text, '4', 11, 6],
|
||||||
|
[:r_paren, nil, 12, 6],
|
||||||
|
[:newline, nil, 13, 6],
|
||||||
|
|
||||||
|
[:text, 'e', 6, 7],
|
||||||
|
[:l_paren, nil, 8, 7],
|
||||||
|
[:requirement, '<', 9, 7],
|
||||||
|
[:text, '5', 11, 7],
|
||||||
|
[:r_paren, nil, 12, 7],
|
||||||
|
[:newline, nil, 13, 7],
|
||||||
|
|
||||||
|
[:text, 'f', 6, 8],
|
||||||
|
[:l_paren, nil, 8, 8],
|
||||||
|
[:requirement, '>=', 9, 8],
|
||||||
|
[:text, '6', 12, 8],
|
||||||
|
[:r_paren, nil, 13, 8],
|
||||||
|
[:newline, nil, 14, 8],
|
||||||
|
|
||||||
|
[:text, 'g', 6, 9],
|
||||||
|
[:l_paren, nil, 8, 9],
|
||||||
|
[:requirement, '<=', 9, 9],
|
||||||
|
[:text, '7', 12, 9],
|
||||||
|
[:r_paren, nil, 13, 9],
|
||||||
|
[:newline, nil, 14, 9],
|
||||||
|
|
||||||
|
[:text, 'h', 6, 10],
|
||||||
|
[:l_paren, nil, 8, 10],
|
||||||
|
[:requirement, '~>', 9, 10],
|
||||||
|
[:text, '8', 12, 10],
|
||||||
|
[:r_paren, nil, 13, 10],
|
||||||
|
[:newline, nil, 14, 10],
|
||||||
|
|
||||||
|
[:newline, nil, 0, 11],
|
||||||
|
|
||||||
|
[:section, 'PLATFORMS', 0, 12],
|
||||||
|
[:newline, nil, 9, 12],
|
||||||
|
|
||||||
|
[:text, Gem::Platform::RUBY, 2, 13],
|
||||||
|
[:newline, nil, 6, 13],
|
||||||
|
|
||||||
|
[:newline, nil, 0, 14],
|
||||||
|
|
||||||
|
[:section, 'DEPENDENCIES', 0, 15],
|
||||||
|
[:newline, nil, 12, 15],
|
||||||
|
|
||||||
|
[:text, 'a', 2, 16],
|
||||||
|
[:newline, nil, 3, 16],
|
||||||
|
]
|
||||||
|
|
||||||
|
assert_equal expected, @lockfile.tokenize
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_tokenize_capitals
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
GEM
|
||||||
|
remote: #{@gem_repo}
|
||||||
|
specs:
|
||||||
|
Ab (2)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
Ab
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
[:section, 'GEM', 0, 0],
|
[:section, 'GEM', 0, 0],
|
||||||
[:newline, nil, 3, 0],
|
[:newline, nil, 3, 0],
|
||||||
@ -163,11 +388,11 @@ DEPENDENCIES
|
|||||||
[:newline, nil, 34, 1],
|
[:newline, nil, 34, 1],
|
||||||
[:entry, 'specs', 2, 2],
|
[:entry, 'specs', 2, 2],
|
||||||
[:newline, nil, 8, 2],
|
[:newline, nil, 8, 2],
|
||||||
[:text, 'a', 4, 3],
|
[:text, 'Ab', 4, 3],
|
||||||
[:l_paren, nil, 6, 3],
|
[:l_paren, nil, 7, 3],
|
||||||
[:text, '2', 7, 3],
|
[:text, '2', 8, 3],
|
||||||
[:r_paren, nil, 8, 3],
|
[:r_paren, nil, 9, 3],
|
||||||
[:newline, nil, 9, 3],
|
[:newline, nil, 10, 3],
|
||||||
[:newline, nil, 0, 4],
|
[:newline, nil, 0, 4],
|
||||||
[:section, 'PLATFORMS', 0, 5],
|
[:section, 'PLATFORMS', 0, 5],
|
||||||
[:newline, nil, 9, 5],
|
[:newline, nil, 9, 5],
|
||||||
@ -176,8 +401,8 @@ DEPENDENCIES
|
|||||||
[:newline, nil, 0, 7],
|
[:newline, nil, 0, 7],
|
||||||
[:section, 'DEPENDENCIES', 0, 8],
|
[:section, 'DEPENDENCIES', 0, 8],
|
||||||
[:newline, nil, 12, 8],
|
[:newline, nil, 12, 8],
|
||||||
[:text, 'a', 2, 9],
|
[:text, 'Ab', 2, 9],
|
||||||
[:newline, nil, 3, 9],
|
[:newline, nil, 4, 9],
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal expected, @lockfile.tokenize
|
assert_equal expected, @lockfile.tokenize
|
||||||
@ -190,7 +415,7 @@ DEPENDENCIES
|
|||||||
@lockfile.tokenize
|
@lockfile.tokenize
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
|
||||||
e.message
|
e.message
|
||||||
|
|
||||||
write_lockfile '|||||||'
|
write_lockfile '|||||||'
|
||||||
@ -199,7 +424,7 @@ DEPENDENCIES
|
|||||||
@lockfile.tokenize
|
@lockfile.tokenize
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
|
||||||
e.message
|
e.message
|
||||||
|
|
||||||
write_lockfile '======='
|
write_lockfile '======='
|
||||||
@ -208,7 +433,7 @@ DEPENDENCIES
|
|||||||
@lockfile.tokenize
|
@lockfile.tokenize
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
|
||||||
e.message
|
e.message
|
||||||
|
|
||||||
write_lockfile '>>>>>>>'
|
write_lockfile '>>>>>>>'
|
||||||
@ -217,16 +442,74 @@ DEPENDENCIES
|
|||||||
@lockfile.tokenize
|
@lockfile.tokenize
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
|
||||||
e.message
|
e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_tokenize_git
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
DEPENDENCIES
|
||||||
|
a!
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
[:section, 'DEPENDENCIES', 0, 0],
|
||||||
|
[:newline, nil, 12, 0],
|
||||||
|
|
||||||
|
[:text, 'a', 2, 1],
|
||||||
|
[:bang, nil, 3, 1],
|
||||||
|
[:newline, nil, 4, 1],
|
||||||
|
]
|
||||||
|
|
||||||
|
assert_equal expected, @lockfile.tokenize
|
||||||
|
end
|
||||||
|
|
||||||
def test_tokenize_missing
|
def test_tokenize_missing
|
||||||
tokens = @lockfile.tokenize
|
tokens = @lockfile.tokenize
|
||||||
|
|
||||||
assert_empty tokens
|
assert_empty tokens
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_tokenize_multiple
|
||||||
|
write_lockfile <<-LOCKFILE
|
||||||
|
GEM
|
||||||
|
remote: #{@gem_repo}
|
||||||
|
specs:
|
||||||
|
a (2)
|
||||||
|
b (~> 3.0, >= 3.0.1)
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
[:section, 'GEM', 0, 0],
|
||||||
|
[:newline, nil, 3, 0],
|
||||||
|
|
||||||
|
[:entry, 'remote', 2, 1],
|
||||||
|
[:text, @gem_repo, 10, 1],
|
||||||
|
[:newline, nil, 34, 1],
|
||||||
|
|
||||||
|
[:entry, 'specs', 2, 2],
|
||||||
|
[:newline, nil, 8, 2],
|
||||||
|
|
||||||
|
[:text, 'a', 4, 3],
|
||||||
|
[:l_paren, nil, 6, 3],
|
||||||
|
[:text, '2', 7, 3],
|
||||||
|
[:r_paren, nil, 8, 3],
|
||||||
|
[:newline, nil, 9, 3],
|
||||||
|
|
||||||
|
[:text, 'b', 6, 4],
|
||||||
|
[:l_paren, nil, 8, 4],
|
||||||
|
[:requirement, '~>', 9, 4],
|
||||||
|
[:text, '3.0', 12, 4],
|
||||||
|
[:comma, nil, 15, 4],
|
||||||
|
[:requirement, '>=', 17, 4],
|
||||||
|
[:text, '3.0.1', 20, 4],
|
||||||
|
[:r_paren, nil, 25, 4],
|
||||||
|
[:newline, nil, 26, 4],
|
||||||
|
]
|
||||||
|
|
||||||
|
assert_equal expected, @lockfile.tokenize
|
||||||
|
end
|
||||||
|
|
||||||
def test_to_s_gem
|
def test_to_s_gem
|
||||||
spec_fetcher do |fetcher|
|
spec_fetcher do |fetcher|
|
||||||
fetcher.spec 'a', 2
|
fetcher.spec 'a', 2
|
||||||
@ -274,6 +557,8 @@ PLATFORMS
|
|||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
a
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
LOCKFILE
|
LOCKFILE
|
||||||
|
|
||||||
assert_equal expected, @lockfile.to_s
|
assert_equal expected, @lockfile.to_s
|
||||||
@ -328,6 +613,7 @@ PLATFORMS
|
|||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
a (>= 1)
|
a (>= 1)
|
||||||
|
b
|
||||||
LOCKFILE
|
LOCKFILE
|
||||||
|
|
||||||
assert_equal expected, @lockfile.to_s
|
assert_equal expected, @lockfile.to_s
|
||||||
@ -346,8 +632,6 @@ PATH
|
|||||||
specs:
|
specs:
|
||||||
#{name} (#{version})
|
#{name} (#{version})
|
||||||
|
|
||||||
GEM
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
#{Gem::Platform::RUBY}
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
@ -371,8 +655,6 @@ PATH
|
|||||||
specs:
|
specs:
|
||||||
#{name} (#{version})
|
#{name} (#{version})
|
||||||
|
|
||||||
GEM
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
#{Gem::Platform::RUBY}
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
@ -408,6 +690,111 @@ DEPENDENCIES
|
|||||||
assert_equal expected, @lockfile.to_s
|
assert_equal expected, @lockfile.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_to_s_gem_source
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.spec 'a', 2
|
||||||
|
fetcher.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
spec_fetcher 'http://other.example/' do |fetcher|
|
||||||
|
fetcher.spec 'b', 2
|
||||||
|
fetcher.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem.sources << 'http://other.example/'
|
||||||
|
|
||||||
|
@set.gem 'a'
|
||||||
|
@set.gem 'b'
|
||||||
|
|
||||||
|
expected = <<-LOCKFILE
|
||||||
|
GEM
|
||||||
|
remote: #{@gem_repo}
|
||||||
|
specs:
|
||||||
|
a (2)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: http://other.example/
|
||||||
|
specs:
|
||||||
|
b (2)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
#{Gem::Platform::RUBY}
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
a
|
||||||
|
b
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
assert_equal expected, @lockfile.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_to_s_git
|
||||||
|
_, _, repository, = git_gem
|
||||||
|
|
||||||
|
head = nil
|
||||||
|
|
||||||
|
Dir.chdir repository do
|
||||||
|
FileUtils.mkdir 'b'
|
||||||
|
|
||||||
|
Dir.chdir 'b' do
|
||||||
|
b = Gem::Specification.new 'b', 1 do |s|
|
||||||
|
s.add_dependency 'a', '~> 1.0'
|
||||||
|
s.add_dependency 'c', '~> 1.0'
|
||||||
|
end
|
||||||
|
|
||||||
|
open 'b.gemspec', 'w' do |io|
|
||||||
|
io.write b.to_ruby
|
||||||
|
end
|
||||||
|
|
||||||
|
system @git, 'add', 'b.gemspec'
|
||||||
|
system @git, 'commit', '--quiet', '-m', 'add b/b.gemspec'
|
||||||
|
end
|
||||||
|
|
||||||
|
FileUtils.mkdir 'c'
|
||||||
|
|
||||||
|
Dir.chdir 'c' do
|
||||||
|
c = Gem::Specification.new 'c', 1
|
||||||
|
|
||||||
|
open 'c.gemspec', 'w' do |io|
|
||||||
|
io.write c.to_ruby
|
||||||
|
end
|
||||||
|
|
||||||
|
system @git, 'add', 'c.gemspec'
|
||||||
|
system @git, 'commit', '--quiet', '-m', 'add c/c.gemspec'
|
||||||
|
end
|
||||||
|
|
||||||
|
head = `#{@git} rev-parse HEAD`.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
@git_set.add_git_gem 'a', repository, 'HEAD', true
|
||||||
|
@git_set.add_git_gem 'b', repository, 'HEAD', true
|
||||||
|
@git_set.add_git_gem 'c', repository, 'HEAD', true
|
||||||
|
|
||||||
|
@set.gem 'b'
|
||||||
|
|
||||||
|
expected = <<-LOCKFILE
|
||||||
|
GIT
|
||||||
|
remote: #{repository}
|
||||||
|
revision: #{head}
|
||||||
|
specs:
|
||||||
|
a (1)
|
||||||
|
b (1)
|
||||||
|
a (~> 1.0)
|
||||||
|
c (~> 1.0)
|
||||||
|
c (1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
a!
|
||||||
|
b!
|
||||||
|
c!
|
||||||
|
LOCKFILE
|
||||||
|
|
||||||
|
assert_equal expected, @lockfile.to_s
|
||||||
|
end
|
||||||
|
|
||||||
def test_unget
|
def test_unget
|
||||||
@lockfile.instance_variable_set :@current_token, :token
|
@lockfile.instance_variable_set :@current_token, :token
|
||||||
|
|
||||||
|
@ -47,6 +47,13 @@ class TestGemRequirement < Gem::TestCase
|
|||||||
def test_for_lockfile
|
def test_for_lockfile
|
||||||
assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile
|
assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile
|
||||||
|
|
||||||
|
assert_equal ' (~> 1.0, >= 1.0.1)', req('>= 1.0.1', '~> 1.0').for_lockfile
|
||||||
|
|
||||||
|
duped = req '= 1.0'
|
||||||
|
duped.requirements << ['=', v('1.0')]
|
||||||
|
|
||||||
|
assert_equal ' (= 1.0)', duped.for_lockfile
|
||||||
|
|
||||||
assert_nil Gem::Requirement.default.for_lockfile
|
assert_nil Gem::Requirement.default.for_lockfile
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -228,14 +228,27 @@ class TestGemResolver < Gem::TestCase
|
|||||||
res = Gem::Resolver.new([ad, bd], s)
|
res = Gem::Resolver.new([ad, bd], s)
|
||||||
|
|
||||||
assert_resolves_to [a1, b1, c1, d4], res
|
assert_resolves_to [a1, b1, c1, d4], res
|
||||||
|
end
|
||||||
|
|
||||||
cons = res.conflicts
|
def test_backoff_higher_version_to_satisfy_dep
|
||||||
|
t3 = util_spec "railties", "3.2"
|
||||||
|
t4 = util_spec "railties", "4.0"
|
||||||
|
|
||||||
assert_equal 1, cons.size
|
r3 = util_spec "rails", "3.2", "railties" => "= 3.2"
|
||||||
con = cons.first
|
r4 = util_spec "rails", "4.0", "railties" => "= 4.0"
|
||||||
|
|
||||||
assert_equal "c (= 1)", con.dependency.to_s
|
rd = make_dep "rails", "3.2"
|
||||||
assert_equal "c-2", con.activated.full_name
|
|
||||||
|
c3 = util_spec "coffee", "3.0", "railties" => "~> 3.0"
|
||||||
|
c4 = util_spec "coffee", "4.0", "railties" => "~> 4.0"
|
||||||
|
|
||||||
|
cd = make_dep "coffee"
|
||||||
|
|
||||||
|
s = set(t3, t4, r3, r4, c3, c4)
|
||||||
|
|
||||||
|
res = Gem::Resolver.new([rd, cd], s)
|
||||||
|
|
||||||
|
assert_resolves_to [r3, t3, c3], res
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_raises_dependency_error
|
def test_raises_dependency_error
|
||||||
|
@ -36,13 +36,31 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||||||
assert @set.need_submodules[repository]
|
assert @set.need_submodules[repository]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_add_git_spec
|
||||||
|
name, version, repository, revision = git_gem
|
||||||
|
|
||||||
|
@set.add_git_spec name, version, repository, revision, true
|
||||||
|
|
||||||
|
dependency = dep 'a'
|
||||||
|
|
||||||
|
specs = @set.find_all dependency
|
||||||
|
|
||||||
|
spec = specs.first
|
||||||
|
|
||||||
|
assert_equal "#{name}-#{version}", spec.full_name
|
||||||
|
|
||||||
|
assert @set.need_submodules[repository]
|
||||||
|
|
||||||
|
refute_path_exists spec.source.repo_cache_dir
|
||||||
|
end
|
||||||
|
|
||||||
def test_find_all
|
def test_find_all
|
||||||
name, _, repository, = git_gem
|
name, _, repository, = git_gem
|
||||||
|
|
||||||
@set.add_git_gem name, repository, 'master', false
|
@set.add_git_gem name, repository, 'master', false
|
||||||
|
|
||||||
dependency = dep 'a', '~> 1.0'
|
dependency = dep 'a', '~> 1.0'
|
||||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
req = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
@reqs.add req
|
@reqs.add req
|
||||||
|
|
||||||
@set.prefetch @reqs
|
@set.prefetch @reqs
|
||||||
@ -66,7 +84,7 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||||||
@set.add_git_gem name, repository, 'master', false
|
@set.add_git_gem name, repository, 'master', false
|
||||||
|
|
||||||
dependency = dep name
|
dependency = dep name
|
||||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
req = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
@reqs.add req
|
@reqs.add req
|
||||||
|
|
||||||
@set.prefetch @reqs
|
@set.prefetch @reqs
|
||||||
@ -80,7 +98,7 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||||||
@set.add_git_gem name, repository, 'master', false
|
@set.add_git_gem name, repository, 'master', false
|
||||||
|
|
||||||
dependency = dep name
|
dependency = dep name
|
||||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
req = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
@reqs.add req
|
@reqs.add req
|
||||||
|
|
||||||
@set.prefetch @reqs
|
@set.prefetch @reqs
|
||||||
@ -98,7 +116,7 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||||||
@set.add_git_gem name, repository, 'master', false
|
@set.add_git_gem name, repository, 'master', false
|
||||||
|
|
||||||
dependency = dep 'b'
|
dependency = dep 'b'
|
||||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
req = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
@reqs.add req
|
@reqs.add req
|
||||||
|
|
||||||
@set.prefetch @reqs
|
@set.prefetch @reqs
|
||||||
@ -112,7 +130,7 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||||||
@set.add_git_gem name, repository, 'master', false
|
@set.add_git_gem name, repository, 'master', false
|
||||||
|
|
||||||
dependency = dep name
|
dependency = dep name
|
||||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
req = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
@reqs.add req
|
@reqs.add req
|
||||||
|
|
||||||
@set.root_dir = "#{@gemhome}2"
|
@set.root_dir = "#{@gemhome}2"
|
||||||
|
@ -80,5 +80,21 @@ class TestGemResolverGitSpecification < Gem::TestCase
|
|||||||
assert_path_exists File.join git_spec.spec.extension_install_dir, 'b.rb'
|
assert_path_exists File.join git_spec.spec.extension_install_dir, 'b.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_install_installed
|
||||||
|
git_gem 'a', 1
|
||||||
|
|
||||||
|
git_spec = Gem::Resolver::GitSpecification.new @set, @spec
|
||||||
|
|
||||||
|
git_spec.install({})
|
||||||
|
|
||||||
|
called = false
|
||||||
|
|
||||||
|
git_spec.install({}) do |installer|
|
||||||
|
called = installer
|
||||||
|
end
|
||||||
|
|
||||||
|
assert called
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@ class TestGemResolverLockSet < Gem::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_add
|
def test_add
|
||||||
@set.add 'a', '2', Gem::Platform::RUBY
|
spec = @set.add 'a', '2', Gem::Platform::RUBY
|
||||||
|
|
||||||
assert_equal %w[a-2], @set.specs.map { |t| t.full_name }
|
assert_equal %w[a-2], @set.specs.map { |t| t.full_name }
|
||||||
|
|
||||||
spec = @set.specs.first
|
assert_kind_of Gem::Resolver::LockSpecification, spec
|
||||||
|
|
||||||
assert_equal @set, spec.set
|
assert_equal @set, spec.set
|
||||||
assert_equal 'a', spec.name
|
assert_equal 'a', spec.name
|
||||||
|
87
test/rubygems/test_gem_resolver_lock_specification.rb
Normal file
87
test/rubygems/test_gem_resolver_lock_specification.rb
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
require 'rubygems/test_case'
|
||||||
|
require 'rubygems/resolver'
|
||||||
|
|
||||||
|
class TestGemResolverLockSpecification < Gem::TestCase
|
||||||
|
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
@LS = Gem::Resolver::LockSpecification
|
||||||
|
|
||||||
|
@source = Gem::Source.new @gem_repo
|
||||||
|
@set = Gem::Resolver::LockSet.new @source
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initialize
|
||||||
|
spec = @LS.new @set, 'a', v(2), @source, Gem::Platform::RUBY
|
||||||
|
|
||||||
|
assert_equal 'a', spec.name
|
||||||
|
assert_equal v(2), spec.version
|
||||||
|
assert_equal Gem::Platform::RUBY, spec.platform
|
||||||
|
|
||||||
|
assert_equal @source, spec.source
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_add_dependency
|
||||||
|
l_spec = @LS.new @set, 'a', v(2), @source, Gem::Platform::RUBY
|
||||||
|
|
||||||
|
b_dep = dep('b', '>= 0')
|
||||||
|
|
||||||
|
l_spec.add_dependency b_dep
|
||||||
|
|
||||||
|
assert_equal [b_dep], l_spec.dependencies
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_install
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.gem 'a', 2
|
||||||
|
fetcher.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
spec = @LS.new @set, 'a', v(2), @source, Gem::Platform::RUBY
|
||||||
|
|
||||||
|
called = false
|
||||||
|
|
||||||
|
spec.install({}) do |installer|
|
||||||
|
called = installer
|
||||||
|
end
|
||||||
|
|
||||||
|
refute_nil called
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_install_installed
|
||||||
|
spec = @LS.new @set, 'a', v(2), @source, Gem::Platform::RUBY
|
||||||
|
|
||||||
|
FileUtils.touch File.join(@gemhome, 'specifications', spec.spec.spec_name)
|
||||||
|
|
||||||
|
called = false
|
||||||
|
|
||||||
|
spec.install({}) do |installer|
|
||||||
|
called = installer
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_nil called
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_spec
|
||||||
|
version = v(2)
|
||||||
|
|
||||||
|
l_spec = @LS.new @set, 'a', version, @source, Gem::Platform::RUBY
|
||||||
|
|
||||||
|
b_dep = dep 'b', '>= 0'
|
||||||
|
c_dep = dep 'c', '~> 1'
|
||||||
|
|
||||||
|
l_spec.add_dependency b_dep
|
||||||
|
l_spec.add_dependency c_dep
|
||||||
|
|
||||||
|
spec = l_spec.spec
|
||||||
|
|
||||||
|
assert_equal 'a', spec.name
|
||||||
|
assert_equal version, spec.version
|
||||||
|
assert_equal Gem::Platform::RUBY, spec.platform
|
||||||
|
|
||||||
|
assert_equal [b_dep, c_dep], l_spec.spec.dependencies
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -9,10 +9,11 @@ class TestGemResolverRequirementList < Gem::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_each
|
def test_each
|
||||||
@list.add 1
|
dep = Gem::Dependency.new "a", "= 1"
|
||||||
@list.add 2
|
req = Gem::Resolver::DependencyRequest.new(dep, nil)
|
||||||
|
@list.add req
|
||||||
|
|
||||||
assert_equal [1, 2], @list.each.to_a
|
assert_equal [req], @list.each.to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -103,5 +103,12 @@ class TestGemSourceLock < Gem::TestCase
|
|||||||
assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock')
|
assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_uri
|
||||||
|
remote = Gem::Source.new @gem_repo
|
||||||
|
lock = Gem::Source::Lock.new remote
|
||||||
|
|
||||||
|
assert_equal URI(@gem_repo), lock.uri
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user