mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/rubygems: Update to RubyGems master 50a8210. Important changes
in this commit: RubyGems now automatically checks for gem.deps.rb or Gemfile when running ruby executables. This behavior is similar to `bundle exec rake`. This change may be reverted before Ruby 2.1.0 if too many bugs are found. * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43767 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b1529a30e0
commit
5307d803f5
30 changed files with 714 additions and 196 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
Fri Nov 22 08:27:13 2013 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* lib/rubygems: Update to RubyGems master 50a8210. Important changes
|
||||
in this commit:
|
||||
|
||||
RubyGems now automatically checks for gem.deps.rb or Gemfile when
|
||||
running ruby executables. This behavior is similar to `bundle exec
|
||||
rake`. This change may be reverted before Ruby 2.1.0 if too many bugs
|
||||
are found.
|
||||
|
||||
* test/rubygems: ditto.
|
||||
|
||||
Thu Nov 21 22:33:59 2013 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* gc.c: RGENGC_CHECK_MODE should be 0.
|
||||
|
|
|
@ -215,50 +215,6 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
def self.detect_gemdeps
|
||||
if path = ENV['RUBYGEMS_GEMDEPS']
|
||||
path = path.dup.untaint
|
||||
|
||||
if path == "-"
|
||||
here = Dir.pwd.untaint
|
||||
start = here
|
||||
|
||||
begin
|
||||
while true
|
||||
path = GEM_DEP_FILES.find { |f| File.file?(f) }
|
||||
|
||||
if path
|
||||
path = File.join here, path
|
||||
break
|
||||
end
|
||||
|
||||
Dir.chdir ".."
|
||||
|
||||
# If we're at a toplevel, stop.
|
||||
return if Dir.pwd == here
|
||||
|
||||
here = Dir.pwd
|
||||
end
|
||||
ensure
|
||||
Dir.chdir start
|
||||
end
|
||||
end
|
||||
|
||||
path.untaint
|
||||
|
||||
return unless File.file? path
|
||||
|
||||
rs = Gem::RequestSet.new
|
||||
rs.load_gemdeps path
|
||||
|
||||
rs.resolve_current.map do |s|
|
||||
sp = s.full_spec
|
||||
sp.activate
|
||||
sp
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Find the full path to the executable for gem +name+. If the +exec_name+
|
||||
# is not given, the gem's default_executable is chosen, otherwise the
|
||||
|
@ -1035,6 +991,61 @@ module Gem
|
|||
load_plugin_files files
|
||||
end
|
||||
|
||||
##
|
||||
# Looks for gem dependency files (gem.deps.rb, Gemfile, Isolate) from the
|
||||
# current directory up and activates the gems in the first file found.
|
||||
#
|
||||
# This is run automatically when rubygems starts. To disable, set
|
||||
# the <code>RUBYGEMS_GEMDEPS=</code> environment variable to an empty
|
||||
# string.
|
||||
|
||||
def self.use_gemdeps
|
||||
return unless path = ENV['RUBYGEMS_GEMDEPS'] || '-'
|
||||
path = path.dup.untaint
|
||||
|
||||
if path == "-"
|
||||
here = Dir.pwd.untaint
|
||||
start = here
|
||||
|
||||
begin
|
||||
while true
|
||||
path = GEM_DEP_FILES.find { |f| File.file?(f) }
|
||||
|
||||
if path
|
||||
path = File.join here, path
|
||||
break
|
||||
end
|
||||
|
||||
Dir.chdir ".."
|
||||
|
||||
# If we're at a toplevel, stop.
|
||||
return if Dir.pwd == here
|
||||
|
||||
here = Dir.pwd
|
||||
end
|
||||
ensure
|
||||
Dir.chdir start
|
||||
end
|
||||
end
|
||||
|
||||
path.untaint
|
||||
|
||||
return unless File.file? path
|
||||
|
||||
rs = Gem::RequestSet.new
|
||||
rs.load_gemdeps path
|
||||
|
||||
rs.resolve_current.map do |s|
|
||||
sp = s.full_spec
|
||||
sp.activate
|
||||
sp
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
alias detect_gemdeps use_gemdeps # :nodoc:
|
||||
end
|
||||
|
||||
# FIX: Almost everywhere else we use the `def self.` way of defining class
|
||||
# methods, and then we switch over to `class << self` here. Pick one or the
|
||||
# other.
|
||||
|
|
|
@ -27,10 +27,13 @@ class Gem::Doctor
|
|||
['gems', ''],
|
||||
]
|
||||
|
||||
raise 'Update REPOSITORY_EXTENSION_MAP' unless
|
||||
Gem::REPOSITORY_SUBDIRECTORIES.sort ==
|
||||
missing =
|
||||
Gem::REPOSITORY_SUBDIRECTORIES.sort -
|
||||
REPOSITORY_EXTENSION_MAP.map { |(k,_)| k }.sort
|
||||
|
||||
raise "Update REPOSITORY_EXTENSION_MAP, missing: #{missing.join ', '}" unless
|
||||
missing.empty?
|
||||
|
||||
##
|
||||
# Creates a new Gem::Doctor that will clean up +gem_repository+. Only one
|
||||
# gem repository may be cleaned at a time.
|
||||
|
|
|
@ -223,7 +223,7 @@ class Gem::UnsatisfiableDependencyError < Gem::Exception
|
|||
attr_reader :dependency
|
||||
|
||||
##
|
||||
# Creates a new UnsatisfiableDepedencyError for the unsatisfiable
|
||||
# Creates a new UnsatisfiableDependencyError for the unsatisfiable
|
||||
# Gem::Resolver::DependencyRequest +dep+
|
||||
|
||||
def initialize dep, platform_mismatch=nil
|
||||
|
|
|
@ -2,6 +2,7 @@ require 'rubygems'
|
|||
require 'rubygems/dependency'
|
||||
require 'rubygems/dependency_list'
|
||||
require 'rubygems/installer'
|
||||
require 'rubygems/resolver'
|
||||
require 'tsort'
|
||||
|
||||
##
|
||||
|
@ -146,8 +147,16 @@ class Gem::RequestSet
|
|||
|
||||
resolve
|
||||
|
||||
if options[:explain]
|
||||
puts "Gems to install:"
|
||||
|
||||
specs.map { |s| s.full_name }.sort.each do |s|
|
||||
puts " #{s}"
|
||||
end
|
||||
else
|
||||
install options, &block
|
||||
end
|
||||
end
|
||||
|
||||
def install_into dir, force = true, options = {}
|
||||
existing = force ? [] : specs_in(dir)
|
||||
|
@ -201,7 +210,7 @@ class Gem::RequestSet
|
|||
# Resolve the requested dependencies and return an Array of Specification
|
||||
# objects to be activated.
|
||||
|
||||
def resolve set = Gem::Resolver::IndexSet.new
|
||||
def resolve set = Gem::Resolver::BestSet.new
|
||||
@sets << set
|
||||
@sets << @git_set
|
||||
@sets << @vendor_set
|
||||
|
@ -253,7 +262,7 @@ class Gem::RequestSet
|
|||
end
|
||||
else
|
||||
unless @soft_missing
|
||||
raise Gem::DependencyError, "Unresolved depedency found during sorting - #{dep}"
|
||||
raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -115,7 +115,7 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
##
|
||||
# A Hash containing gem names and files to require from those gems.
|
||||
|
||||
attr_reader :requires
|
||||
attr_reader :requires # :nodoc:
|
||||
|
||||
##
|
||||
# A set of gems that are loaded via the +:path+ option to #gem
|
||||
|
@ -125,7 +125,7 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
##
|
||||
# The groups of gems to exclude from installation
|
||||
|
||||
attr_accessor :without_groups
|
||||
attr_accessor :without_groups # :nodoc:
|
||||
|
||||
##
|
||||
# Creates a new GemDependencyAPI that will add dependencies to the
|
||||
|
@ -282,6 +282,8 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
true
|
||||
end
|
||||
|
||||
private :gem_github
|
||||
|
||||
##
|
||||
# Handles the :group and :groups +options+ for the gem with the given
|
||||
# +name+.
|
||||
|
@ -361,7 +363,7 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
def gem_requires name, options # :nodoc:
|
||||
if options.include? :require then
|
||||
if requires = options.delete(:require) then
|
||||
@requires[name].concat requires
|
||||
@requires[name].concat Array requires
|
||||
end
|
||||
else
|
||||
@requires[name] << name
|
||||
|
@ -370,6 +372,11 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
|
||||
private :gem_requires
|
||||
|
||||
##
|
||||
# :category: Gem Dependencies DSL
|
||||
#
|
||||
# Block form for specifying gems from a git +repository+.
|
||||
|
||||
def git repository
|
||||
@current_repository = repository
|
||||
|
||||
|
@ -424,6 +431,8 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
|
||||
##
|
||||
# :category: Gem Dependencies DSL
|
||||
#
|
||||
# Block form for restricting gems to a particular platform.
|
||||
|
||||
def platform what
|
||||
@current_platform = what
|
||||
|
@ -436,6 +445,8 @@ class Gem::RequestSet::GemDependencyAPI
|
|||
|
||||
##
|
||||
# :category: Gem Dependencies DSL
|
||||
#
|
||||
# Block form for restricting gems to a particular platform.
|
||||
|
||||
alias :platforms :platform
|
||||
|
||||
|
|
|
@ -29,9 +29,23 @@ class Gem::Resolver
|
|||
|
||||
attr_accessor :soft_missing
|
||||
|
||||
##
|
||||
# Combines +sets+ into a ComposedSet that allows specification lookup in a
|
||||
# uniform manner. If one of the +sets+ is itself a ComposedSet its sets are
|
||||
# flattened into the result ComposedSet.
|
||||
|
||||
def self.compose_sets *sets
|
||||
sets.compact!
|
||||
|
||||
sets = sets.map do |set|
|
||||
case set
|
||||
when Gem::Resolver::ComposedSet then
|
||||
set.sets
|
||||
else
|
||||
set
|
||||
end
|
||||
end.flatten
|
||||
|
||||
case sets.length
|
||||
when 0 then
|
||||
raise ArgumentError, 'one set in the composition must be non-nil'
|
||||
|
@ -77,6 +91,15 @@ class Gem::Resolver
|
|||
end
|
||||
end
|
||||
|
||||
def explain_list(stage, data)
|
||||
if DEBUG_RESOLVER
|
||||
STDOUT.printf "%20s (%d entries)\n", stage.to_s.upcase, data.size
|
||||
data.each do |d|
|
||||
STDOUT.printf "%20s %s\n", "", d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Creates an ActivationRequest for the given +dep+ and the last +possible+
|
||||
# specification.
|
||||
|
@ -134,8 +157,6 @@ class Gem::Resolver
|
|||
# If no good candidate is found, the first state is tried.
|
||||
|
||||
def find_conflict_state conflict, states # :nodoc:
|
||||
rejected = []
|
||||
|
||||
until states.empty? do
|
||||
state = states.pop
|
||||
|
||||
|
@ -145,14 +166,9 @@ class Gem::Resolver
|
|||
state.conflicts << [state.spec, conflict]
|
||||
return state
|
||||
end
|
||||
|
||||
rejected << state
|
||||
end
|
||||
|
||||
return rejected.shift
|
||||
ensure
|
||||
rejected = rejected.concat states
|
||||
states.replace rejected
|
||||
nil
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -172,14 +188,23 @@ class Gem::Resolver
|
|||
|
||||
# If the existing activation indicates that there are other possibles for
|
||||
# it, then issue the conflict on the dependency for the activation itself.
|
||||
# Otherwise, issue it on the requester's request itself.
|
||||
if existing.others_possible? or existing.request.requester.nil? then
|
||||
# Otherwise, if there was a requester, issue it on the requester's
|
||||
# request itself.
|
||||
# Finally, if the existing request has no requester (toplevel) unwind to
|
||||
# it anyway.
|
||||
|
||||
if existing.others_possible?
|
||||
conflict =
|
||||
Gem::Resolver::Conflict.new dep, existing
|
||||
else
|
||||
elsif dep.requester
|
||||
depreq = dep.requester.request
|
||||
conflict =
|
||||
Gem::Resolver::Conflict.new depreq, existing, dep
|
||||
elsif existing.request.requester.nil?
|
||||
conflict =
|
||||
Gem::Resolver::Conflict.new dep, existing
|
||||
else
|
||||
raise Gem::DependencyError, "Unable to figure out how to unwind conflict"
|
||||
end
|
||||
|
||||
@conflicts << conflict unless @conflicts.include? conflict
|
||||
|
@ -234,6 +259,8 @@ class Gem::Resolver
|
|||
while !needed.empty?
|
||||
dep = needed.remove
|
||||
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
|
||||
explain_list :next5, needed.next5
|
||||
explain_list :specs, Array(specs).map { |x| x.full_name }.sort
|
||||
|
||||
# If there is already a spec activated for the requested name...
|
||||
if specs && existing = specs.find { |s| dep.name == s.name }
|
||||
|
@ -284,7 +311,7 @@ class Gem::Resolver
|
|||
# Retry resolution with this spec and add it's dependencies
|
||||
spec, act = activation_request state.dep, state.possibles
|
||||
|
||||
needed = requests spec, act, state.needed
|
||||
needed = requests spec, act, state.needed.dup
|
||||
specs = Gem::List.prepend state.specs, act
|
||||
|
||||
return needed, specs
|
||||
|
|
|
@ -10,13 +10,28 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
|||
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
|
||||
# The Gem::Source that gems are fetched from
|
||||
|
||||
attr_reader :source
|
||||
|
||||
##
|
||||
# The corresponding place to fetch gems.
|
||||
|
||||
attr_reader :uri
|
||||
|
||||
##
|
||||
# Creates a new APISet that will retrieve gems from +uri+ using the RubyGems
|
||||
# API URL +dep_uri+ which is described at
|
||||
# http://guides.rubygems.org/rubygems-org-api
|
||||
|
||||
def initialize dep_uri = 'https://rubygems.org/api/v1/dependencies'
|
||||
dep_uri = URI dep_uri unless URI === dep_uri # for ruby 1.8
|
||||
|
||||
@dep_uri = dep_uri
|
||||
@uri = dep_uri + '../../..'
|
||||
|
||||
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
|
||||
@source = Gem::Source.new @uri
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -41,15 +56,35 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
|||
|
||||
def prefetch reqs
|
||||
names = reqs.map { |r| r.dependency.name }
|
||||
needed = names.find_all { |d| !@data.key?(d) }
|
||||
needed = names - @data.keys
|
||||
|
||||
return if needed.empty?
|
||||
|
||||
uri = @dep_uri + "?gems=#{needed.sort.join ','}"
|
||||
str = Gem::RemoteFetcher.fetcher.fetch_path uri
|
||||
|
||||
loaded = []
|
||||
|
||||
Marshal.load(str).each do |ver|
|
||||
@data[ver[:name]] << ver
|
||||
name = ver[:name]
|
||||
|
||||
@data[name] << ver
|
||||
loaded << name
|
||||
end
|
||||
|
||||
(needed - loaded).each do |missing|
|
||||
@data[missing] = []
|
||||
end
|
||||
end
|
||||
|
||||
def pretty_print q # :nodoc:
|
||||
q.group 2, '[APISet', ']' do
|
||||
q.breakable
|
||||
q.text "URI: #{@dep_uri}"
|
||||
|
||||
q.breakable
|
||||
q.text 'gem names:'
|
||||
q.pp @data.keys
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,5 +34,42 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
|
|||
@dependencies == other.dependencies
|
||||
end
|
||||
|
||||
def pretty_print q # :nodoc:
|
||||
q.group 2, '[APISpecification', ']' do
|
||||
q.breakable
|
||||
q.text "name: #{name}"
|
||||
|
||||
q.breakable
|
||||
q.text "version: #{version}"
|
||||
|
||||
q.breakable
|
||||
q.text "platform: #{platform}"
|
||||
|
||||
q.breakable
|
||||
q.text 'dependencies:'
|
||||
q.breakable
|
||||
q.pp @dependencies
|
||||
|
||||
q.breakable
|
||||
q.text "set uri: #{@set.dep_uri}"
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Fetches a Gem::Specification for this APISpecification.
|
||||
|
||||
def spec # :nodoc:
|
||||
@spec ||=
|
||||
begin
|
||||
tuple = Gem::NameTuple.new @name, @version, @platform
|
||||
|
||||
source.fetch_spec tuple
|
||||
end
|
||||
end
|
||||
|
||||
def source # :nodoc:
|
||||
@set.source
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,17 +1,36 @@
|
|||
##
|
||||
# A ComposedSet allows multiple sets to be queried like a single set.
|
||||
#
|
||||
# To create a composed set with any number of sets use:
|
||||
#
|
||||
# Gem::Resolver.compose_sets set1, set2
|
||||
#
|
||||
# This method will eliminate nesting of composed sets.
|
||||
|
||||
class Gem::Resolver::ComposedSet < Gem::Resolver::Set
|
||||
|
||||
attr_reader :sets # :nodoc:
|
||||
|
||||
##
|
||||
# Creates a new ComposedSet containing +sets+. Use
|
||||
# Gem::Resolver::compose_sets instead.
|
||||
|
||||
def initialize *sets
|
||||
@sets = sets
|
||||
end
|
||||
|
||||
##
|
||||
# Finds all specs matching +req+ in all sets.
|
||||
|
||||
def find_all req
|
||||
res = []
|
||||
@sets.each { |s| res += s.find_all(req) }
|
||||
res
|
||||
end
|
||||
|
||||
##
|
||||
# Prefetches +reqs+ in all sets.
|
||||
|
||||
def prefetch reqs
|
||||
@sets.each { |s| s.prefetch(reqs) }
|
||||
end
|
||||
|
|
|
@ -4,25 +4,38 @@
|
|||
|
||||
class Gem::Resolver::Conflict
|
||||
|
||||
##
|
||||
# The specification that was activated prior to the conflict
|
||||
|
||||
attr_reader :activated
|
||||
|
||||
##
|
||||
# The dependency that is in conflict with the activated gem.
|
||||
|
||||
attr_reader :dependency
|
||||
|
||||
attr_reader :failed_dep # :nodoc:
|
||||
|
||||
##
|
||||
# Creates a new resolver conflict when +dependency+ is in conflict with an
|
||||
# already +activated+ specification.
|
||||
|
||||
def initialize(dependency, activated, failed_dep=dependency)
|
||||
@dependency = dependency
|
||||
@activated = activated
|
||||
@failed_dep = failed_dep
|
||||
end
|
||||
|
||||
def == other
|
||||
def == other # :nodoc:
|
||||
self.class === other and
|
||||
@dependency == other.dependency and
|
||||
@activated == other.activated and
|
||||
@failed_dep == other.failed_dep
|
||||
end
|
||||
|
||||
##
|
||||
# A string explanation of the conflict.
|
||||
|
||||
def explain
|
||||
"<Conflict wanted: #{@failed_dep}, had: #{activated.spec.full_name}>"
|
||||
end
|
||||
|
@ -41,11 +54,15 @@ class Gem::Resolver::Conflict
|
|||
activated = @activated.spec.full_name
|
||||
requirement = @failed_dep.dependency.requirement
|
||||
|
||||
" Activated %s instead of (%s) via:\n %s\n" % [
|
||||
activated, requirement, request_path.join(', ')
|
||||
" Activated %s via:\n %s\n instead of (%s) via:\n %s\n" % [
|
||||
activated, request_path(@activated).join(', '),
|
||||
requirement, request_path(requester).join(', '),
|
||||
]
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true if the conflicting dependency's name matches +spec+.
|
||||
|
||||
def for_spec?(spec)
|
||||
@dependency.name == spec.name
|
||||
end
|
||||
|
@ -72,16 +89,17 @@ class Gem::Resolver::Conflict
|
|||
end
|
||||
|
||||
##
|
||||
# Path of specifications that requested this dependency
|
||||
# Path of activations from the +current+ list.
|
||||
|
||||
def request_path
|
||||
current = requester
|
||||
def request_path current
|
||||
path = []
|
||||
|
||||
while current do
|
||||
path << current.spec.full_name
|
||||
spec_name = current.spec.full_name
|
||||
requirement = current.request.dependency.requirement
|
||||
path << "#{current.spec.full_name} (#{requirement})"
|
||||
|
||||
current = current.request.requester
|
||||
current = current.parent
|
||||
end
|
||||
|
||||
path = ['user request (gem command or Gemfile)'] if path.empty?
|
||||
|
@ -98,5 +116,8 @@ class Gem::Resolver::Conflict
|
|||
|
||||
end
|
||||
|
||||
Gem::Resolver::DependencyConflict = Gem::Resolver::Conflict
|
||||
##
|
||||
# TODO: Remove in RubyGems 3
|
||||
|
||||
Gem::Resolver::DependencyConflict = Gem::Resolver::Conflict # :nodoc:
|
||||
|
||||
|
|
|
@ -42,38 +42,27 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
|
|||
# Finds all git gems matching +req+
|
||||
|
||||
def find_all req
|
||||
@repositories.keys.select do |name|
|
||||
name == req.name
|
||||
end.map do |name|
|
||||
@specs[name] || load_spec(name)
|
||||
end.select do |spec|
|
||||
prefetch nil
|
||||
|
||||
specs.values.select do |spec|
|
||||
req.matches_spec? spec
|
||||
end
|
||||
end
|
||||
|
||||
def load_spec name
|
||||
repository, reference = @repositories[name]
|
||||
|
||||
source = Gem::Source::Git.new name, repository, reference
|
||||
|
||||
spec = source.load_spec name
|
||||
|
||||
git_spec =
|
||||
Gem::Resolver::GitSpecification.new self, spec, source
|
||||
|
||||
@specs[name] = git_spec
|
||||
end
|
||||
|
||||
##
|
||||
# Prefetches specifications from the git repositories in this set.
|
||||
|
||||
def prefetch reqs
|
||||
names = reqs.map { |req| req.name }
|
||||
return unless @specs.empty?
|
||||
|
||||
@repositories.each_key do |name|
|
||||
next unless names.include? name
|
||||
@repositories.each do |name, (repository, reference)|
|
||||
source = Gem::Source::Git.new name, repository, reference
|
||||
|
||||
load_spec name
|
||||
source.specs.each do |spec|
|
||||
git_spec = Gem::Resolver::GitSpecification.new self, spec, source
|
||||
|
||||
@specs[spec.name] = git_spec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,4 +37,8 @@ class Gem::Resolver::RequirementList
|
|||
def remove
|
||||
@list.shift
|
||||
end
|
||||
|
||||
def next5
|
||||
@list[0,5]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,30 @@
|
|||
require 'uri'
|
||||
require 'fileutils'
|
||||
|
||||
##
|
||||
# A Source knows how to list and fetch gems from a RubyGems marshal index.
|
||||
#
|
||||
# There are other Source subclasses for installed gems, local gems, the
|
||||
# bundler dependency API and so-forth.
|
||||
|
||||
class Gem::Source
|
||||
FILES = {
|
||||
|
||||
include Comparable
|
||||
|
||||
FILES = { # :nodoc:
|
||||
:released => 'specs',
|
||||
:latest => 'latest_specs',
|
||||
:prerelease => 'prerelease_specs',
|
||||
}
|
||||
|
||||
##
|
||||
# The URI this source will fetch gems from.
|
||||
|
||||
attr_reader :uri
|
||||
|
||||
##
|
||||
# Creates a new Source which will use the index located at +uri+.
|
||||
|
||||
def initialize(uri)
|
||||
unless uri.kind_of? URI
|
||||
uri = URI.parse(uri.to_s)
|
||||
|
@ -17,13 +34,17 @@ class Gem::Source
|
|||
@api_uri = nil
|
||||
end
|
||||
|
||||
attr_reader :uri
|
||||
##
|
||||
# Use an SRV record on the host to look up the true endpoint for the index.
|
||||
|
||||
def api_uri
|
||||
def api_uri # :nodoc:
|
||||
require 'rubygems/remote_fetcher'
|
||||
@api_uri ||= Gem::RemoteFetcher.fetcher.api_endpoint uri
|
||||
end
|
||||
|
||||
##
|
||||
# Sources are ordered by installation preference.
|
||||
|
||||
def <=>(other)
|
||||
case other
|
||||
when Gem::Source::Installed,
|
||||
|
@ -46,13 +67,11 @@ class Gem::Source
|
|||
end
|
||||
end
|
||||
|
||||
include Comparable
|
||||
|
||||
def ==(other)
|
||||
def == other # :nodoc:
|
||||
self.class === other and @uri == other.uri
|
||||
end
|
||||
|
||||
alias_method :eql?, :==
|
||||
alias_method :eql?, :== # :nodoc:
|
||||
|
||||
##
|
||||
# Returns a Set that can fetch specifications from this source.
|
||||
|
@ -70,7 +89,7 @@ class Gem::Source
|
|||
end
|
||||
end
|
||||
|
||||
def hash
|
||||
def hash # :nodoc:
|
||||
@uri.hash
|
||||
end
|
||||
|
||||
|
@ -83,6 +102,9 @@ class Gem::Source
|
|||
File.join Gem.spec_cache_dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true when it is possible and safe to update the cache directory.
|
||||
|
||||
def update_cache?
|
||||
@update_cache ||=
|
||||
begin
|
||||
|
@ -166,6 +188,10 @@ class Gem::Source
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Downloads +spec+ and writes it to +dir+. See also
|
||||
# Gem::RemoteFetcher#download.
|
||||
|
||||
def download(spec, dir=Dir.pwd)
|
||||
fetcher = Gem::RemoteFetcher.fetcher
|
||||
fetcher.download spec, api_uri.to_s, dir
|
||||
|
@ -176,7 +202,7 @@ class Gem::Source
|
|||
q.breakable
|
||||
q.text @uri.to_s
|
||||
if api = api_uri
|
||||
g.text api
|
||||
q.text api.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,9 +36,11 @@ class Gem::Source::Git < Gem::Source
|
|||
attr_reader :need_submodules
|
||||
|
||||
##
|
||||
# Creates a new git gem source for a gem with the given +name+ that will be
|
||||
# loaded from +reference+ in +repository+. If +submodules+ is true,
|
||||
# submodules will be checked out when the gem is installed.
|
||||
# Creates a new git gem source for a gems from loaded from +repository+ at
|
||||
# the given +reference+. The +name+ is only used to track the repository
|
||||
# back to a gem dependencies file, it has no real significance as a git
|
||||
# repository may contain multiple gems. If +submodules+ is true, submodules
|
||||
# will be checked out when the gem is installed.
|
||||
|
||||
def initialize name, repository, reference, submodules = false
|
||||
super(nil)
|
||||
|
@ -125,34 +127,6 @@ class Gem::Source::Git < Gem::Source
|
|||
File.join Gem.dir, 'bundler', 'gems', "#{@name}-#{dir_shortref}"
|
||||
end
|
||||
|
||||
##
|
||||
# Loads a Gem::Specification for +name+ from this git repository.
|
||||
|
||||
def load_spec name
|
||||
cache
|
||||
|
||||
gemspec_reference = "#{@reference}:#{name}.gemspec"
|
||||
|
||||
Dir.chdir repo_cache_dir do
|
||||
source = Gem::Util.popen @git, 'show', gemspec_reference
|
||||
|
||||
source.force_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
|
||||
source.untaint
|
||||
|
||||
begin
|
||||
spec = eval source, binding, gemspec_reference
|
||||
|
||||
return spec if Gem::Specification === spec
|
||||
|
||||
warn "git gem specification for #{@repository} #{gemspec_reference} is not a Gem::Specification (#{spec.class} instead)."
|
||||
rescue SignalException, SystemExit
|
||||
raise
|
||||
rescue SyntaxError, Exception
|
||||
warn "invalid git gem specification for #{@repository} #{gemspec_reference}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# The directory where the git gem's repository will be cached.
|
||||
|
||||
|
@ -164,12 +138,29 @@ class Gem::Source::Git < Gem::Source
|
|||
# Converts the git reference for the repository into a commit hash.
|
||||
|
||||
def rev_parse # :nodoc:
|
||||
# HACK no safe equivalent of ` exists on 1.8.7
|
||||
Dir.chdir repo_cache_dir do
|
||||
Gem::Util.popen(@git, 'rev-parse', @reference).strip
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Loads all gemspecs in the repository
|
||||
|
||||
def specs
|
||||
checkout
|
||||
|
||||
Dir.chdir install_dir do
|
||||
Dir['{,*,*/*}.gemspec'].map do |spec_file|
|
||||
directory = File.dirname spec_file
|
||||
file = File.basename spec_file
|
||||
|
||||
Dir.chdir directory do
|
||||
Gem::Specification.load file
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# A hash for the git gem based on the git repository URI.
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class Date; end
|
|||
# Gem::Specification.new do |s|
|
||||
# s.name = 'example'
|
||||
# s.version = '0.1.0'
|
||||
# s.licenses = ['MIT']
|
||||
# s.summary = "This is an example!"
|
||||
# s.description = "Much longer explanation of the example!"
|
||||
# s.authors = ["Ruby Coder"]
|
||||
|
@ -530,6 +531,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
end
|
||||
|
||||
##
|
||||
# :category: Recommended gemspec attributes
|
||||
# The license for this gem.
|
||||
#
|
||||
# The license must be a short name, no more than 64 characters.
|
||||
|
@ -538,7 +540,12 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
# text of the license should be inside of the gem when you build it.
|
||||
#
|
||||
# See http://opensource.org/licenses/alphabetical for a list of licenses and
|
||||
# their abbreviations (or short names).
|
||||
# their abbreviations (or short names). GitHub also provides a
|
||||
# license picker at http://choosealicense.com/
|
||||
#
|
||||
# According to copyright law, not having an OSI-approved open source license
|
||||
# means you have no rights to use the code for any purpose-- in other words,
|
||||
# "all rights reserved".
|
||||
#
|
||||
# You can set multiple licenses with #licenses=
|
||||
#
|
||||
|
@ -550,6 +557,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
end
|
||||
|
||||
##
|
||||
# :category: Recommended gemspec attributes
|
||||
# The license(s) for the library.
|
||||
#
|
||||
# Each license must be a short name, no more than 64 characters.
|
||||
|
@ -2526,7 +2534,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|||
}
|
||||
|
||||
warning <<-warning if licenses.empty?
|
||||
licenses is empty. Use a license abbreviation from:
|
||||
licenses is empty, but is recommended. Use a license abbreviation from:
|
||||
http://opensource.org/licenses/alphabetical
|
||||
warning
|
||||
|
||||
|
|
|
@ -1149,8 +1149,10 @@ Also, a list:
|
|||
def dependency_request dep, from_name, from_version, parent = nil
|
||||
remote = Gem::Source.new @uri
|
||||
|
||||
parent ||= Gem::Resolver::DependencyRequest.new \
|
||||
dep, nil
|
||||
unless parent then
|
||||
parent_dep = dep from_name, from_version
|
||||
parent = Gem::Resolver::DependencyRequest.new parent_dep, nil
|
||||
end
|
||||
|
||||
spec = Gem::Resolver::IndexSpecification.new \
|
||||
nil, from_name, from_version, remote, Gem::Platform::RUBY
|
||||
|
|
|
@ -40,8 +40,7 @@ module Gem::Util
|
|||
# for a command.
|
||||
|
||||
def self.popen *command
|
||||
begin
|
||||
r, = IO.popen command, &:read
|
||||
IO.popen command, &:read
|
||||
rescue TypeError # ruby 1.8 only supports string command
|
||||
r, w = IO.pipe
|
||||
|
||||
|
@ -62,5 +61,3 @@ module Gem::Util
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1245,6 +1245,60 @@ class TestGem < Gem::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_use_gemdeps
|
||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
|
||||
|
||||
spec = util_spec 'a', 1
|
||||
|
||||
refute spec.activated?
|
||||
|
||||
open 'Gemfile', 'w' do |io|
|
||||
io.write 'gem "a"'
|
||||
end
|
||||
|
||||
Gem.use_gemdeps
|
||||
|
||||
assert spec.activated?
|
||||
ensure
|
||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||
end
|
||||
|
||||
def test_use_gemdeps_disabled
|
||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], ''
|
||||
|
||||
spec = util_spec 'a', 1
|
||||
|
||||
refute spec.activated?
|
||||
|
||||
open 'Gemfile', 'w' do |io|
|
||||
io.write 'gem "a"'
|
||||
end
|
||||
|
||||
Gem.use_gemdeps
|
||||
|
||||
refute spec.activated?
|
||||
ensure
|
||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||
end
|
||||
|
||||
def test_use_gemdeps_specific
|
||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
|
||||
|
||||
spec = util_spec 'a', 1
|
||||
|
||||
refute spec.activated?
|
||||
|
||||
open 'x', 'w' do |io|
|
||||
io.write 'gem "a"'
|
||||
end
|
||||
|
||||
Gem.use_gemdeps
|
||||
|
||||
assert spec.activated?
|
||||
ensure
|
||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||
end
|
||||
|
||||
def with_plugin(path)
|
||||
test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}",
|
||||
@@project_dir)
|
||||
|
|
|
@ -28,10 +28,14 @@ class TestGemImpossibleDependenciesError < Gem::TestCase
|
|||
|
||||
expected = <<-EXPECTED
|
||||
rye-0.9.8 requires net-ssh (>= 2.0.13) but it conflicted:
|
||||
Activated net-ssh-2.6.5 instead of (~> 2.2.2) via:
|
||||
net-ssh-2.6.5, rye-0.9.8
|
||||
Activated net-ssh-2.2.2 instead of (>= 2.6.5) via:
|
||||
net-ssh-2.2.2, rye-0.9.8
|
||||
Activated net-ssh-2.6.5 via:
|
||||
net-ssh-2.6.5 (>= 2.0.13), rye-0.9.8 (= 0.9.8)
|
||||
instead of (~> 2.2.2) via:
|
||||
net-ssh-2.6.5 (>= 2.0.13), rye-0.9.8 (= 0.9.8)
|
||||
Activated net-ssh-2.2.2 via:
|
||||
net-ssh-2.2.2 (>= 2.0.13), rye-0.9.8 (= 0.9.8)
|
||||
instead of (>= 2.6.5) via:
|
||||
net-ssh-2.2.2 (>= 2.0.13), rye-0.9.8 (= 0.9.8)
|
||||
EXPECTED
|
||||
|
||||
assert_equal expected, error.message
|
||||
|
|
|
@ -123,7 +123,7 @@ class TestGemRequestSet < Gem::TestCase
|
|||
|
||||
assert_equal %w[a-1], names
|
||||
|
||||
assert_equal [@DR::IndexSet, @DR::GitSet, @DR::VendorSet],
|
||||
assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet],
|
||||
rs.sets.map { |set| set.class }
|
||||
end
|
||||
|
||||
|
@ -169,7 +169,7 @@ class TestGemRequestSet < Gem::TestCase
|
|||
|
||||
assert_equal ["a-1", "b-2"], names
|
||||
|
||||
assert_equal [@DR::IndexSet, @DR::GitSet, @DR::VendorSet],
|
||||
assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet],
|
||||
rs.sets.map { |set| set.class }
|
||||
end
|
||||
|
||||
|
|
|
@ -272,10 +272,12 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
|
|||
|
||||
def test_gem_require
|
||||
@gda.gem 'a', :require => %w[b c]
|
||||
@gda.gem 'd', :require => 'e'
|
||||
|
||||
assert_equal [dep('a')], @set.dependencies
|
||||
assert_equal [dep('a'), dep('d')], @set.dependencies
|
||||
|
||||
assert_equal %w[b c], @gda.requires['a']
|
||||
assert_equal %w[e], @gda.requires['d']
|
||||
end
|
||||
|
||||
def test_gem_require_false
|
||||
|
|
|
@ -44,6 +44,21 @@ class TestGemResolver < Gem::TestCase
|
|||
assert_equal [index_set, vendor_set], composed.sets
|
||||
end
|
||||
|
||||
def test_self_compose_sets_nest
|
||||
index_set = @DR::IndexSet.new
|
||||
vendor_set = @DR::VendorSet.new
|
||||
|
||||
inner = @DR.compose_sets index_set, vendor_set
|
||||
|
||||
current_set = @DR::CurrentSet.new
|
||||
|
||||
composed = @DR.compose_sets inner, current_set
|
||||
|
||||
assert_kind_of Gem::Resolver::ComposedSet, composed
|
||||
|
||||
assert_equal [index_set, vendor_set, current_set], composed.sets
|
||||
end
|
||||
|
||||
def test_self_compose_sets_nil
|
||||
index_set = @DR::IndexSet.new
|
||||
|
||||
|
|
|
@ -6,20 +6,161 @@ class TestGemResolverAPISet < Gem::TestCase
|
|||
super
|
||||
|
||||
@DR = Gem::Resolver
|
||||
@dep_uri = URI "#{@gem_repo}api/v1/dependencies"
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
set = @DR::APISet.new
|
||||
|
||||
assert_equal URI('https://rubygems.org/api/v1/dependencies'),
|
||||
set.dep_uri
|
||||
assert_equal URI('https://rubygems.org/api/v1/dependencies'), set.dep_uri
|
||||
assert_equal URI('https://rubygems.org'), set.uri
|
||||
assert_equal Gem::Source.new(URI('https://rubygems.org')), set.source
|
||||
end
|
||||
|
||||
def test_initialize_uri
|
||||
set = @DR::APISet.new @gem_repo
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
assert_equal URI('http://gems.example.com/'),
|
||||
set.dep_uri
|
||||
assert_equal URI("#{@gem_repo}api/v1/dependencies"), set.dep_uri
|
||||
assert_equal URI("#{@gem_repo}"), set.uri
|
||||
end
|
||||
|
||||
def test_find_all
|
||||
spec_fetcher
|
||||
|
||||
data = [
|
||||
{ :name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [], },
|
||||
]
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
|
||||
expected = [
|
||||
@DR::APISpecification.new(set, data.first)
|
||||
]
|
||||
|
||||
assert_equal expected, set.find_all(a_dep)
|
||||
end
|
||||
|
||||
def test_find_all_cache
|
||||
spec_fetcher
|
||||
|
||||
data = [
|
||||
{ :name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [], },
|
||||
]
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
|
||||
set.prefetch [a_dep]
|
||||
|
||||
@fetcher.data.delete "#{@dep_uri}?gems=a"
|
||||
|
||||
expected = [
|
||||
@DR::APISpecification.new(set, data.first)
|
||||
]
|
||||
|
||||
assert_equal expected, set.find_all(a_dep)
|
||||
end
|
||||
|
||||
def test_find_all_missing
|
||||
spec_fetcher
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump []
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
|
||||
assert_empty set.find_all(a_dep)
|
||||
|
||||
@fetcher.data.delete "#{@dep_uri}?gems=a"
|
||||
|
||||
assert_empty set.find_all(a_dep)
|
||||
end
|
||||
|
||||
def test_prefetch
|
||||
spec_fetcher
|
||||
|
||||
data = [
|
||||
{ :name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [], },
|
||||
]
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data
|
||||
@fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump []
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
b_dep = @DR::DependencyRequest.new dep('b'), nil
|
||||
|
||||
set.prefetch [a_dep, b_dep]
|
||||
|
||||
assert_equal %w[a-1], set.find_all(a_dep).map { |s| s.full_name }
|
||||
assert_empty set.find_all(b_dep)
|
||||
end
|
||||
|
||||
def test_prefetch_cache
|
||||
spec_fetcher
|
||||
|
||||
data = [
|
||||
{ :name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [], },
|
||||
]
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
b_dep = @DR::DependencyRequest.new dep('b'), nil
|
||||
|
||||
set.prefetch [a_dep]
|
||||
|
||||
@fetcher.data.delete "#{@dep_uri}?gems=a"
|
||||
@fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump []
|
||||
|
||||
set.prefetch [a_dep, b_dep]
|
||||
end
|
||||
|
||||
def test_prefetch_cache_missing
|
||||
spec_fetcher
|
||||
|
||||
data = [
|
||||
{ :name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [], },
|
||||
]
|
||||
|
||||
@fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data
|
||||
|
||||
set = @DR::APISet.new @dep_uri
|
||||
|
||||
a_dep = @DR::DependencyRequest.new dep('a'), nil
|
||||
b_dep = @DR::DependencyRequest.new dep('b'), nil
|
||||
|
||||
set.prefetch [a_dep, b_dep]
|
||||
|
||||
@fetcher.data.delete "#{@dep_uri}?gems=a,b"
|
||||
|
||||
set.prefetch [a_dep, b_dep]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -28,5 +28,41 @@ class TestGemResolverAPISpecification < Gem::TestCase
|
|||
assert_equal expected, spec.dependencies
|
||||
end
|
||||
|
||||
def test_source
|
||||
set = Gem::Resolver::APISet.new
|
||||
data = {
|
||||
:name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [],
|
||||
}
|
||||
|
||||
api_spec = Gem::Resolver::APISpecification.new set, data
|
||||
|
||||
assert_equal set.source, api_spec.source
|
||||
end
|
||||
|
||||
def test_spec
|
||||
spec_fetcher do |fetcher|
|
||||
fetcher.spec 'a', 1
|
||||
end
|
||||
|
||||
dep_uri = URI(@gem_repo) + 'api/v1/dependencies'
|
||||
set = Gem::Resolver::APISet.new dep_uri
|
||||
data = {
|
||||
:name => 'a',
|
||||
:number => '1',
|
||||
:platform => 'ruby',
|
||||
:dependencies => [],
|
||||
}
|
||||
|
||||
api_spec = Gem::Resolver::APISpecification.new set, data
|
||||
|
||||
spec = api_spec.spec
|
||||
|
||||
assert_kind_of Gem::Specification, spec
|
||||
assert_equal 'a-1', spec.full_name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -12,12 +12,20 @@ class TestGemResolverConflict < Gem::TestCase
|
|||
child =
|
||||
dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', root
|
||||
|
||||
dep = Gem::Resolver::DependencyRequest.new dep('net-ssh', '>= 2.0.13'), nil
|
||||
|
||||
spec = quick_spec 'net-ssh', '2.2.2'
|
||||
active =
|
||||
Gem::Resolver::ActivationRequest.new spec, dep
|
||||
|
||||
conflict =
|
||||
Gem::Resolver::Conflict.new child, child.requester
|
||||
Gem::Resolver::Conflict.new child, active
|
||||
|
||||
expected = <<-EXPECTED
|
||||
Activated net-ssh-2.2.2 instead of (>= 2.6.5) via:
|
||||
net-ssh-2.2.2, rye-0.9.8
|
||||
Activated net-ssh-2.2.2 via:
|
||||
net-ssh-2.2.2 (>= 2.0.13)
|
||||
instead of (>= 2.6.5) via:
|
||||
net-ssh-2.2.2 (>= 2.0.13), rye-0.9.8 (= 0.9.8)
|
||||
EXPECTED
|
||||
|
||||
assert_equal expected, conflict.explanation
|
||||
|
@ -36,7 +44,9 @@ class TestGemResolverConflict < Gem::TestCase
|
|||
conflict = @DR::Conflict.new a1_req, activated
|
||||
|
||||
expected = <<-EXPECTED
|
||||
Activated a-2 instead of (= 1) via:
|
||||
Activated a-2 via:
|
||||
a-2 (= 2)
|
||||
instead of (= 1) via:
|
||||
user request (gem command or Gemfile)
|
||||
EXPECTED
|
||||
|
||||
|
@ -46,13 +56,19 @@ class TestGemResolverConflict < Gem::TestCase
|
|||
def test_request_path
|
||||
root =
|
||||
dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
|
||||
|
||||
child =
|
||||
dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', root
|
||||
dependency_request dep('other', '>= 1.0'), 'net-ssh', '2.2.2', root
|
||||
|
||||
conflict =
|
||||
Gem::Resolver::Conflict.new child, nil
|
||||
Gem::Resolver::Conflict.new nil, nil
|
||||
|
||||
assert_equal %w[net-ssh-2.2.2 rye-0.9.8], conflict.request_path
|
||||
expected = [
|
||||
'net-ssh-2.2.2 (>= 2.0.13)',
|
||||
'rye-0.9.8 (= 0.9.8)'
|
||||
]
|
||||
|
||||
assert_equal expected, conflict.request_path(child.requester)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -66,6 +66,24 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||
refute_empty @set.specs
|
||||
end
|
||||
|
||||
def test_prefetch_cache
|
||||
name, _, repository, = git_gem
|
||||
|
||||
@set.add_git_gem name, repository, 'master', false
|
||||
|
||||
dependency = dep name
|
||||
req = Gem::Resolver::ActivationRequest.new dependency, nil
|
||||
@reqs.add req
|
||||
|
||||
@set.prefetch @reqs
|
||||
|
||||
spec = @set.specs[name]
|
||||
|
||||
@set.prefetch @reqs
|
||||
|
||||
assert_same spec, @set.specs[name]
|
||||
end
|
||||
|
||||
def test_prefetch_filter
|
||||
name, _, repository, = git_gem
|
||||
|
||||
|
@ -77,7 +95,7 @@ class TestGemResolverGitSet < Gem::TestCase
|
|||
|
||||
@set.prefetch @reqs
|
||||
|
||||
assert_empty @set.specs
|
||||
refute_empty @set.specs, 'the git source does not filter'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -78,12 +78,6 @@ class TestGemSourceGit < Gem::TestCase
|
|||
refute_equal @source, source
|
||||
end
|
||||
|
||||
def test_load_spec
|
||||
spec = @source.load_spec @name
|
||||
|
||||
assert_equal "#{@name}-#{@version}", spec.full_name
|
||||
end
|
||||
|
||||
def test_install_dir
|
||||
@source.cache
|
||||
|
||||
|
@ -133,6 +127,38 @@ class TestGemSourceGit < Gem::TestCase
|
|||
assert_equal(-1, git. <=>(installed), 'git <=> installed')
|
||||
end
|
||||
|
||||
def test_specs
|
||||
source = Gem::Source::Git.new @name, @repository, 'master', true
|
||||
|
||||
Dir.chdir 'git/a' do
|
||||
FileUtils.mkdir 'b'
|
||||
|
||||
Dir.chdir 'b' do
|
||||
b = Gem::Specification.new 'b', 1
|
||||
|
||||
open 'b.gemspec', 'w' do |io|
|
||||
io.write b.to_ruby
|
||||
end
|
||||
|
||||
system @git, 'add', 'b.gemspec'
|
||||
system @git, 'commit', '--quiet', '-m', 'add b/b.gemspec'
|
||||
end
|
||||
|
||||
FileUtils.touch 'c.gemspec'
|
||||
|
||||
system @git, 'add', 'c.gemspec'
|
||||
system @git, 'commit', '--quiet', '-m', 'add c.gemspec'
|
||||
end
|
||||
|
||||
specs = nil
|
||||
|
||||
capture_io do
|
||||
specs = source.specs
|
||||
end
|
||||
|
||||
assert_equal %w[a-1 b-1], specs.map { |spec| spec.full_name }
|
||||
end
|
||||
|
||||
def test_uri_hash
|
||||
assert_equal @hash, @source.uri_hash
|
||||
|
||||
|
|
|
@ -2447,7 +2447,7 @@ duplicate dependency on b (>= 1.2.3), (~> 1.2) use:
|
|||
end
|
||||
|
||||
assert_match <<-warning, @ui.error
|
||||
WARNING: licenses is empty. Use a license abbreviation from:
|
||||
WARNING: licenses is empty, but is recommended. Use a license abbreviation from:
|
||||
http://opensource.org/licenses/alphabetical
|
||||
warning
|
||||
end
|
||||
|
|
|
@ -5,6 +5,10 @@ class TestGemUtil < Gem::TestCase
|
|||
|
||||
def test_class_popen
|
||||
assert_equal "0\n", Gem::Util.popen(Gem.ruby, '-e', 'p 0')
|
||||
|
||||
assert_raises Errno::ECHILD do
|
||||
Process.wait -1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue