* 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:
drbrain 2013-11-21 23:27:30 +00:00
Родитель b1529a30e0
Коммит 5307d803f5
30 изменённых файлов: 714 добавлений и 196 удалений

Просмотреть файл

@ -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,8 +2534,8 @@ class Gem::Specification < Gem::BasicSpecification
}
warning <<-warning if licenses.empty?
licenses is empty. Use a license abbreviation from:
http://opensource.org/licenses/alphabetical
licenses is empty, but is recommended. Use a license abbreviation from:
http://opensource.org/licenses/alphabetical
warning
validate_permissions

Просмотреть файл

@ -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
@ -61,6 +60,4 @@ module Gem::Util
end
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,8 +2447,8 @@ 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:
http://opensource.org/licenses/alphabetical
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