diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-19 00:34:13 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-19 00:34:13 +0000 |
commit | a7fa4d5d9aab150ad4b0c3f3217fe444df69f527 (patch) | |
tree | 88ab96d22f7228b556337aa7c34042d4fd279394 | |
parent | e7ec3dad907f2c77f17faddb40a98b2ef4523222 (diff) | |
download | ruby-a7fa4d5d9aab150ad4b0c3f3217fe444df69f527.tar.gz |
* lib/rubygems: Update to RubyGems master 6a3d9f9. Changes include:
Compatibly renamed Gem::DependencyResolver to Gem::Resolver.
Added support for git gems in gem.deps.rb and Gemfile.
Fixed resolver bugs.
* test/rubygems: ditto.
* lib/rubygems/LICENSE.txt: Updated to license from RubyGems trunk.
[ruby-trunk - Bug #9086]
* lib/rubygems/commands/which_command.rb: RubyGems now indicates
failure when any file is missing. [ruby-trunk - Bug #9004]
* lib/rubygems/ext/builder: Extensions are now installed into the
extension install directory and the first directory in the require
path from the gem. This allows backwards compatibility with msgpack
and other gems that calculate full require paths.
[ruby-trunk - Bug #9106]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | lib/rubygems.rb | 49 | ||||
-rw-r--r-- | lib/rubygems/LICENSE.txt | 75 | ||||
-rw-r--r-- | lib/rubygems/available_set.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/basic_specification.rb | 8 | ||||
-rw-r--r-- | lib/rubygems/commands/install_command.rb | 23 | ||||
-rw-r--r-- | lib/rubygems/commands/which_command.rb | 5 | ||||
-rw-r--r-- | lib/rubygems/dependency_installer.rb | 32 | ||||
-rw-r--r-- | lib/rubygems/doctor.rb | 20 | ||||
-rw-r--r-- | lib/rubygems/errors.rb | 17 | ||||
-rw-r--r-- | lib/rubygems/exceptions.rb | 10 | ||||
-rw-r--r-- | lib/rubygems/ext/builder.rb | 3 | ||||
-rw-r--r-- | lib/rubygems/ext/cmake_builder.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/ext/configure_builder.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/ext/ext_conf_builder.rb | 8 | ||||
-rw-r--r-- | lib/rubygems/ext/rake_builder.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/remote_fetcher.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/request_set.rb | 19 | ||||
-rw-r--r-- | lib/rubygems/request_set/gem_dependency_api.rb | 149 | ||||
-rw-r--r-- | lib/rubygems/request_set/lockfile.rb | 27 | ||||
-rw-r--r-- | lib/rubygems/resolver.rb (renamed from lib/rubygems/dependency_resolver.rb) | 104 | ||||
-rw-r--r-- | lib/rubygems/resolver/activation_request.rb (renamed from lib/rubygems/dependency_resolver/activation_request.rb) | 6 | ||||
-rw-r--r-- | lib/rubygems/resolver/api_set.rb (renamed from lib/rubygems/dependency_resolver/api_set.rb) | 4 | ||||
-rw-r--r-- | lib/rubygems/resolver/api_specification.rb (renamed from lib/rubygems/dependency_resolver/api_specification.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/best_set.rb (renamed from lib/rubygems/dependency_resolver/best_set.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/composed_set.rb (renamed from lib/rubygems/dependency_resolver/composed_set.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/conflict.rb (renamed from lib/rubygems/dependency_resolver/dependency_conflict.rb) | 8 | ||||
-rw-r--r-- | lib/rubygems/resolver/current_set.rb (renamed from lib/rubygems/dependency_resolver/current_set.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/dependency_request.rb (renamed from lib/rubygems/dependency_resolver/dependency_request.rb) | 4 | ||||
-rw-r--r-- | lib/rubygems/resolver/git_set.rb | 81 | ||||
-rw-r--r-- | lib/rubygems/resolver/git_specification.rb | 16 | ||||
-rw-r--r-- | lib/rubygems/resolver/index_set.rb (renamed from lib/rubygems/dependency_resolver/index_set.rb) | 4 | ||||
-rw-r--r-- | lib/rubygems/resolver/index_specification.rb (renamed from lib/rubygems/dependency_resolver/index_specification.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/installed_specification.rb (renamed from lib/rubygems/dependency_resolver/installed_specification.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/installer_set.rb (renamed from lib/rubygems/dependency_resolver/installer_set.rb) | 8 | ||||
-rw-r--r-- | lib/rubygems/resolver/lock_set.rb (renamed from lib/rubygems/dependency_resolver/lock_set.rb) | 6 | ||||
-rw-r--r-- | lib/rubygems/resolver/requirement_list.rb | 40 | ||||
-rw-r--r-- | lib/rubygems/resolver/set.rb (renamed from lib/rubygems/dependency_resolver/set.rb) | 9 | ||||
-rw-r--r-- | lib/rubygems/resolver/spec_specification.rb (renamed from lib/rubygems/dependency_resolver/spec_specification.rb) | 6 | ||||
-rw-r--r-- | lib/rubygems/resolver/specification.rb (renamed from lib/rubygems/dependency_resolver/specification.rb) | 4 | ||||
-rw-r--r-- | lib/rubygems/resolver/vendor_set.rb (renamed from lib/rubygems/dependency_resolver/vendor_set.rb) | 6 | ||||
-rw-r--r-- | lib/rubygems/resolver/vendor_specification.rb (renamed from lib/rubygems/dependency_resolver/vendor_specification.rb) | 2 | ||||
-rw-r--r-- | lib/rubygems/source.rb | 25 | ||||
-rw-r--r-- | lib/rubygems/source/git.rb | 189 | ||||
-rw-r--r-- | lib/rubygems/source/installed.rb | 7 | ||||
-rw-r--r-- | lib/rubygems/source/local.rb | 17 | ||||
-rw-r--r-- | lib/rubygems/source/specific_file.rb | 17 | ||||
-rw-r--r-- | lib/rubygems/source/vendor.rb | 18 | ||||
-rw-r--r-- | lib/rubygems/source_list.rb | 15 | ||||
-rw-r--r-- | lib/rubygems/spec_fetcher.rb | 26 | ||||
-rw-r--r-- | lib/rubygems/specification.rb | 5 | ||||
-rw-r--r-- | lib/rubygems/test_case.rb | 70 | ||||
-rw-r--r-- | lib/rubygems/util.rb | 65 | ||||
-rw-r--r-- | lib/rubygems/util/stringio.rb | 34 | ||||
-rw-r--r-- | test/rubygems/test_gem.rb | 2 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_which_command.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_dependency_resolution_error.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_dependency_resolver_vendor_specification.rb | 72 | ||||
-rw-r--r-- | test/rubygems/test_gem_ext_builder.rb | 22 | ||||
-rw-r--r-- | test/rubygems/test_gem_impossible_dependencies_error.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_installer.rb | 14 | ||||
-rw-r--r-- | test/rubygems/test_gem_remote_fetcher.rb | 2 | ||||
-rw-r--r-- | test/rubygems/test_gem_request_set.rb | 31 | ||||
-rw-r--r-- | test/rubygems/test_gem_request_set_gem_dependency_api.rb | 199 | ||||
-rw-r--r-- | test/rubygems/test_gem_request_set_lockfile.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver.rb (renamed from test/rubygems/test_gem_dependency_resolver.rb) | 93 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_activation_request.rb (renamed from test/rubygems/test_gem_dependency_resolver_activation_request.rb) | 6 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_api_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_api_set.rb) | 5 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_api_specification.rb (renamed from test/rubygems/test_gem_dependency_resolver_api_specification.rb) | 7 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_best_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_best_set.rb) | 5 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_conflict.rb (renamed from test/rubygems/test_gem_dependency_resolver_dependency_conflict.rb) | 15 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_dependency_request.rb (renamed from test/rubygems/test_gem_dependency_resolver_dependency_request.rb) | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_git_set.rb | 84 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_git_specification.rb | 36 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_index_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_index_set.rb) | 5 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_index_specification.rb (renamed from test/rubygems/test_gem_dependency_resolver_index_specification.rb) | 19 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_installed_specification.rb (renamed from test/rubygems/test_gem_dependency_resolver_installed_specification.rb) | 7 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_installer_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_installer_set.rb) | 5 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_lock_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_lock_set.rb) | 5 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_requirement_list.rb | 19 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_vendor_set.rb (renamed from test/rubygems/test_gem_dependency_resolver_vendor_set.rb) | 9 | ||||
-rw-r--r-- | test/rubygems/test_gem_resolver_vendor_specification.rb | 71 | ||||
-rw-r--r-- | test/rubygems/test_gem_source.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_source_git.rb | 153 | ||||
-rw-r--r-- | test/rubygems/test_gem_source_vendor.rb | 14 | ||||
-rw-r--r-- | test/rubygems/test_gem_specification.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_stub_specification.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_util.rb | 11 |
88 files changed, 1801 insertions, 432 deletions
@@ -1,3 +1,28 @@ +Tue Nov 19 09:33:52 2013 Eric Hodel <drbrain@segment7.net> + + * lib/rubygems: Update to RubyGems master 6a3d9f9. Changes include: + + Compatibly renamed Gem::DependencyResolver to Gem::Resolver. + + Added support for git gems in gem.deps.rb and Gemfile. + + Fixed resolver bugs. + + * test/rubygems: ditto. + + * lib/rubygems/LICENSE.txt: Updated to license from RubyGems trunk. + [ruby-trunk - Bug #9086] + + * lib/rubygems/commands/which_command.rb: RubyGems now indicates + failure when any file is missing. [ruby-trunk - Bug #9004] + + * lib/rubygems/ext/builder: Extensions are now installed into the + extension install directory and the first directory in the require + path from the gem. This allows backwards compatibility with msgpack + and other gems that calculate full require paths. + [ruby-trunk - Bug #9106] + + Tue Nov 19 07:21:56 2013 Tanaka Akira <akr@fsij.org> * configure.in (LOCALTIME_OVERFLOW_PROBLEM): Define it for cross diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 1c84356bd7..2e8ad7bba1 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -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 @@ -302,7 +302,6 @@ module Gem # The path where gem executables are to be installed. def self.bindir(install_dir=Gem.dir) - # TODO: move to Gem::Dirs return File.join install_dir, 'bin' unless install_dir.to_s == Gem.default_dir.to_s Gem.default_bindir @@ -362,16 +361,21 @@ module Gem Zlib::Deflate.deflate data end - # DOC: needs doc'd or :nodoc'd + # Retrieve the PathSupport object that RubyGems uses to + # lookup files. + def self.paths @paths ||= Gem::PathSupport.new end - # DOC: needs doc'd or :nodoc'd + # Initialize the filesystem paths to use from +env+. + # +env+ is a hash-like object (typically ENV) that + # is queried for 'GEM_HOME', 'GEM_PATH', and 'GEM_SPEC_CACHE' + def self.paths=(env) clear_paths @paths = Gem::PathSupport.new env - Gem::Specification.dirs = @paths.path # FIX: home is at end + Gem::Specification.dirs = @paths.path end ## @@ -380,12 +384,10 @@ module Gem # FIXME deprecate these once everything else has been done -ebh def self.dir - # TODO: raise "no" paths.home end def self.path - # TODO: raise "no" paths.path end @@ -552,42 +554,30 @@ module Gem private_class_method :find_home + # FIXME deprecate these in 3.0 + ## # Zlib::GzipReader wrapper that unzips +data+. def self.gunzip(data) - # TODO: move to utils - require 'stringio' - require 'zlib' - data = StringIO.new data - - unzipped = Zlib::GzipReader.new(data).read - unzipped.force_encoding Encoding::BINARY if Object.const_defined? :Encoding - unzipped + require 'rubygems/util' + Gem::Util.gunzip data end ## # Zlib::GzipWriter wrapper that zips +data+. def self.gzip(data) - # TODO: move to utils - require 'stringio' - require 'zlib' - zipped = StringIO.new - zipped.set_encoding Encoding::BINARY if Object.const_defined? :Encoding - - Zlib::GzipWriter.wrap zipped do |io| io.write data end - - zipped.string + require 'rubygems/util' + Gem::Util.gzip data end ## # A Zlib::Inflate#inflate wrapper def self.inflate(data) - # TODO: move to utils - require 'zlib' - Zlib::Inflate.inflate data + require 'rubygems/util' + Gem::Util.inflate data end ## @@ -693,7 +683,6 @@ module Gem file = $1 lineno = $2.to_i - # TODO: it is ALWAYS joined! STUPID! [file, lineno] end @@ -974,7 +963,6 @@ module Gem paths = nil if paths == [nil] paths = paths.first if Array === Array(paths).first self.paths = { "GEM_HOME" => home, "GEM_PATH" => paths } - # TODO: self.paths = home, paths end ## @@ -1169,7 +1157,8 @@ module Gem autoload :ConfigFile, 'rubygems/config_file' autoload :Dependency, 'rubygems/dependency' autoload :DependencyList, 'rubygems/dependency_list' - autoload :DependencyResolver, 'rubygems/dependency_resolver' + autoload :Resolver, 'rubygems/resolver' + autoload :DependencyResolver, 'rubygems/resolver' autoload :PathSupport, 'rubygems/path_support' autoload :Platform, 'rubygems/platform' autoload :RequestSet, 'rubygems/request_set' diff --git a/lib/rubygems/LICENSE.txt b/lib/rubygems/LICENSE.txt index db88c5e118..8a0a51dec1 100644 --- a/lib/rubygems/LICENSE.txt +++ b/lib/rubygems/LICENSE.txt @@ -1,53 +1,54 @@ RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim Weirich and others. You can redistribute it and/or modify it under -either the terms of the GPL (see the GPL.txt file), or the conditions -below: +either the terms of the MIT license (see the file MIT.txt), or the +conditions below: - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. +1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the + original copyright notices and associated disclaimers. - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: +2. You may modify your copy of the software in any way, provided that + you do at least ONE of the following: - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. + a. place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or by allowing + the author to include your modifications in the software. - b) use the modified software only within your corporation or - organization. + b. use the modified software only within your corporation or + organization. - c) rename any non-standard executables so the names do not conflict - with standard executables, which must also be provided. + c. give non-standard executables non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 3. You may distribute the software in object code or executable - form, provided that you do at least ONE of the following: +3. You may distribute the software in object code or executable + form, provided that you do at least ONE of the following: - a) distribute the executables and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. + a. distribute the executables and library files of the software, + together with instructions (in the manual page or equivalent) + on where to get the original distribution. - b) accompany the distribution with the machine-readable source of - the software. + b. accompany the distribution with the machine-readable source of + the software. - c) give non-standard executables non-standard names, with - instructions on where to get the original software distribution. + c. give non-standard executables non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 4. You may modify and include the part of the software into any other - software (possibly commercial). +4. You may modify and include the part of the software into any other + software (possibly commercial). - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. +5. The scripts and library files supplied as input to or produced as + output from the software do not automatically fall under the + copyright of the software, but belong to whomever generated them, + and may be sold commercially, and may be aggregated with this + software. + +6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. diff --git a/lib/rubygems/available_set.rb b/lib/rubygems/available_set.rb index bb0b3a3abe..4ab4d77716 100644 --- a/lib/rubygems/available_set.rb +++ b/lib/rubygems/available_set.rb @@ -116,7 +116,7 @@ class Gem::AvailableSet ## # - # Used by the DependencyResolver, the protocol to use a AvailableSet as a + # Used by the Resolver, the protocol to use a AvailableSet as a # search Set. def find_all(req) @@ -127,7 +127,7 @@ class Gem::AvailableSet end match.map do |t| - Gem::DependencyResolver::InstalledSpecification.new(self, t.spec, t.source) + Gem::Resolver::InstalledSpecification.new(self, t.spec, t.source) end end diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb index a29ed0aa6d..4f96fcac3d 100644 --- a/lib/rubygems/basic_specification.rb +++ b/lib/rubygems/basic_specification.rb @@ -107,7 +107,7 @@ class Gem::BasicSpecification File.join full_gem_path, path end - full_paths << extension_install_dir unless @extensions.empty? + full_paths.unshift extension_install_dir unless @extensions.empty? full_paths end @@ -155,6 +155,10 @@ class Gem::BasicSpecification raise NotImplementedError end + def raw_require_paths # :nodoc: + @require_paths + end + ## # Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is # activated. @@ -179,7 +183,7 @@ class Gem::BasicSpecification File.join '..', '..', 'extensions', Gem::Platform.local.to_s, Gem.extension_api_version, full_name - @require_paths + [relative_extension_install_dir] + [relative_extension_install_dir].concat @require_paths end ## diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb index ad90b37fdc..68a2fad129 100644 --- a/lib/rubygems/commands/install_command.rb +++ b/lib/rubygems/commands/install_command.rb @@ -56,6 +56,12 @@ class Gem::Commands::InstallCommand < Gem::Command o[:install_as_default] = v end + add_option(:"Install/Update", '--explain', + 'Rather than install the gems, indicate which would', + 'be installed') do |v,o| + o[:explain] = v + end + @installed_specs = nil end @@ -185,8 +191,23 @@ to write the specification by hand. For example: return if options[:conservative] and not Gem::Dependency.new(name, version).matching_specs.empty? + req = Gem::Requirement.create(version) + inst = Gem::DependencyInstaller.new options - inst.install name, Gem::Requirement.create(version) + + if options[:explain] + request_set = inst.resolve_dependencies name, req + + puts "Gems to install:" + + request_set.specs.map { |s| s.full_name }.sort.each do |s| + puts " #{s}" + end + + return + else + inst.install name, req + end @installed_specs.push(*inst.installed_gems) diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb index 18706afdf5..96eeb86288 100644 --- a/lib/rubygems/commands/which_command.rb +++ b/lib/rubygems/commands/which_command.rb @@ -35,7 +35,7 @@ requiring to see why it does not behave as you expect. end def execute - found = false + found = true options[:args].each do |arg| arg = arg.sub(/#{Regexp.union(*Gem.suffixes)}$/, '') @@ -56,9 +56,10 @@ requiring to see why it does not behave as you expect. if paths.empty? then alert_error "Can't find ruby library file or shared library #{arg}" + + found &&= false else say paths - found = true end end diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index 22ff6f5cb7..e404d42b3a 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -1,6 +1,5 @@ require 'rubygems' require 'rubygems/dependency_list' -require 'rubygems/dependency_resolver' require 'rubygems/package' require 'rubygems/installer' require 'rubygems/spec_fetcher' @@ -196,7 +195,7 @@ class Gem::DependencyInstaller # sources. Gems are sorted with newer gems preferred over older gems, and # local gems preferred over remote gems. - def find_gems_with_sources dep # :nodoc: + def find_gems_with_sources dep, best_only=false # :nodoc: set = Gem::AvailableSet.new if consider_local? @@ -211,7 +210,26 @@ class Gem::DependencyInstaller if consider_remote? begin - found, errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep + # TODO this is pulled from #spec_for_dependency to allow + # us to filter tuples before fetching specs. + # + tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep + + if best_only && !tuples.empty? + tuples.sort! { |a,b| b[0].version <=> a[0].version } + tuples = [tuples.first] + end + + specs = [] + tuples.each do |tup, source| + begin + spec = source.fetch_spec(tup) + rescue Gem::RemoteFetcher::FetchError => e + errors << Gem::SourceFetchProblem.new(source, e) + else + specs << [spec, source] + end + end if @errors @errors += errors @@ -219,7 +237,7 @@ class Gem::DependencyInstaller @errors = errors end - set << found + set << specs rescue Gem::RemoteFetcher::FetchError => e # FIX if there is a problem talking to the network, we either need to always tell @@ -271,7 +289,7 @@ class Gem::DependencyInstaller dep = Gem::Dependency.new gem_name, version dep.prerelease = true if prerelease - set = find_gems_with_sources(dep) + set = find_gems_with_sources(dep, true) set.match_platform! end @@ -402,7 +420,7 @@ class Gem::DependencyInstaller request_set = as.to_request_set install_development_deps request_set.soft_missing = @force - installer_set = Gem::DependencyResolver::InstallerSet.new @domain + installer_set = Gem::Resolver::InstallerSet.new @domain installer_set.always_install.concat request_set.always_install installer_set.ignore_installed = @only_install_dir @@ -411,7 +429,7 @@ class Gem::DependencyInstaller request_set.soft_missing = true end - composed_set = Gem::DependencyResolver.compose_sets as, installer_set + composed_set = Gem::Resolver.compose_sets as, installer_set request_set.resolve composed_set diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb index 0de337f7de..2cb8901b4d 100644 --- a/lib/rubygems/doctor.rb +++ b/lib/rubygems/doctor.rb @@ -1,6 +1,5 @@ require 'rubygems' require 'rubygems/user_interaction' -require 'pathname' ## # Cleans up after a partially-failed uninstall or for an invalid @@ -39,7 +38,7 @@ class Gem::Doctor # If +dry_run+ is true no files or directories will be removed. def initialize gem_repository, dry_run = false - @gem_repository = Pathname(gem_repository) + @gem_repository = gem_repository @dry_run = dry_run @installed_specs = nil @@ -97,26 +96,29 @@ class Gem::Doctor # Removes files in +sub_directory+ with +extension+ def doctor_child sub_directory, extension # :nodoc: - directory = @gem_repository + sub_directory + directory = File.join(@gem_repository, sub_directory) - directory.children.sort.each do |child| - next unless child.exist? + Dir.entries(directory).sort.each do |ent| + next if ent == "." || ent == ".." - basename = child.basename(extension).to_s + child = File.join(directory, ent) + next unless File.exists?(child) + + basename = File.basename(child, extension) next if installed_specs.include? basename next if /^rubygems-\d/ =~ basename next if 'specifications' == sub_directory and 'default' == basename - type = child.directory? ? 'directory' : 'file' + type = File.directory?(child) ? 'directory' : 'file' action = if @dry_run then 'Extra' else - child.rmtree + FileUtils.rm_r(child) 'Removed' end - say "#{action} #{type} #{sub_directory}/#{child.basename}" + say "#{action} #{type} #{sub_directory}/#{File.basename(child)}" end rescue Errno::ENOENT # ignore diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb index 3c5486a800..fc9bfbc0dc 100644 --- a/lib/rubygems/errors.rb +++ b/lib/rubygems/errors.rb @@ -73,12 +73,27 @@ module Gem # data from a source class SourceFetchProblem < ErrorReason + + ## + # Creates a new SourceFetchProblem for the given +source+ and +error+. + def initialize(source, error) @source = source @error = error end - attr_reader :source, :error + ## + # The source that had the fetch problem. + + attr_reader :source + + ## + # The fetch error which is an Exception subclass. + + attr_reader :error + + ## + # An English description of the error. def wordy "Unable to download data from #{@source.uri} - #{@error.message}" diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb index 6d92b144b6..ee3d8fecdf 100644 --- a/lib/rubygems/exceptions.rb +++ b/lib/rubygems/exceptions.rb @@ -23,7 +23,7 @@ class Gem::DependencyError < Gem::Exception; end class Gem::DependencyRemovalException < Gem::Exception; end ## -# Raised by Gem::DependencyResolver when a Gem::DependencyConflict reaches the +# Raised by Gem::Resolver when a Gem::Dependency::Conflict reaches the # toplevel. Indicates which dependencies were incompatible through #conflict # and #conflicting_dependencies @@ -117,7 +117,7 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException end ## -# Raised by Gem::DependencyResolver when dependencies conflict and create the +# Raised by Gem::Resolver when dependencies conflict and create the # inability to find a valid possible spec for a request. class Gem::ImpossibleDependenciesError < Gem::Exception @@ -211,20 +211,20 @@ class Gem::SystemExitException < SystemExit end ## -# Raised by DependencyResolver when a dependency requests a gem for which +# Raised by Resolver when a dependency requests a gem for which # there is no spec. class Gem::UnsatisfiableDependencyError < Gem::Exception ## # The unsatisfiable dependency. This is a - # Gem::DependencyResolver::DependencyRequest, not a Gem::Dependency + # Gem::Resolver::DependencyRequest, not a Gem::Dependency attr_reader :dependency ## # Creates a new UnsatisfiableDepedencyError for the unsatisfiable - # Gem::DependencyResolver::DependencyRequest +dep+ + # Gem::Resolver::DependencyRequest +dep+ def initialize dep, platform_mismatch=nil if platform_mismatch and !platform_mismatch.empty? diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index 761505636c..e9244c760c 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -149,6 +149,7 @@ EOF extension ||= '' # I wish I knew why this line existed extension_dir = File.expand_path File.join @gem_dir, File.dirname(extension) + lib_dir = File.join @spec.full_gem_path, @spec.raw_require_paths.first builder = builder_for extension @@ -158,7 +159,7 @@ EOF CHDIR_MUTEX.synchronize do Dir.chdir extension_dir do results = builder.build(extension, @gem_dir, dest_path, - results, @build_args) + results, @build_args, lib_dir) say results.join("\n") if Gem.configuration.really_verbose end diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb index 17bd6c296e..24531bc75c 100644 --- a/lib/rubygems/ext/cmake_builder.rb +++ b/lib/rubygems/ext/cmake_builder.rb @@ -1,7 +1,7 @@ require 'rubygems/command' class Gem::Ext::CmakeBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results) + def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}" cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty? diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb index 2a542e6bd0..f66e39387a 100644 --- a/lib/rubygems/ext/configure_builder.rb +++ b/lib/rubygems/ext/configure_builder.rb @@ -6,7 +6,7 @@ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results, args=[]) + def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "sh ./configure --prefix=#{dest_path}" cmd << " #{args.join ' '}" unless args.empty? diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index 9a656a30a3..6e736d8062 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -10,7 +10,7 @@ require 'tempfile' class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder FileEntry = FileUtils::Entry_ # :nodoc: - def self.build(extension, directory, dest_path, results, args=[]) + def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) tmp_dest = Dir.mktmpdir(".gem.", ".") t = nil @@ -44,6 +44,12 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder if tmp_dest FileEntry.new(tmp_dest).traverse do |ent| + # TODO remove in RubyGems 3 + if lib_dir then + libent = ent.class.new lib_dir, ent.rel + libent.exist? or ent.copy libent.path + end + destent = ent.class.new(dest_path, ent.rel) destent.exist? or File.rename(ent.path, destent.path) end diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 984c54bc1b..2093bcabdd 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -6,7 +6,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results, args=[]) + def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) if File.basename(extension) =~ /mkrf_conf/i then cmd = "#{Gem.ruby} #{File.basename extension}" cmd << " #{args.join " "}" unless args.empty? diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index b96c77033a..c6816e8f0f 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -90,7 +90,7 @@ class Gem::RemoteFetcher rescue Resolv::ResolvError uri else - URI.parse "#{res.target}#{uri.path}" + URI.parse "#{uri.scheme}://#{res.target}#{uri.path}" end end diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index 3a997f32ee..42d457063f 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -1,6 +1,5 @@ require 'rubygems' require 'rubygems/dependency' -require 'rubygems/dependency_resolver' require 'rubygems/dependency_list' require 'rubygems/installer' require 'tsort' @@ -32,6 +31,11 @@ class Gem::RequestSet attr_accessor :development ## + # The set of git gems imported via load_gemdeps. + + attr_reader :git_set # :nodoc: + + ## # Sets used for resolution attr_reader :sets # :nodoc: @@ -61,6 +65,7 @@ class Gem::RequestSet @always_install = [] @dependency_names = {} @development = false + @git_set = nil @requests = [] @sets = [] @soft_missing = false @@ -184,7 +189,8 @@ class Gem::RequestSet # Load a dependency management file. def load_gemdeps path, without_groups = [] - @vendor_set = Gem::DependencyResolver::VendorSet.new + @git_set = Gem::Resolver::GitSet.new + @vendor_set = Gem::Resolver::VendorSet.new gf = Gem::RequestSet::GemDependencyAPI.new self, path gf.without_groups = without_groups if without_groups @@ -195,13 +201,14 @@ class Gem::RequestSet # Resolve the requested dependencies and return an Array of Specification # objects to be activated. - def resolve set = Gem::DependencyResolver::IndexSet.new + def resolve set = Gem::Resolver::IndexSet.new @sets << set + @sets << @git_set @sets << @vendor_set - set = Gem::DependencyResolver.compose_sets(*@sets) + set = Gem::Resolver.compose_sets(*@sets) - resolver = Gem::DependencyResolver.new @dependencies, set + resolver = Gem::Resolver.new @dependencies, set resolver.development = @development resolver.soft_missing = @soft_missing @@ -213,7 +220,7 @@ class Gem::RequestSet # and return an Array of Specification objects to be activated. def resolve_current - resolve Gem::DependencyResolver::CurrentSet.new + resolve Gem::Resolver::CurrentSet.new end def sorted_requests diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb index e8f3138990..8e29eb87e5 100644 --- a/lib/rubygems/request_set/gem_dependency_api.rb +++ b/lib/rubygems/request_set/gem_dependency_api.rb @@ -108,6 +108,11 @@ class Gem::RequestSet::GemDependencyAPI } ## + # A set of gems that are loaded via the +:git+ option to #gem + + attr_reader :git_set # :nodoc: + + ## # A Hash containing gem names and files to require from those gems. attr_reader :requires @@ -130,13 +135,55 @@ class Gem::RequestSet::GemDependencyAPI @set = set @path = path - @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 = [] + @current_groups = nil + @current_platform = nil + @current_repository = nil + @default_sources = true + @git_set = @set.git_set + @requires = Hash.new { |h, name| h[name] = [] } + @vendor_set = @set.vendor_set + @gem_sources = {} + @without_groups = [] + end + + ## + # Adds +dependencies+ to the request set if any of the +groups+ are allowed. + # This is used for gemspec dependencies. + + def add_dependencies groups, dependencies # :nodoc: + return unless (groups & @without_groups).empty? + + dependencies.each do |dep| + @set.gem dep.name, *dep.requirement + end + end + + private :add_dependencies + + ## + # Finds a gemspec with the given +name+ that lives at +path+. + + def find_gemspec name, path # :nodoc: + glob = File.join path, "#{name}.gemspec" + + spec_files = Dir[glob] + + case spec_files.length + when 1 then + spec_file = spec_files.first + + spec = Gem::Specification.load spec_file + + return spec if spec + + raise ArgumentError, "invalid gemspec #{spec_file}" + when 0 then + raise ArgumentError, "no gemspecs found at #{Dir.pwd}" + else + raise ArgumentError, + "found multiple gemspecs at #{Dir.pwd}, " + + "use the name: option to specify the one you want" + end end ## @@ -160,7 +207,13 @@ class Gem::RequestSet::GemDependencyAPI options = requirements.pop if requirements.last.kind_of?(Hash) options ||= {} - source_set = gem_path name, options + options[:git] = @current_repository if @current_repository + + source_set = false + + source_set ||= gem_path name, options + source_set ||= gem_git name, options + source_set ||= gem_github name, options return unless gem_platforms options @@ -182,6 +235,54 @@ class Gem::RequestSet::GemDependencyAPI end ## + # Handles the git: option from +options+ for gem +name+. + # + # Returns +true+ if the path option was handled. + + def gem_git name, options # :nodoc: + if gist = options.delete(:gist) then + options[:git] = "https://gist.github.com/#{gist}.git" + end + + return unless repository = options.delete(:git) + + raise ArgumentError, + "duplicate source git: #{repository} for gem #{name}" if + @gem_sources.include? name + + reference = nil + reference ||= options.delete :ref + reference ||= options.delete :branch + reference ||= options.delete :tag + reference ||= 'master' + + submodules = options.delete :submodules + + @git_set.add_git_gem name, repository, reference, submodules + + @gem_sources[name] = repository + + true + end + + private :gem_git + + ## + # Handles the github: option from +options+ for gem +name+. + # + # Returns +true+ if the path option was handled. + + def gem_github name, options # :nodoc: + return unless path = options.delete(:github) + + options[:git] = "git://github.com/#{path}.git" + + gem_git name, options + + true + end + + ## # Handles the :group and :groups +options+ for the gem with the given # +name+. @@ -269,6 +370,15 @@ class Gem::RequestSet::GemDependencyAPI private :gem_requires + def git repository + @current_repository = repository + + yield + + ensure + @current_repository = nil + end + ## # Returns the basename of the file the dependencies were loaded from @@ -278,6 +388,29 @@ class Gem::RequestSet::GemDependencyAPI ## # :category: Gem Dependencies DSL + # + # Loads dependencies from a gemspec file. + + def gemspec options = {} + name = options.delete(:name) || '{,*}' + path = options.delete(:path) || '.' + development_group = options.delete(:development_group) || :development + + spec = find_gemspec name, path + + groups = gem_group spec.name, {} + + add_dependencies groups, spec.runtime_dependencies + + groups << development_group + + add_dependencies groups, spec.development_dependencies + + gem_requires spec.name, options + end + + ## + # :category: Gem Dependencies DSL # Block form for placing a dependency in the given +groups+. def group *groups diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb index a9c419549d..0073bfdcc5 100644 --- a/lib/rubygems/request_set/lockfile.rb +++ b/lib/rubygems/request_set/lockfile.rb @@ -1,5 +1,3 @@ -require 'pathname' - class Gem::RequestSet::Lockfile ## @@ -46,8 +44,8 @@ class Gem::RequestSet::Lockfile 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 + @gem_deps_file = File.expand_path(gem_deps_file) + @gem_deps_dir = File.dirname(@gem_deps_file) @current_token = nil @line = 0 @@ -62,7 +60,7 @@ class Gem::RequestSet::Lockfile @set.dependencies.sort.map do |dependency| source = @requests.find do |req| req.name == dependency.name and - req.spec.class == Gem::DependencyResolver::VendorSpecification + req.spec.class == Gem::Resolver::VendorSpecification end source_dep = '!' if source @@ -102,15 +100,26 @@ class Gem::RequestSet::Lockfile out << nil end + def relative_path_from(dest, base) + dest = File.expand_path(dest) + base = File.expand_path(base) + + if dest.index(base) == 0 + return dest[base.size+1..-1] + else + dest + end + end + def add_PATH out # :nodoc: return unless path_requests = - @spec_groups.delete(Gem::DependencyResolver::VendorSpecification) + @spec_groups.delete(Gem::Resolver::VendorSpecification) out << "PATH" path_requests.each do |request| - directory = Pathname(request.spec.source.uri).expand_path + directory = File.expand_path(request.spec.source.uri) - out << " remote: #{directory.relative_path_from @gem_deps_dir}" + out << " remote: #{relative_path_from directory, @gem_deps_dir}" out << " specs:" out << " #{request.name} (#{request.version})" end @@ -208,7 +217,7 @@ class Gem::RequestSet::Lockfile skip :newline - set = Gem::DependencyResolver::LockSet.new source + set = Gem::Resolver::LockSet.new source while not @tokens.empty? and :text == peek.first do _, name, = get :text diff --git a/lib/rubygems/dependency_resolver.rb b/lib/rubygems/resolver.rb index 35fbe925ad..2669cc4f24 100644 --- a/lib/rubygems/dependency_resolver.rb +++ b/lib/rubygems/resolver.rb @@ -12,7 +12,7 @@ require 'net/http' # objects which indicate all the specs that should be activated to meet the # all the requirements. -class Gem::DependencyResolver +class Gem::Resolver ## # Contains all the conflicts encountered while doing resolution @@ -38,20 +38,20 @@ class Gem::DependencyResolver when 1 then sets.first else - Gem::DependencyResolver::ComposedSet.new(*sets) + Gem::Resolver::ComposedSet.new(*sets) end end ## - # Provide a DependencyResolver that queries only against the already + # Provide a Resolver that queries only against the already # installed gems. def self.for_current_gems needed - new needed, Gem::DependencyResolver::CurrentSet.new + new needed, Gem::Resolver::CurrentSet.new end ## - # Create DependencyResolver object which will resolve the tree starting + # Create Resolver object which will resolve the tree starting # with +needed+ Dependency objects. # # +set+ is an object that provides where to look for specifications to @@ -59,7 +59,7 @@ class Gem::DependencyResolver # rubygems.org. def initialize needed, set = nil - @set = set || Gem::DependencyResolver::IndexSet.new + @set = set || Gem::Resolver::IndexSet.new @needed = needed @conflicts = [] @@ -68,6 +68,15 @@ class Gem::DependencyResolver @soft_missing = false end + DEBUG_RESOLVER = !ENV['DEBUG_RESOLVER'].nil? + + def explain(stage, *data) + if DEBUG_RESOLVER + d = data.map { |x| x.inspect }.join(", ") + STDOUT.printf "%20s %s\n", stage.to_s.upcase, d + end + end + ## # Creates an ActivationRequest for the given +dep+ and the last +possible+ # specification. @@ -77,8 +86,10 @@ class Gem::DependencyResolver def activation_request dep, possible # :nodoc: spec = possible.pop + explain :activate, [spec.full_name, possible.size] + activation_request = - Gem::DependencyResolver::ActivationRequest.new spec, dep, possible + Gem::Resolver::ActivationRequest.new spec, dep, possible return spec, activation_request end @@ -86,7 +97,7 @@ class Gem::DependencyResolver def requests s, act, reqs=nil s.dependencies.reverse_each do |d| next if d.type == :development and not @development - reqs = Gem::List.new Gem::DependencyResolver::DependencyRequest.new(d, act), reqs + reqs.add Gem::Resolver::DependencyRequest.new(d, act) end @set.prefetch reqs @@ -100,18 +111,18 @@ class Gem::DependencyResolver def resolve @conflicts = [] - needed = nil + needed = RequirementList.new @needed.reverse_each do |n| - request = Gem::DependencyResolver::DependencyRequest.new n, nil + request = Gem::Resolver::DependencyRequest.new n, nil - needed = Gem::List.new request, needed + needed.add request end res = resolve_for needed, nil raise Gem::DependencyResolutionError, res if - res.kind_of? Gem::DependencyResolver::DependencyConflict + res.kind_of? Gem::Resolver::Conflict res.to_a end @@ -128,6 +139,8 @@ class Gem::DependencyResolver until states.empty? do state = states.pop + explain :consider, state.dep, conflict.failed_dep + if conflict.for_spec? state.spec state.conflicts << [state.spec, conflict] return state @@ -162,11 +175,11 @@ class Gem::DependencyResolver # Otherwise, issue it on the requester's request itself. if existing.others_possible? or existing.request.requester.nil? then conflict = - Gem::DependencyResolver::DependencyConflict.new dep, existing + Gem::Resolver::Conflict.new dep, existing else - depreq = existing.request.requester.request + depreq = dep.requester.request conflict = - Gem::DependencyResolver::DependencyConflict.new depreq, existing, dep + Gem::Resolver::Conflict.new depreq, existing, dep end @conflicts << conflict unless @conflicts.include? conflict @@ -182,7 +195,7 @@ class Gem::DependencyResolver # +spec+ is the Specification for this state. # +possible+ is List of DependencyRequest objects that can be tried to # find a complete set. - # +conflicts+ is a [DependencyRequest, DependencyConflict] hit tried to + # +conflicts+ is a [DependencyRequest, Conflict] hit tried to # activate the state. # State = Struct.new(:needed, :specs, :dep, :spec, :possibles, :conflicts) do @@ -218,9 +231,9 @@ class Gem::DependencyResolver # The State objects that are used to attempt the activation tree. states = [] - while needed - dep = needed.value - needed = needed.tail + while !needed.empty? + dep = needed.remove + explain :try, [dep, dep.requester ? dep.requester.request : :toplevel] # If there is already a spec activated for the requested name... if specs && existing = specs.find { |s| dep.name == s.name } @@ -228,6 +241,7 @@ class Gem::DependencyResolver next if dep.matches_spec? existing conflict = handle_conflict dep, existing + explain :conflict, conflict.explain state = find_conflict_state conflict, states @@ -292,7 +306,9 @@ class Gem::DependencyResolver # 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. - states << State.new(needed, specs, dep, spec, possible, []) + states << State.new(needed.dup, specs, dep, spec, possible, []) + + explain :states, states.map { |s| s.dep } needed = requests spec, act, needed specs = Gem::List.prepend specs, act @@ -341,24 +357,32 @@ class Gem::DependencyResolver end -require 'rubygems/dependency_resolver/activation_request' -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/vendor_specification' +## +# TODO remove in RubyGems 3 + +Gem::DependencyResolver = Gem::Resolver # :nodoc: + +require 'rubygems/resolver/activation_request' +require 'rubygems/resolver/conflict' +require 'rubygems/resolver/dependency_request' +require 'rubygems/resolver/requirement_list' + +require 'rubygems/resolver/set' +require 'rubygems/resolver/api_set' +require 'rubygems/resolver/composed_set' +require 'rubygems/resolver/best_set' +require 'rubygems/resolver/current_set' +require 'rubygems/resolver/git_set' +require 'rubygems/resolver/index_set' +require 'rubygems/resolver/installer_set' +require 'rubygems/resolver/lock_set' +require 'rubygems/resolver/vendor_set' + +require 'rubygems/resolver/specification' +require 'rubygems/resolver/spec_specification' +require 'rubygems/resolver/api_specification' +require 'rubygems/resolver/git_specification' +require 'rubygems/resolver/index_specification' +require 'rubygems/resolver/installed_specification' +require 'rubygems/resolver/vendor_specification' diff --git a/lib/rubygems/dependency_resolver/activation_request.rb b/lib/rubygems/resolver/activation_request.rb index c5d1e24d85..ca82ac408a 100644 --- a/lib/rubygems/dependency_resolver/activation_request.rb +++ b/lib/rubygems/resolver/activation_request.rb @@ -3,7 +3,7 @@ # Also contains a dependency that was used to introduce this # activation. -class Gem::DependencyResolver::ActivationRequest +class Gem::Resolver::ActivationRequest attr_reader :request @@ -19,7 +19,7 @@ class Gem::DependencyResolver::ActivationRequest case other when Gem::Specification @spec == other - when Gem::DependencyResolver::ActivationRequest + when Gem::Resolver::ActivationRequest @spec == other.spec && @request == other.request else false @@ -70,7 +70,7 @@ class Gem::DependencyResolver::ActivationRequest def installed? case @spec - when Gem::DependencyResolver::VendorSpecification then + when Gem::Resolver::VendorSpecification then true else this_spec = full_spec diff --git a/lib/rubygems/dependency_resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb index 9dd34562b1..60bf911063 100644 --- a/lib/rubygems/dependency_resolver/api_set.rb +++ b/lib/rubygems/resolver/api_set.rb @@ -2,7 +2,7 @@ # The global rubygems pool, available via the rubygems.org API. # Returns instances of APISpecification. -class Gem::DependencyResolver::APISet < Gem::DependencyResolver::Set +class Gem::Resolver::APISet < Gem::Resolver::Set ## # The URI for the dependency API this APISet uses. @@ -28,7 +28,7 @@ class Gem::DependencyResolver::APISet < Gem::DependencyResolver::Set versions(req.name).each do |ver| if req.dependency.match? req.name, ver[:number] - res << Gem::DependencyResolver::APISpecification.new(self, ver) + res << Gem::Resolver::APISpecification.new(self, ver) end end diff --git a/lib/rubygems/dependency_resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb index 5178d7c28e..19611e17d8 100644 --- a/lib/rubygems/dependency_resolver/api_specification.rb +++ b/lib/rubygems/resolver/api_specification.rb @@ -4,7 +4,7 @@ # This is used to avoid loading the full Specification object when all we need # is the name, version, and dependencies. -class Gem::DependencyResolver::APISpecification < Gem::DependencyResolver::Specification +class Gem::Resolver::APISpecification < Gem::Resolver::Specification ## # Creates an APISpecification for the given +set+ from the rubygems.org diff --git a/lib/rubygems/dependency_resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb index 987eea552e..533a0db58f 100644 --- a/lib/rubygems/dependency_resolver/best_set.rb +++ b/lib/rubygems/resolver/best_set.rb @@ -3,7 +3,7 @@ # # It combines IndexSet and APISet -class Gem::DependencyResolver::BestSet < Gem::DependencyResolver::ComposedSet +class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet ## # Creates a BestSet for the given +sources+ or Gem::sources if none are diff --git a/lib/rubygems/dependency_resolver/composed_set.rb b/lib/rubygems/resolver/composed_set.rb index aeecf047b8..e4aa15e4d0 100644 --- a/lib/rubygems/dependency_resolver/composed_set.rb +++ b/lib/rubygems/resolver/composed_set.rb @@ -1,4 +1,4 @@ -class Gem::DependencyResolver::ComposedSet < Gem::DependencyResolver::Set +class Gem::Resolver::ComposedSet < Gem::Resolver::Set attr_reader :sets # :nodoc: diff --git a/lib/rubygems/dependency_resolver/dependency_conflict.rb b/lib/rubygems/resolver/conflict.rb index 092f000cdb..b081972658 100644 --- a/lib/rubygems/dependency_resolver/dependency_conflict.rb +++ b/lib/rubygems/resolver/conflict.rb @@ -2,7 +2,7 @@ # Used internally to indicate that a dependency conflicted # with a spec that would be activated. -class Gem::DependencyResolver::DependencyConflict +class Gem::Resolver::Conflict attr_reader :activated @@ -23,6 +23,10 @@ class Gem::DependencyResolver::DependencyConflict @failed_dep == other.failed_dep end + def explain + "<Conflict wanted: #{@failed_dep}, had: #{activated.spec.full_name}>" + end + ## # Return the 2 dependency objects that conflicted @@ -94,3 +98,5 @@ class Gem::DependencyResolver::DependencyConflict end +Gem::Resolver::DependencyConflict = Gem::Resolver::Conflict + diff --git a/lib/rubygems/dependency_resolver/current_set.rb b/lib/rubygems/resolver/current_set.rb index ef15c9d7f3..4e8d34026b 100644 --- a/lib/rubygems/dependency_resolver/current_set.rb +++ b/lib/rubygems/resolver/current_set.rb @@ -3,7 +3,7 @@ # all the normal settings that control where to look # for installed gems. -class Gem::DependencyResolver::CurrentSet < Gem::DependencyResolver::Set +class Gem::Resolver::CurrentSet < Gem::Resolver::Set def find_all req req.dependency.matching_specs diff --git a/lib/rubygems/dependency_resolver/dependency_request.rb b/lib/rubygems/resolver/dependency_request.rb index 36b77ab558..e63b443c62 100644 --- a/lib/rubygems/dependency_resolver/dependency_request.rb +++ b/lib/rubygems/resolver/dependency_request.rb @@ -2,7 +2,7 @@ # Used Internally. Wraps a Dependency object to also track which spec # contained the Dependency. -class Gem::DependencyResolver::DependencyRequest +class Gem::Resolver::DependencyRequest attr_reader :dependency @@ -17,7 +17,7 @@ class Gem::DependencyResolver::DependencyRequest case other when Gem::Dependency @dependency == other - when Gem::DependencyResolver::DependencyRequest + when Gem::Resolver::DependencyRequest @dependency == other.dependency && @requester == other.requester else false diff --git a/lib/rubygems/resolver/git_set.rb b/lib/rubygems/resolver/git_set.rb new file mode 100644 index 0000000000..3c38d3dca0 --- /dev/null +++ b/lib/rubygems/resolver/git_set.rb @@ -0,0 +1,81 @@ +## +# A GitSet represents gems that are sourced from git repositories. +# +# This is used for gem dependency file support. +# +# Example: +# +# set = Gem::Resolver::GitSet.new +# set.add_git_gem 'rake', 'git://example/rake.git', tag: 'rake-10.1.0' + +class Gem::Resolver::GitSet < Gem::Resolver::Set + + ## + # Contains repositories needing submodules + + attr_reader :need_submodules # :nodoc: + + ## + # A Hash containing git gem names for keys and a Hash of repository and + # git commit reference as values. + + attr_reader :repositories # :nodoc: + + ## + # A hash of gem names to Gem::Resolver::GitSpecifications + + attr_reader :specs # :nodoc: + + def initialize # :nodoc: + @git = ENV['git'] || 'git' + @need_submodules = {} + @repositories = {} + @specs = {} + end + + def add_git_gem name, repository, reference, submodules # :nodoc: + @repositories[name] = [repository, reference] + @need_submodules[repository] = submodules + end + + ## + # 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| + 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 } + + @repositories.each_key do |name| + next unless names.include? name + + load_spec name + end + end + +end + diff --git a/lib/rubygems/resolver/git_specification.rb b/lib/rubygems/resolver/git_specification.rb new file mode 100644 index 0000000000..ac8d4e9aeb --- /dev/null +++ b/lib/rubygems/resolver/git_specification.rb @@ -0,0 +1,16 @@ +## +# A GitSpecification represents a gem that is sourced from a git repository +# and is being loaded through a gem dependencies file through the +git:+ +# option. + +class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification + + def == other # :nodoc: + self.class === other and + @set == other.set and + @spec == other.spec and + @source == other.source + end + +end + diff --git a/lib/rubygems/dependency_resolver/index_set.rb b/lib/rubygems/resolver/index_set.rb index 04d6ec816f..0ba3c78a44 100644 --- a/lib/rubygems/dependency_resolver/index_set.rb +++ b/lib/rubygems/resolver/index_set.rb @@ -2,7 +2,7 @@ # The global rubygems pool represented via the traditional # source index. -class Gem::DependencyResolver::IndexSet < Gem::DependencyResolver::Set +class Gem::Resolver::IndexSet < Gem::Resolver::Set def initialize source = nil # :nodoc: @f = @@ -38,7 +38,7 @@ class Gem::DependencyResolver::IndexSet < Gem::DependencyResolver::Set @all[name].each do |uri, n| if req.dependency.match? n then - res << Gem::DependencyResolver::IndexSpecification.new( + res << Gem::Resolver::IndexSpecification.new( self, n.name, n.version, uri, n.platform) end end diff --git a/lib/rubygems/dependency_resolver/index_specification.rb b/lib/rubygems/resolver/index_specification.rb index 9b4057f0c8..56fecb5753 100644 --- a/lib/rubygems/dependency_resolver/index_specification.rb +++ b/lib/rubygems/resolver/index_specification.rb @@ -3,7 +3,7 @@ # delay needed to download full Specification objects when only the +name+ # and +version+ are needed. -class Gem::DependencyResolver::IndexSpecification < Gem::DependencyResolver::Specification +class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification ## # An IndexSpecification is created from the index format described in `gem diff --git a/lib/rubygems/dependency_resolver/installed_specification.rb b/lib/rubygems/resolver/installed_specification.rb index 4b591661a8..647ff7499a 100644 --- a/lib/rubygems/dependency_resolver/installed_specification.rb +++ b/lib/rubygems/resolver/installed_specification.rb @@ -2,7 +2,7 @@ # An InstalledSpecification represents a gem that is already installed # locally. -class Gem::DependencyResolver::InstalledSpecification < Gem::DependencyResolver::SpecSpecification +class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification def == other # :nodoc: self.class === other and diff --git a/lib/rubygems/dependency_resolver/installer_set.rb b/lib/rubygems/resolver/installer_set.rb index 801b60a8bb..73d9e39651 100644 --- a/lib/rubygems/dependency_resolver/installer_set.rb +++ b/lib/rubygems/resolver/installer_set.rb @@ -2,7 +2,7 @@ # A set of gems for installation sourced from remote sources and local .gem # files -class Gem::DependencyResolver::InstallerSet < Gem::DependencyResolver::Set +class Gem::Resolver::InstallerSet < Gem::Resolver::Set ## # List of Gem::Specification objects that must always be installed. @@ -64,14 +64,14 @@ class Gem::DependencyResolver::InstallerSet < Gem::DependencyResolver::Set dep.matching_specs.each do |gemspec| next if @always_install.include? gemspec - res << Gem::DependencyResolver::InstalledSpecification.new(self, gemspec) + res << Gem::Resolver::InstalledSpecification.new(self, gemspec) end unless @ignore_installed if consider_local? then local_source = Gem::Source::Local.new if spec = local_source.find_gem(name, dep.requirement) then - res << Gem::DependencyResolver::IndexSpecification.new( + res << Gem::Resolver::IndexSpecification.new( self, spec.name, spec.version, local_source, spec.platform) end end @@ -81,7 +81,7 @@ class Gem::DependencyResolver::InstallerSet < Gem::DependencyResolver::Set @all[name].each do |remote_source, n| if dep.match? n then - res << Gem::DependencyResolver::IndexSpecification.new( + res << Gem::Resolver::IndexSpecification.new( self, n.name, n.version, remote_source, n.platform) end end diff --git a/lib/rubygems/dependency_resolver/lock_set.rb b/lib/rubygems/resolver/lock_set.rb index f95c7f0fd6..6885e70945 100644 --- a/lib/rubygems/dependency_resolver/lock_set.rb +++ b/lib/rubygems/resolver/lock_set.rb @@ -1,7 +1,7 @@ ## # A set of gems from a gem dependencies lockfile. -class Gem::DependencyResolver::LockSet < Gem::DependencyResolver::Set +class Gem::Resolver::LockSet < Gem::Resolver::Set attr_reader :specs # :nodoc: @@ -24,8 +24,8 @@ class Gem::DependencyResolver::LockSet < Gem::DependencyResolver::Set version = Gem::Version.new version spec = - Gem::DependencyResolver::IndexSpecification.new self, name, version, - @source, platform + Gem::Resolver::IndexSpecification.new self, name, version, @source, + platform @specs << spec end diff --git a/lib/rubygems/resolver/requirement_list.rb b/lib/rubygems/resolver/requirement_list.rb new file mode 100644 index 0000000000..8123e84fc7 --- /dev/null +++ b/lib/rubygems/resolver/requirement_list.rb @@ -0,0 +1,40 @@ +## +# Used internally to hold the requirements being considered +# while attempting to find a proper activation set. + +class Gem::Resolver::RequirementList + + include Enumerable + + def initialize + @list = [] + end + + def initialize_copy(other) + @list = @list.dup + end + + def add(req) + @list.push req + req + end + + ## + # Enumerates requirements in the list + + def each # :nodoc: + return enum_for __method__ unless block_given? + + @list.each do |requirement| + yield requirement + end + end + + def empty? + @list.empty? + end + + def remove + @list.shift + end +end diff --git a/lib/rubygems/dependency_resolver/set.rb b/lib/rubygems/resolver/set.rb index 65801871ac..32c137ef6b 100644 --- a/lib/rubygems/dependency_resolver/set.rb +++ b/lib/rubygems/resolver/set.rb @@ -1,13 +1,12 @@ ## -# DependencyResolver sets are used to look up specifications (and their +# Resolver sets are used to look up specifications (and their # dependencies) used in resolution. This set is abstract. -class Gem::DependencyResolver::Set +class Gem::Resolver::Set ## - # The find_all method must be implemented. It returns all - # DependencyResolver Specification objects matching the given - # DependencyRequest +req+. + # The find_all method must be implemented. It returns all Resolver + # Specification objects matching the given DependencyRequest +req+. def find_all req raise NotImplementedError diff --git a/lib/rubygems/dependency_resolver/spec_specification.rb b/lib/rubygems/resolver/spec_specification.rb index cca1d58b9f..0c411bdf5f 100644 --- a/lib/rubygems/dependency_resolver/spec_specification.rb +++ b/lib/rubygems/resolver/spec_specification.rb @@ -1,8 +1,8 @@ ## -# The DependencyResolver::SpecSpecification contains common functionality for -# DependencyResolver specifications that are backed by a Gem::Specification. +# The Resolver::SpecSpecification contains common functionality for +# Resolver specifications that are backed by a Gem::Specification. -class Gem::DependencyResolver::SpecSpecification < Gem::DependencyResolver::Specification +class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification attr_reader :spec # :nodoc: diff --git a/lib/rubygems/dependency_resolver/specification.rb b/lib/rubygems/resolver/specification.rb index 6fbd241316..7dd4c2e829 100644 --- a/lib/rubygems/dependency_resolver/specification.rb +++ b/lib/rubygems/resolver/specification.rb @@ -1,9 +1,9 @@ ## -# A DependencyResolver::Specification contains a subset of the information +# A Resolver::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 +class Gem::Resolver::Specification ## # The dependencies of the gem for this specification diff --git a/lib/rubygems/dependency_resolver/vendor_set.rb b/lib/rubygems/resolver/vendor_set.rb index 87eb6fd818..e9cbcd8303 100644 --- a/lib/rubygems/dependency_resolver/vendor_set.rb +++ b/lib/rubygems/resolver/vendor_set.rb @@ -6,14 +6,14 @@ # # Example: # -# set = Gem::DependencyResolver::VendorSet.new +# set = Gem::Resolver::VendorSet.new # # set.add_vendor_gem 'rake', 'vendor/rake' # # The directory vendor/rake must contain an unpacked rake gem along with a # rake.gemspec (watching the given name). -class Gem::DependencyResolver::VendorSet < Gem::DependencyResolver::Set +class Gem::Resolver::VendorSet < Gem::Resolver::Set def initialize # :nodoc: @directories = {} @@ -47,7 +47,7 @@ class Gem::DependencyResolver::VendorSet < Gem::DependencyResolver::Set req.matches_spec? spec end.map do |spec| source = Gem::Source::Vendor.new @directories[spec] - Gem::DependencyResolver::VendorSpecification.new self, spec, source + Gem::Resolver::VendorSpecification.new self, spec, source end end diff --git a/lib/rubygems/dependency_resolver/vendor_specification.rb b/lib/rubygems/resolver/vendor_specification.rb index 27b2fd6df2..24e033d084 100644 --- a/lib/rubygems/dependency_resolver/vendor_specification.rb +++ b/lib/rubygems/resolver/vendor_specification.rb @@ -3,7 +3,7 @@ # and is being loaded through a gem dependencies file through the +path:+ # option. -class Gem::DependencyResolver::VendorSpecification < Gem::DependencyResolver::SpecSpecification +class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification def == other # :nodoc: self.class === other and diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index b39b3ae69d..a40a27594b 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -28,7 +28,9 @@ class Gem::Source case other when Gem::Source::Installed, Gem::Source::Local, - Gem::Source::SpecificFile then + Gem::Source::SpecificFile, + Gem::Source::Git, + Gem::Source::Vendor then -1 when Gem::Source then if !@uri @@ -62,9 +64,9 @@ class Gem::Source fetcher = Gem::RemoteFetcher.fetcher fetcher.fetch_path bundler_api_uri, nil, true rescue Gem::RemoteFetcher::FetchError - Gem::DependencyResolver::IndexSet.new self + Gem::Resolver::IndexSet.new self else - Gem::DependencyResolver::APISet.new bundler_api_uri + Gem::Resolver::APISet.new bundler_api_uri end end @@ -90,12 +92,15 @@ class Gem::Source end end - def fetch_spec(name) + ## + # Fetches a specification for the given +name_tuple+. + + def fetch_spec name_tuple fetcher = Gem::RemoteFetcher.fetcher - spec_file_name = name.spec_name + spec_file_name = name_tuple.spec_name - uri = @uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}" + uri = api_uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}" cache_dir = cache_dir uri @@ -139,7 +144,7 @@ class Gem::Source file = FILES[type] fetcher = Gem::RemoteFetcher.fetcher file_name = "#{file}.#{Gem.marshal_version}" - spec_path = @uri + "#{file_name}.gz" + spec_path = api_uri + "#{file_name}.gz" cache_dir = cache_dir spec_path local_file = File.join(cache_dir, file_name) retried = false @@ -163,18 +168,22 @@ class Gem::Source def download(spec, dir=Dir.pwd) fetcher = Gem::RemoteFetcher.fetcher - fetcher.download spec, @uri.to_s, dir + fetcher.download spec, api_uri.to_s, dir end def pretty_print q # :nodoc: q.group 2, '[Remote:', ']' do q.breakable q.text @uri.to_s + if api = api_uri + g.text api + end end end end +require 'rubygems/source/git' require 'rubygems/source/installed' require 'rubygems/source/specific_file' require 'rubygems/source/local' diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb new file mode 100644 index 0000000000..8453aa5fd7 --- /dev/null +++ b/lib/rubygems/source/git.rb @@ -0,0 +1,189 @@ +require 'digest' +require 'rubygems/util' + +## +# A git gem for use in a gem dependencies file. +# +# Example: +# +# source = +# Gem::Source::Git.new 'rake', 'git@example:rake.git', 'rake-10.1.0', false +# +# spec = source.load_spec 'rake' +# +# source.checkout + +class Gem::Source::Git < Gem::Source + + ## + # The name of the gem created by this git gem. + + attr_reader :name + + ## + # The commit reference used for checking out this git gem. + + attr_reader :reference + + ## + # The git repository this gem is sourced from. + + attr_reader :repository + + ## + # Does this repository need submodules checked out too? + + 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. + + def initialize name, repository, reference, submodules = false + super(nil) + + @name = name + @repository = repository + @reference = reference + @need_submodules = submodules + + @git = ENV['git'] || 'git' + end + + def <=> other + case other + when Gem::Source::Git then + 0 + when Gem::Source::Installed then + -1 + when Gem::Source then + 1 + else + nil + end + end + + def == other # :nodoc: + super and + @name == other.name and + @repository == other.repository and + @reference == other.reference and + @need_submodules == other.need_submodules + end + + ## + # Checks out the files for the repository into the install_dir. + + def checkout # :nodoc: + cache + + unless File.exist? install_dir then + system @git, 'clone', '--quiet', '--no-checkout', + repo_cache_dir, install_dir + end + + Dir.chdir install_dir do + system @git, 'fetch', '--quiet', '--force', '--tags', install_dir + + success = system @git, 'reset', '--quiet', '--hard', @reference + + success &&= + system @git, 'submodule', 'update', + '--quiet', '--init', '--recursive' if @need_submodules + + success + end + end + + ## + # Creates a local cache repository for the git gem. + + def cache # :nodoc: + if File.exist? repo_cache_dir then + Dir.chdir repo_cache_dir do + system @git, 'fetch', '--quiet', '--force', '--tags', + @repository, 'refs/heads/*:refs/heads/*' + end + else + system @git, 'clone', '--quiet', '--bare', '--no-hardlinks', + @repository, repo_cache_dir + end + end + + ## + # A short reference for use in git gem directories + + def dir_shortref # :nodoc: + rev_parse[0..11] + end + + ## + # The directory where the git gem will be installed. + + def install_dir # :nodoc: + 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. + + def repo_cache_dir # :nodoc: + File.join Gem.dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}" + end + + ## + # 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 + + ## + # A hash for the git gem based on the git repository URI. + + def uri_hash # :nodoc: + normalized = + if @repository =~ %r%^\w+://(\w+@)?% then + uri = URI(@repository).normalize.to_s.sub %r%/$%,'' + uri.sub(/\A(\w+)/) { $1.downcase } + else + @repository + end + + Digest::SHA1.hexdigest normalized + end + +end + diff --git a/lib/rubygems/source/installed.rb b/lib/rubygems/source/installed.rb index 8e3a3560bf..2661dd6844 100644 --- a/lib/rubygems/source/installed.rb +++ b/lib/rubygems/source/installed.rb @@ -1,6 +1,9 @@ +## +# Represents an installed gem. This is used for dependency resolution. + class Gem::Source::Installed < Gem::Source - def initialize + def initialize # :nodoc: @uri = nil end @@ -9,6 +12,8 @@ class Gem::Source::Installed < Gem::Source def <=> other case other + when Gem::Source::Vendor then + -1 when Gem::Source::Installed then 0 when Gem::Source then diff --git a/lib/rubygems/source/local.rb b/lib/rubygems/source/local.rb index 16a028b2f3..3aae20c8ed 100644 --- a/lib/rubygems/source/local.rb +++ b/lib/rubygems/source/local.rb @@ -1,5 +1,10 @@ +## +# The local source finds gems in the current directory for fulfilling +# dependencies. + class Gem::Source::Local < Gem::Source - def initialize + + def initialize # :nodoc: @specs = nil @api_uri = nil @uri = nil @@ -26,7 +31,7 @@ class Gem::Source::Local < Gem::Source "#<%s specs: %p>" % [self.class, keys] end - def load_specs(type) + def load_specs type # :nodoc: names = [] @specs = {} @@ -68,8 +73,8 @@ class Gem::Source::Local < Gem::Source names end - def find_gem(gem_name, version=Gem::Requirement.default, - prerelease=false) + def find_gem gem_name, version = Gem::Requirement.default, # :nodoc: + prerelease = false load_specs :complete found = [] @@ -91,7 +96,7 @@ class Gem::Source::Local < Gem::Source found.max_by { |s| s.version } end - def fetch_spec(name) + def fetch_spec name # :nodoc: load_specs :complete if data = @specs[name] @@ -101,7 +106,7 @@ class Gem::Source::Local < Gem::Source end end - def download(spec, cache_dir=nil) + def download spec, cache_dir = nil # :nodoc: load_specs :complete @specs.each do |name, data| diff --git a/lib/rubygems/source/specific_file.rb b/lib/rubygems/source/specific_file.rb index 8d328b38c2..a7b6c53542 100644 --- a/lib/rubygems/source/specific_file.rb +++ b/lib/rubygems/source/specific_file.rb @@ -1,4 +1,12 @@ +## +# A source representing a single .gem file. This is used for installation of +# local gems. + class Gem::Source::SpecificFile < Gem::Source + + ## + # Creates a new SpecificFile for the gem in +file+ + def initialize(file) @uri = nil @path = ::File.expand_path(file) @@ -8,19 +16,22 @@ class Gem::Source::SpecificFile < Gem::Source @name = @spec.name_tuple end + ## + # The Gem::Specification extracted from this .gem. + attr_reader :spec - def load_specs(*a) + def load_specs *a # :nodoc: [@name] end - def fetch_spec(name) + def fetch_spec name # :nodoc: return @spec if name == @name raise Gem::Exception, "Unable to find '#{name}'" @spec end - def download(spec, dir=nil) + def download spec, dir = nil # :nodoc: return @path if spec == @spec raise Gem::Exception, "Unable to download '#{spec.full_name}'" end diff --git a/lib/rubygems/source/vendor.rb b/lib/rubygems/source/vendor.rb index f2cf540c8d..244c4201d8 100644 --- a/lib/rubygems/source/vendor.rb +++ b/lib/rubygems/source/vendor.rb @@ -3,8 +3,22 @@ class Gem::Source::Vendor < Gem::Source::Installed - def initialize uri - @uri = uri + ## + # Creates a new Vendor source for a gem that was unpacked at +path+. + + def initialize path + @uri = path + end + + def <=> other + case other + when Gem::Source::Vendor then + 0 + when Gem::Source then + 1 + else + nil + end end end diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb index e6da50c2e5..e01f11cc1e 100644 --- a/lib/rubygems/source_list.rb +++ b/lib/rubygems/source_list.rb @@ -1,5 +1,18 @@ require 'rubygems/source' +## +# The SourceList represents the sources rubygems has been configured to use. +# A source may be created from an array of sources: +# +# Gem::SourceList.from %w[https://rubygems.example https://internal.example] +# +# Or by adding them: +# +# sources = Gem::SourceList.new +# sources.add 'https://rubygems.example' +# +# The most common way to get a SourceList is Gem.sources. + class Gem::SourceList include Enumerable @@ -91,7 +104,7 @@ class Gem::SourceList @sources.empty? end - def ==(other) + def == other # :nodoc: to_a == other end diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb index 22fa68db69..12b8fb27d8 100644 --- a/lib/rubygems/spec_fetcher.rb +++ b/lib/rubygems/spec_fetcher.rb @@ -34,6 +34,10 @@ class Gem::SpecFetcher @fetcher = nil + ## + # Default fetcher instance. Use this instead of ::new to reduce object + # allocation. + def self.fetcher @fetcher ||= new end @@ -43,8 +47,8 @@ class Gem::SpecFetcher end ## - # Creates a new SpecFetcher. Ordinarily you want to use - # Gem::SpecFetcher::fetcher which uses the Gem.sources. + # Creates a new SpecFetcher. Ordinarily you want to use the default fetcher + # from 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. @@ -84,7 +88,11 @@ class Gem::SpecFetcher rejected_specs = {} if dependency.prerelease? - type = :complete + if dependency.specific? + type = :complete + else + type = :abs_latest + end elsif dependency.latest_version? type = :latest else @@ -224,6 +232,12 @@ class Gem::SpecFetcher tuples_for(source, :released) names.sort + when :abs_latest + names = + tuples_for(source, :prerelease, true) + + tuples_for(source, :latest) + + names.sort when :prerelease tuples_for(source, :prerelease) else @@ -239,7 +253,11 @@ class Gem::SpecFetcher [list, errors] end - def tuples_for(source, type, gracefully_ignore=false) + ## + # Retrieves NameTuples from +source+ of the given +type+ (:prerelease, + # etc.). If +gracefully_ignore+ is true, errors are ignored. + + def tuples_for(source, type, gracefully_ignore=false) # :nodoc: cache = @caches[type] tuples = diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 308aa6f011..b95e2c0699 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -12,6 +12,7 @@ require 'rubygems/platform' require 'rubygems/deprecate' require 'rubygems/basic_specification' require 'rubygems/stub_specification' +require 'rubygems/util/stringio' # :stopdoc: # date.rb can't be loaded for `make install` due to miniruby @@ -2165,7 +2166,7 @@ class Gem::Specification < Gem::BasicSpecification end ## - # Used by Gem::DependencyResolver to order Gem::Specification objects + # Used by Gem::Resolver to order Gem::Specification objects def source # :nodoc: self @@ -2363,7 +2364,7 @@ class Gem::Specification < Gem::BasicSpecification builder << self ast = builder.tree - io = StringIO.new + io = Gem::StringSink.new io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding Psych::Visitors::Emitter.new(io).accept(ast) diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index b04cbfc1f3..d1b471f619 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -233,6 +233,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase ruby end + @git = ENV['GIT'] || 'git' + Gem.ensure_gem_subdirectories @gemhome @orig_LOAD_PATH = $LOAD_PATH.dup @@ -373,6 +375,64 @@ class Gem::TestCase < MiniTest::Unit::TestCase end ## + # A git_gem is used with a gem dependencies file. The gem created here + # has no files, just a gem specification for the given +name+ and +version+. + # + # Yields the +specification+ to the block, if given + + def git_gem name = 'a', version = 1 + have_git? + + directory = File.join 'git', name + directory = File.expand_path directory + + git_spec = Gem::Specification.new name, version do |specification| + yield specification if block_given? + end + + FileUtils.mkdir_p directory + + gemspec = "#{name}.gemspec" + + open File.join(directory, gemspec), 'w' do |io| + io.write git_spec.to_ruby + end + + head = nil + + Dir.chdir directory do + unless File.exist? '.git' then + system @git, 'init', '--quiet' + system @git, 'config', 'user.name', 'RubyGems Tests' + system @git, 'config', 'user.email', 'rubygems@example' + end + + system @git, 'add', gemspec + system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet' + head = Gem::Util.popen('git', 'rev-parse', 'master').strip + end + + return name, git_spec.version, directory, head + end + + ## + # Skips this test unless you have a git executable + + def have_git? + return if in_path? @git + + skip 'cannot find git executable, use GIT environment variable to set' + end + + def in_path? executable # :nodoc: + return true if %r%\A([A-Z]:|/)% =~ executable and File.exist? executable + + ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| + File.exist? File.join directory, executable + end + end + + ## # Builds and installs the Gem::Specification +spec+ def install_gem spec, options = {} @@ -1082,21 +1142,21 @@ Also, a list: end ## - # Constructs a Gem::DependencyResolver::DependencyRequest from a + # Constructs a Gem::Resolver::DependencyRequest from a # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the # dependency and a +parent+ DependencyRequest def dependency_request dep, from_name, from_version, parent = nil remote = Gem::Source.new @uri - parent ||= Gem::DependencyResolver::DependencyRequest.new \ + parent ||= Gem::Resolver::DependencyRequest.new \ dep, nil - spec = Gem::DependencyResolver::IndexSpecification.new \ + spec = Gem::Resolver::IndexSpecification.new \ nil, from_name, from_version, remote, Gem::Platform::RUBY - activation = Gem::DependencyResolver::ActivationRequest.new spec, parent + activation = Gem::Resolver::ActivationRequest.new spec, parent - Gem::DependencyResolver::DependencyRequest.new dep, activation + Gem::Resolver::DependencyRequest.new dep, activation end ## diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb new file mode 100644 index 0000000000..e862458d21 --- /dev/null +++ b/lib/rubygems/util.rb @@ -0,0 +1,65 @@ +module Gem::Util + ## + # Zlib::GzipReader wrapper that unzips +data+. + + def self.gunzip(data) + require 'zlib' + require 'rubygems/util/stringio' + data = Gem::StringSource.new data + + unzipped = Zlib::GzipReader.new(data).read + unzipped.force_encoding Encoding::BINARY if Object.const_defined? :Encoding + unzipped + end + + ## + # Zlib::GzipWriter wrapper that zips +data+. + + def self.gzip(data) + require 'zlib' + require 'rubygems/util/stringio' + zipped = Gem::StringSink.new + zipped.set_encoding Encoding::BINARY if Object.const_defined? :Encoding + + Zlib::GzipWriter.wrap zipped do |io| io.write data end + + zipped.string + end + + ## + # A Zlib::Inflate#inflate wrapper + + def self.inflate(data) + require 'zlib' + Zlib::Inflate.inflate data + end + + ## + # This calls IO.popen where it accepts an array for a +command+ (Ruby 1.9+) + # and implements an IO.popen-like behavior where it does not accept an array + # for a command. + + def self.popen *command + begin + r, = IO.popen command + rescue TypeError # ruby 1.8 only supports string command + r, w = IO.pipe + + pid = fork do + STDIN.close + STDOUT.reopen w + + exec(*command) + end + + w.close + + Process.wait pid + + r + end + + r.read + end + +end diff --git a/lib/rubygems/util/stringio.rb b/lib/rubygems/util/stringio.rb new file mode 100644 index 0000000000..2ea69617bc --- /dev/null +++ b/lib/rubygems/util/stringio.rb @@ -0,0 +1,34 @@ +class Gem::StringSink + def initialize + @string = "" + end + + attr_reader :string + + def write(s) + @string += s + s.size + end + + def set_encoding(enc) + @string.force_encoding enc + end +end + +class Gem::StringSource + def initialize(str) + @string = str.dup + end + + def read(count=nil) + if count + @string.slice!(0,count) + else + s = @string + @string = "" + s + end + end + + alias_method :readpartial, :read +end diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fd4d1de5c6..ec7f7299ec 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1120,7 +1120,7 @@ class TestGem < Gem::TestCase ENV['RUBYGEMS_GEMDEPS'] = "-" - assert_equal [a,b,c], Gem.detect_gemdeps + assert_equal [a,b,c], Gem.detect_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".untaint, __FILE__.untaint diff --git a/test/rubygems/test_gem_commands_which_command.rb b/test/rubygems/test_gem_commands_which_command.rb index b19f204c4a..7ce26c861a 100644 --- a/test/rubygems/test_gem_commands_which_command.rb +++ b/test/rubygems/test_gem_commands_which_command.rb @@ -44,7 +44,9 @@ class TestGemCommandsWhichCommand < Gem::TestCase @cmd.handle_options %w[foo_bar missinglib] use_ui @ui do - @cmd.execute + assert_raises Gem::MockGemUi::TermError do + @cmd.execute + end end assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output diff --git a/test/rubygems/test_gem_dependency_resolution_error.rb b/test/rubygems/test_gem_dependency_resolution_error.rb index 0ac0b06028..0442082e6a 100644 --- a/test/rubygems/test_gem_dependency_resolution_error.rb +++ b/test/rubygems/test_gem_dependency_resolution_error.rb @@ -5,7 +5,7 @@ class TestGemDependencyResolutionError < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver @spec = util_spec 'a', 2 @@ -14,7 +14,7 @@ class TestGemDependencyResolutionError < Gem::TestCase @activated = @DR::ActivationRequest.new @spec, @a2_req - @conflict = @DR::DependencyConflict.new @a1_req, @activated + @conflict = @DR::Conflict.new @a1_req, @activated @error = Gem::DependencyResolutionError.new @conflict end diff --git a/test/rubygems/test_gem_dependency_resolver_vendor_specification.rb b/test/rubygems/test_gem_dependency_resolver_vendor_specification.rb deleted file mode 100644 index 77d78d1dc7..0000000000 --- a/test/rubygems/test_gem_dependency_resolver_vendor_specification.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'rubygems/test_case' -require 'rubygems/dependency_resolver' - -class TestGemDependencyResolverVendorSpecification < Gem::TestCase - - def setup - super - - @set = Gem::DependencyResolver::VendorSet.new - @spec = Gem::Specification.new 'a', 1 - end - - def test_equals2 - v_spec_a = Gem::DependencyResolver::VendorSpecification.new @set, @spec - - assert_equal v_spec_a, v_spec_a - - spec_b = Gem::Specification.new 'b', 1 - v_spec_b = Gem::DependencyResolver::VendorSpecification.new @set, spec_b - - refute_equal v_spec_a, v_spec_b - - v_set = Gem::DependencyResolver::VendorSet.new - v_spec_s = Gem::DependencyResolver::VendorSpecification.new v_set, @spec - - refute_equal v_spec_a, v_spec_s - - i_set = Gem::DependencyResolver::IndexSet.new - source = Gem::Source.new @gem_repo - i_spec = Gem::DependencyResolver::IndexSpecification.new( - i_set, 'a', v(1), source, Gem::Platform::RUBY) - - refute_equal v_spec_a, i_spec - end - - def test_dependencies - @spec.add_dependency 'b' - @spec.add_dependency 'c' - - v_spec = Gem::DependencyResolver::VendorSpecification.new @set, @spec - - assert_equal [dep('b'), dep('c')], v_spec.dependencies - end - - def test_full_name - v_spec = Gem::DependencyResolver::VendorSpecification.new @set, @spec - - assert_equal 'a-1', v_spec.full_name - end - - def test_name - v_spec = Gem::DependencyResolver::VendorSpecification.new @set, @spec - - assert_equal 'a', v_spec.name - end - - def test_platform - v_spec = Gem::DependencyResolver::VendorSpecification.new @set, @spec - - assert_equal Gem::Platform::RUBY, v_spec.platform - end - - def test_version - spec = Gem::Specification.new 'a', 1 - - v_spec = Gem::DependencyResolver::VendorSpecification.new @set, spec - - assert_equal v(1), v_spec.version - end - -end - diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index d7e5880a96..3da9bc9e60 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -98,22 +98,26 @@ install: end def test_build_extensions - @spec.extensions << 'extconf.rb' + @spec.extensions << 'ext/extconf.rb' - FileUtils.mkdir_p @spec.gem_dir + ext_dir = File.join @spec.gem_dir, 'ext' + + FileUtils.mkdir_p ext_dir - extconf_rb = File.join @spec.gem_dir, 'extconf.rb' + extconf_rb = File.join ext_dir, 'extconf.rb' open extconf_rb, 'w' do |f| f.write <<-'RUBY' - open 'Makefile', 'w' do |f| - f.puts "clean:\n\techo cleaned" - f.puts "default:\n\techo built" - f.puts "install:\n\techo installed" - end + require 'mkmf' + + create_makefile 'a' RUBY end + ext_lib_dir = File.join ext_dir, 'lib' + FileUtils.mkdir ext_lib_dir + FileUtils.touch File.join ext_lib_dir, 'a.rb' + use_ui @ui do @builder.build_extensions end @@ -121,6 +125,8 @@ install: assert_path_exists @spec.extension_install_dir assert_path_exists @spec.gem_build_complete_path assert_path_exists File.join @spec.extension_install_dir, 'gem_make.out' + assert_path_exists File.join @spec.extension_install_dir, 'a.rb' + assert_path_exists File.join @spec.gem_dir, 'lib', 'a.rb' end def test_build_extensions_none diff --git a/test/rubygems/test_gem_impossible_dependencies_error.rb b/test/rubygems/test_gem_impossible_dependencies_error.rb index 9a0472fa36..f61b86e490 100644 --- a/test/rubygems/test_gem_impossible_dependencies_error.rb +++ b/test/rubygems/test_gem_impossible_dependencies_error.rb @@ -15,10 +15,10 @@ class TestGemImpossibleDependenciesError < Gem::TestCase net_ssh_2_6_5 = dependency_request dep('net-ssh', '~> 2.2.2'), 'net-ssh', '2.6.5', request - conflict1 = Gem::DependencyResolver::DependencyConflict.new \ + conflict1 = Gem::Resolver::Conflict.new \ net_ssh_2_6_5, net_ssh_2_6_5.requester - conflict2 = Gem::DependencyResolver::DependencyConflict.new \ + conflict2 = Gem::Resolver::Conflict.new \ net_ssh_2_2_2, net_ssh_2_2_2.requester conflicts << [net_ssh_2_6_5.requester.spec, conflict1] diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 0abb58b655..f0dd52cd36 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -1004,6 +1004,10 @@ gem 'other', version skip '1.9.2 and earlier mkmf.rb does not create TOUCH' if RUBY_VERSION < '1.9.3' + if RUBY_VERSION == "1.9.3" and RUBY_PATCHLEVEL <= 194 + skip "TOUCH was introduced into 1.9.3 after p194" + end + @spec.require_paths = ["."] @spec.extensions << "extconf.rb" @@ -1038,8 +1042,14 @@ gem 'other', version puts '-' * 78 puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile') puts '-' * 78 - puts File.read File.join(@gemhome, 'gems', 'a-2', 'gem_make.out') - puts '-' * 78 + + path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out') + + if File.exists?(path) + puts File.read(path) + puts '-' * 78 + end + raise end diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index 5f36e71807..7e6d9c7693 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -165,7 +165,7 @@ gems: def test_api_endpoint uri = URI.parse "http://gems.example.com/foo" target = MiniTest::Mock.new - target.expect :target, "http://blah.com" + target.expect :target, "blah.com" dns = MiniTest::Mock.new dns.expect :getresource, target, [String, Object] diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index 9b215c2bc7..531b6c09d1 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -7,7 +7,7 @@ class TestGemRequestSet < Gem::TestCase Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new - @DR = Gem::DependencyResolver + @DR = Gem::Resolver end def test_gem @@ -69,6 +69,7 @@ class TestGemRequestSet < Gem::TestCase assert_equal [dep('a')], rs.dependencies + assert rs.git_set assert rs.vendor_set end @@ -100,6 +101,32 @@ class TestGemRequestSet < Gem::TestCase assert_equal ["a-2", "b-2"], names end + def test_resolve_git + name, _, repository, = git_gem + + rs = Gem::RequestSet.new + + Tempfile.open 'gem.deps.rb' do |io| + io.puts <<-gems_deps_rb + gem "#{name}", :git => "#{repository}" + gems_deps_rb + + io.flush + + rs.load_gemdeps io.path + end + + res = rs.resolve + assert_equal 1, res.size + + names = res.map { |s| s.full_name }.sort + + assert_equal %w[a-1], names + + assert_equal [@DR::IndexSet, @DR::GitSet, @DR::VendorSet], + rs.sets.map { |set| set.class } + end + def test_resolve_incompatible a1 = util_spec 'a', 1 a2 = util_spec 'a', 2 @@ -142,7 +169,7 @@ class TestGemRequestSet < Gem::TestCase assert_equal ["a-1", "b-2"], names - assert_equal [@DR::IndexSet, @DR::VendorSet], + assert_equal [@DR::IndexSet, @DR::GitSet, @DR::VendorSet], rs.sets.map { |set| set.class } end diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb index 154449dde2..4286a761cb 100644 --- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb +++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb @@ -10,9 +10,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase @set = Gem::RequestSet.new - @vendor_set = Gem::DependencyResolver::VendorSet.new + @git_set = Gem::Resolver::GitSet.new + @vendor_set = Gem::Resolver::VendorSet.new @gda = @GDA.new @set, 'gem.deps.rb' + @gda.instance_variable_set :@git_set, @git_set @gda.instance_variable_set :@vendor_set, @vendor_set end @@ -48,6 +50,18 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase Gem.instance_variables.include? :@ruby_version end + def test_gemspec_without_group + @gda.send :add_dependencies, [:development], [dep('a', '= 1')] + + assert_equal [dep('a', '= 1')], @set.dependencies + + @gda.without_groups << :development + + @gda.send :add_dependencies, [:development], [dep('b', '= 2')] + + assert_equal [dep('a', '= 1')], @set.dependencies + end + def test_gem @gda.gem 'a' @@ -56,6 +70,65 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase assert_equal %w[a], @gda.requires['a'] end + def test_gem_git + @gda.gem 'a', :git => 'git/a' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git/a master], @git_set.repositories['a'] + end + + def test_gem_git_branch + @gda.gem 'a', :git => 'git/a', :branch => 'other', :tag => 'v1' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git/a other], @git_set.repositories['a'] + end + + def test_gem_git_gist + @gda.gem 'a', :gist => 'a' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[https://gist.github.com/a.git master], + @git_set.repositories['a'] + end + + def test_gem_git_ref + @gda.gem 'a', :git => 'git/a', :ref => 'abcd123', :branch => 'other' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git/a abcd123], @git_set.repositories['a'] + end + + def test_gem_git_submodules + @gda.gem 'a', :git => 'git/a', :submodules => true + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git/a master], @git_set.repositories['a'] + assert_equal %w[git/a], @git_set.need_submodules.keys + end + + def test_gem_git_tag + @gda.gem 'a', :git => 'git/a', :tag => 'v1' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git/a v1], @git_set.repositories['a'] + end + + def test_gem_github + @gda.gem 'a', :github => 'example/repository' + + assert_equal [dep('a')], @set.dependencies + + assert_equal %w[git://github.com/example/repository.git master], + @git_set.repositories['a'] + end + def test_gem_group @gda.gem 'a', :group => :test @@ -284,6 +357,130 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase assert_equal [:a, :b, :c, :d], groups.sort_by { |group| group.to_s } end + def test_gemspec + spec = util_spec 'a', 1, 'b' => 2 + spec.add_development_dependency 'c', 3 + + open 'a.gemspec', 'w' do |io| + io.write spec.to_ruby_for_cache + end + + @gda.gemspec + + assert_equal [dep('b', '= 2'), dep('c', '=3')], @set.dependencies + + assert_equal %w[a], @gda.requires['a'] + end + + def test_gemspec_bad + FileUtils.touch 'a.gemspec' + + e = assert_raises ArgumentError do + capture_io do + @gda.gemspec + end + end + + assert_equal 'invalid gemspec ./a.gemspec', e.message + end + + def test_gemspec_development_group + spec = util_spec 'a', 1, 'b' => 2 + spec.add_development_dependency 'c', 3 + + open 'a.gemspec', 'w' do |io| + io.write spec.to_ruby_for_cache + end + + @gda.without_groups << :other + + @gda.gemspec :development_group => :other + + assert_equal [dep('b', '= 2')], @set.dependencies + + assert_equal %w[a], @gda.requires['a'] + end + + def test_gemspec_multiple + open 'a.gemspec', 'w' do |io| + spec = util_spec 'a', 1, 'b' => 2 + io.write spec.to_ruby_for_cache + end + + open 'b.gemspec', 'w' do |io| + spec = util_spec 'b', 2, 'c' => 3 + io.write spec.to_ruby_for_cache + end + + e = assert_raises ArgumentError do + @gda.gemspec + end + + assert_equal "found multiple gemspecs at #{@tempdir}, use the name: option to specify the one you want", e.message + end + + def test_gemspec_name + open 'a.gemspec', 'w' do |io| + spec = util_spec 'a', 1, 'b' => 2 + io.write spec.to_ruby_for_cache + end + + open 'b.gemspec', 'w' do |io| + spec = util_spec 'b', 2, 'c' => 3 + io.write spec.to_ruby_for_cache + end + + @gda.gemspec :name => 'b' + + assert_equal [dep('c', '= 3')], @set.dependencies + end + + def test_gemspec_named + spec = util_spec 'a', 1, 'b' => 2 + + open 'other.gemspec', 'w' do |io| + io.write spec.to_ruby_for_cache + end + + @gda.gemspec + + assert_equal [dep('b', '= 2')], @set.dependencies + end + + def test_gemspec_none + e = assert_raises ArgumentError do + @gda.gemspec + end + + assert_equal "no gemspecs found at #{@tempdir}", e.message + end + + def test_gemspec_path + spec = util_spec 'a', 1, 'b' => 2 + + FileUtils.mkdir 'other' + + open 'other/a.gemspec', 'w' do |io| + io.write spec.to_ruby_for_cache + end + + @gda.gemspec :path => 'other' + + assert_equal [dep('b', '= 2')], @set.dependencies + end + + def test_git + @gda.git 'git://example/repo.git' do + @gda.gem 'a' + @gda.gem 'b' + end + + assert_equal [dep('a'), dep('b')], @set.dependencies + + assert_equal %w[git://example/repo.git master], @git_set.repositories['a'] + assert_equal %w[git://example/repo.git master], @git_set.repositories['b'] + end + def test_group @gda.group :test do @gda.gem 'a' diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb index 9e947f54ec..fcd4ecfaf7 100644 --- a/test/rubygems/test_gem_request_set_lockfile.rb +++ b/test/rubygems/test_gem_request_set_lockfile.rb @@ -13,7 +13,7 @@ class TestGemRequestSetLockfile < Gem::TestCase @set = Gem::RequestSet.new - @vendor_set = Gem::DependencyResolver::VendorSet.new + @vendor_set = Gem::Resolver::VendorSet.new @set.instance_variable_set :@vendor_set, @vendor_set @@ -96,7 +96,7 @@ DEPENDENCIES assert_equal [Gem::Platform::RUBY], @lockfile.platforms lockfile_set = @set.sets.find do |set| - Gem::DependencyResolver::LockSet === set + Gem::Resolver::LockSet === set end assert lockfile_set, 'could not find a LockSet' diff --git a/test/rubygems/test_gem_dependency_resolver.rb b/test/rubygems/test_gem_resolver.rb index ceecab6d55..80769de8cf 100644 --- a/test/rubygems/test_gem_dependency_resolver.rb +++ b/test/rubygems/test_gem_resolver.rb @@ -1,12 +1,11 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolver < Gem::TestCase +class TestGemResolver < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver end def make_dep(name, *req) @@ -30,13 +29,17 @@ class TestGemDependencyResolver < Gem::TestCase flunk e.message end + def test_self_compatibility + assert_same Gem::Resolver, Gem::DependencyResolver + 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_kind_of Gem::Resolver::ComposedSet, composed assert_equal [index_set, vendor_set], composed.sets end @@ -66,13 +69,13 @@ class TestGemDependencyResolver < Gem::TestCase 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 + r1 = Gem::Resolver::DependencyRequest.new dep('a', '= 1'), nil + r2 = Gem::Resolver::DependencyRequest.new dep('a', '= 2'), nil + r3 = Gem::Resolver::DependencyRequest.new dep('a', '= 3'), nil - existing = Gem::DependencyResolver::ActivationRequest.new a1, r1, false + existing = Gem::Resolver::ActivationRequest.new a1, r1, false - res = Gem::DependencyResolver.new [a1] + res = Gem::Resolver.new [a1] res.handle_conflict r2, existing res.handle_conflict r2, existing @@ -92,7 +95,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a, b) - res = Gem::DependencyResolver.new(deps, s) + res = Gem::Resolver.new(deps, s) assert_resolves_to [a, b], res end @@ -109,7 +112,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a, b, c) - res = Gem::DependencyResolver.new(deps, s) + res = Gem::Resolver.new(deps, s) assert_resolves_to [a, b, c], res end @@ -122,13 +125,13 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a" - res = Gem::DependencyResolver.new([ad], s) + res = Gem::Resolver.new([ad], s) assert_resolves_to [a2], res end def test_picks_best_platform - is = Gem::DependencyResolver::IndexSpecification + is = Gem::Resolver::IndexSpecification unknown = Gem::Platform.new 'unknown' a2_p1 = a3_p2 = nil @@ -153,7 +156,7 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a" - res = Gem::DependencyResolver.new([ad], s) + res = Gem::Resolver.new([ad], s) assert_resolves_to [a2_p1], res end @@ -169,7 +172,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, b1, c1) - res = Gem::DependencyResolver.new([ad, bd], s) + res = Gem::Resolver.new([ad, bd], s) assert_resolves_to [a1, b1, c1], res end @@ -186,17 +189,9 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, b1, c1, c2) - res = Gem::DependencyResolver.new([ad, bd], s) + res = Gem::Resolver.new([ad, bd], s) assert_resolves_to [a1, b1, c1], res - - cons = res.conflicts - - assert_equal 1, cons.size - con = cons.first - - assert_equal "c (= 1)", con.dependency.to_s - assert_equal "c-2", con.activated.full_name end def test_conflict_resolution_only_effects_correct_spec @@ -214,7 +209,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, b1, d3, d4, c1, c2) - res = Gem::DependencyResolver.new([ad, bd], s) + res = Gem::Resolver.new([ad, bd], s) assert_resolves_to [a1, b1, c1, d4], res @@ -239,31 +234,31 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, b1, c1, c2) - r = Gem::DependencyResolver.new([ad, bd], s) + r = Gem::Resolver.new([ad, bd], s) e = assert_raises Gem::DependencyResolutionError do r.resolve end - deps = [make_dep("c", "= 2"), make_dep("c", "= 1")] + deps = [make_dep("c", "= 1"), make_dep("c", "= 2")] assert_equal deps, e.conflicting_dependencies con = e.conflict act = con.activated - assert_equal "c-1", act.spec.full_name + assert_equal "c-2", act.spec.full_name parent = act.parent - assert_equal "a-1", parent.spec.full_name + assert_equal "b-1", parent.spec.full_name act = con.requester - assert_equal "b-1", act.spec.full_name + assert_equal "a-1", act.spec.full_name end def test_raises_when_a_gem_is_missing ad = make_dep "a" - r = Gem::DependencyResolver.new([ad], set) + r = Gem::Resolver.new([ad], set) e = assert_raises Gem::UnsatisfiableDepedencyError do r.resolve @@ -280,7 +275,7 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a", "= 3" - r = Gem::DependencyResolver.new([ad], set(a1)) + r = Gem::Resolver.new([ad], set(a1)) e = assert_raises Gem::UnsatisfiableDepedencyError do r.resolve @@ -293,7 +288,7 @@ class TestGemDependencyResolver < Gem::TestCase a1 = util_spec "a", "1" ad = make_dep "a", "= 3" - r = Gem::DependencyResolver.new([ad], set(a1)) + r = Gem::Resolver.new([ad], set(a1)) e = assert_raises Gem::UnsatisfiableDepedencyError do r.resolve @@ -310,7 +305,7 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a", "= 1" - r = Gem::DependencyResolver.new([ad], set(a1)) + r = Gem::Resolver.new([ad], set(a1)) e = assert_raises Gem::UnsatisfiableDepedencyError do r.resolve @@ -333,7 +328,7 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a" bd = make_dep "b" - r = Gem::DependencyResolver.new([ad, bd], s) + r = Gem::Resolver.new([ad, bd], s) e = assert_raises Gem::DependencyResolutionError do r.resolve @@ -345,11 +340,11 @@ class TestGemDependencyResolver < Gem::TestCase assert_equal req('>= 0'), dependency.requirement activated = e.conflict.activated - assert_equal 'c-2', activated.full_name + assert_equal 'c-1', activated.full_name - assert_equal dep('c', '>= 2'), activated.request.dependency + assert_equal dep('c', '= 1'), activated.request.dependency - assert_equal [dep('c', '= 1'), dep('c', '>= 2')], + assert_equal [dep('c', '>= 2'), dep('c', '= 1')], e.conflict.conflicting_dependencies end @@ -363,7 +358,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, b1, c1) - r = Gem::DependencyResolver.new([ad, bd], s) + r = Gem::Resolver.new([ad, bd], s) assert_resolves_to [a1, b1, c1], r end @@ -382,13 +377,13 @@ class TestGemDependencyResolver < Gem::TestCase s = set(lib1, rails, ap, rack100, rack101) - r = Gem::DependencyResolver.new([d1, d2], s) + r = Gem::Resolver.new([d1, d2], s) assert_resolves_to [rails, ap, rack101, lib1], r # check it with the deps reverse too - r = Gem::DependencyResolver.new([d2, d1], s) + r = Gem::Resolver.new([d2, d1], s) assert_resolves_to [lib1, rack101, rails, ap], r end @@ -405,7 +400,7 @@ class TestGemDependencyResolver < Gem::TestCase s = set(a1, a2, a3, a4) - r = Gem::DependencyResolver.new([d1, d2, d3], s) + r = Gem::Resolver.new([d1, d2, d3], s) assert_raises Gem::DependencyResolutionError do r.resolve @@ -423,7 +418,7 @@ class TestGemDependencyResolver < Gem::TestCase a_dep = dep 'a', '~> 1.0' b_dep = dep 'b' - r = Gem::DependencyResolver.new [a_dep, b_dep], s + r = Gem::Resolver.new [a_dep, b_dep], s assert_raises Gem::DependencyResolutionError do r.resolve @@ -444,7 +439,7 @@ class TestGemDependencyResolver < Gem::TestCase a_dep = dep 'a', '= 1' - r = Gem::DependencyResolver.new [a_dep], s + r = Gem::Resolver.new [a_dep], s assert_resolves_to [a1, b1, c1], r end @@ -461,7 +456,7 @@ class TestGemDependencyResolver < Gem::TestCase a_dep = dep 'a', '~> 1.0' b_dep = dep 'b' - r = Gem::DependencyResolver.new [a_dep, b_dep], s + r = Gem::Resolver.new [a_dep, b_dep], s assert_resolves_to [a1, b1], r end @@ -484,7 +479,7 @@ class TestGemDependencyResolver < Gem::TestCase d1 = make_dep "activemerchant" d2 = make_dep "actionmailer" - r = Gem::DependencyResolver.new([d1, d2], s) + r = Gem::Resolver.new([d1, d2], s) assert_resolves_to [merch, mail, sup1], r end @@ -502,13 +497,13 @@ class TestGemDependencyResolver < Gem::TestCase p1 = make_dep "b", "> 0" p2 = make_dep "d", "> 0" - r = Gem::DependencyResolver.new([p1, p2], s) + r = Gem::Resolver.new([p1, p2], s) assert_resolves_to [b1, c1, d2], r end def test_select_local_platforms - r = Gem::DependencyResolver.new nil, nil + r = Gem::Resolver.new nil, nil a1 = util_spec 'a', 1 a1_p1 = util_spec 'a', 1 do |s| s.platform = Gem::Platform.local end @@ -526,7 +521,7 @@ class TestGemDependencyResolver < Gem::TestCase ad = make_dep "a", "= 1" - r = Gem::DependencyResolver.new([ad], set(a1)) + r = Gem::Resolver.new([ad], set(a1)) e = assert_raises Gem::UnsatisfiableDepedencyError do r.resolve diff --git a/test/rubygems/test_gem_dependency_resolver_activation_request.rb b/test/rubygems/test_gem_resolver_activation_request.rb index ac554d128c..54de6bf16a 100644 --- a/test/rubygems/test_gem_dependency_resolver_activation_request.rb +++ b/test/rubygems/test_gem_resolver_activation_request.rb @@ -1,11 +1,11 @@ require 'rubygems/test_case' -class TestGemDependencyResolverActivationRequest < Gem::TestCase +class TestGemResolverActivationRequest < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver @dep = @DR::DependencyRequest.new dep('a', '>= 0'), nil @@ -36,7 +36,7 @@ class TestGemDependencyResolverActivationRequest < Gem::TestCase end def test_installed_eh - v_spec = Gem::DependencyResolver::VendorSpecification.new nil, @a3 + v_spec = Gem::Resolver::VendorSpecification.new nil, @a3 @req = @DR::ActivationRequest.new v_spec, @dep, [@a1, @a2] diff --git a/test/rubygems/test_gem_dependency_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb index ef99b6ca7f..976d861cdf 100644 --- a/test/rubygems/test_gem_dependency_resolver_api_set.rb +++ b/test/rubygems/test_gem_resolver_api_set.rb @@ -1,12 +1,11 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverAPISet < Gem::TestCase +class TestGemResolverAPISet < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver end def test_initialize diff --git a/test/rubygems/test_gem_dependency_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb index cdbecec822..e61d30c7c6 100644 --- a/test/rubygems/test_gem_dependency_resolver_api_specification.rb +++ b/test/rubygems/test_gem_resolver_api_specification.rb @@ -1,10 +1,9 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverAPISpecification < Gem::TestCase +class TestGemResolverAPISpecification < Gem::TestCase def test_initialize - set = Gem::DependencyResolver::APISet.new + set = Gem::Resolver::APISet.new data = { :name => 'rails', :number => '3.0.3', @@ -15,7 +14,7 @@ class TestGemDependencyResolverAPISpecification < Gem::TestCase ], } - spec = Gem::DependencyResolver::APISpecification.new set, data + spec = Gem::Resolver::APISpecification.new set, data assert_equal 'rails', spec.name assert_equal Gem::Version.new('3.0.3'), spec.version diff --git a/test/rubygems/test_gem_dependency_resolver_best_set.rb b/test/rubygems/test_gem_resolver_best_set.rb index 20fbf4514f..5bcff4aca7 100644 --- a/test/rubygems/test_gem_dependency_resolver_best_set.rb +++ b/test/rubygems/test_gem_resolver_best_set.rb @@ -1,12 +1,11 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverBestSet < Gem::TestCase +class TestGemResolverBestSet < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver end def test_find_all_index diff --git a/test/rubygems/test_gem_dependency_resolver_dependency_conflict.rb b/test/rubygems/test_gem_resolver_conflict.rb index 68e17f8a98..3ae2a7cf5f 100644 --- a/test/rubygems/test_gem_dependency_resolver_dependency_conflict.rb +++ b/test/rubygems/test_gem_resolver_conflict.rb @@ -1,7 +1,10 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverDependencyConflict < Gem::TestCase +class TestGemResolverConflict < Gem::TestCase + + def test_self_compatibility + assert_same Gem::Resolver::Conflict, Gem::Resolver::DependencyConflict + end def test_explanation root = @@ -10,7 +13,7 @@ class TestGemDependencyResolverDependencyConflict < Gem::TestCase dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', root conflict = - Gem::DependencyResolver::DependencyConflict.new child, child.requester + Gem::Resolver::Conflict.new child, child.requester expected = <<-EXPECTED Activated net-ssh-2.2.2 instead of (>= 2.6.5) via: @@ -21,7 +24,7 @@ class TestGemDependencyResolverDependencyConflict < Gem::TestCase end def test_explanation_user_request - @DR = Gem::DependencyResolver + @DR = Gem::Resolver spec = util_spec 'a', 2 @@ -30,7 +33,7 @@ class TestGemDependencyResolverDependencyConflict < Gem::TestCase activated = @DR::ActivationRequest.new spec, a2_req - conflict = @DR::DependencyConflict.new a1_req, activated + conflict = @DR::Conflict.new a1_req, activated expected = <<-EXPECTED Activated a-2 instead of (= 1) via: @@ -47,7 +50,7 @@ class TestGemDependencyResolverDependencyConflict < Gem::TestCase dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', root conflict = - Gem::DependencyResolver::DependencyConflict.new child, nil + Gem::Resolver::Conflict.new child, nil assert_equal %w[net-ssh-2.2.2 rye-0.9.8], conflict.request_path end diff --git a/test/rubygems/test_gem_dependency_resolver_dependency_request.rb b/test/rubygems/test_gem_resolver_dependency_request.rb index f5b3a6960e..e1a98826fb 100644 --- a/test/rubygems/test_gem_dependency_resolver_dependency_request.rb +++ b/test/rubygems/test_gem_resolver_dependency_request.rb @@ -1,11 +1,11 @@ require 'rubygems/test_case' -class TestGemDependencyResolverDependencyRequest < Gem::TestCase +class TestGemResolverDependencyRequest < Gem::TestCase def setup super - @DR = Gem::DependencyResolver::DependencyRequest + @DR = Gem::Resolver::DependencyRequest end def test_requirement diff --git a/test/rubygems/test_gem_resolver_git_set.rb b/test/rubygems/test_gem_resolver_git_set.rb new file mode 100644 index 0000000000..6943df9ec8 --- /dev/null +++ b/test/rubygems/test_gem_resolver_git_set.rb @@ -0,0 +1,84 @@ +require 'rubygems/test_case' + +class TestGemResolverGitSet < Gem::TestCase + + def setup + super + + @set = Gem::Resolver::GitSet.new + + @reqs = Gem::Resolver::RequirementList.new + end + + def test_add_git_gem + name, version, repository, = git_gem + + @set.add_git_gem name, repository, 'master', false + + dependency = dep 'a' + + specs = @set.find_all dependency + + assert_equal "#{name}-#{version}", specs.first.full_name + + refute @set.need_submodules[repository] + end + + def test_add_git_gem_submodules + name, _, repository, = git_gem + + @set.add_git_gem name, repository, 'master', true + + dependency = dep 'a' + + refute_empty @set.find_all dependency + + assert @set.need_submodules[repository] + end + + def test_find_all + name, _, repository, = git_gem + + @set.add_git_gem name, repository, 'master', false + + dependency = dep 'a', '~> 1.0' + req = Gem::Resolver::ActivationRequest.new dependency, nil + @reqs.add req + + @set.prefetch @reqs + + found = @set.find_all dependency + + assert_equal [@set.specs['a']], found + end + + def test_prefetch + 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 + + refute_empty @set.specs + end + + def test_prefetch_filter + name, _, repository, = git_gem + + @set.add_git_gem name, repository, 'master', false + + dependency = dep 'b' + req = Gem::Resolver::ActivationRequest.new dependency, nil + @reqs.add req + + @set.prefetch @reqs + + assert_empty @set.specs + end + +end + diff --git a/test/rubygems/test_gem_resolver_git_specification.rb b/test/rubygems/test_gem_resolver_git_specification.rb new file mode 100644 index 0000000000..f961a7709a --- /dev/null +++ b/test/rubygems/test_gem_resolver_git_specification.rb @@ -0,0 +1,36 @@ +require 'rubygems/test_case' + +class TestGemResolverGitSpecification < Gem::TestCase + + def setup + super + + @set = Gem::Resolver::GitSet.new + @spec = Gem::Specification.new 'a', 1 + end + + def test_equals2 + g_spec_a = Gem::Resolver::GitSpecification.new @set, @spec + + assert_equal g_spec_a, g_spec_a + + spec_b = Gem::Specification.new 'b', 1 + g_spec_b = Gem::Resolver::GitSpecification.new @set, spec_b + + refute_equal g_spec_a, g_spec_b + + g_set = Gem::Resolver::GitSet.new + g_spec_s = Gem::Resolver::GitSpecification.new g_set, @spec + + refute_equal g_spec_a, g_spec_s + + i_set = Gem::Resolver::IndexSet.new + source = Gem::Source.new @gem_repo + i_spec = Gem::Resolver::IndexSpecification.new( + i_set, 'a', v(1), source, Gem::Platform::RUBY) + + refute_equal g_spec_a, i_spec + end + +end + diff --git a/test/rubygems/test_gem_dependency_resolver_index_set.rb b/test/rubygems/test_gem_resolver_index_set.rb index 83b7cce501..137e9b5cac 100644 --- a/test/rubygems/test_gem_dependency_resolver_index_set.rb +++ b/test/rubygems/test_gem_resolver_index_set.rb @@ -1,12 +1,11 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverIndexSet < Gem::TestCase +class TestGemResolverIndexSet < Gem::TestCase def setup super - @DR = Gem::DependencyResolver + @DR = Gem::Resolver end def test_initialize diff --git a/test/rubygems/test_gem_dependency_resolver_index_specification.rb b/test/rubygems/test_gem_resolver_index_specification.rb index 751ed34db3..ef474ab2d4 100644 --- a/test/rubygems/test_gem_dependency_resolver_index_specification.rb +++ b/test/rubygems/test_gem_resolver_index_specification.rb @@ -1,15 +1,14 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' require 'rubygems/available_set' -class TestGemDependencyResolverIndexSpecification < Gem::TestCase +class TestGemResolverIndexSpecification < Gem::TestCase def test_initialize - set = Gem::DependencyResolver::IndexSet.new + set = Gem::Resolver::IndexSet.new source = Gem::Source.new @gem_repo version = Gem::Version.new '3.0.3' - spec = Gem::DependencyResolver::IndexSpecification.new( + spec = Gem::Resolver::IndexSpecification.new( set, 'rails', version, source, Gem::Platform::RUBY) assert_equal 'rails', spec.name @@ -20,11 +19,11 @@ class TestGemDependencyResolverIndexSpecification < Gem::TestCase end def test_initialize_platform - set = Gem::DependencyResolver::IndexSet.new + set = Gem::Resolver::IndexSet.new source = Gem::Source::Local.new version = Gem::Version.new '3.0.3' - spec = Gem::DependencyResolver::IndexSpecification.new( + spec = Gem::Resolver::IndexSpecification.new( set, 'rails', version, source, Gem::Platform.local) assert_equal Gem::Platform.local.to_s, spec.platform @@ -39,8 +38,8 @@ class TestGemDependencyResolverIndexSpecification < Gem::TestCase source = Gem::Source.new @gem_repo version = v 2 - set = Gem::DependencyResolver::IndexSet.new - i_spec = Gem::DependencyResolver::IndexSpecification.new \ + set = Gem::Resolver::IndexSet.new + i_spec = Gem::Resolver::IndexSpecification.new \ set, 'a', version, source, Gem::Platform.local spec = i_spec.spec @@ -53,10 +52,10 @@ class TestGemDependencyResolverIndexSpecification < Gem::TestCase Gem::Package.build a_2_p source = Gem::Source::Local.new - set = Gem::DependencyResolver::InstallerSet.new :local + set = Gem::Resolver::InstallerSet.new :local set.always_install << a_2_p - i_spec = Gem::DependencyResolver::IndexSpecification.new \ + i_spec = Gem::Resolver::IndexSpecification.new \ set, 'a', v(2), source, Gem::Platform.local spec = i_spec.spec diff --git a/test/rubygems/test_gem_dependency_resolver_installed_specification.rb b/test/rubygems/test_gem_resolver_installed_specification.rb index e1f4262e4b..f9dda29a6c 100644 --- a/test/rubygems/test_gem_dependency_resolver_installed_specification.rb +++ b/test/rubygems/test_gem_resolver_installed_specification.rb @@ -1,14 +1,13 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverInstalledSpecification < Gem::TestCase +class TestGemResolverInstalledSpecification < Gem::TestCase def test_initialize - set = Gem::DependencyResolver::CurrentSet.new + set = Gem::Resolver::CurrentSet.new source_spec = util_spec 'a' - spec = Gem::DependencyResolver::InstalledSpecification.new set, source_spec + spec = Gem::Resolver::InstalledSpecification.new set, source_spec assert_equal 'a', spec.name assert_equal Gem::Version.new(2), spec.version diff --git a/test/rubygems/test_gem_dependency_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb index 6341c6bc73..af4db646a9 100644 --- a/test/rubygems/test_gem_dependency_resolver_installer_set.rb +++ b/test/rubygems/test_gem_resolver_installer_set.rb @@ -1,7 +1,6 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverInstallerSet < Gem::TestCase +class TestGemResolverInstallerSet < Gem::TestCase def test_load_spec specs = spec_fetcher do |fetcher| @@ -12,7 +11,7 @@ class TestGemDependencyResolverInstallerSet < Gem::TestCase source = Gem::Source.new @gem_repo version = v 2 - set = Gem::DependencyResolver::InstallerSet.new :remote + set = Gem::Resolver::InstallerSet.new :remote spec = set.load_spec 'a', version, Gem::Platform.local, source diff --git a/test/rubygems/test_gem_dependency_resolver_lock_set.rb b/test/rubygems/test_gem_resolver_lock_set.rb index 6142f2b8d0..71b28efd4f 100644 --- a/test/rubygems/test_gem_dependency_resolver_lock_set.rb +++ b/test/rubygems/test_gem_resolver_lock_set.rb @@ -1,14 +1,13 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverLockSet < Gem::TestCase +class TestGemResolverLockSet < Gem::TestCase def setup super @source = Gem::Source.new @gem_repo - @set = Gem::DependencyResolver::LockSet.new @source + @set = Gem::Resolver::LockSet.new @source end def test_add diff --git a/test/rubygems/test_gem_resolver_requirement_list.rb b/test/rubygems/test_gem_resolver_requirement_list.rb new file mode 100644 index 0000000000..3d09ce5f92 --- /dev/null +++ b/test/rubygems/test_gem_resolver_requirement_list.rb @@ -0,0 +1,19 @@ +require 'rubygems/test_case' + +class TestGemResolverRequirementList < Gem::TestCase + + def setup + super + + @list = Gem::Resolver::RequirementList.new + end + + def test_each + @list.add 1 + @list.add 2 + + assert_equal [1, 2], @list.each.to_a + end + +end + diff --git a/test/rubygems/test_gem_dependency_resolver_vendor_set.rb b/test/rubygems/test_gem_resolver_vendor_set.rb index 227cf369c8..58519fbf14 100644 --- a/test/rubygems/test_gem_dependency_resolver_vendor_set.rb +++ b/test/rubygems/test_gem_resolver_vendor_set.rb @@ -1,12 +1,11 @@ require 'rubygems/test_case' -require 'rubygems/dependency_resolver' -class TestGemDependencyResolverVendorSet < Gem::TestCase +class TestGemResolverVendorSet < Gem::TestCase def setup super - @set = Gem::DependencyResolver::VendorSet.new + @set = Gem::Resolver::VendorSet.new end def test_add_vendor_gem @@ -39,7 +38,7 @@ class TestGemDependencyResolverVendorSet < Gem::TestCase dependency = dep 'a', '~> 1' - req = Gem::DependencyResolver::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = @set.find_all req @@ -48,7 +47,7 @@ class TestGemDependencyResolverVendorSet < Gem::TestCase source = Gem::Source::Vendor.new directory expected = [ - Gem::DependencyResolver::VendorSpecification.new(@set, spec, source) + Gem::Resolver::VendorSpecification.new(@set, spec, source) ] assert_equal expected, found diff --git a/test/rubygems/test_gem_resolver_vendor_specification.rb b/test/rubygems/test_gem_resolver_vendor_specification.rb new file mode 100644 index 0000000000..d7aca569e2 --- /dev/null +++ b/test/rubygems/test_gem_resolver_vendor_specification.rb @@ -0,0 +1,71 @@ +require 'rubygems/test_case' + +class TestGemResolverVendorSpecification < Gem::TestCase + + def setup + super + + @set = Gem::Resolver::VendorSet.new + @spec = Gem::Specification.new 'a', 1 + end + + def test_equals2 + v_spec_a = Gem::Resolver::VendorSpecification.new @set, @spec + + assert_equal v_spec_a, v_spec_a + + spec_b = Gem::Specification.new 'b', 1 + v_spec_b = Gem::Resolver::VendorSpecification.new @set, spec_b + + refute_equal v_spec_a, v_spec_b + + v_set = Gem::Resolver::VendorSet.new + v_spec_s = Gem::Resolver::VendorSpecification.new v_set, @spec + + refute_equal v_spec_a, v_spec_s + + i_set = Gem::Resolver::IndexSet.new + source = Gem::Source.new @gem_repo + i_spec = Gem::Resolver::IndexSpecification.new( + i_set, 'a', v(1), source, Gem::Platform::RUBY) + + refute_equal v_spec_a, i_spec + end + + def test_dependencies + @spec.add_dependency 'b' + @spec.add_dependency 'c' + + v_spec = Gem::Resolver::VendorSpecification.new @set, @spec + + assert_equal [dep('b'), dep('c')], v_spec.dependencies + end + + def test_full_name + v_spec = Gem::Resolver::VendorSpecification.new @set, @spec + + assert_equal 'a-1', v_spec.full_name + end + + def test_name + v_spec = Gem::Resolver::VendorSpecification.new @set, @spec + + assert_equal 'a', v_spec.name + end + + def test_platform + v_spec = Gem::Resolver::VendorSpecification.new @set, @spec + + assert_equal Gem::Platform::RUBY, v_spec.platform + end + + def test_version + spec = Gem::Specification.new 'a', 1 + + v_spec = Gem::Resolver::VendorSpecification.new @set, spec + + assert_equal v(1), v_spec.version + end + +end + diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb index 3ed40a625a..d207bcac7f 100644 --- a/test/rubygems/test_gem_source.rb +++ b/test/rubygems/test_gem_source.rb @@ -44,13 +44,13 @@ class TestGemSource < Gem::TestCase set = @source.dependency_resolver_set - assert_kind_of Gem::DependencyResolver::APISet, set + assert_kind_of Gem::Resolver::APISet, set end def test_dependency_resolver_set_marshal_api set = @source.dependency_resolver_set - assert_kind_of Gem::DependencyResolver::IndexSet, set + assert_kind_of Gem::Resolver::IndexSet, set end def test_fetch_spec diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb new file mode 100644 index 0000000000..78c415a9d3 --- /dev/null +++ b/test/rubygems/test_gem_source_git.rb @@ -0,0 +1,153 @@ +require 'rubygems/test_case' +require 'rubygems/source' + +class TestGemSourceGit < Gem::TestCase + + def setup + super + + @name, @version, @repository, @head = git_gem + + @hash = Digest::SHA1.hexdigest @repository + + @source = Gem::Source::Git.new @name, @repository, 'master', false + end + + def test_checkout + @source.checkout + + assert_path_exists File.join @source.install_dir, 'a.gemspec' + end + + def test_checkout_submodules + source = Gem::Source::Git.new @name, @repository, 'master', true + + git_gem 'b' + + Dir.chdir 'git/a' do + system @git, 'submodule', '--quiet', 'add', File.expand_path('../b'), 'b' + system @git, 'commit', '--quiet', '-m', 'add submodule b' + end + + source.checkout + + assert_path_exists File.join source.install_dir, 'a.gemspec' + assert_path_exists File.join source.install_dir, 'b/b.gemspec' + end + + def test_cache + assert @source.cache + + assert_path_exists @source.repo_cache_dir + + Dir.chdir @source.repo_cache_dir do + assert_equal @head, Gem::Util.popen(@git, 'rev-parse', 'master').strip + end + end + + def test_dir_shortref + @source.cache + + assert_equal @head[0..11], @source.dir_shortref + end + + def test_equals2 + assert_equal @source, @source + + assert_equal @source, @source.dup + + source = + Gem::Source::Git.new @source.name, @source.repository, 'other', false + + refute_equal @source, source + + source = + Gem::Source::Git.new @source.name, 'repo/other', @source.reference, false + + refute_equal @source, source + + source = + Gem::Source::Git.new 'b', @source.repository, @source.reference, false + + refute_equal @source, source + + source = + Gem::Source::Git.new @source.name, @source.repository, @source.reference, + true + + 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 + + expected = File.join Gem.dir, 'bundler', 'gems', "a-#{@head[0..11]}" + + assert_equal expected, @source.install_dir + end + + def test_repo_cache_dir + expected = + File.join Gem.dir, 'cache', 'bundler', 'git', "a-#{@hash}" + + assert_equal expected, @source.repo_cache_dir + end + + def test_rev_parse + @source.cache + + assert_equal @head, @source.rev_parse + + Dir.chdir @repository do + system @git, 'checkout', '--quiet', '-b', 'other' + end + + master_head = @head + + git_gem 'a', 2 + + source = Gem::Source::Git.new @name, @repository, 'other', false + + source.cache + + refute_equal master_head, source.rev_parse + end + + def test_spaceship + git = Gem::Source::Git.new 'a', 'git/a', 'master', false + remote = Gem::Source.new @gem_repo + installed = Gem::Source::Installed.new + + assert_equal( 0, git. <=>(git), 'git <=> git') + + assert_equal( 1, git. <=>(remote), 'git <=> remote') + assert_equal(-1, remote. <=>(git), 'remote <=> git') + + assert_equal( 1, installed.<=>(git), 'installed <=> git') + assert_equal(-1, git. <=>(installed), 'git <=> installed') + end + + def test_uri_hash + assert_equal @hash, @source.uri_hash + + source = + Gem::Source::Git.new 'a', 'http://git@example/repo.git', 'master', false + + assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe', + source.uri_hash + + source = + Gem::Source::Git.new 'a', 'HTTP://git@EXAMPLE/repo.git', 'master', false + + assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe', + source.uri_hash + end + +end + diff --git a/test/rubygems/test_gem_source_vendor.rb b/test/rubygems/test_gem_source_vendor.rb index 17403a1fc8..3f4121e5f6 100644 --- a/test/rubygems/test_gem_source_vendor.rb +++ b/test/rubygems/test_gem_source_vendor.rb @@ -9,5 +9,19 @@ class TestGemSourceVendor < Gem::TestCase assert_equal 'vendor/foo', source.uri end + def test_spaceship + vendor = Gem::Source::Vendor.new 'vendor/foo' + remote = Gem::Source.new @gem_repo + installed = Gem::Source::Installed.new + + assert_equal( 0, vendor. <=>(vendor), 'vendor <=> vendor') + + assert_equal( 1, vendor. <=>(remote), 'vendor <=> remote') + assert_equal(-1, remote. <=>(vendor), 'remote <=> vendor') + + assert_equal( 1, vendor. <=>(installed), 'vendor <=> installed') + assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor') + end + end diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 75ea4092b7..3924191db9 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -1733,7 +1733,7 @@ dependencies: [] full_gem_path = Pathname(@ext.full_gem_path) relative_install_dir = ext_install_dir.relative_path_from full_gem_path - assert_equal ['lib', relative_install_dir.to_s], @ext.require_paths + assert_equal [relative_install_dir.to_s, 'lib'], @ext.require_paths ensure RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared end @@ -1744,8 +1744,8 @@ dependencies: [] @ext.require_path = 'lib' expected = [ - File.join(@gemhome, 'gems', @ext.original_name, 'lib'), @ext.extension_install_dir, + File.join(@gemhome, 'gems', @ext.original_name, 'lib'), ] assert_equal expected, @ext.full_require_paths diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb index bb04fb4dcc..50621e28ae 100644 --- a/test/rubygems/test_gem_stub_specification.rb +++ b/test/rubygems/test_gem_stub_specification.rb @@ -31,7 +31,7 @@ class TestStubSpecification < Gem::TestCase assert_equal 'stub_e', stub.name assert_equal v(2), stub.version assert_equal Gem::Platform::RUBY, stub.platform - assert_equal ['lib', relative_install_dir], stub.require_paths + assert_equal [relative_install_dir, 'lib'], stub.require_paths assert_equal %w[ext/stub_e/extconf.rb], stub.extensions end @@ -78,8 +78,8 @@ class TestStubSpecification < Gem::TestCase stub = stub_with_extension expected = [ - File.join(stub.full_gem_path, 'lib'), stub.extension_install_dir, + File.join(stub.full_gem_path, 'lib'), ] assert_equal expected, stub.full_require_paths diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb new file mode 100644 index 0000000000..bf67b14d38 --- /dev/null +++ b/test/rubygems/test_gem_util.rb @@ -0,0 +1,11 @@ +require 'rubygems/test_case' +require 'rubygems/util' + +class TestGemUtil < Gem::TestCase + + def test_class_popen + assert_equal "0\n", Gem::Util.popen(Gem.ruby, '-e', 'p 0') + end + +end + |