mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/rubygems: Update to RubyGems master 4bdc4f2. Important changes
in this commit: RubyGems now chooses the test server port reliably. Patch by akr. Partial implementation of bundler's Gemfile format. Refactorings to improve the new resolver. Fixes bugs in the resolver. * test/rubygems: Tests for the above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43643 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
31d355aaa9
commit
4f6779bac7
75 changed files with 3143 additions and 616 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
Mon Nov 11 02:51:17 2013 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* lib/rubygems: Update to RubyGems master 4bdc4f2. Important changes
|
||||
in this commit:
|
||||
|
||||
RubyGems now chooses the test server port reliably. Patch by akr.
|
||||
|
||||
Partial implementation of bundler's Gemfile format.
|
||||
|
||||
Refactorings to improve the new resolver.
|
||||
|
||||
Fixes bugs in the resolver.
|
||||
|
||||
* test/rubygems: Tests for the above.
|
||||
|
||||
Mon Nov 11 01:02:06 2013 Zachary Scott <e@zzak.io>
|
||||
|
||||
* lib/timeout.rb: [DOC] Add note about change from #8730 [Fixes GH-440]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
require 'rbconfig'
|
||||
|
||||
module Gem
|
||||
VERSION = '2.2.0'
|
||||
VERSION = '2.2.0.preview.2'
|
||||
end
|
||||
|
||||
# Must be first since it unloads the prelude from 1.9.2
|
||||
|
|
|
@ -196,5 +196,13 @@ class Gem::BasicSpecification
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
##
|
||||
# Whether this specification is stubbed - i.e. we have information
|
||||
# about the gem from a stub line, without having to evaluate the
|
||||
# entire gemspec file.
|
||||
def stubbed?
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ class Gem::Commands::InstallCommand < Gem::Command
|
|||
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
|
||||
:format_executable => false,
|
||||
:version => Gem::Requirement.default,
|
||||
:without_groups => [],
|
||||
})
|
||||
|
||||
super 'install', 'Install a gem into the local repository', defaults
|
||||
|
@ -42,6 +43,13 @@ class Gem::Commands::InstallCommand < Gem::Command
|
|||
o[:gemdeps] = v
|
||||
end
|
||||
|
||||
add_option(:"Install/Update", '--without GROUPS', Array,
|
||||
'Omit the named groups (comma separated)',
|
||||
'when installing from a gem dependencies',
|
||||
'file') do |v,o|
|
||||
o[:without_groups].concat v.map { |without| without.intern }
|
||||
end
|
||||
|
||||
add_option(:"Install/Update", '--default',
|
||||
'Add the gem\'s full specification to',
|
||||
'specifications/default and extract only its bin') do |v,o|
|
||||
|
@ -133,8 +141,8 @@ to write the specification by hand. For example:
|
|||
end
|
||||
|
||||
def execute
|
||||
if gf = options[:gemdeps] then
|
||||
install_from_gemdeps gf
|
||||
if options.include? :gemdeps then
|
||||
install_from_gemdeps
|
||||
return # not reached
|
||||
end
|
||||
|
||||
|
@ -154,14 +162,11 @@ to write the specification by hand. For example:
|
|||
terminate_interaction exit_code
|
||||
end
|
||||
|
||||
def install_from_gemdeps gf # :nodoc:
|
||||
def install_from_gemdeps # :nodoc:
|
||||
require 'rubygems/request_set'
|
||||
rs = Gem::RequestSet.new
|
||||
rs.load_gemdeps gf
|
||||
|
||||
rs.resolve
|
||||
|
||||
specs = rs.install options do |req, inst|
|
||||
specs = rs.install_from_gemdeps options do |req, inst|
|
||||
s = req.full_spec
|
||||
|
||||
if inst
|
||||
|
|
|
@ -112,7 +112,7 @@ command to remove old versions.
|
|||
|
||||
spec_tuples, errors = fetcher.search_for_dependency dependency
|
||||
|
||||
error = errors.find { |errors| errors.respond_to? :exception }
|
||||
error = errors.find { |e| e.respond_to? :exception }
|
||||
|
||||
raise error if error
|
||||
|
||||
|
|
|
@ -250,6 +250,14 @@ class Gem::DependencyInstaller
|
|||
if gem_name =~ /\.gem$/ and File.file? gem_name then
|
||||
src = Gem::Source::SpecificFile.new(gem_name)
|
||||
set.add src.spec, src
|
||||
elsif gem_name =~ /\.gem$/ then
|
||||
Dir[gem_name].each do |name|
|
||||
begin
|
||||
src = Gem::Source::SpecificFile.new name
|
||||
set.add src.spec, src
|
||||
rescue Gem::Package::FormatError
|
||||
end
|
||||
end
|
||||
else
|
||||
local = Gem::Source::Local.new
|
||||
|
||||
|
|
|
@ -30,7 +30,16 @@ class Gem::DependencyResolver
|
|||
attr_accessor :soft_missing
|
||||
|
||||
def self.compose_sets *sets
|
||||
Gem::DependencyResolver::ComposedSet.new(*sets)
|
||||
sets.compact!
|
||||
|
||||
case sets.length
|
||||
when 0 then
|
||||
raise ArgumentError, 'one set in the composition must be non-nil'
|
||||
when 1 then
|
||||
sets.first
|
||||
else
|
||||
Gem::DependencyResolver::ComposedSet.new(*sets)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -53,12 +62,27 @@ class Gem::DependencyResolver
|
|||
@set = set || Gem::DependencyResolver::IndexSet.new
|
||||
@needed = needed
|
||||
|
||||
@conflicts = nil
|
||||
@conflicts = []
|
||||
@development = false
|
||||
@missing = []
|
||||
@soft_missing = false
|
||||
end
|
||||
|
||||
##
|
||||
# Creates an ActivationRequest for the given +dep+ and the last +possible+
|
||||
# specification.
|
||||
#
|
||||
# Returns the Specification and the ActivationRequest
|
||||
|
||||
def activation_request dep, possible # :nodoc:
|
||||
spec = possible.pop
|
||||
|
||||
activation_request =
|
||||
Gem::DependencyResolver::ActivationRequest.new spec, dep, possible
|
||||
|
||||
return spec, activation_request
|
||||
end
|
||||
|
||||
def requests s, act, reqs=nil
|
||||
s.dependencies.reverse_each do |d|
|
||||
next if d.type == :development and not @development
|
||||
|
@ -95,27 +119,38 @@ class Gem::DependencyResolver
|
|||
##
|
||||
# Finds the State in +states+ that matches the +conflict+ so that we can try
|
||||
# other possible sets.
|
||||
#
|
||||
# If no good candidate is found, the first state is tried.
|
||||
|
||||
def find_conflict_state conflict, states # :nodoc:
|
||||
rejected = []
|
||||
|
||||
until states.empty? do
|
||||
if conflict.for_spec? states.last.spec
|
||||
state = states.last
|
||||
state = states.pop
|
||||
|
||||
if conflict.for_spec? state.spec
|
||||
state.conflicts << [state.spec, conflict]
|
||||
return state
|
||||
else
|
||||
states.pop
|
||||
end
|
||||
|
||||
rejected << state
|
||||
end
|
||||
|
||||
nil
|
||||
return rejected.shift
|
||||
ensure
|
||||
rejected = rejected.concat states
|
||||
states.replace rejected
|
||||
end
|
||||
|
||||
##
|
||||
# Extracts the specifications that may be able to fulfill +dependency+
|
||||
# Extracts the specifications that may be able to fulfill +dependency+ and
|
||||
# returns those that match the local platform and all those that match.
|
||||
|
||||
def find_possible dependency # :nodoc:
|
||||
possible = @set.find_all dependency
|
||||
select_local_platforms possible
|
||||
all = @set.find_all dependency
|
||||
matching_platform = select_local_platforms all
|
||||
|
||||
return matching_platform, all
|
||||
end
|
||||
|
||||
def handle_conflict(dep, existing)
|
||||
|
@ -134,7 +169,7 @@ class Gem::DependencyResolver
|
|||
Gem::DependencyResolver::DependencyConflict.new depreq, existing, dep
|
||||
end
|
||||
|
||||
@conflicts << conflict
|
||||
@conflicts << conflict unless @conflicts.include? conflict
|
||||
|
||||
return conflict
|
||||
end
|
||||
|
@ -150,7 +185,29 @@ class Gem::DependencyResolver
|
|||
# +conflicts+ is a [DependencyRequest, DependencyConflict] hit tried to
|
||||
# activate the state.
|
||||
#
|
||||
State = Struct.new(:needed, :specs, :dep, :spec, :possibles, :conflicts)
|
||||
State = Struct.new(:needed, :specs, :dep, :spec, :possibles, :conflicts) do
|
||||
def summary # :nodoc:
|
||||
nd = needed.map { |s| s.to_s }.sort if nd
|
||||
|
||||
if specs then
|
||||
ss = specs.map { |s| s.full_name }.sort
|
||||
ss.unshift ss.length
|
||||
end
|
||||
|
||||
d = dep.to_s
|
||||
d << " from #{dep.requester.full_name}" if dep.requester
|
||||
|
||||
ps = possibles.map { |p| p.full_name }.sort
|
||||
ps.unshift ps.length
|
||||
|
||||
cs = conflicts.map do |(s, c)|
|
||||
[s.full_name, c.conflicting_dependencies.map { |cd| cd.to_s }]
|
||||
end
|
||||
|
||||
{ :needed => nd, :specs => ss, :dep => d, :spec => spec.full_name,
|
||||
:possibles => ps, :conflicts => cs }
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# The meat of the algorithm. Given +needed+ DependencyRequest objects and
|
||||
|
@ -178,20 +235,22 @@ class Gem::DependencyResolver
|
|||
|
||||
needed, specs = resolve_for_conflict needed, specs, state
|
||||
|
||||
states << state unless state.possibles.empty?
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
possible = find_possible dep
|
||||
matching, all = find_possible dep
|
||||
|
||||
case possible.size
|
||||
case matching.size
|
||||
when 0
|
||||
resolve_for_zero dep
|
||||
resolve_for_zero dep, all
|
||||
when 1
|
||||
needed, specs =
|
||||
resolve_for_single needed, specs, dep, possible
|
||||
resolve_for_single needed, specs, dep, matching
|
||||
else
|
||||
needed, specs =
|
||||
resolve_for_multiple needed, specs, states, dep, possible
|
||||
resolve_for_multiple needed, specs, states, dep, matching
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -208,10 +267,8 @@ class Gem::DependencyResolver
|
|||
raise Gem::ImpossibleDependenciesError.new state.dep, state.conflicts if
|
||||
state.possibles.empty?
|
||||
|
||||
spec = state.possibles.pop
|
||||
|
||||
# Retry resolution with this spec and add it's dependencies
|
||||
act = Gem::DependencyResolver::ActivationRequest.new spec, state.dep
|
||||
spec, act = activation_request state.dep, state.possibles
|
||||
|
||||
needed = requests spec, act, state.needed
|
||||
specs = Gem::List.prepend state.specs, act
|
||||
|
@ -230,19 +287,11 @@ class Gem::DependencyResolver
|
|||
[s.source, s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
|
||||
end
|
||||
|
||||
# To figure out which to pick, we keep resolving given each one being
|
||||
# activated and if there isn't a conflict, we know we've found a full set.
|
||||
#
|
||||
# We use an until loop rather than reverse_each to keep the stack short
|
||||
# since we're using a recursive algorithm.
|
||||
spec = possible.pop
|
||||
spec, act = activation_request dep, possible
|
||||
|
||||
# We may need to try all of +possible+, so we setup state to unwind back
|
||||
# to current +needed+ and +specs+ so we can try another. This is code is
|
||||
# what makes conflict resolution possible.
|
||||
|
||||
act = Gem::DependencyResolver::ActivationRequest.new spec, dep
|
||||
|
||||
states << State.new(needed, specs, dep, spec, possible, [])
|
||||
|
||||
needed = requests spec, act, needed
|
||||
|
@ -256,8 +305,7 @@ class Gem::DependencyResolver
|
|||
# dependencies by adding them to +needed+.
|
||||
|
||||
def resolve_for_single needed, specs, dep, possible # :nodoc:
|
||||
spec = possible.first
|
||||
act = Gem::DependencyResolver::ActivationRequest.new spec, dep, false
|
||||
spec, act = activation_request dep, possible
|
||||
|
||||
specs = Gem::List.prepend specs, act
|
||||
|
||||
|
@ -274,11 +322,11 @@ class Gem::DependencyResolver
|
|||
##
|
||||
# When there are no possible specifications for +dep+ our work is done.
|
||||
|
||||
def resolve_for_zero dep # :nodoc:
|
||||
def resolve_for_zero dep, platform_mismatch # :nodoc:
|
||||
@missing << dep
|
||||
|
||||
unless @soft_missing
|
||||
raise Gem::UnsatisfiableDependencyError, dep
|
||||
raise Gem::UnsatisfiableDependencyError.new(dep, platform_mismatch)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -287,23 +335,30 @@ class Gem::DependencyResolver
|
|||
|
||||
def select_local_platforms specs # :nodoc:
|
||||
specs.select do |spec|
|
||||
Gem::Platform.match spec.platform
|
||||
Gem::Platform.installable? spec
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
require 'rubygems/dependency_resolver/api_set'
|
||||
require 'rubygems/dependency_resolver/api_specification'
|
||||
require 'rubygems/dependency_resolver/activation_request'
|
||||
require 'rubygems/dependency_resolver/composed_set'
|
||||
require 'rubygems/dependency_resolver/current_set'
|
||||
require 'rubygems/dependency_resolver/dependency_conflict'
|
||||
require 'rubygems/dependency_resolver/dependency_request'
|
||||
|
||||
require 'rubygems/dependency_resolver/set'
|
||||
require 'rubygems/dependency_resolver/api_set'
|
||||
require 'rubygems/dependency_resolver/composed_set'
|
||||
require 'rubygems/dependency_resolver/best_set'
|
||||
require 'rubygems/dependency_resolver/current_set'
|
||||
require 'rubygems/dependency_resolver/index_set'
|
||||
require 'rubygems/dependency_resolver/installer_set'
|
||||
require 'rubygems/dependency_resolver/lock_set'
|
||||
require 'rubygems/dependency_resolver/vendor_set'
|
||||
|
||||
require 'rubygems/dependency_resolver/specification'
|
||||
require 'rubygems/dependency_resolver/spec_specification'
|
||||
require 'rubygems/dependency_resolver/api_specification'
|
||||
require 'rubygems/dependency_resolver/index_specification'
|
||||
require 'rubygems/dependency_resolver/installed_specification'
|
||||
require 'rubygems/dependency_resolver/installer_set'
|
||||
require 'rubygems/dependency_resolver/vendor_set'
|
||||
require 'rubygems/dependency_resolver/vendor_specification'
|
||||
|
||||
|
|
|
@ -47,11 +47,21 @@ class Gem::DependencyResolver::ActivationRequest
|
|||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
others_possible = nil
|
||||
others_possible = ' (others possible)' if @others_possible
|
||||
others =
|
||||
case @others_possible
|
||||
when true then # TODO remove at RubyGems 3
|
||||
' (others possible)'
|
||||
when false then # TODO remove at RubyGems 3
|
||||
nil
|
||||
else
|
||||
unless @others_possible.empty? then
|
||||
others = @others_possible.map { |s| s.full_name }
|
||||
" (others possible: #{others.join ', '})"
|
||||
end
|
||||
end
|
||||
|
||||
'#<%s for %p from %s%s>' % [
|
||||
self.class, @spec, @request, others_possible
|
||||
self.class, @spec, @request, others
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -59,10 +69,15 @@ class Gem::DependencyResolver::ActivationRequest
|
|||
# Indicates if the requested gem has already been installed.
|
||||
|
||||
def installed?
|
||||
this_spec = full_spec
|
||||
case @spec
|
||||
when Gem::DependencyResolver::VendorSpecification then
|
||||
true
|
||||
else
|
||||
this_spec = full_spec
|
||||
|
||||
Gem::Specification.any? do |s|
|
||||
s == this_spec
|
||||
Gem::Specification.any? do |s|
|
||||
s == this_spec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,7 +90,12 @@ class Gem::DependencyResolver::ActivationRequest
|
|||
# requests for the same Dependency request.
|
||||
|
||||
def others_possible?
|
||||
@others_possible
|
||||
case @others_possible
|
||||
when true, false then
|
||||
@others_possible
|
||||
else
|
||||
not @others_possible.empty?
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -95,9 +115,18 @@ class Gem::DependencyResolver::ActivationRequest
|
|||
q.text ' for '
|
||||
q.pp @request
|
||||
|
||||
|
||||
q.breakable
|
||||
q.text ' (other possible)' if @others_possible
|
||||
case @others_possible
|
||||
when false then
|
||||
when true then
|
||||
q.breakable
|
||||
q.text 'others possible'
|
||||
else
|
||||
unless @others_possible.empty? then
|
||||
q.breakable
|
||||
q.text 'others '
|
||||
q.pp @others_possible.map { |s| s.full_name }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,11 +2,21 @@
|
|||
# The global rubygems pool, available via the rubygems.org API.
|
||||
# Returns instances of APISpecification.
|
||||
|
||||
class Gem::DependencyResolver::APISet
|
||||
class Gem::DependencyResolver::APISet < Gem::DependencyResolver::Set
|
||||
|
||||
def initialize
|
||||
##
|
||||
# The URI for the dependency API this APISet uses.
|
||||
|
||||
attr_reader :dep_uri # :nodoc:
|
||||
|
||||
##
|
||||
# Creates a new APISet that will retrieve gems from +uri+ using the RubyGems
|
||||
# API described at http://guides.rubygems.org/rubygems-org-api
|
||||
|
||||
def initialize uri = 'https://rubygems.org/api/v1/dependencies'
|
||||
uri = URI uri unless URI === uri # for ruby 1.8
|
||||
@data = Hash.new { |h,k| h[k] = [] }
|
||||
@dep_uri = URI 'https://rubygems.org/api/v1/dependencies'
|
||||
@dep_uri = uri
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -46,7 +56,7 @@ class Gem::DependencyResolver::APISet
|
|||
##
|
||||
# Return data for all versions of the gem +name+.
|
||||
|
||||
def versions name
|
||||
def versions name # :nodoc:
|
||||
if @data.key?(name)
|
||||
return @data[name]
|
||||
end
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
##
|
||||
# Represents a specification retrieved via the rubygems.org
|
||||
# API. This is used to avoid having to load the full
|
||||
# Specification object when all we need is the name, version,
|
||||
# and dependencies.
|
||||
# Represents a specification retrieved via the rubygems.org API.
|
||||
#
|
||||
# This is used to avoid loading the full Specification object when all we need
|
||||
# is the name, version, and dependencies.
|
||||
|
||||
class Gem::DependencyResolver::APISpecification
|
||||
class Gem::DependencyResolver::APISpecification < Gem::DependencyResolver::Specification
|
||||
|
||||
attr_reader :dependencies
|
||||
attr_reader :name
|
||||
attr_reader :platform
|
||||
attr_reader :set # :nodoc:
|
||||
attr_reader :version
|
||||
##
|
||||
# Creates an APISpecification for the given +set+ from the rubygems.org
|
||||
# +api_data+.
|
||||
#
|
||||
# See http://guides.rubygems.org/rubygems-org-api/#misc_methods for the
|
||||
# format of the +api_data+.
|
||||
|
||||
def initialize(set, api_data)
|
||||
super()
|
||||
|
||||
@set = set
|
||||
@name = api_data[:name]
|
||||
@version = Gem::Version.new api_data[:number]
|
||||
|
@ -31,9 +34,5 @@ class Gem::DependencyResolver::APISpecification
|
|||
@dependencies == other.dependencies
|
||||
end
|
||||
|
||||
def full_name
|
||||
"#{@name}-#{@version}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
21
lib/rubygems/dependency_resolver/best_set.rb
Normal file
21
lib/rubygems/dependency_resolver/best_set.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
##
|
||||
# The BestSet chooses the best available method to query a remote index.
|
||||
#
|
||||
# It combines IndexSet and APISet
|
||||
|
||||
class Gem::DependencyResolver::BestSet < Gem::DependencyResolver::ComposedSet
|
||||
|
||||
##
|
||||
# Creates a BestSet for the given +sources+ or Gem::sources if none are
|
||||
# specified. +sources+ must be a Gem::SourceList.
|
||||
|
||||
def initialize sources = Gem.sources
|
||||
super()
|
||||
|
||||
sources.each_source do |source|
|
||||
@sets << source.dependency_resolver_set
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
class Gem::DependencyResolver::ComposedSet
|
||||
class Gem::DependencyResolver::ComposedSet < Gem::DependencyResolver::Set
|
||||
|
||||
attr_reader :sets # :nodoc:
|
||||
|
||||
def initialize *sets
|
||||
@sets = sets
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
# all the normal settings that control where to look
|
||||
# for installed gems.
|
||||
|
||||
class Gem::DependencyResolver::CurrentSet
|
||||
class Gem::DependencyResolver::CurrentSet < Gem::DependencyResolver::Set
|
||||
|
||||
def find_all req
|
||||
req.dependency.matching_specs
|
||||
end
|
||||
|
||||
def prefetch gems
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -8,12 +8,21 @@ class Gem::DependencyResolver::DependencyConflict
|
|||
|
||||
attr_reader :dependency
|
||||
|
||||
attr_reader :failed_dep # :nodoc:
|
||||
|
||||
def initialize(dependency, activated, failed_dep=dependency)
|
||||
@dependency = dependency
|
||||
@activated = activated
|
||||
@failed_dep = failed_dep
|
||||
end
|
||||
|
||||
def == other
|
||||
self.class === other and
|
||||
@dependency == other.dependency and
|
||||
@activated == other.activated and
|
||||
@failed_dep == other.failed_dep
|
||||
end
|
||||
|
||||
##
|
||||
# Return the 2 dependency objects that conflicted
|
||||
|
||||
|
@ -71,6 +80,8 @@ class Gem::DependencyResolver::DependencyConflict
|
|||
current = current.request.requester
|
||||
end
|
||||
|
||||
path = ['user request (gem command or Gemfile)'] if path.empty?
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
|
|
|
@ -32,6 +32,22 @@ class Gem::DependencyResolver::DependencyRequest
|
|||
@dependency.name
|
||||
end
|
||||
|
||||
# Indicate that the request is for a gem explicitly requested by the user
|
||||
def explicit?
|
||||
@requester.nil?
|
||||
end
|
||||
|
||||
# Indicate that the requset is for a gem requested as a dependency of another gem
|
||||
def implicit?
|
||||
!explicit?
|
||||
end
|
||||
|
||||
# Return a String indicating who caused this request to be added (only
|
||||
# valid for implicit requests)
|
||||
def request_context
|
||||
@requester ? @requester.request : "(unknown)"
|
||||
end
|
||||
|
||||
def pretty_print q # :nodoc:
|
||||
q.group 2, '[Dependency request ', ']' do
|
||||
q.breakable
|
||||
|
@ -43,6 +59,10 @@ class Gem::DependencyResolver::DependencyRequest
|
|||
end
|
||||
end
|
||||
|
||||
def requirement
|
||||
@dependency.requirement
|
||||
end
|
||||
|
||||
def to_s # :nodoc:
|
||||
@dependency.to_s
|
||||
end
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
# The global rubygems pool represented via the traditional
|
||||
# source index.
|
||||
|
||||
class Gem::DependencyResolver::IndexSet
|
||||
class Gem::DependencyResolver::IndexSet < Gem::DependencyResolver::Set
|
||||
|
||||
def initialize
|
||||
@f = Gem::SpecFetcher.fetcher
|
||||
def initialize source = nil # :nodoc:
|
||||
@f =
|
||||
if source then
|
||||
sources = Gem::SourceList.from [source]
|
||||
|
||||
Gem::SpecFetcher.new sources
|
||||
else
|
||||
Gem::SpecFetcher.fetcher
|
||||
end
|
||||
|
||||
@all = Hash.new { |h,k| h[k] = [] }
|
||||
|
||||
|
@ -39,26 +46,5 @@ class Gem::DependencyResolver::IndexSet
|
|||
res
|
||||
end
|
||||
|
||||
##
|
||||
# Called from IndexSpecification to get a true Specification
|
||||
# object.
|
||||
|
||||
def load_spec name, ver, platform, source
|
||||
key = "#{name}-#{ver}-#{platform}"
|
||||
|
||||
@specs.fetch key do
|
||||
tuple = Gem::NameTuple.new name, ver, platform
|
||||
|
||||
@specs[key] = source.fetch_spec tuple
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# No prefetching needed since we load the whole index in
|
||||
# initially.
|
||||
|
||||
def prefetch gems
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -3,17 +3,20 @@
|
|||
# delay needed to download full Specification objects when only the +name+
|
||||
# and +version+ are needed.
|
||||
|
||||
class Gem::DependencyResolver::IndexSpecification
|
||||
class Gem::DependencyResolver::IndexSpecification < Gem::DependencyResolver::Specification
|
||||
|
||||
attr_reader :name
|
||||
|
||||
attr_reader :platform
|
||||
|
||||
attr_reader :source
|
||||
|
||||
attr_reader :version
|
||||
##
|
||||
# An IndexSpecification is created from the index format described in `gem
|
||||
# help generate_index`.
|
||||
#
|
||||
# The +set+ contains other specifications for this (URL) +source+.
|
||||
#
|
||||
# The +name+, +version+ and +platform+ are the name, version and platform of
|
||||
# the gem.
|
||||
|
||||
def initialize set, name, version, source, platform
|
||||
super()
|
||||
|
||||
@set = set
|
||||
@name = name
|
||||
@version = version
|
||||
|
@ -23,14 +26,13 @@ class Gem::DependencyResolver::IndexSpecification
|
|||
@spec = nil
|
||||
end
|
||||
|
||||
##
|
||||
# The dependencies of the gem for this specification
|
||||
|
||||
def dependencies
|
||||
spec.dependencies
|
||||
end
|
||||
|
||||
def full_name
|
||||
"#{@name}-#{@version}"
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
'#<%s %s source %s>' % [self.class, full_name, @source]
|
||||
end
|
||||
|
@ -51,8 +53,16 @@ class Gem::DependencyResolver::IndexSpecification
|
|||
end
|
||||
end
|
||||
|
||||
def spec
|
||||
@spec ||= @set.load_spec(@name, @version, @platform, @source)
|
||||
##
|
||||
# Fetches a Gem::Specification for this IndexSpecification from the #source.
|
||||
|
||||
def spec # :nodoc:
|
||||
@spec ||=
|
||||
begin
|
||||
tuple = Gem::NameTuple.new @name, @version, @platform
|
||||
|
||||
@source.fetch_spec tuple
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
class Gem::DependencyResolver::InstalledSpecification
|
||||
##
|
||||
# An InstalledSpecification represents a gem that is already installed
|
||||
# locally.
|
||||
|
||||
attr_reader :spec
|
||||
|
||||
def initialize set, spec, source=nil
|
||||
@set = set
|
||||
@source = source
|
||||
@spec = spec
|
||||
end
|
||||
class Gem::DependencyResolver::InstalledSpecification < Gem::DependencyResolver::SpecSpecification
|
||||
|
||||
def == other # :nodoc:
|
||||
self.class === other and
|
||||
|
@ -14,29 +10,25 @@ class Gem::DependencyResolver::InstalledSpecification
|
|||
@spec == other.spec
|
||||
end
|
||||
|
||||
def dependencies
|
||||
@spec.dependencies
|
||||
##
|
||||
# Returns +true+ if this gem is installable for the current platform.
|
||||
|
||||
def installable_platform?
|
||||
# BACKCOMPAT If the file is coming out of a specified file, then we
|
||||
# ignore the platform. This code can be removed in RG 3.0.
|
||||
if @source.kind_of? Gem::Source::SpecificFile
|
||||
return true
|
||||
else
|
||||
Gem::Platform.match @spec.platform
|
||||
end
|
||||
end
|
||||
|
||||
def full_name
|
||||
"#{@spec.name}-#{@spec.version}"
|
||||
end
|
||||
|
||||
def name
|
||||
@spec.name
|
||||
end
|
||||
|
||||
def platform
|
||||
@spec.platform
|
||||
end
|
||||
##
|
||||
# The source for this specification
|
||||
|
||||
def source
|
||||
@source ||= Gem::Source::Installed.new
|
||||
end
|
||||
|
||||
def version
|
||||
@spec.version
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -2,23 +2,23 @@
|
|||
# A set of gems for installation sourced from remote sources and local .gem
|
||||
# files
|
||||
|
||||
class Gem::DependencyResolver::InstallerSet
|
||||
class Gem::DependencyResolver::InstallerSet < Gem::DependencyResolver::Set
|
||||
|
||||
##
|
||||
# List of Gem::Specification objects that must always be installed.
|
||||
|
||||
attr_reader :always_install
|
||||
attr_reader :always_install # :nodoc:
|
||||
|
||||
##
|
||||
# Only install gems in the always_install list
|
||||
|
||||
attr_accessor :ignore_dependencies
|
||||
attr_accessor :ignore_dependencies # :nodoc:
|
||||
|
||||
##
|
||||
# Do not look in the installed set when finding specifications. This is
|
||||
# used by the --install-dir option to `gem install`
|
||||
|
||||
attr_accessor :ignore_installed
|
||||
attr_accessor :ignore_installed # :nodoc:
|
||||
|
||||
def initialize domain
|
||||
@domain = domain
|
||||
|
@ -36,14 +36,14 @@ class Gem::DependencyResolver::InstallerSet
|
|||
##
|
||||
# Should local gems should be considered?
|
||||
|
||||
def consider_local?
|
||||
def consider_local? # :nodoc:
|
||||
@domain == :both or @domain == :local
|
||||
end
|
||||
|
||||
##
|
||||
# Should remote gems should be considered?
|
||||
|
||||
def consider_remote?
|
||||
def consider_remote? # :nodoc:
|
||||
@domain == :both or @domain == :remote
|
||||
end
|
||||
|
||||
|
@ -101,7 +101,7 @@ class Gem::DependencyResolver::InstallerSet
|
|||
##
|
||||
# Loads remote prerelease specs if +dep+ is a prerelease dependency
|
||||
|
||||
def load_remote_specs dep
|
||||
def load_remote_specs dep # :nodoc:
|
||||
types = [:released]
|
||||
types << :prerelease if dep.prerelease?
|
||||
|
||||
|
@ -123,7 +123,7 @@ class Gem::DependencyResolver::InstallerSet
|
|||
# Called from IndexSpecification to get a true Specification
|
||||
# object.
|
||||
|
||||
def load_spec name, ver, platform, source
|
||||
def load_spec name, ver, platform, source # :nodoc:
|
||||
key = "#{name}-#{ver}-#{platform}"
|
||||
|
||||
@specs.fetch key do
|
||||
|
@ -133,12 +133,6 @@ class Gem::DependencyResolver::InstallerSet
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# No prefetching needed since we load the whole index in initially.
|
||||
|
||||
def prefetch(reqs)
|
||||
end
|
||||
|
||||
def pretty_print q # :nodoc:
|
||||
q.group 2, '[InstallerSet', ']' do
|
||||
q.breakable
|
||||
|
|
60
lib/rubygems/dependency_resolver/lock_set.rb
Normal file
60
lib/rubygems/dependency_resolver/lock_set.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
##
|
||||
# A set of gems from a gem dependencies lockfile.
|
||||
|
||||
class Gem::DependencyResolver::LockSet < Gem::DependencyResolver::Set
|
||||
|
||||
attr_reader :specs # :nodoc:
|
||||
|
||||
##
|
||||
# Creates a new LockSet from the given +source+
|
||||
|
||||
def initialize source
|
||||
@source = source
|
||||
@specs = []
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new IndexSpecification in this set using the given +name+,
|
||||
# +version+ and +platform+.
|
||||
#
|
||||
# The specification's set will be the current set, and the source will be
|
||||
# the current set's source.
|
||||
|
||||
def add name, version, platform # :nodoc:
|
||||
version = Gem::Version.new version
|
||||
|
||||
spec =
|
||||
Gem::DependencyResolver::IndexSpecification.new self, name, version,
|
||||
@source, platform
|
||||
|
||||
@specs << spec
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an Array of IndexSpecification objects matching the
|
||||
# DependencyRequest +req+.
|
||||
|
||||
def find_all req
|
||||
@specs.select do |spec|
|
||||
req.matches_spec? spec
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Loads a Gem::Specification with the given +name+, +version+ and
|
||||
# +platform+. +source+ is ignored.
|
||||
|
||||
def load_spec name, version, platform, source # :nodoc:
|
||||
dep = Gem::Dependency.new name, version
|
||||
|
||||
found = @specs.find do |spec|
|
||||
dep.matches_spec? spec and spec.platform == platform
|
||||
end
|
||||
|
||||
tuple = Gem::NameTuple.new found.name, found.version, found.platform
|
||||
|
||||
found.source.fetch_spec tuple
|
||||
end
|
||||
|
||||
end
|
||||
|
28
lib/rubygems/dependency_resolver/set.rb
Normal file
28
lib/rubygems/dependency_resolver/set.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
##
|
||||
# DependencyResolver sets are used to look up specifications (and their
|
||||
# dependencies) used in resolution. This set is abstract.
|
||||
|
||||
class Gem::DependencyResolver::Set
|
||||
|
||||
##
|
||||
# The find_all method must be implemented. It returns all
|
||||
# DependencyResolver Specification objects matching the given
|
||||
# DependencyRequest +req+.
|
||||
|
||||
def find_all req
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
##
|
||||
# The #prefetch method may be overridden, but this is not necessary. This
|
||||
# default implementation does nothing, which is suitable for sets where
|
||||
# looking up a specification is cheap (such as installed gems).
|
||||
#
|
||||
# When overridden, the #prefetch method should look up specifications
|
||||
# matching +reqs+.
|
||||
|
||||
def prefetch reqs
|
||||
end
|
||||
|
||||
end
|
||||
|
58
lib/rubygems/dependency_resolver/spec_specification.rb
Normal file
58
lib/rubygems/dependency_resolver/spec_specification.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
##
|
||||
# The DependencyResolver::SpecSpecification contains common functionality for
|
||||
# DependencyResolver specifications that are backed by a Gem::Specification.
|
||||
|
||||
class Gem::DependencyResolver::SpecSpecification < Gem::DependencyResolver::Specification
|
||||
|
||||
attr_reader :spec # :nodoc:
|
||||
|
||||
##
|
||||
# A SpecSpecification is created for a +set+ for a Gem::Specification in
|
||||
# +spec+. The +source+ is either where the +spec+ came from, or should be
|
||||
# loaded from.
|
||||
|
||||
def initialize set, spec, source = nil
|
||||
@set = set
|
||||
@source = source
|
||||
@spec = spec
|
||||
end
|
||||
|
||||
##
|
||||
# The dependencies of the gem for this specification
|
||||
|
||||
def dependencies
|
||||
spec.dependencies
|
||||
end
|
||||
|
||||
##
|
||||
# The name and version of the specification.
|
||||
#
|
||||
# Unlike Gem::Specification#full_name, the platform is not included.
|
||||
|
||||
def full_name
|
||||
"#{spec.name}-#{spec.version}"
|
||||
end
|
||||
|
||||
##
|
||||
# The name of the gem for this specification
|
||||
|
||||
def name
|
||||
spec.name
|
||||
end
|
||||
|
||||
##
|
||||
# The platform this gem works on.
|
||||
|
||||
def platform
|
||||
spec.platform
|
||||
end
|
||||
|
||||
##
|
||||
# The version of the gem for this specification.
|
||||
|
||||
def version
|
||||
spec.version
|
||||
end
|
||||
|
||||
end
|
||||
|
60
lib/rubygems/dependency_resolver/specification.rb
Normal file
60
lib/rubygems/dependency_resolver/specification.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
##
|
||||
# A DependencyResolver::Specification contains a subset of the information
|
||||
# contained in a Gem::Specification. Only the information necessary for
|
||||
# dependency resolution in the resolver is included.
|
||||
|
||||
class Gem::DependencyResolver::Specification
|
||||
|
||||
##
|
||||
# The dependencies of the gem for this specification
|
||||
|
||||
attr_reader :dependencies
|
||||
|
||||
##
|
||||
# The name of the gem for this specification
|
||||
|
||||
attr_reader :name
|
||||
|
||||
##
|
||||
# The platform this gem works on.
|
||||
|
||||
attr_reader :platform
|
||||
|
||||
##
|
||||
# The set this specification came from.
|
||||
|
||||
attr_reader :set
|
||||
|
||||
##
|
||||
# The source for this specification
|
||||
|
||||
attr_reader :source
|
||||
|
||||
##
|
||||
# The version of the gem for this specification.
|
||||
|
||||
attr_reader :version
|
||||
|
||||
##
|
||||
# Sets default instance variables for the specification.
|
||||
|
||||
def initialize
|
||||
@dependencies = nil
|
||||
@name = nil
|
||||
@platform = nil
|
||||
@set = nil
|
||||
@source = nil
|
||||
@version = nil
|
||||
end
|
||||
|
||||
##
|
||||
# The name and version of the specification.
|
||||
#
|
||||
# Unlike Gem::Specification#full_name, the platform is not included.
|
||||
|
||||
def full_name
|
||||
"#{@name}-#{@version}"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -13,17 +13,18 @@
|
|||
# The directory vendor/rake must contain an unpacked rake gem along with a
|
||||
# rake.gemspec (watching the given name).
|
||||
|
||||
class Gem::DependencyResolver::VendorSet
|
||||
class Gem::DependencyResolver::VendorSet < Gem::DependencyResolver::Set
|
||||
|
||||
def initialize
|
||||
@specs = {}
|
||||
def initialize # :nodoc:
|
||||
@directories = {}
|
||||
@specs = {}
|
||||
end
|
||||
|
||||
##
|
||||
# Adds a specification to the set with the given +name+ which has been
|
||||
# unpacked into the given +directory+.
|
||||
|
||||
def add_vendor_gem name, directory
|
||||
def add_vendor_gem name, directory # :nodoc:
|
||||
gemspec = File.join directory, "#{name}.gemspec"
|
||||
|
||||
spec = Gem::Specification.load gemspec
|
||||
|
@ -33,7 +34,8 @@ class Gem::DependencyResolver::VendorSet
|
|||
|
||||
key = "#{spec.name}-#{spec.version}-#{spec.platform}"
|
||||
|
||||
@specs[key] = spec
|
||||
@specs[key] = spec
|
||||
@directories[spec] = directory
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -44,7 +46,8 @@ class Gem::DependencyResolver::VendorSet
|
|||
@specs.values.select do |spec|
|
||||
req.matches_spec? spec
|
||||
end.map do |spec|
|
||||
Gem::DependencyResolver::VendorSpecification.new self, spec, nil
|
||||
source = Gem::Source::Vendor.new @directories[spec]
|
||||
Gem::DependencyResolver::VendorSpecification.new self, spec, source
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,17 +56,11 @@ class Gem::DependencyResolver::VendorSet
|
|||
# +source+ is defined when the specification was added to index it is not
|
||||
# used.
|
||||
|
||||
def load_spec name, version, platform, source
|
||||
def load_spec name, version, platform, source # :nodoc:
|
||||
key = "#{name}-#{version}-#{platform}"
|
||||
|
||||
@specs.fetch key
|
||||
end
|
||||
|
||||
##
|
||||
# No prefetch is needed as the index is loaded at creation time.
|
||||
|
||||
def prefetch gems
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,43 +1,15 @@
|
|||
class Gem::DependencyResolver::VendorSpecification
|
||||
##
|
||||
# A VendorSpecification represents a gem that has been unpacked into a project
|
||||
# and is being loaded through a gem dependencies file through the +path:+
|
||||
# option.
|
||||
|
||||
attr_reader :spec
|
||||
|
||||
attr_reader :set
|
||||
|
||||
def initialize set, spec, source=nil
|
||||
@set = set
|
||||
@source = source
|
||||
@spec = spec
|
||||
end
|
||||
class Gem::DependencyResolver::VendorSpecification < Gem::DependencyResolver::SpecSpecification
|
||||
|
||||
def == other # :nodoc:
|
||||
self.class === other and
|
||||
@set == other.set and
|
||||
@spec == other.spec
|
||||
end
|
||||
|
||||
def dependencies
|
||||
@spec.dependencies
|
||||
end
|
||||
|
||||
def full_name
|
||||
"#{@spec.name}-#{@spec.version}"
|
||||
end
|
||||
|
||||
def name
|
||||
@spec.name
|
||||
end
|
||||
|
||||
def platform
|
||||
@spec.platform
|
||||
end
|
||||
|
||||
def source
|
||||
@source ||= Gem::Source::Vendor.new
|
||||
end
|
||||
|
||||
def version
|
||||
@spec.version
|
||||
@spec == other.spec and
|
||||
@source == other.source
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -19,8 +19,6 @@ module Gem
|
|||
attr_accessor :requirement
|
||||
end
|
||||
|
||||
# FIX: does this need to exist? The subclass is the only other reference
|
||||
# I can find.
|
||||
class ErrorReason; end
|
||||
|
||||
# Generated when trying to lookup a gem to indicate that the gem
|
||||
|
|
|
@ -35,7 +35,7 @@ class Gem::DependencyResolutionError < Gem::Exception
|
|||
@conflict = conflict
|
||||
a, b = conflicting_dependencies
|
||||
|
||||
super "unable to resolve conflicting dependencies '#{a}' and '#{b}'"
|
||||
super "conflicting dependencies #{a} and #{b}\n#{@conflict.explanation}"
|
||||
end
|
||||
|
||||
def conflicting_dependencies
|
||||
|
@ -226,10 +226,17 @@ class Gem::UnsatisfiableDependencyError < Gem::Exception
|
|||
# Creates a new UnsatisfiableDepedencyError for the unsatisfiable
|
||||
# Gem::DependencyResolver::DependencyRequest +dep+
|
||||
|
||||
def initialize dep
|
||||
requester = dep.requester ? dep.requester.request : '(unknown)'
|
||||
|
||||
super "Unable to resolve dependency: #{requester} requires #{dep}"
|
||||
def initialize dep, platform_mismatch=nil
|
||||
if platform_mismatch and !platform_mismatch.empty?
|
||||
plats = platform_mismatch.map { |x| x.platform.to_s }.sort.uniq
|
||||
super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(', ')}"
|
||||
else
|
||||
if dep.explicit?
|
||||
super "Unable to resolve dependency: user requested '#{dep}'"
|
||||
else
|
||||
super "Unable to resolve dependency: '#{dep.request_context}' requires '#{dep}'"
|
||||
end
|
||||
end
|
||||
|
||||
@dependency = dep
|
||||
end
|
||||
|
|
|
@ -29,6 +29,14 @@ class Gem::Platform
|
|||
end
|
||||
end
|
||||
|
||||
def self.installable?(spec)
|
||||
if spec.respond_to? :installable_platform?
|
||||
spec.installable_platform?
|
||||
else
|
||||
match spec.platform
|
||||
end
|
||||
end
|
||||
|
||||
def self.new(arch) # :nodoc:
|
||||
case arch
|
||||
when Gem::Platform::CURRENT then
|
||||
|
|
|
@ -78,7 +78,6 @@ class Gem::RemoteFetcher
|
|||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Given a source at +uri+, calculate what hostname to actually
|
||||
# connect to query the data for it.
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@ class Gem::RequestSet
|
|||
|
||||
attr_accessor :development
|
||||
|
||||
##
|
||||
# Sets used for resolution
|
||||
|
||||
attr_reader :sets # :nodoc:
|
||||
|
||||
##
|
||||
# Treat missing dependencies as silent errors
|
||||
|
||||
|
@ -53,13 +58,15 @@ class Gem::RequestSet
|
|||
def initialize *deps
|
||||
@dependencies = deps
|
||||
|
||||
@always_install = []
|
||||
@development = false
|
||||
@requests = []
|
||||
@soft_missing = false
|
||||
@sorted = nil
|
||||
@specs = nil
|
||||
@vendor_set = nil
|
||||
@always_install = []
|
||||
@dependency_names = {}
|
||||
@development = false
|
||||
@requests = []
|
||||
@sets = []
|
||||
@soft_missing = false
|
||||
@sorted = nil
|
||||
@specs = nil
|
||||
@vendor_set = nil
|
||||
|
||||
yield self if block_given?
|
||||
end
|
||||
|
@ -68,7 +75,13 @@ class Gem::RequestSet
|
|||
# Declare that a gem of name +name+ with +reqs+ requirements is needed.
|
||||
|
||||
def gem name, *reqs
|
||||
@dependencies << Gem::Dependency.new(name, reqs)
|
||||
if dep = @dependency_names[name] then
|
||||
dep.requirement.concat reqs
|
||||
else
|
||||
dep = Gem::Dependency.new name, reqs
|
||||
@dependency_names[name] = dep
|
||||
@dependencies << dep
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -78,7 +91,14 @@ class Gem::RequestSet
|
|||
@dependencies.concat deps
|
||||
end
|
||||
|
||||
def install options, &block
|
||||
##
|
||||
# Installs gems for this RequestSet using the Gem::Installer +options+.
|
||||
#
|
||||
# If a +block+ is given an activation +request+ and +installer+ are yielded.
|
||||
# The +installer+ will be +nil+ if a gem matching the request was already
|
||||
# installed.
|
||||
|
||||
def install options, &block # :yields: request, installer
|
||||
if dir = options[:install_dir]
|
||||
return install_into dir, false, options, &block
|
||||
end
|
||||
|
@ -109,6 +129,21 @@ class Gem::RequestSet
|
|||
specs
|
||||
end
|
||||
|
||||
##
|
||||
# Installs from the gem dependencies files in the +:gemdeps+ option in
|
||||
# +options+, yielding to the +block+ as in #install.
|
||||
#
|
||||
# If +:without_groups+ is given in the +options+, those groups in the gem
|
||||
# dependencies file are not used. See Gem::Installer for other +options+.
|
||||
|
||||
def install_from_gemdeps options, &block
|
||||
load_gemdeps options[:gemdeps], options[:without_groups]
|
||||
|
||||
resolve
|
||||
|
||||
install options, &block
|
||||
end
|
||||
|
||||
def install_into dir, force = true, options = {}
|
||||
existing = force ? [] : specs_in(dir)
|
||||
existing.delete_if { |s| @always_install.include? s }
|
||||
|
@ -148,10 +183,11 @@ class Gem::RequestSet
|
|||
##
|
||||
# Load a dependency management file.
|
||||
|
||||
def load_gemdeps path
|
||||
def load_gemdeps path, without_groups = []
|
||||
@vendor_set = Gem::DependencyResolver::VendorSet.new
|
||||
|
||||
gf = Gem::RequestSet::GemDependencyAPI.new self, path
|
||||
gf.without_groups = without_groups if without_groups
|
||||
gf.load
|
||||
end
|
||||
|
||||
|
@ -160,13 +196,10 @@ class Gem::RequestSet
|
|||
# objects to be activated.
|
||||
|
||||
def resolve set = Gem::DependencyResolver::IndexSet.new
|
||||
sets = [set, @vendor_set].compact
|
||||
@sets << set
|
||||
@sets << @vendor_set
|
||||
|
||||
set = if sets.size == 1 then
|
||||
sets.first
|
||||
else
|
||||
Gem::DependencyResolver.compose_sets(*sets)
|
||||
end
|
||||
set = Gem::DependencyResolver.compose_sets(*@sets)
|
||||
|
||||
resolver = Gem::DependencyResolver.new @dependencies, set
|
||||
resolver.development = @development
|
||||
|
|
|
@ -3,16 +3,125 @@
|
|||
|
||||
class Gem::RequestSet::GemDependencyAPI
|
||||
|
||||
##
|
||||
# The dependency groups created by #group in the dependency API file.
|
||||
ENGINE_MAP = { # :nodoc:
|
||||
:jruby => %w[jruby],
|
||||
:jruby_18 => %w[jruby],
|
||||
:jruby_19 => %w[jruby],
|
||||
:maglev => %w[maglev],
|
||||
:mri => %w[ruby],
|
||||
:mri_18 => %w[ruby],
|
||||
:mri_19 => %w[ruby],
|
||||
:mri_20 => %w[ruby],
|
||||
:mri_21 => %w[ruby],
|
||||
:rbx => %w[rbx],
|
||||
:ruby => %w[ruby rbx maglev],
|
||||
:ruby_18 => %w[ruby rbx maglev],
|
||||
:ruby_19 => %w[ruby rbx maglev],
|
||||
:ruby_20 => %w[ruby rbx maglev],
|
||||
:ruby_21 => %w[ruby rbx maglev],
|
||||
}
|
||||
|
||||
attr_reader :dependency_groups
|
||||
x86_mingw = Gem::Platform.new 'x86-mingw32'
|
||||
x64_mingw = Gem::Platform.new 'x64-mingw32'
|
||||
|
||||
PLATFORM_MAP = { # :nodoc:
|
||||
:jruby => Gem::Platform::RUBY,
|
||||
:jruby_18 => Gem::Platform::RUBY,
|
||||
:jruby_19 => Gem::Platform::RUBY,
|
||||
:maglev => Gem::Platform::RUBY,
|
||||
:mingw => x86_mingw,
|
||||
:mingw_18 => x86_mingw,
|
||||
:mingw_19 => x86_mingw,
|
||||
:mingw_20 => x86_mingw,
|
||||
:mingw_21 => x86_mingw,
|
||||
:mri => Gem::Platform::RUBY,
|
||||
:mri_18 => Gem::Platform::RUBY,
|
||||
:mri_19 => Gem::Platform::RUBY,
|
||||
:mri_20 => Gem::Platform::RUBY,
|
||||
:mri_21 => Gem::Platform::RUBY,
|
||||
:mswin => Gem::Platform::RUBY,
|
||||
:rbx => Gem::Platform::RUBY,
|
||||
:ruby => Gem::Platform::RUBY,
|
||||
:ruby_18 => Gem::Platform::RUBY,
|
||||
:ruby_19 => Gem::Platform::RUBY,
|
||||
:ruby_20 => Gem::Platform::RUBY,
|
||||
:ruby_21 => Gem::Platform::RUBY,
|
||||
:x64_mingw => x64_mingw,
|
||||
:x64_mingw_20 => x64_mingw,
|
||||
:x64_mingw_21 => x64_mingw
|
||||
}
|
||||
|
||||
gt_eq_0 = Gem::Requirement.new '>= 0'
|
||||
tilde_gt_1_8_0 = Gem::Requirement.new '~> 1.8.0'
|
||||
tilde_gt_1_9_0 = Gem::Requirement.new '~> 1.9.0'
|
||||
tilde_gt_2_0_0 = Gem::Requirement.new '~> 2.0.0'
|
||||
tilde_gt_2_1_0 = Gem::Requirement.new '~> 2.1.0'
|
||||
|
||||
VERSION_MAP = { # :nodoc:
|
||||
:jruby => gt_eq_0,
|
||||
:jruby_18 => tilde_gt_1_8_0,
|
||||
:jruby_19 => tilde_gt_1_9_0,
|
||||
:maglev => gt_eq_0,
|
||||
:mingw => gt_eq_0,
|
||||
:mingw_18 => tilde_gt_1_8_0,
|
||||
:mingw_19 => tilde_gt_1_9_0,
|
||||
:mingw_20 => tilde_gt_2_0_0,
|
||||
:mingw_21 => tilde_gt_2_1_0,
|
||||
:mri => gt_eq_0,
|
||||
:mri_18 => tilde_gt_1_8_0,
|
||||
:mri_19 => tilde_gt_1_9_0,
|
||||
:mri_20 => tilde_gt_2_0_0,
|
||||
:mri_21 => tilde_gt_2_1_0,
|
||||
:mswin => gt_eq_0,
|
||||
:rbx => gt_eq_0,
|
||||
:ruby => gt_eq_0,
|
||||
:ruby_18 => tilde_gt_1_8_0,
|
||||
:ruby_19 => tilde_gt_1_9_0,
|
||||
:ruby_20 => tilde_gt_2_0_0,
|
||||
:ruby_21 => tilde_gt_2_1_0,
|
||||
:x64_mingw => gt_eq_0,
|
||||
:x64_mingw_20 => tilde_gt_2_0_0,
|
||||
:x64_mingw_21 => tilde_gt_2_1_0,
|
||||
}
|
||||
|
||||
WINDOWS = { # :nodoc:
|
||||
:mingw => :only,
|
||||
:mingw_18 => :only,
|
||||
:mingw_19 => :only,
|
||||
:mingw_20 => :only,
|
||||
:mingw_21 => :only,
|
||||
:mri => :never,
|
||||
:mri_18 => :never,
|
||||
:mri_19 => :never,
|
||||
:mri_20 => :never,
|
||||
:mri_21 => :never,
|
||||
:mswin => :only,
|
||||
:rbx => :never,
|
||||
:ruby => :never,
|
||||
:ruby_18 => :never,
|
||||
:ruby_19 => :never,
|
||||
:ruby_20 => :never,
|
||||
:ruby_21 => :never,
|
||||
:x64_mingw => :only,
|
||||
:x64_mingw_20 => :only,
|
||||
:x64_mingw_21 => :only,
|
||||
}
|
||||
|
||||
##
|
||||
# A Hash containing gem names and files to require from those gems.
|
||||
|
||||
attr_reader :requires
|
||||
|
||||
##
|
||||
# A set of gems that are loaded via the +:path+ option to #gem
|
||||
|
||||
attr_reader :vendor_set # :nodoc:
|
||||
|
||||
##
|
||||
# The groups of gems to exclude from installation
|
||||
|
||||
attr_accessor :without_groups
|
||||
|
||||
##
|
||||
# Creates a new GemDependencyAPI that will add dependencies to the
|
||||
# Gem::RequestSet +set+ based on the dependency API description in +path+.
|
||||
|
@ -21,9 +130,13 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
@set = set
|
||||
@path = path
|
||||
|
||||
@current_groups = nil
|
||||
@dependency_groups = Hash.new { |h, group| h[group] = [] }
|
||||
@vendor_set = @set.vendor_set
|
||||
@current_groups = nil
|
||||
@current_platform = nil
|
||||
@default_sources = true
|
||||
@requires = Hash.new { |h, name| h[name] = [] }
|
||||
@vendor_set = @set.vendor_set
|
||||
@gem_sources = {}
|
||||
@without_groups = []
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -47,10 +160,32 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
options = requirements.pop if requirements.last.kind_of?(Hash)
|
||||
options ||= {}
|
||||
|
||||
if directory = options.delete(:path) then
|
||||
@vendor_set.add_vendor_gem name, directory
|
||||
source_set = gem_path name, options
|
||||
|
||||
return unless gem_platforms options
|
||||
|
||||
groups = gem_group name, options
|
||||
|
||||
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
|
||||
|
||||
@set.gem name, *requirements
|
||||
end
|
||||
|
||||
##
|
||||
# Handles the :group and :groups +options+ for the gem with the given
|
||||
# +name+.
|
||||
|
||||
def gem_group name, options # :nodoc:
|
||||
g = options.delete :group
|
||||
all_groups = g ? Array(g) : []
|
||||
|
||||
|
@ -59,19 +194,81 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
|
||||
all_groups |= @current_groups if @current_groups
|
||||
|
||||
unless all_groups.empty? then
|
||||
all_groups.each do |group|
|
||||
gem_arguments = [name, *requirements]
|
||||
gem_arguments << options unless options.empty?
|
||||
@dependency_groups[group] << gem_arguments
|
||||
all_groups
|
||||
end
|
||||
|
||||
private :gem_group
|
||||
|
||||
##
|
||||
# Handles the path: option from +options+ for gem +name+.
|
||||
#
|
||||
# Returns +true+ if the path option was handled.
|
||||
|
||||
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
|
||||
|
||||
private :gem_path
|
||||
|
||||
##
|
||||
# Handles the platforms: option from +options+. Returns true if the
|
||||
# platform matches the current platform.
|
||||
|
||||
def gem_platforms options # :nodoc:
|
||||
platform_names = Array(options.delete :platforms)
|
||||
platform_names << @current_platform if @current_platform
|
||||
|
||||
return true if platform_names.empty?
|
||||
|
||||
platform_names.any? do |platform_name|
|
||||
raise ArgumentError, "unknown platform #{platform_name.inspect}" unless
|
||||
platform = PLATFORM_MAP[platform_name]
|
||||
|
||||
next false unless Gem::Platform.match platform
|
||||
|
||||
if engines = ENGINE_MAP[platform_name] then
|
||||
next false unless engines.include? Gem.ruby_engine
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
case WINDOWS[platform_name]
|
||||
when :only then
|
||||
next false unless Gem.win_platform?
|
||||
when :never then
|
||||
next false if Gem.win_platform?
|
||||
end
|
||||
|
||||
@set.gem name, *requirements
|
||||
VERSION_MAP[platform_name].satisfied_by? Gem.ruby_version
|
||||
end
|
||||
end
|
||||
|
||||
private :gem_platforms
|
||||
|
||||
##
|
||||
# Handles the require: option from +options+ and adds those files, or the
|
||||
# default file to the require list for +name+.
|
||||
|
||||
def gem_requires name, options # :nodoc:
|
||||
if options.include? :require then
|
||||
if requires = options.delete(:require) then
|
||||
@requires[name].concat requires
|
||||
end
|
||||
else
|
||||
@requires[name] << name
|
||||
end
|
||||
end
|
||||
|
||||
private :gem_requires
|
||||
|
||||
##
|
||||
# Returns the basename of the file the dependencies were loaded from
|
||||
|
||||
|
@ -96,9 +293,12 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
# :category: Gem Dependencies DSL
|
||||
|
||||
def platform what
|
||||
if what == :ruby
|
||||
yield
|
||||
end
|
||||
@current_platform = what
|
||||
|
||||
yield
|
||||
|
||||
ensure
|
||||
@current_platform = nil
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -112,23 +312,58 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
# +:engine+ options from Bundler are currently ignored.
|
||||
|
||||
def ruby version, options = {}
|
||||
return true if version == RUBY_VERSION
|
||||
engine = options[:engine]
|
||||
engine_version = options[:engine_version]
|
||||
|
||||
message = "Your Ruby version is #{RUBY_VERSION}, " +
|
||||
"but your #{gem_deps_file} specified #{version}"
|
||||
raise ArgumentError,
|
||||
'you must specify engine_version along with the ruby engine' if
|
||||
engine and not engine_version
|
||||
|
||||
raise Gem::RubyVersionMismatch, message
|
||||
unless RUBY_VERSION == version then
|
||||
message = "Your Ruby version is #{RUBY_VERSION}, " +
|
||||
"but your #{gem_deps_file} requires #{version}"
|
||||
|
||||
raise Gem::RubyVersionMismatch, message
|
||||
end
|
||||
|
||||
if engine and engine != Gem.ruby_engine then
|
||||
message = "Your ruby engine is #{Gem.ruby_engine}, " +
|
||||
"but your #{gem_deps_file} requires #{engine}"
|
||||
|
||||
raise Gem::RubyVersionMismatch, message
|
||||
end
|
||||
|
||||
if engine_version then
|
||||
my_engine_version = Object.const_get "#{Gem.ruby_engine.upcase}_VERSION"
|
||||
|
||||
if engine_version != my_engine_version then
|
||||
message =
|
||||
"Your ruby engine version is #{Gem.ruby_engine} #{my_engine_version}, " +
|
||||
"but your #{gem_deps_file} requires #{engine} #{engine_version}"
|
||||
|
||||
raise Gem::RubyVersionMismatch, message
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Gem Dependencies DSL
|
||||
#
|
||||
# Sets +url+ as a source for gems for this dependency API.
|
||||
|
||||
def source url
|
||||
Gem.sources.clear if @default_sources
|
||||
|
||||
@default_sources = false
|
||||
|
||||
Gem.sources << url
|
||||
end
|
||||
|
||||
# TODO: remove this typo name at RubyGems 3.0
|
||||
|
||||
Gem::RequestSet::DepedencyAPI = self # :nodoc:
|
||||
Gem::RequestSet::GemDepedencyAPI = self # :nodoc:
|
||||
|
||||
end
|
||||
|
||||
|
|
347
lib/rubygems/request_set/lockfile.rb
Normal file
347
lib/rubygems/request_set/lockfile.rb
Normal file
|
@ -0,0 +1,347 @@
|
|||
require 'pathname'
|
||||
|
||||
class Gem::RequestSet::Lockfile
|
||||
|
||||
##
|
||||
# Raised when a lockfile cannot be parsed
|
||||
|
||||
class ParseError < Gem::Exception
|
||||
|
||||
##
|
||||
# The column where the error was encountered
|
||||
|
||||
attr_reader :column
|
||||
|
||||
##
|
||||
# The line where the error was encountered
|
||||
|
||||
attr_reader :line
|
||||
|
||||
##
|
||||
# The location of the lock file
|
||||
|
||||
attr_reader :path
|
||||
|
||||
##
|
||||
# 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
|
||||
|
||||
##
|
||||
# The platforms for this Lockfile
|
||||
|
||||
attr_reader :platforms
|
||||
|
||||
##
|
||||
# Creates a new Lockfile for the given +request_set+ and +gem_deps_file+
|
||||
# location.
|
||||
|
||||
def initialize request_set, gem_deps_file
|
||||
@set = request_set
|
||||
@gem_deps_file = Pathname(gem_deps_file).expand_path
|
||||
@gem_deps_dir = @gem_deps_file.dirname
|
||||
|
||||
@current_token = nil
|
||||
@line = 0
|
||||
@line_pos = 0
|
||||
@platforms = []
|
||||
@tokens = []
|
||||
end
|
||||
|
||||
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::DependencyResolver::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:"
|
||||
|
||||
requests.sort_by { |request| request.name }.each do |request|
|
||||
platform = "-#{request.spec.platform}" unless
|
||||
Gem::Platform::RUBY == request.spec.platform
|
||||
|
||||
out << " #{request.name} (#{request.version}#{platform})"
|
||||
|
||||
request.full_spec.dependencies.sort.each do |dependency|
|
||||
requirement = dependency.requirement
|
||||
out << " #{dependency.name}#{requirement.for_lockfile}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
out << nil
|
||||
end
|
||||
|
||||
def add_PATH out # :nodoc:
|
||||
return unless path_requests =
|
||||
@spec_groups.delete(Gem::DependencyResolver::VendorSpecification)
|
||||
|
||||
out << "PATH"
|
||||
path_requests.each do |request|
|
||||
directory = Pathname(request.spec.source.uri).expand_path
|
||||
|
||||
out << " remote: #{directory.relative_path_from @gem_deps_dir}"
|
||||
out << " specs:"
|
||||
out << " #{request.name} (#{request.version})"
|
||||
end
|
||||
|
||||
out << nil
|
||||
end
|
||||
|
||||
def add_PLATFORMS out # :nodoc:
|
||||
out << "PLATFORMS"
|
||||
|
||||
platforms = @requests.map { |request| request.spec.platform }.uniq
|
||||
platforms.delete Gem::Platform::RUBY if platforms.length > 1
|
||||
|
||||
platforms.each do |platform|
|
||||
out << " #{platform}"
|
||||
end
|
||||
|
||||
out << nil
|
||||
end
|
||||
|
||||
##
|
||||
# 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
|
||||
end
|
||||
|
||||
def parse # :nodoc:
|
||||
tokenize
|
||||
|
||||
until @tokens.empty? do
|
||||
type, data, column, line = get
|
||||
|
||||
case type
|
||||
when :section then
|
||||
skip :newline
|
||||
|
||||
case data
|
||||
when 'DEPENDENCIES' then
|
||||
parse_DEPENDENCIES
|
||||
when 'GEM' then
|
||||
parse_GEM
|
||||
when 'PLATFORMS' then
|
||||
parse_PLATFORMS
|
||||
else
|
||||
type, = get until @tokens.empty? or peek.first == :section
|
||||
end
|
||||
else
|
||||
raise "BUG: unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_DEPENDENCIES # :nodoc:
|
||||
while not @tokens.empty? and :text == peek.first do
|
||||
_, name, = get :text
|
||||
|
||||
@set.gem name
|
||||
|
||||
skip :newline
|
||||
end
|
||||
end
|
||||
|
||||
def parse_GEM # :nodoc:
|
||||
get :entry, 'remote'
|
||||
_, data, = get :text
|
||||
|
||||
source = Gem::Source.new data
|
||||
|
||||
skip :newline
|
||||
|
||||
get :entry, 'specs'
|
||||
|
||||
skip :newline
|
||||
|
||||
set = Gem::DependencyResolver::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
|
||||
|
||||
skip :newline
|
||||
end
|
||||
|
||||
@set.sets << set
|
||||
end
|
||||
|
||||
def parse_PLATFORMS # :nodoc:
|
||||
while not @tokens.empty? and :text == peek.first do
|
||||
_, name, = get :text
|
||||
|
||||
@platforms << name
|
||||
|
||||
skip :newline
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Peeks at the next token for Lockfile
|
||||
|
||||
def peek # :nodoc:
|
||||
@tokens.first
|
||||
end
|
||||
|
||||
def skip type # :nodoc:
|
||||
get while not @tokens.empty? and peek.first == type
|
||||
end
|
||||
|
||||
def to_s
|
||||
@set.resolve
|
||||
|
||||
out = []
|
||||
|
||||
@requests = @set.sorted_requests
|
||||
|
||||
@spec_groups = @requests.group_by do |request|
|
||||
request.spec.class
|
||||
end
|
||||
|
||||
add_PATH out
|
||||
|
||||
add_GEM out
|
||||
|
||||
add_PLATFORMS out
|
||||
|
||||
add_DEPENDENCIES out
|
||||
|
||||
out.join "\n"
|
||||
end
|
||||
|
||||
##
|
||||
# Calculates the column (by byte) and the line of the current token based on
|
||||
# +byte_offset+.
|
||||
|
||||
def token_pos byte_offset # :nodoc:
|
||||
[byte_offset - @line_pos, @line]
|
||||
end
|
||||
|
||||
def tokenize # :nodoc:
|
||||
@line = 0
|
||||
@line_pos = 0
|
||||
|
||||
@platforms = []
|
||||
@tokens = []
|
||||
@current_token = nil
|
||||
|
||||
lock_file = "#{@gem_deps_file}.lock"
|
||||
|
||||
@input = File.read lock_file
|
||||
s = StringScanner.new @input
|
||||
|
||||
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 <<
|
||||
case
|
||||
when s.scan(/\r?\n/) then
|
||||
token = [:newline, nil, *token_pos(pos)]
|
||||
@line_pos = s.pos
|
||||
@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)]
|
||||
when s.scan(/\(/) then
|
||||
[: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}"
|
||||
end
|
||||
end
|
||||
|
||||
@tokens
|
||||
end
|
||||
|
||||
##
|
||||
# Ungets the last token retrieved by #get
|
||||
|
||||
def unget # :nodoc:
|
||||
@tokens.unshift @current_token
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -21,11 +21,21 @@ class Gem::Requirement
|
|||
}
|
||||
|
||||
quoted = OPS.keys.map { |k| Regexp.quote k }.join "|"
|
||||
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*"
|
||||
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*" # :nodoc:
|
||||
|
||||
##
|
||||
# A regular expression that matches a requirement
|
||||
|
||||
PATTERN = /\A#{PATTERN_RAW}\z/
|
||||
|
||||
##
|
||||
# The default requirement matches any version
|
||||
|
||||
DefaultRequirement = [">=", Gem::Version.new(0)]
|
||||
|
||||
##
|
||||
# Raised when a bad requirement is encountered
|
||||
|
||||
class BadRequirementError < ArgumentError; end
|
||||
|
||||
##
|
||||
|
@ -107,10 +117,28 @@ class Gem::Requirement
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Concatenates the +new+ requirements onto this requirement.
|
||||
|
||||
def concat new
|
||||
new = new.flatten
|
||||
new.compact!
|
||||
new.uniq!
|
||||
new = new.map { |r| self.class.parse r }
|
||||
|
||||
@requirements.concat new
|
||||
end
|
||||
|
||||
##
|
||||
# Formats this requirement for use in a Gem::RequestSet::Lockfile.
|
||||
|
||||
def for_lockfile # :nodoc:
|
||||
" (#{to_s})" unless [DefaultRequirement] == @requirements
|
||||
end
|
||||
|
||||
##
|
||||
# true if this gem has no requirements.
|
||||
|
||||
# FIX: maybe this should be using #default ?
|
||||
def none?
|
||||
if @requirements.size == 1
|
||||
@requirements[0] == DefaultRequirement
|
||||
|
@ -152,11 +180,11 @@ class Gem::Requirement
|
|||
yaml_initialize coder.tag, coder.map
|
||||
end
|
||||
|
||||
def to_yaml_properties
|
||||
def to_yaml_properties # :nodoc:
|
||||
["@requirements"]
|
||||
end
|
||||
|
||||
def encode_with(coder)
|
||||
def encode_with coder # :nodoc:
|
||||
coder.add 'requirements', @requirements
|
||||
end
|
||||
|
||||
|
@ -200,15 +228,13 @@ class Gem::Requirement
|
|||
as_list.join ", "
|
||||
end
|
||||
|
||||
# DOC: this should probably be :nodoc'd
|
||||
def == other
|
||||
def == other # :nodoc:
|
||||
Gem::Requirement === other and to_s == other.to_s
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# DOC: this should probably be :nodoc'd
|
||||
def fix_syck_default_key_in_requirements
|
||||
def fix_syck_default_key_in_requirements # :nodoc:
|
||||
Gem.load_yaml
|
||||
|
||||
# Fixup the Syck DefaultKey bug
|
||||
|
@ -220,9 +246,9 @@ class Gem::Requirement
|
|||
end
|
||||
end
|
||||
|
||||
# This is needed for compatibility with older yaml
|
||||
# gemspecs.
|
||||
|
||||
class Gem::Version
|
||||
Requirement = Gem::Requirement
|
||||
# This is needed for compatibility with older yaml
|
||||
# gemspecs.
|
||||
|
||||
Requirement = Gem::Requirement # :nodoc:
|
||||
end
|
||||
|
|
|
@ -445,7 +445,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
@spec_dirs = @gem_dirs.map { |gem_dir| File.join gem_dir, 'specifications' }
|
||||
@spec_dirs.reject! { |spec_dir| !File.directory? spec_dir }
|
||||
|
||||
Gem::Specification.dirs = @gem_dirs
|
||||
reset_gems
|
||||
|
||||
@have_rdoc_4_plus = nil
|
||||
end
|
||||
|
@ -470,7 +470,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
end
|
||||
|
||||
def latest_specs(req, res)
|
||||
Gem::Specification.reset
|
||||
reset_gems
|
||||
|
||||
res['content-type'] = 'application/x-gzip'
|
||||
|
||||
|
@ -531,7 +531,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
end
|
||||
|
||||
def quick(req, res)
|
||||
Gem::Specification.reset
|
||||
reset_gems
|
||||
|
||||
res['content-type'] = 'text/plain'
|
||||
add_date res
|
||||
|
@ -567,7 +567,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
end
|
||||
|
||||
def root(req, res)
|
||||
Gem::Specification.reset
|
||||
reset_gems
|
||||
|
||||
add_date res
|
||||
|
||||
raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless
|
||||
|
@ -697,6 +698,13 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
res.body = template.result binding
|
||||
end
|
||||
|
||||
##
|
||||
# Updates the server to use the latest installed gems.
|
||||
|
||||
def reset_gems # :nodoc:
|
||||
Gem::Specification.dirs = @gem_dirs
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true and prepares http response, if rdoc for the requested gem
|
||||
# name pattern was found.
|
||||
|
@ -787,7 +795,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
end
|
||||
|
||||
def specs(req, res)
|
||||
Gem::Specification.reset
|
||||
reset_gems
|
||||
|
||||
add_date res
|
||||
|
||||
|
|
|
@ -52,6 +52,24 @@ class Gem::Source
|
|||
|
||||
alias_method :eql?, :==
|
||||
|
||||
##
|
||||
# Returns a Set that can fetch specifications from this source.
|
||||
|
||||
def dependency_resolver_set # :nodoc:
|
||||
uri = api_uri
|
||||
|
||||
bundler_api_uri = api_uri + './api/v1/dependencies'
|
||||
|
||||
begin
|
||||
fetcher = Gem::RemoteFetcher.fetcher
|
||||
fetcher.fetch_path bundler_api_uri, nil, true
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
Gem::DependencyResolver::IndexSet.new self
|
||||
else
|
||||
Gem::DependencyResolver::APISet.new bundler_api_uri
|
||||
end
|
||||
end
|
||||
|
||||
def hash
|
||||
@uri.hash
|
||||
end
|
||||
|
|
|
@ -2,5 +2,10 @@
|
|||
# This represents a vendored source that is similar to an installed gem.
|
||||
|
||||
class Gem::Source::Vendor < Gem::Source::Installed
|
||||
|
||||
def initialize uri
|
||||
@uri = uri
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,28 +1,40 @@
|
|||
require 'rubygems/source'
|
||||
|
||||
class Gem::SourceList
|
||||
|
||||
include Enumerable
|
||||
|
||||
##
|
||||
# Creates a new SourceList
|
||||
|
||||
def initialize
|
||||
@sources = []
|
||||
end
|
||||
|
||||
##
|
||||
# The sources in this list
|
||||
|
||||
attr_reader :sources
|
||||
|
||||
##
|
||||
# Creates a new SourceList from an array of sources.
|
||||
|
||||
def self.from(ary)
|
||||
list = new
|
||||
|
||||
if ary
|
||||
ary.each do |x|
|
||||
list << x
|
||||
end
|
||||
end
|
||||
list.replace ary
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
def initialize_copy(other)
|
||||
def initialize_copy(other) # :nodoc:
|
||||
@sources = @sources.dup
|
||||
end
|
||||
|
||||
##
|
||||
# Appends +obj+ to the source list which may be a Gem::Source, URI or URI
|
||||
# String.
|
||||
|
||||
def <<(obj)
|
||||
src = case obj
|
||||
when URI
|
||||
|
@ -37,8 +49,12 @@ class Gem::SourceList
|
|||
src
|
||||
end
|
||||
|
||||
##
|
||||
# Replaces this SourceList with the sources in +other+ See #<< for
|
||||
# acceptable items in +other+.
|
||||
|
||||
def replace(other)
|
||||
@sources.clear
|
||||
clear
|
||||
|
||||
other.each do |x|
|
||||
self << x
|
||||
|
@ -47,28 +63,58 @@ class Gem::SourceList
|
|||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Removes all sources from the SourceList.
|
||||
|
||||
def clear
|
||||
@sources.clear
|
||||
end
|
||||
|
||||
##
|
||||
# Yields each source URI in the list.
|
||||
|
||||
def each
|
||||
@sources.each { |s| yield s.uri.to_s }
|
||||
end
|
||||
|
||||
##
|
||||
# Yields each source in the list.
|
||||
|
||||
def each_source(&b)
|
||||
@sources.each(&b)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true if there are no sources in this SourceList.
|
||||
|
||||
def empty?
|
||||
@sources.empty?
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
to_a == other
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an Array of source URI Strings.
|
||||
|
||||
def to_a
|
||||
@sources.map { |x| x.uri.to_s }
|
||||
end
|
||||
|
||||
alias_method :to_ary, :to_a
|
||||
|
||||
##
|
||||
# Returns the first source in the list.
|
||||
|
||||
def first
|
||||
@sources.first
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true if this source list includes +other+ which may be a
|
||||
# Gem::Source or a source URI.
|
||||
|
||||
def include?(other)
|
||||
if other.kind_of? Gem::Source
|
||||
@sources.include? other
|
||||
|
@ -77,11 +123,14 @@ class Gem::SourceList
|
|||
end
|
||||
end
|
||||
|
||||
def delete(uri)
|
||||
if uri.kind_of? Gem::Source
|
||||
@sources.delete uri
|
||||
##
|
||||
# Deletes +source+ from the source list which may be a Gem::Source or a URI.
|
||||
|
||||
def delete source
|
||||
if source.kind_of? Gem::Source
|
||||
@sources.delete source
|
||||
else
|
||||
@sources.delete_if { |x| x.uri.to_s == uri.to_s }
|
||||
@sources.delete_if { |x| x.uri.to_s == source.to_s }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,11 @@ class Gem::SpecFetcher
|
|||
|
||||
attr_reader :latest_specs # :nodoc:
|
||||
|
||||
##
|
||||
# Sources for this SpecFetcher
|
||||
|
||||
attr_reader :sources # :nodoc:
|
||||
|
||||
##
|
||||
# Cache of all released specs
|
||||
|
||||
|
@ -37,7 +42,16 @@ class Gem::SpecFetcher
|
|||
@fetcher = fetcher
|
||||
end
|
||||
|
||||
def initialize
|
||||
##
|
||||
# Creates a new SpecFetcher. Ordinarily you want to use
|
||||
# Gem::SpecFetcher::fetcher which uses the Gem.sources.
|
||||
#
|
||||
# If you need to retrieve specifications from a different +source+, you can
|
||||
# send it as an argument.
|
||||
|
||||
def initialize sources = nil
|
||||
@sources = sources || Gem.sources
|
||||
|
||||
@update_cache =
|
||||
begin
|
||||
File.stat(Gem.user_home).uid == Process.uid
|
||||
|
@ -197,7 +211,7 @@ class Gem::SpecFetcher
|
|||
errors = []
|
||||
list = {}
|
||||
|
||||
Gem.sources.each_source do |source|
|
||||
@sources.each_source do |source|
|
||||
begin
|
||||
names = case type
|
||||
when :latest
|
||||
|
|
|
@ -856,12 +856,8 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
# this resets the list of known specs.
|
||||
|
||||
def self.dirs= dirs
|
||||
# TODO: find extra calls to dir=
|
||||
# warn "NOTE: dirs= called from #{caller.first} for #{dirs.inspect}"
|
||||
|
||||
self.reset
|
||||
|
||||
# ugh
|
||||
@@dirs = Array(dirs).map { |dir| File.join dir, "specifications" }
|
||||
end
|
||||
|
||||
|
@ -1105,9 +1101,6 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
# Removes +spec+ from the known specs.
|
||||
|
||||
def self.remove_spec spec
|
||||
# TODO: beat on the tests
|
||||
raise "wtf: #{spec.full_name} not in #{all_names.inspect}" unless
|
||||
_all.include? spec
|
||||
_all.delete spec
|
||||
stubs.delete_if { |s| s.full_name == spec.full_name }
|
||||
end
|
||||
|
@ -1400,7 +1393,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
# Returns the build_args used to install the gem
|
||||
|
||||
def build_args
|
||||
if File.exist? build_info_file
|
||||
if File.exists? build_info_file
|
||||
File.readlines(build_info_file).map { |x| x.strip }
|
||||
else
|
||||
[]
|
||||
|
@ -1788,6 +1781,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
end
|
||||
|
||||
def init_with coder # :nodoc:
|
||||
@installed_by_version ||= nil
|
||||
yaml_initialize coder.tag, coder.map
|
||||
end
|
||||
|
||||
|
@ -2293,9 +2287,9 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
end
|
||||
end
|
||||
|
||||
if defined?(@installed_by_version) && @installed_by_version then
|
||||
if @installed_by_version then
|
||||
result << nil
|
||||
result << " s.installed_by_version = \"#{Gem::VERSION}\""
|
||||
result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version"
|
||||
end
|
||||
|
||||
unless dependencies.empty? then
|
||||
|
@ -2488,7 +2482,6 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
end
|
||||
end
|
||||
|
||||
# FIX: uhhhh single element array.each?
|
||||
[:authors].each do |field|
|
||||
val = self.send field
|
||||
raise Gem::InvalidSpecificationException, "#{field} may not be empty" if
|
||||
|
@ -2540,7 +2533,6 @@ licenses is empty. Use a license abbreviation from:
|
|||
|
||||
# reject lazy developers:
|
||||
|
||||
# FIX: Doesn't this just evaluate to "FIXME" or "TODO"?
|
||||
lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
|
||||
|
||||
unless authors.grep(/FI XME|TO DO/x).empty? then
|
||||
|
@ -2586,19 +2578,80 @@ licenses is empty. Use a license abbreviation from:
|
|||
warning "#{executable_path} is missing #! line" unless shebang
|
||||
end
|
||||
|
||||
validate_dependencies
|
||||
|
||||
true
|
||||
ensure
|
||||
if $! or @warnings > 0 then
|
||||
alert_warning "See http://guides.rubygems.org/specification-reference/ for help"
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Checks that dependencies use requirements as we recommend. Warnings are
|
||||
# issued when dependencies are open-ended or overly strict for semantic
|
||||
# versioning.
|
||||
|
||||
def validate_dependencies # :nodoc:
|
||||
seen = {}
|
||||
|
||||
dependencies.each do |dep|
|
||||
if prev = seen[dep.name] then
|
||||
raise Gem::InvalidSpecificationException, <<-MESSAGE
|
||||
duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
||||
add_runtime_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}'
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
seen[dep.name] = dep
|
||||
|
||||
prerelease_dep = dep.requirements_list.any? do |req|
|
||||
Gem::Requirement.new(req).prerelease?
|
||||
end
|
||||
|
||||
warning "prerelease dependency on #{dep} is not recommended" if
|
||||
prerelease_dep
|
||||
end
|
||||
|
||||
true
|
||||
ensure
|
||||
if $! or @warnings > 0 then
|
||||
alert_warning "See http://guides.rubygems.org/specification-reference/ for help"
|
||||
overly_strict = dep.requirement.requirements.length == 1 &&
|
||||
dep.requirement.requirements.any? do |op, version|
|
||||
op == '~>' and
|
||||
not version.prerelease? and
|
||||
version.segments.length > 2
|
||||
end
|
||||
|
||||
if overly_strict then
|
||||
_, dep_version = dep.requirement.requirements.first
|
||||
|
||||
base = dep_version.segments.first 2
|
||||
|
||||
warning <<-WARNING
|
||||
pessimistic dependency on #{dep} may be overly strict
|
||||
if #{dep.name} is semantically versioned, use:
|
||||
add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}', '>= #{dep_version}'
|
||||
WARNING
|
||||
end
|
||||
|
||||
open_ended = dep.requirement.requirements.all? do |op, version|
|
||||
not version.prerelease? and (op == '>' or op == '>=')
|
||||
end
|
||||
|
||||
if open_ended then
|
||||
op, dep_version = dep.requirement.requirements.first
|
||||
|
||||
base = dep_version.segments.first 2
|
||||
|
||||
bugfix = if op == '>' then
|
||||
", '> #{dep_version}'"
|
||||
elsif op == '>=' and base != dep_version.segments then
|
||||
", '>= #{dep_version}'"
|
||||
end
|
||||
|
||||
warning <<-WARNING
|
||||
open-ended dependency on #{dep} is not recommended
|
||||
if #{dep.name} is semantically versioned, use:
|
||||
add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}
|
||||
WARNING
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2633,7 +2686,10 @@ licenses is empty. Use a license abbreviation from:
|
|||
return @version
|
||||
end
|
||||
|
||||
# FIX: have this handle the platform/new_platform/original_platform bullshit
|
||||
def stubbed?
|
||||
false
|
||||
end
|
||||
|
||||
def yaml_initialize(tag, vals) # :nodoc:
|
||||
vals.each do |ivar, val|
|
||||
case ivar
|
||||
|
@ -2667,6 +2723,8 @@ licenses is empty. Use a license abbreviation from:
|
|||
|
||||
instance_variable_set "@#{attribute}", value
|
||||
end
|
||||
|
||||
@installed_by_version ||= nil
|
||||
end
|
||||
|
||||
def warning statement # :nodoc:
|
||||
|
|
23
lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem
Normal file
23
lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem
Normal file
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||
+OkuE6N36B9K
|
||||
-----END CERTIFICATE-----
|
|
@ -241,6 +241,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase
|
|||
@orig_ENV_HOME = ENV['HOME']
|
||||
ENV['HOME'] = @userhome
|
||||
Gem.instance_variable_set :@user_home, nil
|
||||
Gem.send :remove_instance_variable, :@ruby_version if
|
||||
Gem.instance_variables.include? :@ruby_version
|
||||
|
||||
FileUtils.mkdir_p @gemhome
|
||||
FileUtils.mkdir_p @userhome
|
||||
|
@ -376,7 +378,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
|
|||
|
||||
gem = File.join @tempdir, "gems", "#{spec.full_name}.gem"
|
||||
|
||||
unless File.exist? gem
|
||||
unless File.exists? gem
|
||||
use_ui Gem::MockGemUi.new do
|
||||
Dir.chdir @tempdir do
|
||||
Gem::Package.build spec
|
||||
|
@ -898,14 +900,35 @@ Also, a list:
|
|||
spec_fetcher.prerelease_specs[@uri] << spec.name_tuple
|
||||
end
|
||||
|
||||
v = Gem.marshal_version
|
||||
# HACK for test_download_to_cache
|
||||
unless Gem::RemoteFetcher === @fetcher then
|
||||
v = Gem.marshal_version
|
||||
|
||||
Gem::Specification.each do |spec|
|
||||
path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
|
||||
data = Marshal.dump spec
|
||||
data_deflate = Zlib::Deflate.deflate data
|
||||
@fetcher.data[path] = data_deflate
|
||||
end unless Gem::RemoteFetcher === @fetcher # HACK for test_download_to_cache
|
||||
specs = all.map { |spec| spec.name_tuple }
|
||||
s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs
|
||||
|
||||
latest_specs = Gem::Specification.latest_specs.map do |spec|
|
||||
spec.name_tuple
|
||||
end
|
||||
|
||||
l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs
|
||||
|
||||
prerelease_specs = prerelease.map { |spec| spec.name_tuple }
|
||||
p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs
|
||||
|
||||
@fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip
|
||||
@fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip
|
||||
|
||||
v = Gem.marshal_version
|
||||
|
||||
Gem::Specification.each do |spec|
|
||||
path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
|
||||
data = Marshal.dump spec
|
||||
data_deflate = Zlib::Deflate.deflate data
|
||||
@fetcher.data[path] = data_deflate
|
||||
end
|
||||
end
|
||||
|
||||
nil # force errors
|
||||
end
|
||||
|
@ -1088,6 +1111,62 @@ Also, a list:
|
|||
Gem::Specification.new name, v(version), &block
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a SpecFetcher pre-filled with the gems or specs defined in the
|
||||
# block.
|
||||
#
|
||||
# Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds
|
||||
# a specification to the SpecFetcher while +gem+ adds both a specification
|
||||
# and the gem data to the RemoteFetcher so the built gem can be downloaded.
|
||||
#
|
||||
# If only the a-3 gem is supposed to be downloaded you can save setup
|
||||
# time by creating only specs for the other versions:
|
||||
#
|
||||
# spec_fetcher do |fetcher|
|
||||
# fetcher.spec 'a', 1
|
||||
# fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3
|
||||
# fetcher.gem 'a', 3 do |spec|
|
||||
# # spec is a Gem::Specification
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
|
||||
def spec_fetcher
|
||||
gems = {}
|
||||
|
||||
fetcher = Object.new
|
||||
fetcher.instance_variable_set :@test, self
|
||||
fetcher.instance_variable_set :@gems, gems
|
||||
|
||||
def fetcher.gem name, version, dependencies = nil, &block
|
||||
spec, gem = @test.util_gem name, version, dependencies, &block
|
||||
|
||||
@gems[spec] = gem
|
||||
|
||||
spec
|
||||
end
|
||||
|
||||
def fetcher.spec name, version, dependencies = nil, &block
|
||||
spec = @test.util_spec name, version, dependencies, &block
|
||||
|
||||
@gems[spec] = nil
|
||||
|
||||
spec
|
||||
end
|
||||
|
||||
yield fetcher
|
||||
|
||||
util_setup_fake_fetcher unless @fetcher
|
||||
util_setup_spec_fetcher(*gems.keys)
|
||||
|
||||
gems.each do |spec, gem|
|
||||
next unless gem
|
||||
|
||||
@fetcher.data["http://gems.example.com/gems/#{spec.file_name}"] =
|
||||
Gem.read_binary(gem)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Construct a new Gem::Version.
|
||||
|
||||
|
|
|
@ -145,8 +145,6 @@ class Gem::Version
|
|||
|
||||
include Comparable
|
||||
|
||||
# FIX: These are only used once, in .correct?. Do they deserve to be
|
||||
# constants?
|
||||
VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc:
|
||||
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc:
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class TestBundledCA < Gem::TestCase
|
|||
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||
http.cert_store = bundled_certificate_store
|
||||
http.get('/')
|
||||
rescue Errno::ENOENT
|
||||
rescue Errno::ENOENT, Errno::ETIMEDOUT
|
||||
skip "#{host} seems offline, I can't tell whether ssl would work."
|
||||
rescue OpenSSL::SSL::SSLError => e
|
||||
# Only fail for certificate verification errors
|
||||
|
|
|
@ -420,12 +420,13 @@ class TestGem < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_self_latest_spec_for
|
||||
a1 = quick_spec 'a', 1
|
||||
a2 = quick_spec 'a', 2
|
||||
a3a = quick_spec 'a', '3.a'
|
||||
a2 = nil
|
||||
|
||||
util_setup_fake_fetcher
|
||||
util_setup_spec_fetcher a1, a2, a3a
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 1
|
||||
fetcher.spec 'a', '3.a'
|
||||
a2 = fetcher.spec 'a', 2
|
||||
end
|
||||
|
||||
spec = Gem.latest_spec_for 'a'
|
||||
|
||||
|
@ -433,12 +434,11 @@ class TestGem < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_self_latest_rubygems_version
|
||||
r1 = quick_spec 'rubygems-update', '1.8.23'
|
||||
r2 = quick_spec 'rubygems-update', '1.8.24'
|
||||
r3 = quick_spec 'rubygems-update', '2.0.0.preview3'
|
||||
|
||||
util_setup_fake_fetcher
|
||||
util_setup_spec_fetcher r1, r2, r3
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'rubygems-update', '1.8.23'
|
||||
fetcher.spec 'rubygems-update', '1.8.24'
|
||||
fetcher.spec 'rubygems-update', '2.0.0.preview3'
|
||||
end
|
||||
|
||||
version = Gem.latest_rubygems_version
|
||||
|
||||
|
@ -446,12 +446,11 @@ class TestGem < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_self_latest_version_for
|
||||
a1 = quick_spec 'a', 1
|
||||
a2 = quick_spec 'a', 2
|
||||
a3a = quick_spec 'a', '3.a'
|
||||
|
||||
util_setup_fake_fetcher
|
||||
util_setup_spec_fetcher a1, a2, a3a
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 1
|
||||
fetcher.spec 'a', 2
|
||||
fetcher.spec 'a', '3.a'
|
||||
end
|
||||
|
||||
version = Gem.latest_version_for 'a'
|
||||
|
||||
|
|
|
@ -168,17 +168,10 @@ ERROR: Only reverse dependencies for local gems are supported.
|
|||
end
|
||||
|
||||
def test_execute_remote
|
||||
foo = quick_gem 'foo' do |gem|
|
||||
gem.add_dependency 'bar', '> 1'
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'foo', 2, 'bar' => '> 1'
|
||||
end
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications', foo.spec_name)
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:domain] = :remote
|
||||
|
||||
|
|
|
@ -855,4 +855,14 @@ ERROR: Possible alternatives: non_existent_with_hint
|
|||
assert_equal 'gem.deps.rb', @cmd.options[:gemdeps]
|
||||
end
|
||||
|
||||
def test_handle_options_without
|
||||
@cmd.handle_options %w[--without test]
|
||||
|
||||
assert_equal [:test], @cmd.options[:without_groups]
|
||||
|
||||
@cmd.handle_options %w[--without test,development]
|
||||
|
||||
assert_equal [:test, :development], @cmd.options[:without_groups]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -14,13 +14,10 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_execute
|
||||
remote_10 = quick_spec 'foo', '1.0'
|
||||
remote_20 = quick_spec 'foo', '2.0'
|
||||
|
||||
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
|
||||
|
||||
util_clear_gems
|
||||
util_setup_spec_fetcher remote_10, remote_20
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'foo', '1.0'
|
||||
fetcher.spec 'foo', '2.0'
|
||||
end
|
||||
|
||||
quick_gem 'foo', '0.1'
|
||||
quick_gem 'foo', '0.2'
|
||||
|
|
|
@ -152,14 +152,9 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_execute_remote
|
||||
foo = quick_gem 'foo'
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications', foo.spec_name)
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'foo', 1
|
||||
end
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:domain] = :remote
|
||||
|
@ -173,16 +168,10 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_execute_remote_with_version
|
||||
foo1 = quick_gem 'foo', "1"
|
||||
foo2 = quick_gem 'foo', "2"
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo1, foo2
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications', foo1.spec_name)
|
||||
FileUtils.rm File.join(@gemhome, 'specifications', foo2.spec_name)
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'foo', "1"
|
||||
fetcher.spec 'foo', "2"
|
||||
end
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:version] = "1"
|
||||
|
@ -198,16 +187,12 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_execute_remote_without_prerelease
|
||||
foo = new_spec 'foo', '2.0.0'
|
||||
foo_pre = new_spec 'foo', '2.0.1.pre'
|
||||
spec_fetcher do |fetcher|
|
||||
foo = fetcher.spec 'foo', '2.0.0'
|
||||
foo_pre = fetcher.spec 'foo', '2.0.1.pre'
|
||||
|
||||
install_specs foo, foo_pre
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
util_setup_spec_fetcher foo_pre
|
||||
install_specs foo, foo_pre
|
||||
end
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:domain] = :remote
|
||||
|
@ -225,16 +210,12 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_execute_remote_with_prerelease
|
||||
foo = new_spec 'foo', '2.0.0'
|
||||
foo_pre = new_spec 'foo', '2.0.1.pre'
|
||||
spec_fetcher do |fetcher|
|
||||
foo = fetcher.spec 'foo', '2.0.0'
|
||||
foo_pre = fetcher.spec 'foo', '2.0.1.pre'
|
||||
|
||||
install_specs foo, foo_pre
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
util_setup_spec_fetcher foo_pre
|
||||
install_specs foo, foo_pre
|
||||
end
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:domain] = :remote
|
||||
|
|
|
@ -682,7 +682,7 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|||
inst.install 'b'
|
||||
end
|
||||
|
||||
expected = "Unable to resolve dependency: b (= 1) requires a (>= 0)"
|
||||
expected = "Unable to resolve dependency: 'b (= 1)' requires 'a (>= 0)'"
|
||||
assert_equal expected, e.message
|
||||
end
|
||||
|
||||
|
@ -816,6 +816,17 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|||
assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_platform_is_ignored_when_a_file_is_specified
|
||||
_, a_gem = util_gem 'a', '1' do |s|
|
||||
s.platform = Gem::Platform.new %w[cpu other_platform 1]
|
||||
end
|
||||
|
||||
inst = Gem::DependencyInstaller.new :domain => :local
|
||||
inst.install a_gem
|
||||
|
||||
assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
if defined? OpenSSL then
|
||||
def test_install_security_policy
|
||||
util_setup_gems
|
||||
|
@ -904,6 +915,29 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|||
assert_equal Gem::Source.new(@gem_repo), s.source
|
||||
end
|
||||
|
||||
def test_find_spec_by_name_and_version_wildcard
|
||||
util_gem 'a', 1
|
||||
FileUtils.mv 'gems/a-1.gem', @tempdir
|
||||
|
||||
FileUtils.touch 'rdoc.gem'
|
||||
|
||||
inst = Gem::DependencyInstaller.new
|
||||
|
||||
available = inst.find_spec_by_name_and_version('*.gem')
|
||||
|
||||
assert_equal %w[a-1], available.each_spec.map { |spec| spec.full_name }
|
||||
end
|
||||
|
||||
def test_find_spec_by_name_and_version_wildcard_bad_gem
|
||||
FileUtils.touch 'rdoc.gem'
|
||||
|
||||
inst = Gem::DependencyInstaller.new
|
||||
|
||||
assert_raises Gem::Package::FormatError do
|
||||
inst.find_spec_by_name_and_version '*.gem'
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_spec_by_name_and_version_bad_gem
|
||||
FileUtils.touch 'rdoc.gem'
|
||||
|
||||
|
|
28
test/rubygems/test_gem_dependency_resolution_error.rb
Normal file
28
test/rubygems/test_gem_dependency_resolution_error.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
require 'rubygems/test_case'
|
||||
|
||||
class TestGemDependencyResolutionError < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
|
||||
@spec = quick_spec 'a', 2
|
||||
|
||||
@a1_req = @DR::DependencyRequest.new dep('a', '= 1'), nil
|
||||
@a2_req = @DR::DependencyRequest.new dep('a', '= 2'), nil
|
||||
|
||||
@activated = @DR::ActivationRequest.new @spec, @a2_req
|
||||
|
||||
@conflict = @DR::DependencyConflict.new @a1_req, @activated
|
||||
|
||||
@error = Gem::DependencyResolutionError.new @conflict
|
||||
end
|
||||
|
||||
def test_message
|
||||
assert_match %r%^conflicting dependencies a \(= 1\) and a \(= 2\)$%,
|
||||
@error.message
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,6 +3,12 @@ require 'rubygems/dependency_resolver'
|
|||
|
||||
class TestGemDependencyResolver < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
end
|
||||
|
||||
def make_dep(name, *req)
|
||||
Gem::Dependency.new(name, *req)
|
||||
end
|
||||
|
@ -21,7 +27,58 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
|
||||
assert_equal exp, act, msg
|
||||
rescue Gem::DependencyResolutionError => e
|
||||
flunk "#{e.message}\n#{e.conflict.explanation}"
|
||||
flunk e.message
|
||||
end
|
||||
|
||||
def test_self_compose_sets_multiple
|
||||
index_set = @DR::IndexSet.new
|
||||
vendor_set = @DR::VendorSet.new
|
||||
|
||||
composed = @DR.compose_sets index_set, vendor_set
|
||||
|
||||
assert_kind_of Gem::DependencyResolver::ComposedSet, composed
|
||||
|
||||
assert_equal [index_set, vendor_set], composed.sets
|
||||
end
|
||||
|
||||
def test_self_compose_sets_nil
|
||||
index_set = @DR::IndexSet.new
|
||||
|
||||
composed = @DR.compose_sets index_set, nil
|
||||
|
||||
assert_same index_set, composed
|
||||
|
||||
e = assert_raises ArgumentError do
|
||||
@DR.compose_sets nil
|
||||
end
|
||||
|
||||
assert_equal 'one set in the composition must be non-nil', e.message
|
||||
end
|
||||
|
||||
def test_self_compose_sets_single
|
||||
index_set = @DR::IndexSet.new
|
||||
|
||||
composed = @DR.compose_sets index_set
|
||||
|
||||
assert_same index_set, composed
|
||||
end
|
||||
|
||||
def test_handle_conflict
|
||||
a1 = util_spec 'a', 1
|
||||
|
||||
r1 = Gem::DependencyResolver::DependencyRequest.new dep('a', '= 1'), nil
|
||||
r2 = Gem::DependencyResolver::DependencyRequest.new dep('a', '= 2'), nil
|
||||
r3 = Gem::DependencyResolver::DependencyRequest.new dep('a', '= 3'), nil
|
||||
|
||||
existing = Gem::DependencyResolver::ActivationRequest.new a1, r1, false
|
||||
|
||||
res = Gem::DependencyResolver.new [a1]
|
||||
|
||||
res.handle_conflict r2, existing
|
||||
res.handle_conflict r2, existing
|
||||
res.handle_conflict r3, existing
|
||||
|
||||
assert_equal 2, res.conflicts.length
|
||||
end
|
||||
|
||||
def test_no_overlap_specificly
|
||||
|
@ -71,10 +128,15 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_picks_best_platform
|
||||
is = Gem::DependencyResolver::IndexSpecification
|
||||
is = Gem::DependencyResolver::IndexSpecification
|
||||
unknown = Gem::Platform.new 'unknown'
|
||||
a2_p1 = quick_spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
a3_p2 = quick_spec 'a', 3 do |s| s.platform = unknown end
|
||||
a2_p1 = a3_p2 = nil
|
||||
|
||||
spec_fetcher do |fetcher|
|
||||
a2_p1 = fetcher.spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
a3_p2 = fetcher.spec 'a', 3 do |s| s.platform = unknown end
|
||||
end
|
||||
|
||||
v2 = v(2)
|
||||
v3 = v(3)
|
||||
source = Gem::Source.new @gem_repo
|
||||
|
@ -183,8 +245,6 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
r.resolve
|
||||
end
|
||||
|
||||
assert_equal "unable to resolve conflicting dependencies 'c (= 2)' and 'c (= 1)'", e.message
|
||||
|
||||
deps = [make_dep("c", "= 2"), make_dep("c", "= 1")]
|
||||
assert_equal deps, e.conflicting_dependencies
|
||||
|
||||
|
@ -209,7 +269,7 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
r.resolve
|
||||
end
|
||||
|
||||
assert_equal "Unable to resolve dependency: (unknown) requires a (>= 0)",
|
||||
assert_equal "Unable to resolve dependency: user requested 'a (>= 0)'",
|
||||
e.message
|
||||
|
||||
assert_equal "a (>= 0)", e.dependency.to_s
|
||||
|
@ -229,6 +289,37 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
assert_equal "a (= 3)", e.dependency.to_s
|
||||
end
|
||||
|
||||
def test_raises_and_reports_a_toplevel_request_properly
|
||||
a1 = util_spec "a", "1"
|
||||
ad = make_dep "a", "= 3"
|
||||
|
||||
r = Gem::DependencyResolver.new([ad], set(a1))
|
||||
|
||||
e = assert_raises Gem::UnsatisfiableDepedencyError do
|
||||
r.resolve
|
||||
end
|
||||
|
||||
assert_equal "Unable to resolve dependency: user requested 'a (= 3)'",
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_raises_and_reports_an_implicit_request_properly
|
||||
a1 = util_spec "a", "1" do |s|
|
||||
s.add_runtime_dependency 'b', '= 2'
|
||||
end
|
||||
|
||||
ad = make_dep "a", "= 1"
|
||||
|
||||
r = Gem::DependencyResolver.new([ad], set(a1))
|
||||
|
||||
e = assert_raises Gem::UnsatisfiableDepedencyError do
|
||||
r.resolve
|
||||
end
|
||||
|
||||
assert_equal "Unable to resolve dependency: 'a (= 1)' requires 'b (= 2)'",
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_raises_when_possibles_are_exhausted
|
||||
a1 = util_spec "a", "1", "c" => ">= 2"
|
||||
b1 = util_spec "b", "1", "c" => "= 1"
|
||||
|
@ -244,18 +335,22 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
|
||||
r = Gem::DependencyResolver.new([ad, bd], s)
|
||||
|
||||
e = assert_raises Gem::ImpossibleDependenciesError do
|
||||
e = assert_raises Gem::DependencyResolutionError do
|
||||
r.resolve
|
||||
end
|
||||
|
||||
assert_match "a-1 requires c (>= 2) but it conflicted", e.message
|
||||
dependency = e.conflict.dependency
|
||||
|
||||
assert_equal "c (>= 2)", e.dependency.to_s
|
||||
assert_equal 'a', dependency.name
|
||||
assert_equal req('>= 0'), dependency.requirement
|
||||
|
||||
s, con = e.conflicts[0]
|
||||
assert_equal "c-3", s.full_name
|
||||
assert_equal "c (= 1)", con.dependency.to_s
|
||||
assert_equal "b-1", con.requester.full_name
|
||||
activated = e.conflict.activated
|
||||
assert_equal 'c-2', activated.full_name
|
||||
|
||||
assert_equal dep('c', '>= 2'), activated.request.dependency
|
||||
|
||||
assert_equal [dep('c', '= 1'), dep('c', '>= 2')],
|
||||
e.conflict.conflicting_dependencies
|
||||
end
|
||||
|
||||
def test_keeps_resolving_after_seeing_satisfied_dep
|
||||
|
@ -312,7 +407,7 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
|
||||
r = Gem::DependencyResolver.new([d1, d2, d3], s)
|
||||
|
||||
assert_raises Gem::ImpossibleDependenciesError do
|
||||
assert_raises Gem::DependencyResolutionError do
|
||||
r.resolve
|
||||
end
|
||||
end
|
||||
|
@ -335,6 +430,42 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_resolve_bug_699
|
||||
a1 = util_spec 'a', '1', 'b' => '= 2',
|
||||
'c' => '~> 1.0.3'
|
||||
|
||||
b1 = util_spec 'b', '2', 'c' => '~> 1.0'
|
||||
|
||||
c1 = util_spec 'c', '1.0.9'
|
||||
c2 = util_spec 'c', '1.1.0'
|
||||
c3 = util_spec 'c', '1.2.0'
|
||||
|
||||
s = set a1, b1, c1, c2, c3
|
||||
|
||||
a_dep = dep 'a', '= 1'
|
||||
|
||||
r = Gem::DependencyResolver.new [a_dep], s
|
||||
|
||||
assert_resolves_to [a1, b1, c1], r
|
||||
end
|
||||
|
||||
def test_resolve_rollback
|
||||
a1 = util_spec 'a', 1
|
||||
a2 = util_spec 'a', 2
|
||||
|
||||
b1 = util_spec 'b', 1, 'a' => '~> 1.0'
|
||||
b2 = util_spec 'b', 2, 'a' => '~> 2.0'
|
||||
|
||||
s = set a1, a2, b1, b2
|
||||
|
||||
a_dep = dep 'a', '~> 1.0'
|
||||
b_dep = dep 'b'
|
||||
|
||||
r = Gem::DependencyResolver.new [a_dep, b_dep], s
|
||||
|
||||
assert_resolves_to [a1, b1], r
|
||||
end
|
||||
|
||||
# actionmailer 2.3.4
|
||||
# activemerchant 1.5.0
|
||||
# activesupport 2.3.5, 2.3.4
|
||||
|
@ -388,5 +519,22 @@ class TestGemDependencyResolver < Gem::TestCase
|
|||
assert_equal [a1, a1_p1], selected
|
||||
end
|
||||
|
||||
def test_raises_and_explains_when_platform_prevents_install
|
||||
a1 = util_spec "a", "1" do |s|
|
||||
s.platform = Gem::Platform.new %w[c p 1]
|
||||
end
|
||||
|
||||
ad = make_dep "a", "= 1"
|
||||
|
||||
r = Gem::DependencyResolver.new([ad], set(a1))
|
||||
|
||||
e = assert_raises Gem::UnsatisfiableDepedencyError do
|
||||
r.resolve
|
||||
end
|
||||
|
||||
assert_match "No match for 'a (= 1)' on this platform. Found: c-p-1",
|
||||
e.message
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
require 'rubygems/test_case'
|
||||
|
||||
class TestGemDependencyResolverActivationRequest < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
|
||||
@dep = @DR::DependencyRequest.new dep('a', '>= 0'), nil
|
||||
|
||||
source = Gem::Source::Local.new
|
||||
platform = Gem::Platform::RUBY
|
||||
|
||||
@a1 = @DR::IndexSpecification.new nil, 'a', v(1), source, platform
|
||||
@a2 = @DR::IndexSpecification.new nil, 'a', v(2), source, platform
|
||||
@a3 = @DR::IndexSpecification.new nil, 'a', v(3), source, platform
|
||||
|
||||
@req = @DR::ActivationRequest.new @a3, @dep, [@a1, @a2]
|
||||
end
|
||||
|
||||
def test_inspect
|
||||
assert_match 'a-3', @req.inspect
|
||||
assert_match 'from a (>= 0)', @req.inspect
|
||||
assert_match '(others possible: a-1, a-2)', @req.inspect
|
||||
end
|
||||
|
||||
def test_inspect_legacy
|
||||
req = @DR::ActivationRequest.new @a3, @dep, true
|
||||
|
||||
assert_match '(others possible)', req.inspect
|
||||
|
||||
req = @DR::ActivationRequest.new @a3, @dep, false
|
||||
|
||||
refute_match '(others possible)', req.inspect
|
||||
end
|
||||
|
||||
def test_installed_eh
|
||||
v_spec = Gem::DependencyResolver::VendorSpecification.new nil, @a3
|
||||
|
||||
@req = @DR::ActivationRequest.new v_spec, @dep, [@a1, @a2]
|
||||
|
||||
assert @req.installed?
|
||||
end
|
||||
|
||||
def test_others_possible_eh
|
||||
assert @req.others_possible?
|
||||
|
||||
req = @DR::ActivationRequest.new @a3, @dep, []
|
||||
|
||||
refute req.others_possible?
|
||||
|
||||
req = @DR::ActivationRequest.new @a3, @dep, true
|
||||
|
||||
assert req.others_possible?
|
||||
|
||||
req = @DR::ActivationRequest.new @a3, @dep, false
|
||||
|
||||
refute req.others_possible?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -7,73 +7,20 @@ class TestGemDependencyResolverAPISet < Gem::TestCase
|
|||
super
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
|
||||
@api_set = @DR::APISet.new
|
||||
@uri = 'https://rubygems.org/api/v1/dependencies'
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
end
|
||||
|
||||
def test_find_all
|
||||
b_entry = {
|
||||
:name => 'b',
|
||||
:number => '2',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [['a', '>= 0']],
|
||||
}
|
||||
def test_initialize
|
||||
set = @DR::APISet.new
|
||||
|
||||
@fetcher.data["#{@uri}?gems=b"] = Marshal.dump [b_entry]
|
||||
|
||||
b_req = @DR::DependencyRequest.new dep('b', '>= 0'), nil
|
||||
|
||||
expected = [
|
||||
@DR::APISpecification.new(@api_set, b_entry)
|
||||
]
|
||||
|
||||
assert_equal expected, @api_set.find_all(b_req)
|
||||
assert_equal URI('https://rubygems.org/api/v1/dependencies'),
|
||||
set.dep_uri
|
||||
end
|
||||
|
||||
def test_prefetch
|
||||
b_entry = {
|
||||
:name => 'b',
|
||||
:number => '2',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [['a', '>= 0']],
|
||||
}
|
||||
def test_initialize_uri
|
||||
set = @DR::APISet.new @gem_repo
|
||||
|
||||
a_entry = {
|
||||
:name => 'a',
|
||||
:number => '2',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [],
|
||||
}
|
||||
|
||||
@fetcher.data["#{@uri}?gems=a,b"] = Marshal.dump [a_entry, b_entry]
|
||||
|
||||
a_req = @DR::DependencyRequest.new dep('a', '>= 0'), nil
|
||||
b_req = @DR::DependencyRequest.new dep('b', '>= 0'), nil
|
||||
|
||||
@api_set.prefetch([b_req, a_req])
|
||||
|
||||
assert_equal [a_entry], @api_set.versions('a')
|
||||
assert_equal [b_entry], @api_set.versions('b')
|
||||
end
|
||||
|
||||
def test_versions_cache
|
||||
entry = {
|
||||
:name => 'b',
|
||||
:number => '2',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [['a', '>= 0']],
|
||||
}
|
||||
|
||||
@fetcher.data["#{@uri}?gems=b"] = Marshal.dump [entry]
|
||||
|
||||
assert_equal [entry], @api_set.versions('b')
|
||||
|
||||
@fetcher.data["#{@uri}?gems=b"] = 'garbage'
|
||||
|
||||
assert_equal [entry], @api_set.versions('b'), 'version data must be cached'
|
||||
assert_equal URI('http://gems.example.com/'),
|
||||
set.dep_uri
|
||||
end
|
||||
|
||||
end
|
||||
|
|
31
test/rubygems/test_gem_dependency_resolver_best_set.rb
Normal file
31
test/rubygems/test_gem_dependency_resolver_best_set.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'rubygems/test_case'
|
||||
require 'rubygems/dependency_resolver'
|
||||
|
||||
class TestGemDependencyResolverBestSet < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
end
|
||||
|
||||
def test_find_all_index
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 1
|
||||
fetcher.spec 'a', 2
|
||||
fetcher.spec 'b', 1
|
||||
end
|
||||
|
||||
set = @DR::BestSet.new
|
||||
|
||||
dependency = dep 'a', '~> 1'
|
||||
|
||||
req = @DR::DependencyRequest.new dependency, nil
|
||||
|
||||
found = set.find_all req
|
||||
|
||||
assert_equal %w[a-1], found.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -20,6 +20,26 @@ class TestGemDependencyResolverDependencyConflict < Gem::TestCase
|
|||
assert_equal expected, conflict.explanation
|
||||
end
|
||||
|
||||
def test_explanation_user_request
|
||||
@DR = Gem::DependencyResolver
|
||||
|
||||
spec = quick_spec 'a', 2
|
||||
|
||||
a1_req = @DR::DependencyRequest.new dep('a', '= 1'), nil
|
||||
a2_req = @DR::DependencyRequest.new dep('a', '= 2'), nil
|
||||
|
||||
activated = @DR::ActivationRequest.new spec, a2_req
|
||||
|
||||
conflict = @DR::DependencyConflict.new a1_req, activated
|
||||
|
||||
expected = <<-EXPECTED
|
||||
Activated a-2 instead of (= 1) via:
|
||||
user request (gem command or Gemfile)
|
||||
EXPECTED
|
||||
|
||||
assert_equal expected, conflict.explanation
|
||||
end
|
||||
|
||||
def test_request_path
|
||||
root =
|
||||
dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
require 'rubygems/test_case'
|
||||
|
||||
class TestGemDependencyResolverDependencyRequest < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@DR = Gem::DependencyResolver::DependencyRequest
|
||||
end
|
||||
|
||||
def test_requirement
|
||||
dependency = dep 'a', '>= 1'
|
||||
|
||||
dr = @DR.new dependency, nil
|
||||
|
||||
assert_equal dependency, dr.dependency
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,50 +3,26 @@ require 'rubygems/dependency_resolver'
|
|||
|
||||
class TestGemDependencyResolverIndexSet < Gem::TestCase
|
||||
|
||||
def test_load_spec
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
def setup
|
||||
super
|
||||
|
||||
a_2 = quick_spec 'a', 2
|
||||
a_2_p = quick_spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
|
||||
Gem::Specification.add_specs a_2, a_2_p
|
||||
|
||||
util_setup_spec_fetcher a_2, a_2_p
|
||||
|
||||
source = Gem::Source.new @gem_repo
|
||||
version = v 2
|
||||
|
||||
set = Gem::DependencyResolver::IndexSet.new
|
||||
|
||||
spec = set.load_spec 'a', version, Gem::Platform.local, source
|
||||
|
||||
assert_equal a_2_p.full_name, spec.full_name
|
||||
@DR = Gem::DependencyResolver
|
||||
end
|
||||
|
||||
def test_load_spec_cached
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
def test_initialize
|
||||
set = @DR::IndexSet.new
|
||||
|
||||
a_2 = quick_spec 'a', 2
|
||||
a_2_p = quick_spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
fetcher = set.instance_variable_get :@f
|
||||
|
||||
Gem::Specification.add_specs a_2, a_2_p
|
||||
assert_same Gem::SpecFetcher.fetcher, fetcher
|
||||
end
|
||||
|
||||
util_setup_spec_fetcher a_2, a_2_p
|
||||
def test_initialize_source
|
||||
set = @DR::IndexSet.new 'http://alternate.example'
|
||||
|
||||
source = Gem::Source.new @gem_repo
|
||||
version = v 2
|
||||
fetcher = set.instance_variable_get :@f
|
||||
|
||||
set = Gem::DependencyResolver::IndexSet.new
|
||||
|
||||
first = set.load_spec 'a', version, Gem::Platform.local, source
|
||||
|
||||
util_setup_spec_fetcher # clear
|
||||
|
||||
second = set.load_spec 'a', version, Gem::Platform.local, source
|
||||
|
||||
assert_same first, second
|
||||
refute_same Gem::SpecFetcher.fetcher, fetcher
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -31,15 +31,12 @@ class TestGemDependencyResolverIndexSpecification < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_spec
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
a_2_p = nil
|
||||
|
||||
a_2 = quick_spec 'a', 2
|
||||
a_2_p = quick_spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
|
||||
Gem::Specification.add_specs a_2, a_2_p
|
||||
|
||||
util_setup_spec_fetcher a_2, a_2_p
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2
|
||||
a_2_p = fetcher.spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
end
|
||||
|
||||
source = Gem::Source.new @gem_repo
|
||||
version = v 2
|
||||
|
|
|
@ -4,15 +4,12 @@ require 'rubygems/dependency_resolver'
|
|||
class TestGemDependencyResolverInstallerSet < Gem::TestCase
|
||||
|
||||
def test_load_spec
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
a_2_p = nil
|
||||
|
||||
a_2 = quick_spec 'a', 2
|
||||
a_2_p = quick_spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
|
||||
Gem::Specification.add_specs a_2, a_2_p
|
||||
|
||||
util_setup_spec_fetcher a_2, a_2_p
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2
|
||||
a_2_p = fetcher.spec 'a', 2 do |s| s.platform = Gem::Platform.local end
|
||||
end
|
||||
|
||||
source = Gem::Source.new @gem_repo
|
||||
version = v 2
|
||||
|
|
57
test/rubygems/test_gem_dependency_resolver_lock_set.rb
Normal file
57
test/rubygems/test_gem_dependency_resolver_lock_set.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'rubygems/test_case'
|
||||
require 'rubygems/dependency_resolver'
|
||||
|
||||
class TestGemDependencyResolverLockSet < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@source = Gem::Source.new @gem_repo
|
||||
|
||||
@set = Gem::DependencyResolver::LockSet.new @source
|
||||
end
|
||||
|
||||
def test_add
|
||||
@set.add 'a', '2', Gem::Platform::RUBY
|
||||
|
||||
assert_equal %w[a-2], @set.specs.map { |t| t.full_name }
|
||||
|
||||
spec = @set.specs.first
|
||||
|
||||
assert_equal @set, spec.set
|
||||
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_find_all
|
||||
@set.add 'a', '2', Gem::Platform::RUBY
|
||||
@set.add 'b', '2', Gem::Platform::RUBY
|
||||
|
||||
found = @set.find_all dep 'a'
|
||||
|
||||
assert_equal %w[a-2], found.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_load_spec
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2
|
||||
end
|
||||
|
||||
version = v(2)
|
||||
@set.add 'a', version, Gem::Platform::RUBY
|
||||
|
||||
loaded = @set.load_spec 'a', version, Gem::Platform::RUBY, @source
|
||||
|
||||
assert_kind_of Gem::Specification, loaded
|
||||
|
||||
assert_equal 'a-2', loaded.full_name
|
||||
end
|
||||
|
||||
def test_prefetch
|
||||
assert_respond_to @set, :prefetch
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -20,7 +20,7 @@ class TestGemDependencyResolverVendorSet < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_add_vendor_gem_missing
|
||||
name, version, directory = vendor_gem
|
||||
name, _, directory = vendor_gem
|
||||
|
||||
FileUtils.rm_r directory
|
||||
|
||||
|
@ -45,15 +45,19 @@ class TestGemDependencyResolverVendorSet < Gem::TestCase
|
|||
|
||||
spec = @set.load_spec name, version, Gem::Platform::RUBY, nil
|
||||
|
||||
source = Gem::Source::Vendor.new directory
|
||||
|
||||
expected = [
|
||||
Gem::DependencyResolver::VendorSpecification.new(@set, spec, nil)
|
||||
Gem::DependencyResolver::VendorSpecification.new(@set, spec, source)
|
||||
]
|
||||
|
||||
assert_equal expected, found
|
||||
end
|
||||
|
||||
def test_load_spec
|
||||
assert_raises KeyError do
|
||||
error = Object.const_defined?(:KeyError) ? KeyError : IndexError
|
||||
|
||||
assert_raises error do
|
||||
@set.load_spec 'a', v(1), Gem::Platform::RUBY, nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -60,12 +60,6 @@ class TestGemDependencyResolverVendorSpecification < Gem::TestCase
|
|||
assert_equal Gem::Platform::RUBY, v_spec.platform
|
||||
end
|
||||
|
||||
def test_source
|
||||
v_spec = Gem::DependencyResolver::VendorSpecification.new @set, @spec
|
||||
|
||||
assert_equal Gem::Source::Vendor.new, v_spec.source
|
||||
end
|
||||
|
||||
def test_version
|
||||
spec = Gem::Specification.new 'a', 1
|
||||
|
||||
|
|
|
@ -75,12 +75,6 @@ gems:
|
|||
|
||||
PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2')
|
||||
|
||||
# don't let 1.8 and 1.9 autotest collide
|
||||
RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/
|
||||
# don't let parallel runners collide
|
||||
PROXY_PORT = process_based_port + 100 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
SERVER_PORT = process_based_port + 200 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
|
||||
DIR = File.expand_path(File.dirname(__FILE__))
|
||||
|
||||
def setup
|
||||
|
@ -93,8 +87,8 @@ gems:
|
|||
self.class.enable_yaml = true
|
||||
self.class.enable_zip = false
|
||||
|
||||
base_server_uri = "http://localhost:#{SERVER_PORT}"
|
||||
@proxy_uri = "http://localhost:#{PROXY_PORT}"
|
||||
base_server_uri = "http://localhost:#{self.class.normal_server_port}"
|
||||
@proxy_uri = "http://localhost:#{self.class.proxy_server_port}"
|
||||
|
||||
@server_uri = base_server_uri + "/yaml"
|
||||
@server_z_uri = base_server_uri + "/yaml.Z"
|
||||
|
@ -712,12 +706,20 @@ gems:
|
|||
attr_accessor :enable_zip, :enable_yaml
|
||||
|
||||
def start_servers
|
||||
@normal_server ||= start_server(SERVER_PORT, SERVER_DATA)
|
||||
@proxy_server ||= start_server(PROXY_PORT, PROXY_DATA)
|
||||
@normal_server ||= start_server(SERVER_DATA)
|
||||
@proxy_server ||= start_server(PROXY_DATA)
|
||||
@enable_yaml = true
|
||||
@enable_zip = false
|
||||
end
|
||||
|
||||
def normal_server_port
|
||||
@normal_server[:server].config[:Port]
|
||||
end
|
||||
|
||||
def proxy_server_port
|
||||
@proxy_server[:server].config[:Port]
|
||||
end
|
||||
|
||||
DIR = File.expand_path(File.dirname(__FILE__))
|
||||
|
||||
def start_ssl_server(config = {})
|
||||
|
@ -763,45 +765,45 @@ gems:
|
|||
|
||||
private
|
||||
|
||||
def start_server(port, data)
|
||||
Thread.new do
|
||||
def start_server(data)
|
||||
null_logger = NilLog.new
|
||||
s = WEBrick::HTTPServer.new(
|
||||
:Port => 0,
|
||||
:DocumentRoot => nil,
|
||||
:Logger => null_logger,
|
||||
:AccessLog => null_logger
|
||||
)
|
||||
s.mount_proc("/kill") { |req, res| s.shutdown }
|
||||
s.mount_proc("/yaml") { |req, res|
|
||||
if @enable_yaml
|
||||
res.body = data
|
||||
res['Content-Type'] = 'text/plain'
|
||||
res['content-length'] = data.size
|
||||
else
|
||||
res.status = "404"
|
||||
res.body = "<h1>NOT FOUND</h1>"
|
||||
res['Content-Type'] = 'text/html'
|
||||
end
|
||||
}
|
||||
s.mount_proc("/yaml.Z") { |req, res|
|
||||
if @enable_zip
|
||||
res.body = Zlib::Deflate.deflate(data)
|
||||
res['Content-Type'] = 'text/plain'
|
||||
else
|
||||
res.status = "404"
|
||||
res.body = "<h1>NOT FOUND</h1>"
|
||||
res['Content-Type'] = 'text/html'
|
||||
end
|
||||
}
|
||||
th = Thread.new do
|
||||
begin
|
||||
null_logger = NilLog.new
|
||||
s = WEBrick::HTTPServer.new(
|
||||
:Port => port,
|
||||
:DocumentRoot => nil,
|
||||
:Logger => null_logger,
|
||||
:AccessLog => null_logger
|
||||
)
|
||||
s.mount_proc("/kill") { |req, res| s.shutdown }
|
||||
s.mount_proc("/yaml") { |req, res|
|
||||
if @enable_yaml
|
||||
res.body = data
|
||||
res['Content-Type'] = 'text/plain'
|
||||
res['content-length'] = data.size
|
||||
else
|
||||
res.status = "404"
|
||||
res.body = "<h1>NOT FOUND</h1>"
|
||||
res['Content-Type'] = 'text/html'
|
||||
end
|
||||
}
|
||||
s.mount_proc("/yaml.Z") { |req, res|
|
||||
if @enable_zip
|
||||
res.body = Zlib::Deflate.deflate(data)
|
||||
res['Content-Type'] = 'text/plain'
|
||||
else
|
||||
res.status = "404"
|
||||
res.body = "<h1>NOT FOUND</h1>"
|
||||
res['Content-Type'] = 'text/html'
|
||||
end
|
||||
}
|
||||
s.start
|
||||
rescue Exception => ex
|
||||
abort ex.message
|
||||
puts "ERROR during server thread: #{ex.message}"
|
||||
abort "ERROR during server thread: #{ex.message}"
|
||||
end
|
||||
end
|
||||
sleep 0.2 # Give the servers time to startup
|
||||
th[:server] = s
|
||||
th
|
||||
end
|
||||
|
||||
def cert(filename)
|
||||
|
|
|
@ -6,6 +6,8 @@ class TestGemRequestSet < Gem::TestCase
|
|||
super
|
||||
|
||||
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
|
||||
|
||||
@DR = Gem::DependencyResolver
|
||||
end
|
||||
|
||||
def test_gem
|
||||
|
@ -17,6 +19,15 @@ class TestGemRequestSet < Gem::TestCase
|
|||
assert_equal [Gem::Dependency.new("a", "=2")], rs.dependencies
|
||||
end
|
||||
|
||||
def test_gem_duplicate
|
||||
rs = Gem::RequestSet.new
|
||||
|
||||
rs.gem 'a', '1'
|
||||
rs.gem 'a', '2'
|
||||
|
||||
assert_equal [dep('a', '= 1', '= 2')], rs.dependencies
|
||||
end
|
||||
|
||||
def test_import
|
||||
rs = Gem::RequestSet.new
|
||||
rs.gem 'a'
|
||||
|
@ -26,6 +37,26 @@ class TestGemRequestSet < Gem::TestCase
|
|||
assert_equal [dep('a'), dep('b')], rs.dependencies
|
||||
end
|
||||
|
||||
def test_install_from_gemdeps
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.gem 'a', 2
|
||||
end
|
||||
|
||||
rs = Gem::RequestSet.new
|
||||
installed = []
|
||||
|
||||
Tempfile.open 'gem.deps.rb' do |io|
|
||||
io.puts 'gem "a"'
|
||||
io.flush
|
||||
|
||||
rs.install_from_gemdeps :gemdeps => io.path do |req, installer|
|
||||
installed << req.full_name
|
||||
end
|
||||
end
|
||||
|
||||
assert_includes installed, 'a-2'
|
||||
end
|
||||
|
||||
def test_load_gemdeps
|
||||
rs = Gem::RequestSet.new
|
||||
|
||||
|
@ -41,6 +72,19 @@ class TestGemRequestSet < Gem::TestCase
|
|||
assert rs.vendor_set
|
||||
end
|
||||
|
||||
def test_load_gemdeps_without_groups
|
||||
rs = Gem::RequestSet.new
|
||||
|
||||
Tempfile.open 'gem.deps.rb' do |io|
|
||||
io.puts 'gem "a", :group => :test'
|
||||
io.flush
|
||||
|
||||
rs.load_gemdeps io.path, [:test]
|
||||
end
|
||||
|
||||
assert_empty rs.dependencies
|
||||
end
|
||||
|
||||
def test_resolve
|
||||
a = util_spec "a", "2", "b" => ">= 2"
|
||||
b = util_spec "b", "2"
|
||||
|
@ -56,6 +100,21 @@ class TestGemRequestSet < Gem::TestCase
|
|||
assert_equal ["a-2", "b-2"], names
|
||||
end
|
||||
|
||||
def test_resolve_incompatible
|
||||
a1 = util_spec 'a', 1
|
||||
a2 = util_spec 'a', 2
|
||||
|
||||
rs = Gem::RequestSet.new
|
||||
rs.gem 'a', '= 1'
|
||||
rs.gem 'a', '= 2'
|
||||
|
||||
set = StaticSet.new [a1, a2]
|
||||
|
||||
assert_raises Gem::UnsatisfiableDependencyError do
|
||||
rs.resolve set
|
||||
end
|
||||
end
|
||||
|
||||
def test_resolve_vendor
|
||||
a_name, _, a_directory = vendor_gem 'a', 1 do |s|
|
||||
s.add_dependency 'b', '~> 2.0'
|
||||
|
@ -82,6 +141,9 @@ class TestGemRequestSet < Gem::TestCase
|
|||
names = res.map { |s| s.full_name }.sort
|
||||
|
||||
assert_equal ["a-1", "b-2"], names
|
||||
|
||||
assert_equal [@DR::IndexSet, @DR::VendorSet],
|
||||
rs.sets.map { |set| set.class }
|
||||
end
|
||||
|
||||
def test_sorted_requests
|
||||
|
@ -99,13 +161,10 @@ class TestGemRequestSet < Gem::TestCase
|
|||
end
|
||||
|
||||
def test_install_into
|
||||
a, ad = util_gem "a", "1", "b" => "= 1"
|
||||
b, bd = util_gem "b", "1"
|
||||
|
||||
util_setup_spec_fetcher a, b
|
||||
|
||||
@fetcher.data["http://gems.example.com/gems/#{a.file_name}"] = Gem.read_binary(ad)
|
||||
@fetcher.data["http://gems.example.com/gems/#{b.file_name}"] = Gem.read_binary(bd)
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.gem "a", "1", "b" => "= 1"
|
||||
fetcher.gem "b", "1"
|
||||
end
|
||||
|
||||
rs = Gem::RequestSet.new
|
||||
rs.gem "a"
|
||||
|
|
|
@ -16,20 +16,56 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
@gda.instance_variable_set :@vendor_set, @vendor_set
|
||||
end
|
||||
|
||||
def with_engine_version name, version
|
||||
engine = RUBY_ENGINE if Object.const_defined? :RUBY_ENGINE
|
||||
engine_version_const = "#{Gem.ruby_engine.upcase}_VERSION"
|
||||
engine_version = Object.const_get engine_version_const
|
||||
|
||||
Object.send :remove_const, :RUBY_ENGINE if engine
|
||||
Object.send :remove_const, engine_version_const if name == 'ruby' and
|
||||
Object.const_defined? engine_version_const
|
||||
|
||||
new_engine_version_const = "#{name.upcase}_VERSION"
|
||||
Object.const_set :RUBY_ENGINE, name if name
|
||||
Object.const_set new_engine_version_const, version if version
|
||||
|
||||
Gem.instance_variable_set :@ruby_version, Gem::Version.new(version)
|
||||
|
||||
yield
|
||||
|
||||
ensure
|
||||
Object.send :remove_const, :RUBY_ENGINE if name
|
||||
Object.send :remove_const, new_engine_version_const if version
|
||||
|
||||
Object.send :remove_const, engine_version_const if name == 'ruby' and
|
||||
Object.const_defined? engine_version_const
|
||||
|
||||
Object.const_set :RUBY_ENGINE, engine if engine
|
||||
Object.const_set engine_version_const, engine_version unless
|
||||
Object.const_defined? engine_version_const
|
||||
|
||||
Gem.send :remove_instance_variable, :@ruby_version if
|
||||
Gem.instance_variables.include? :@ruby_version
|
||||
end
|
||||
|
||||
def test_gem
|
||||
@gda.gem 'a'
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
|
||||
assert_equal %w[a], @gda.requires['a']
|
||||
end
|
||||
|
||||
def test_gem_group
|
||||
@gda.gem 'a', :group => :test
|
||||
|
||||
expected = {
|
||||
:test => [['a']],
|
||||
}
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
end
|
||||
|
||||
assert_equal expected, @gda.dependency_groups
|
||||
def test_gem_group_without
|
||||
@gda.without_groups << :test
|
||||
|
||||
@gda.gem 'a', :group => :test
|
||||
|
||||
assert_empty @set.dependencies
|
||||
end
|
||||
|
@ -37,14 +73,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
def test_gem_groups
|
||||
@gda.gem 'a', :groups => [:test, :development]
|
||||
|
||||
expected = {
|
||||
:development => [['a']],
|
||||
:test => [['a']],
|
||||
}
|
||||
|
||||
assert_equal expected, @gda.dependency_groups
|
||||
|
||||
assert_empty @set.dependencies
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
end
|
||||
|
||||
def test_gem_path
|
||||
|
@ -59,6 +88,133 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
assert_equal "#{name}-#{version}", loaded.full_name
|
||||
end
|
||||
|
||||
def test_gem_platforms
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
@gda.gem 'a', :platforms => :ruby
|
||||
|
||||
refute_empty @set.dependencies
|
||||
end
|
||||
end
|
||||
|
||||
def test_gem_platforms_bundler_ruby
|
||||
win_platform, Gem.win_platform = Gem.win_platform?, false
|
||||
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :ruby
|
||||
|
||||
refute_empty set.dependencies
|
||||
end
|
||||
|
||||
with_engine_version 'rbx', '2.0.0' do
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :ruby
|
||||
|
||||
refute_empty set.dependencies
|
||||
end
|
||||
|
||||
with_engine_version 'jruby', '1.7.6' do
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :ruby
|
||||
|
||||
assert_empty set.dependencies
|
||||
end
|
||||
|
||||
Gem.win_platform = true
|
||||
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :ruby
|
||||
|
||||
assert_empty set.dependencies
|
||||
end
|
||||
|
||||
Gem.win_platform = win_platform
|
||||
end
|
||||
|
||||
def test_gem_platforms_engine
|
||||
with_engine_version 'jruby', '1.7.6' do
|
||||
@gda.gem 'a', :platforms => :mri
|
||||
|
||||
assert_empty @set.dependencies
|
||||
end
|
||||
end
|
||||
|
||||
def test_gem_platforms_maglev
|
||||
with_engine_version 'maglev', '1.0.0' do
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :ruby
|
||||
|
||||
refute_empty set.dependencies
|
||||
|
||||
set = Gem::RequestSet.new
|
||||
gda = @GDA.new set, 'gem.deps.rb'
|
||||
gda.gem 'a', :platforms => :maglev
|
||||
|
||||
refute_empty set.dependencies
|
||||
end
|
||||
end
|
||||
|
||||
def test_gem_platforms_multiple
|
||||
win_platform, Gem.win_platform = Gem.win_platform?, false
|
||||
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
@gda.gem 'a', :platforms => [:mswin, :jruby]
|
||||
|
||||
assert_empty @set.dependencies
|
||||
end
|
||||
|
||||
ensure
|
||||
Gem.win_platform = win_platform
|
||||
end
|
||||
|
||||
def test_gem_platforms_version
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
@gda.gem 'a', :platforms => :ruby_18
|
||||
|
||||
assert_empty @set.dependencies
|
||||
end
|
||||
end
|
||||
|
||||
def test_gem_platforms_unknown
|
||||
e = assert_raises ArgumentError do
|
||||
@gda.gem 'a', :platforms => :unknown
|
||||
end
|
||||
|
||||
assert_equal 'unknown platform :unknown', e.message
|
||||
end
|
||||
|
||||
def test_gem_require
|
||||
@gda.gem 'a', :require => %w[b c]
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
|
||||
assert_equal %w[b c], @gda.requires['a']
|
||||
end
|
||||
|
||||
def test_gem_require_false
|
||||
@gda.gem 'a', :require => false
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
|
||||
assert_empty @gda.requires
|
||||
end
|
||||
|
||||
def test_gem_require_without_group
|
||||
@gda.without_groups << :test
|
||||
|
||||
@gda.gem 'a', :group => :test
|
||||
|
||||
assert_empty @set.dependencies
|
||||
|
||||
assert_empty @gda.requires['a']
|
||||
end
|
||||
|
||||
def test_gem_requirement
|
||||
@gda.gem 'a', '~> 1.0'
|
||||
|
||||
|
@ -77,6 +233,31 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
assert_equal [dep('c')], @set.dependencies
|
||||
end
|
||||
|
||||
def test_gem_source_mismatch
|
||||
name, _, directory = vendor_gem
|
||||
|
||||
gda = @GDA.new @set, nil
|
||||
gda.gem name
|
||||
|
||||
e = assert_raises ArgumentError do
|
||||
gda.gem name, :path => directory
|
||||
end
|
||||
|
||||
assert_equal "duplicate source path: #{directory} for gem #{name}",
|
||||
e.message
|
||||
|
||||
gda = @GDA.new @set, nil
|
||||
gda.instance_variable_set :@vendor_set, @vendor_set
|
||||
gda.gem name, :path => directory
|
||||
|
||||
e = assert_raises ArgumentError do
|
||||
gda.gem name
|
||||
end
|
||||
|
||||
assert_equal "duplicate source (default) for gem #{name}",
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_gem_deps_file
|
||||
assert_equal 'gem.deps.rb', @gda.gem_deps_file
|
||||
|
||||
|
@ -85,25 +266,22 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
assert_equal 'Gemfile', gda.gem_deps_file
|
||||
end
|
||||
|
||||
def test_gem_group_method
|
||||
groups = []
|
||||
|
||||
@gda.group :a do
|
||||
groups = @gda.send :gem_group, 'a', :group => :b, :groups => [:c, :d]
|
||||
end
|
||||
|
||||
assert_equal [:a, :b, :c, :d], groups.sort_by { |group| group.to_s }
|
||||
end
|
||||
|
||||
def test_group
|
||||
@gda.group :test do
|
||||
@gda.gem 'a'
|
||||
end
|
||||
|
||||
assert_equal [['a']], @gda.dependency_groups[:test]
|
||||
|
||||
assert_empty @set.dependencies
|
||||
end
|
||||
|
||||
def test_group_multiple
|
||||
@gda.group :a do
|
||||
@gda.gem 'a', :group => :b, :groups => [:c, :d]
|
||||
end
|
||||
|
||||
assert_equal [['a']], @gda.dependency_groups[:a]
|
||||
assert_equal [['a']], @gda.dependency_groups[:b]
|
||||
assert_equal [['a']], @gda.dependency_groups[:c]
|
||||
assert_equal [['a']], @gda.dependency_groups[:d]
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
end
|
||||
|
||||
def test_load
|
||||
|
@ -121,18 +299,12 @@ end
|
|||
|
||||
gda.load
|
||||
|
||||
expected = {
|
||||
:test => [['b']],
|
||||
}
|
||||
|
||||
assert_equal expected, gda.dependency_groups
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
assert_equal [dep('a'), dep('b')], @set.dependencies
|
||||
end
|
||||
end
|
||||
|
||||
def test_name_typo
|
||||
assert_same @GDA, Gem::RequestSet::DepedencyAPI
|
||||
assert_same @GDA, Gem::RequestSet::GemDepedencyAPI
|
||||
end
|
||||
|
||||
def test_platform_mswin
|
||||
|
@ -152,11 +324,30 @@ end
|
|||
end
|
||||
|
||||
def test_platforms
|
||||
win_platform, Gem.win_platform = Gem.win_platform?, false
|
||||
|
||||
@gda.platforms :ruby do
|
||||
@gda.gem 'a'
|
||||
end
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
|
||||
@gda.platforms :mswin do
|
||||
@gda.gem 'b'
|
||||
end
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
|
||||
Gem.win_platform = true
|
||||
|
||||
@gda.platforms :mswin do
|
||||
@gda.gem 'c'
|
||||
end
|
||||
|
||||
assert_equal [dep('a'), dep('c')], @set.dependencies
|
||||
|
||||
ensure
|
||||
Gem.win_platform = win_platform
|
||||
end
|
||||
|
||||
def test_ruby
|
||||
|
@ -164,8 +355,42 @@ end
|
|||
end
|
||||
|
||||
def test_ruby_engine
|
||||
assert @gda.ruby RUBY_VERSION,
|
||||
:engine => 'jruby', :engine_version => '1.7.4'
|
||||
with_engine_version 'jruby', '1.7.6' do
|
||||
assert @gda.ruby RUBY_VERSION,
|
||||
:engine => 'jruby', :engine_version => '1.7.6'
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def test_ruby_engine_mismatch_engine
|
||||
with_engine_version 'ruby', '2.0.0' do
|
||||
e = assert_raises Gem::RubyVersionMismatch do
|
||||
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
|
||||
end
|
||||
|
||||
assert_equal 'Your ruby engine is ruby, but your gem.deps.rb requires jruby',
|
||||
e.message
|
||||
end
|
||||
end
|
||||
|
||||
def test_ruby_engine_mismatch_version
|
||||
with_engine_version 'jruby', '1.7.6' do
|
||||
e = assert_raises Gem::RubyVersionMismatch do
|
||||
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
|
||||
end
|
||||
|
||||
assert_equal 'Your ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4',
|
||||
e.message
|
||||
end
|
||||
end
|
||||
|
||||
def test_ruby_engine_no_engine_version
|
||||
e = assert_raises ArgumentError do
|
||||
@gda.ruby RUBY_VERSION, :engine => 'jruby'
|
||||
end
|
||||
|
||||
assert_equal 'you must specify engine_version along with the ruby engine',
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_ruby_mismatch
|
||||
|
@ -173,7 +398,42 @@ end
|
|||
@gda.ruby '1.8.0'
|
||||
end
|
||||
|
||||
assert_equal "Your Ruby version is #{RUBY_VERSION}, but your gem.deps.rb specified 1.8.0", e.message
|
||||
assert_equal "Your Ruby version is #{RUBY_VERSION}, but your gem.deps.rb requires 1.8.0", e.message
|
||||
end
|
||||
|
||||
def test_source
|
||||
sources = Gem.sources
|
||||
|
||||
@gda.source 'http://first.example'
|
||||
|
||||
assert_equal %w[http://first.example], Gem.sources
|
||||
|
||||
assert_same sources, Gem.sources
|
||||
|
||||
@gda.source 'http://second.example'
|
||||
|
||||
assert_equal %w[http://first.example http://second.example], Gem.sources
|
||||
end
|
||||
|
||||
def test_with_engine_version
|
||||
version = RUBY_VERSION
|
||||
engine = Gem.ruby_engine
|
||||
|
||||
engine_version_const = "#{Gem.ruby_engine.upcase}_VERSION"
|
||||
engine_version = Object.const_get engine_version_const
|
||||
|
||||
with_engine_version 'other', '1.2.3' do
|
||||
assert_equal 'other', Gem.ruby_engine
|
||||
assert_equal '1.2.3', OTHER_VERSION
|
||||
|
||||
assert_equal version, RUBY_VERSION if engine
|
||||
end
|
||||
|
||||
assert_equal version, RUBY_VERSION
|
||||
assert_equal engine, Gem.ruby_engine
|
||||
|
||||
assert_equal engine_version, Object.const_get(engine_version_const) if
|
||||
engine
|
||||
end
|
||||
|
||||
end
|
||||
|
|
404
test/rubygems/test_gem_request_set_lockfile.rb
Normal file
404
test/rubygems/test_gem_request_set_lockfile.rb
Normal file
|
@ -0,0 +1,404 @@
|
|||
require 'rubygems/test_case'
|
||||
require 'rubygems/request_set'
|
||||
require 'rubygems/request_set/lockfile'
|
||||
|
||||
class TestGemRequestSetLockfile < Gem::TestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
|
||||
|
||||
util_set_arch 'i686-darwin8.10.1'
|
||||
|
||||
@set = Gem::RequestSet.new
|
||||
|
||||
@vendor_set = Gem::DependencyResolver::VendorSet.new
|
||||
|
||||
@set.instance_variable_set :@vendor_set, @vendor_set
|
||||
|
||||
@gem_deps_file = 'gem.deps.rb'
|
||||
|
||||
@lockfile = Gem::RequestSet::Lockfile.new @set, @gem_deps_file
|
||||
end
|
||||
|
||||
def write_gem_deps gem_deps
|
||||
open @gem_deps_file, 'w' do |io|
|
||||
io.write gem_deps
|
||||
end
|
||||
end
|
||||
|
||||
def write_lockfile lockfile
|
||||
@lock_file = File.expand_path "#{@gem_deps_file}.lock"
|
||||
|
||||
open @lock_file, 'w' do |io|
|
||||
io.write lockfile
|
||||
end
|
||||
end
|
||||
|
||||
def test_get
|
||||
@lockfile.instance_variable_set :@tokens, [:token]
|
||||
|
||||
assert_equal :token, @lockfile.get
|
||||
end
|
||||
|
||||
def test_get_type_mismatch
|
||||
@lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.get :text
|
||||
end
|
||||
|
||||
expected = 'unexpected token [:section, "x"], expected :text (at 5:1)'
|
||||
|
||||
assert_equal expected, e.message
|
||||
|
||||
assert_equal 5, e.line
|
||||
assert_equal 1, e.column
|
||||
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
||||
end
|
||||
|
||||
def test_get_type_value_mismatch
|
||||
@lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.get :section, 'y'
|
||||
end
|
||||
|
||||
expected =
|
||||
'unexpected token [:section, "x"], expected [:section, "y"] (at 5:1)'
|
||||
|
||||
assert_equal expected, e.message
|
||||
|
||||
assert_equal 5, e.line
|
||||
assert_equal 1, e.column
|
||||
assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
|
||||
end
|
||||
|
||||
def test_parse
|
||||
write_lockfile <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
|
||||
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::DependencyResolver::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_peek
|
||||
@lockfile.instance_variable_set :@tokens, [:token]
|
||||
|
||||
assert_equal :token, @lockfile.peek
|
||||
|
||||
assert_equal :token, @lockfile.get
|
||||
end
|
||||
|
||||
def test_skip
|
||||
tokens = [[:token]]
|
||||
|
||||
@lockfile.instance_variable_set :@tokens, tokens
|
||||
|
||||
@lockfile.skip :token
|
||||
|
||||
assert_empty tokens
|
||||
end
|
||||
|
||||
def test_token_pos
|
||||
assert_equal [5, 0], @lockfile.token_pos(5)
|
||||
|
||||
@lockfile.instance_variable_set :@line_pos, 2
|
||||
@lockfile.instance_variable_set :@line, 1
|
||||
|
||||
assert_equal [3, 1], @lockfile.token_pos(5)
|
||||
end
|
||||
|
||||
def test_tokenize
|
||||
write_lockfile <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a
|
||||
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],
|
||||
[:newline, nil, 0, 4],
|
||||
[:section, 'PLATFORMS', 0, 5],
|
||||
[:newline, nil, 9, 5],
|
||||
[:text, Gem::Platform::RUBY, 2, 6],
|
||||
[:newline, nil, 6, 6],
|
||||
[:newline, nil, 0, 7],
|
||||
[:section, 'DEPENDENCIES', 0, 8],
|
||||
[:newline, nil, 12, 8],
|
||||
[:text, 'a', 2, 9],
|
||||
[:newline, nil, 3, 9],
|
||||
]
|
||||
|
||||
assert_equal expected, @lockfile.tokenize
|
||||
end
|
||||
|
||||
def test_tokenize_conflict_markers
|
||||
write_lockfile '<<<<<<<'
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.tokenize
|
||||
end
|
||||
|
||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
||||
e.message
|
||||
|
||||
write_lockfile '|||||||'
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.tokenize
|
||||
end
|
||||
|
||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
||||
e.message
|
||||
|
||||
write_lockfile '======='
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.tokenize
|
||||
end
|
||||
|
||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
||||
e.message
|
||||
|
||||
write_lockfile '>>>>>>>'
|
||||
|
||||
e = assert_raises Gem::RequestSet::Lockfile::ParseError do
|
||||
@lockfile.tokenize
|
||||
end
|
||||
|
||||
assert_equal "your #{@lock_file} contains merge conflict markers (at 0:0)",
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_to_s_gem
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2
|
||||
end
|
||||
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_dependency
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2, 'c' => '>= 0', 'b' => '>= 0'
|
||||
fetcher.spec 'b', 2
|
||||
fetcher.spec 'c', 2
|
||||
end
|
||||
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
b
|
||||
c
|
||||
b (2)
|
||||
c (2)
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_dependency_non_default
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2, 'b' => '>= 1'
|
||||
fetcher.spec 'b', 2
|
||||
end
|
||||
|
||||
@set.gem 'b'
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
b (>= 1)
|
||||
b (2)
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a
|
||||
b
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_dependency_requirement
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2, 'b' => '>= 0'
|
||||
fetcher.spec 'b', 2
|
||||
end
|
||||
|
||||
@set.gem 'a', '>= 1'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2)
|
||||
b
|
||||
b (2)
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a (>= 1)
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_path
|
||||
name, version, directory = vendor_gem
|
||||
|
||||
@vendor_set.add_vendor_gem name, directory
|
||||
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
PATH
|
||||
remote: #{directory}
|
||||
specs:
|
||||
#{name} (#{version})
|
||||
|
||||
GEM
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a!
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_path_absolute
|
||||
name, version, directory = vendor_gem
|
||||
|
||||
@vendor_set.add_vendor_gem name, File.expand_path(directory)
|
||||
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
PATH
|
||||
remote: #{directory}
|
||||
specs:
|
||||
#{name} (#{version})
|
||||
|
||||
GEM
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform::RUBY}
|
||||
|
||||
DEPENDENCIES
|
||||
a!
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_to_s_gem_platform
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 2 do |spec|
|
||||
spec.platform = Gem::Platform.local
|
||||
end
|
||||
end
|
||||
|
||||
@set.gem 'a'
|
||||
|
||||
expected = <<-LOCKFILE
|
||||
GEM
|
||||
remote: #{@gem_repo}
|
||||
specs:
|
||||
a (2-#{Gem::Platform.local})
|
||||
|
||||
PLATFORMS
|
||||
#{Gem::Platform.local}
|
||||
|
||||
DEPENDENCIES
|
||||
a
|
||||
LOCKFILE
|
||||
|
||||
assert_equal expected, @lockfile.to_s
|
||||
end
|
||||
|
||||
def test_unget
|
||||
@lockfile.instance_variable_set :@current_token, :token
|
||||
|
||||
@lockfile.unget
|
||||
|
||||
assert_equal :token, @lockfile.get
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,6 +3,14 @@ require "rubygems/requirement"
|
|||
|
||||
class TestGemRequirement < Gem::TestCase
|
||||
|
||||
def test_concat
|
||||
r = req '>= 1'
|
||||
|
||||
r.concat ['< 2']
|
||||
|
||||
assert_equal [['>=', v(1)], ['<', v(2)]], r.requirements
|
||||
end
|
||||
|
||||
def test_equals2
|
||||
r = req "= 1.2"
|
||||
assert_equal r, r.dup
|
||||
|
@ -36,6 +44,12 @@ class TestGemRequirement < Gem::TestCase
|
|||
assert_equal false, r.none?
|
||||
end
|
||||
|
||||
def test_for_lockfile
|
||||
assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile
|
||||
|
||||
assert_nil Gem::Requirement.default.for_lockfile
|
||||
end
|
||||
|
||||
def test_parse
|
||||
assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1')
|
||||
assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1')
|
||||
|
|
|
@ -85,6 +85,30 @@ class TestGemServer < Gem::TestCase
|
|||
Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_latest_specs_gemdirs
|
||||
data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
dir = "#{@gemhome}2"
|
||||
|
||||
spec = quick_spec 'z', 9
|
||||
|
||||
specs_dir = File.join dir, 'specifications'
|
||||
FileUtils.mkdir_p specs_dir
|
||||
|
||||
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
||||
io.write spec.to_ruby
|
||||
end
|
||||
|
||||
server = Gem::Server.new dir, process_based_port, false
|
||||
|
||||
@req.parse data
|
||||
|
||||
server.latest_specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status
|
||||
|
||||
assert_equal [['z', v(9), Gem::Platform::RUBY]], Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_latest_specs_gz
|
||||
data = StringIO.new "GET /latest_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
@ -120,8 +144,41 @@ class TestGemServer < Gem::TestCase
|
|||
assert_equal 2, @server.server.listeners.length
|
||||
end
|
||||
|
||||
def test_quick_gemdirs
|
||||
data = StringIO.new "GET /quick/Marshal.4.8/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
dir = "#{@gemhome}2"
|
||||
|
||||
server = Gem::Server.new dir, process_based_port, false
|
||||
|
||||
@req.parse data
|
||||
|
||||
server.quick @req, @res
|
||||
|
||||
assert_equal 404, @res.status
|
||||
|
||||
spec = quick_spec 'z', 9
|
||||
|
||||
specs_dir = File.join dir, 'specifications'
|
||||
|
||||
FileUtils.mkdir_p specs_dir
|
||||
|
||||
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
||||
io.write spec.to_ruby
|
||||
end
|
||||
|
||||
data.rewind
|
||||
|
||||
req = WEBrick::HTTPRequest.new :Logger => nil
|
||||
res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
|
||||
req.parse data
|
||||
|
||||
server.quick req, res
|
||||
|
||||
assert_equal 200, res.status
|
||||
end
|
||||
|
||||
def test_quick_missing
|
||||
data = StringIO.new "GET /quick/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
data = StringIO.new "GET /quick/Marshal.4.8/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
@ -188,6 +245,29 @@ class TestGemServer < Gem::TestCase
|
|||
assert_equal 'text/html', @res['content-type']
|
||||
end
|
||||
|
||||
def test_root_gemdirs
|
||||
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
||||
dir = "#{@gemhome}2"
|
||||
|
||||
spec = quick_spec 'z', 9
|
||||
|
||||
specs_dir = File.join dir, 'specifications'
|
||||
FileUtils.mkdir_p specs_dir
|
||||
|
||||
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
||||
io.write spec.to_ruby
|
||||
end
|
||||
|
||||
server = Gem::Server.new dir, process_based_port, false
|
||||
|
||||
@req.parse data
|
||||
|
||||
server.root @req, @res
|
||||
|
||||
assert_equal 200, @res.status
|
||||
assert_match 'z 9', @res.body
|
||||
end
|
||||
|
||||
def test_specs
|
||||
data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
@ -203,6 +283,30 @@ class TestGemServer < Gem::TestCase
|
|||
Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_specs_gemdirs
|
||||
data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
dir = "#{@gemhome}2"
|
||||
|
||||
spec = quick_spec 'z', 9
|
||||
|
||||
specs_dir = File.join dir, 'specifications'
|
||||
FileUtils.mkdir_p specs_dir
|
||||
|
||||
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
||||
io.write spec.to_ruby
|
||||
end
|
||||
|
||||
server = Gem::Server.new dir, process_based_port, false
|
||||
|
||||
@req.parse data
|
||||
|
||||
server.specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status
|
||||
|
||||
assert_equal [['z', v(9), Gem::Platform::RUBY]], Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_specs_gz
|
||||
data = StringIO.new "GET /specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
|
|
@ -68,6 +68,20 @@ class TestGemSource < Gem::TestCase
|
|||
assert cache_dir !~ /:/, "#{cache_dir} should not contain a :"
|
||||
end
|
||||
|
||||
def test_dependency_resolver_set_bundler_api
|
||||
@fetcher.data["#{@gem_repo}api/v1/dependencies"] = 'data'
|
||||
|
||||
set = @source.dependency_resolver_set
|
||||
|
||||
assert_kind_of Gem::DependencyResolver::APISet, set
|
||||
end
|
||||
|
||||
def test_dependency_resolver_set_marshal_api
|
||||
set = @source.dependency_resolver_set
|
||||
|
||||
assert_kind_of Gem::DependencyResolver::IndexSet, set
|
||||
end
|
||||
|
||||
def test_fetch_spec
|
||||
spec_uri = "#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}"
|
||||
@fetcher.data["#{spec_uri}.rz"] = util_zip(Marshal.dump(@a1))
|
||||
|
|
|
@ -18,6 +18,10 @@ class TestGemSourceList < Gem::TestCase
|
|||
assert_equal [Gem::Source.new(@uri)], sl.sources
|
||||
end
|
||||
|
||||
def test_Enumerable
|
||||
assert_includes Gem::SourceList.ancestors, Enumerable
|
||||
end
|
||||
|
||||
def test_append
|
||||
sl = Gem::SourceList.new
|
||||
source = (sl << @uri)
|
||||
|
@ -30,6 +34,16 @@ class TestGemSourceList < Gem::TestCase
|
|||
assert_equal [source], sl.sources
|
||||
end
|
||||
|
||||
def test_clear
|
||||
sl = Gem::SourceList.new
|
||||
|
||||
sl << 'http://source.example'
|
||||
|
||||
sl.clear
|
||||
|
||||
assert_empty sl
|
||||
end
|
||||
|
||||
def test_replace
|
||||
sl = Gem::SourceList.new
|
||||
sl.replace [@uri]
|
||||
|
@ -49,6 +63,16 @@ class TestGemSourceList < Gem::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_empty?
|
||||
sl = Gem::SourceList.new
|
||||
|
||||
assert_empty sl
|
||||
|
||||
sl << 'http://source.example'
|
||||
|
||||
refute_empty sl
|
||||
end
|
||||
|
||||
def test_equal_to_another_list
|
||||
sl2 = Gem::SourceList.new
|
||||
sl2 << Gem::Source.new(@uri)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require 'rubygems/test_case'
|
||||
require 'rubygems/source/local'
|
||||
require 'rubygems/source'
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
|
|
13
test/rubygems/test_gem_source_vendor.rb
Normal file
13
test/rubygems/test_gem_source_vendor.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
require 'rubygems/test_case'
|
||||
require 'rubygems/source'
|
||||
|
||||
class TestGemSourceVendor < Gem::TestCase
|
||||
|
||||
def test_initialize
|
||||
source = Gem::Source::Vendor.new 'vendor/foo'
|
||||
|
||||
assert_equal 'vendor/foo', source.uri
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -52,7 +52,22 @@ class TestGemSpecFetcher < Gem::TestCase
|
|||
['x', Gem::Version.new(1), 'ruby']]
|
||||
end
|
||||
|
||||
def test_initialize_unwritable_home_dir
|
||||
def test_initialize
|
||||
fetcher = Gem::SpecFetcher.new
|
||||
|
||||
assert_same Gem.sources, fetcher.sources
|
||||
end
|
||||
|
||||
def test_initialize_source
|
||||
alternate = 'http://alternate.example'
|
||||
fetcher = Gem::SpecFetcher.new alternate
|
||||
|
||||
refute_same Gem.sources, fetcher.sources
|
||||
|
||||
assert_equal alternate, fetcher.sources
|
||||
end
|
||||
|
||||
def test_initialize_nonexistent_home_dir
|
||||
FileUtils.rmdir Gem.user_home
|
||||
|
||||
assert Gem::SpecFetcher.new
|
||||
|
|
|
@ -873,6 +873,31 @@ dependencies: []
|
|||
Gem::Specification.outdated_and_latest_version.to_a
|
||||
end
|
||||
|
||||
def test_self_remove_spec
|
||||
assert_includes Gem::Specification.all_names, 'a-1'
|
||||
assert_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
|
||||
|
||||
Gem::Specification.remove_spec @a1
|
||||
|
||||
refute_includes Gem::Specification.all_names, 'a-1'
|
||||
refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
|
||||
end
|
||||
|
||||
def test_self_remove_spec_removed
|
||||
open @a1.spec_file, 'w' do |io|
|
||||
io.write @a1.to_ruby
|
||||
end
|
||||
|
||||
Gem::Specification.reset
|
||||
|
||||
FileUtils.rm @a1.spec_file # bug #698
|
||||
|
||||
Gem::Specification.remove_spec @a1
|
||||
|
||||
refute_includes Gem::Specification.all_names, 'a-1'
|
||||
refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
|
||||
end
|
||||
|
||||
DATA_PATH = File.expand_path "../data", __FILE__
|
||||
|
||||
def test_handles_private_null_type
|
||||
|
@ -1886,7 +1911,7 @@ Gem::Specification.new do |s|
|
|||
s.rubygems_version = "#{Gem::VERSION}"
|
||||
s.summary = "this is a summary"
|
||||
|
||||
s.installed_by_version = "#{Gem::VERSION}"
|
||||
s.installed_by_version = "#{Gem::VERSION}" if s.respond_to? :installed_by_version
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
|
||||
|
@ -2128,6 +2153,15 @@ end
|
|||
Dir.chdir @tempdir do
|
||||
@a1.add_runtime_dependency 'b', '>= 1.0.rc1'
|
||||
@a1.add_development_dependency 'c', '>= 2.0.rc2'
|
||||
@a1.add_runtime_dependency 'd', '~> 1.2.3'
|
||||
@a1.add_runtime_dependency 'e', '~> 1.2.3.4'
|
||||
@a1.add_runtime_dependency 'g', '~> 1.2.3', '>= 1.2.3.4'
|
||||
@a1.add_runtime_dependency 'h', '>= 1.2.3', '<= 2'
|
||||
@a1.add_runtime_dependency 'i', '>= 1.2'
|
||||
@a1.add_runtime_dependency 'j', '>= 1.2.3'
|
||||
@a1.add_runtime_dependency 'k', '> 1.2'
|
||||
@a1.add_runtime_dependency 'l', '> 1.2.3'
|
||||
@a1.add_runtime_dependency 'm', '~> 2.1.0'
|
||||
|
||||
use_ui @ui do
|
||||
@a1.validate
|
||||
|
@ -2136,9 +2170,57 @@ end
|
|||
expected = <<-EXPECTED
|
||||
#{w}: prerelease dependency on b (>= 1.0.rc1) is not recommended
|
||||
#{w}: prerelease dependency on c (>= 2.0.rc2, development) is not recommended
|
||||
#{w}: pessimistic dependency on d (~> 1.2.3) may be overly strict
|
||||
if d is semantically versioned, use:
|
||||
add_runtime_dependency 'd', '~> 1.2', '>= 1.2.3'
|
||||
#{w}: pessimistic dependency on e (~> 1.2.3.4) may be overly strict
|
||||
if e is semantically versioned, use:
|
||||
add_runtime_dependency 'e', '~> 1.2', '>= 1.2.3.4'
|
||||
#{w}: open-ended dependency on i (>= 1.2) is not recommended
|
||||
if i is semantically versioned, use:
|
||||
add_runtime_dependency 'i', '~> 1.2'
|
||||
#{w}: open-ended dependency on j (>= 1.2.3) is not recommended
|
||||
if j is semantically versioned, use:
|
||||
add_runtime_dependency 'j', '~> 1.2', '>= 1.2.3'
|
||||
#{w}: open-ended dependency on k (> 1.2) is not recommended
|
||||
if k is semantically versioned, use:
|
||||
add_runtime_dependency 'k', '~> 1.2', '> 1.2'
|
||||
#{w}: open-ended dependency on l (> 1.2.3) is not recommended
|
||||
if l is semantically versioned, use:
|
||||
add_runtime_dependency 'l', '~> 1.2', '> 1.2.3'
|
||||
#{w}: pessimistic dependency on m (~> 2.1.0) may be overly strict
|
||||
if m is semantically versioned, use:
|
||||
add_runtime_dependency 'm', '~> 2.1', '>= 2.1.0'
|
||||
#{w}: See http://guides.rubygems.org/specification-reference/ for help
|
||||
EXPECTED
|
||||
|
||||
assert_match expected, @ui.error, 'warning'
|
||||
assert_equal expected, @ui.error, 'warning'
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_dependencies_open_ended
|
||||
util_setup_validate
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
@a1.add_runtime_dependency 'b', '~> 1.2'
|
||||
@a1.add_runtime_dependency 'b', '>= 1.2.3'
|
||||
|
||||
use_ui @ui do
|
||||
e = assert_raises Gem::InvalidSpecificationException do
|
||||
@a1.validate
|
||||
end
|
||||
|
||||
expected = <<-EXPECTED
|
||||
duplicate dependency on b (>= 1.2.3), (~> 1.2) use:
|
||||
add_runtime_dependency 'b', '>= 1.2.3', '~> 1.2'
|
||||
EXPECTED
|
||||
|
||||
assert_equal expected, e.message
|
||||
end
|
||||
|
||||
assert_equal <<-EXPECTED, @ui.error
|
||||
#{w}: See http://guides.rubygems.org/specification-reference/ for help
|
||||
EXPECTED
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@ class TestStubSpecification < Gem::TestCase
|
|||
def test_initialize_extension
|
||||
stub = stub_with_extension
|
||||
|
||||
gem_dir = File.join stub.gems_dir, stub.full_name
|
||||
|
||||
ext_install_dir = Pathname(stub.extension_install_dir)
|
||||
full_gem_path = Pathname(stub.full_gem_path)
|
||||
relative_install_dir = ext_install_dir.relative_path_from full_gem_path
|
||||
|
|
Loading…
Add table
Reference in a new issue