Geminstaller C0 Coverage Information - RCov

spec/fixture/rubygems_dist/rubygems-trunk/lib/rubygems/dependency_installer.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
spec/fixture/rubygems_dist/rubygems-trunk/lib/rubygems/dependency_installer.rb 286 181
86.71%
79.56%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 require 'rubygems'
2 require 'rubygems/dependency_list'
3 require 'rubygems/installer'
4 require 'rubygems/spec_fetcher'
5 require 'rubygems/user_interaction'
6 
7 ##
8 # Installs a gem along with all its dependencies from local and remote gems.
9 
10 class Gem::DependencyInstaller
11 
12   include Gem::UserInteraction
13 
14   attr_reader :gems_to_install
15   attr_reader :installed_gems
16 
17   DEFAULT_OPTIONS = {
18     :env_shebang => false,
19     :domain => :both, # HACK dup
20     :force => false,
21     :format_executable => false, # HACK dup
22     :ignore_dependencies => false,
23     :prerelease => false,
24     :security_policy => nil, # HACK NoSecurity requires OpenSSL.  AlmostNo? Low?
25     :wrappers => true,
26   }
27 
28   ##
29   # Creates a new installer instance.
30   #
31   # Options are:
32   # :cache_dir:: Alternate repository path to store .gem files in.
33   # :domain:: :local, :remote, or :both.  :local only searches gems in the
34   #           current directory.  :remote searches only gems in Gem::sources.
35   #           :both searches both.
36   # :env_shebang:: See Gem::Installer::new.
37   # :force:: See Gem::Installer#install.
38   # :format_executable:: See Gem::Installer#initialize.
39   # :ignore_dependencies:: Don't install any dependencies.
40   # :install_dir:: See Gem::Installer#install.
41   # :prerelease:: Allow prerelease versions.  See #install.
42   # :security_policy:: See Gem::Installer::new and Gem::Security.
43   # :user_install:: See Gem::Installer.new
44   # :wrappers:: See Gem::Installer::new
45 
46   def initialize(options = {})
47     if options[:install_dir] then
48       spec_dir = options[:install_dir], 'specifications'
49       @source_index = Gem::SourceIndex.from_gems_in spec_dir
50     else
51       @source_index = Gem.source_index
52     end
53 
54     options = DEFAULT_OPTIONS.merge options
55 
56     @bin_dir = options[:bin_dir]
57     @development = options[:development]
58     @domain = options[:domain]
59     @env_shebang = options[:env_shebang]
60     @force = options[:force]
61     @format_executable = options[:format_executable]
62     @ignore_dependencies = options[:ignore_dependencies]
63     @prerelease = options[:prerelease]
64     @security_policy = options[:security_policy]
65     @user_install = options[:user_install]
66     @wrappers = options[:wrappers]
67 
68     @installed_gems = []
69 
70     @install_dir = options[:install_dir] || Gem.dir
71     @cache_dir = options[:cache_dir] || @install_dir
72 
73     # Set with any errors that SpecFetcher finds while search through
74     # gemspecs for a dep
75     @errors = nil
76   end
77 
78   ##
79   # Returns a list of pairs of gemspecs and source_uris that match
80   # Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources)
81   # sources.  Gems are sorted with newer gems prefered over older gems, and
82   # local gems preferred over remote gems.
83 
84   def find_gems_with_sources(dep)
85     # Reset the errors
86     @errors = nil
87     gems_and_sources = []
88 
89     if @domain == :both or @domain == :local then
90       Dir[File.join(Dir.pwd, "#{dep.name}-[0-9]*.gem")].each do |gem_file|
91         spec = Gem::Format.from_file_by_path(gem_file).spec
92         gems_and_sources << [spec, gem_file] if spec.name == dep.name
93       end
94     end
95 
96     if @domain == :both or @domain == :remote then
97       begin
98         requirements = dep.requirement.requirements.map do |req, ver|
99           req
100         end
101 
102         all = !dep.prerelease? &&
103               # we only need latest if there's one requirement and it is
104               # guaranteed to match the newest specs
105               (requirements.length > 1 or
106                 (requirements.first != ">=" and requirements.first != ">"))
107 
108         found, @errors = Gem::SpecFetcher.fetcher.fetch_with_errors dep, all, true, dep.prerelease?
109 
110         gems_and_sources.push(*found)
111 
112       rescue Gem::RemoteFetcher::FetchError => e
113         if Gem.configuration.really_verbose then
114           say "Error fetching remote data:\t\t#{e.message}"
115           say "Falling back to local-only install"
116         end
117         @domain = :local
118       end
119     end
120 
121     gems_and_sources.sort_by do |gem, source|
122       [gem, source =~ /^http:\/\// ? 0 : 1] # local gems win
123     end
124   end
125 
126   ##
127   # Gathers all dependencies necessary for the installation from local and
128   # remote sources unless the ignore_dependencies was given.
129 
130   def gather_dependencies
131     specs = @specs_and_sources.map { |spec,_| spec }
132 
133     dependency_list = Gem::DependencyList.new @development
134     dependency_list.add(*specs)
135 
136     unless @ignore_dependencies then
137       to_do = specs.dup
138       seen = {}
139 
140       until to_do.empty? do
141         spec = to_do.shift
142         next if spec.nil? or seen[spec.name]
143         seen[spec.name] = true
144 
145         deps = spec.runtime_dependencies
146         deps |= spec.development_dependencies if @development
147 
148         deps.each do |dep|
149           results = find_gems_with_sources(dep).reverse
150 
151           results.reject! do |dep_spec,|
152             to_do.push dep_spec
153 
154             @source_index.any? do |_, installed_spec|
155               dep.name == installed_spec.name and
156                 dep.requirement.satisfied_by? installed_spec.version
157             end
158           end
159 
160           results.each do |dep_spec, source_uri|
161             next if seen[dep_spec.name]
162             @specs_and_sources << [dep_spec, source_uri]
163             dependency_list.add dep_spec
164           end
165         end
166       end
167     end
168 
169     @gems_to_install = dependency_list.dependency_order.reverse
170   end
171 
172   ##
173   # Finds a spec and the source_uri it came from for gem +gem_name+ and
174   # +version+.  Returns an Array of specs and sources required for
175   # installation of the gem.
176 
177   def find_spec_by_name_and_version(gem_name,
178                                     version = Gem::Requirement.default,
179                                     prerelease = false)
180     spec_and_source = nil
181 
182     glob = if File::ALT_SEPARATOR then
183              gem_name.gsub File::ALT_SEPARATOR, File::SEPARATOR
184            else
185              gem_name
186            end
187 
188     local_gems = Dir["#{glob}*"].sort.reverse
189 
190     unless local_gems.empty? then
191       local_gems.each do |gem_file|
192         next unless gem_file =~ /gem$/
193         begin
194           spec = Gem::Format.from_file_by_path(gem_file).spec
195           spec_and_source = [spec, gem_file]
196           break
197         rescue SystemCallError, Gem::Package::FormatError
198         end
199       end
200     end
201 
202     if spec_and_source.nil? then
203       dep = Gem::Dependency.new gem_name, version
204       dep.prerelease = true if prerelease
205       spec_and_sources = find_gems_with_sources(dep).reverse
206 
207       spec_and_source = spec_and_sources.find { |spec, source|
208         Gem::Platform.match spec.platform
209       }
210     end
211 
212     if spec_and_source.nil? then
213       raise Gem::GemNotFoundException.new(
214         "Could not find a valid gem '#{gem_name}' (#{version}) locally or in a repository",
215         gem_name, version, @errors)
216     end
217 
218     @specs_and_sources = [spec_and_source]
219   end
220 
221   ##
222   # Installs the gem +dep_or_name+ and all its dependencies.  Returns an Array
223   # of installed gem specifications.
224   #
225   # If the +:prerelease+ option is set and there is a prerelease for
226   # +dep_or_name+ the prerelease version will be installed.
227   #
228   # Unless explicitly specified as a prerelease dependency, prerelease gems
229   # that +dep_or_name+ depend on will not be installed.
230   #
231   # If c-1.a depends on b-1 and a-1.a and there is a gem b-1.a available then
232   # c-1.a, b-1 and a-1.a will be installed.  b-1.a will need to be installed
233   # separately.
234 
235   def install dep_or_name, version = Gem::Requirement.default
236     if String === dep_or_name then
237       find_spec_by_name_and_version dep_or_name, version, @prerelease
238     else
239       dep_or_name.prerelease = @prerelease
240       @specs_and_sources = [find_gems_with_sources(dep_or_name).last]
241     end
242 
243     @installed_gems = []
244 
245     gather_dependencies
246 
247     @gems_to_install.each do |spec|
248       last = spec == @gems_to_install.last
249       # HACK is this test for full_name acceptable?
250       next if @source_index.any? { |n,_| n == spec.full_name } and not last
251 
252       # TODO: make this sorta_verbose so other users can benefit from it
253       say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
254 
255       _, source_uri = @specs_and_sources.assoc spec
256       begin
257         local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri,
258                                                              @cache_dir
259       rescue Gem::RemoteFetcher::FetchError
260         next if @force
261         raise
262       end
263 
264       inst = Gem::Installer.new local_gem_path,
265                                 :bin_dir             => @bin_dir,
266                                 :development         => @development,
267                                 :env_shebang         => @env_shebang,
268                                 :force               => @force,
269                                 :format_executable   => @format_executable,
270                                 :ignore_dependencies => @ignore_dependencies,
271                                 :install_dir         => @install_dir,
272                                 :security_policy     => @security_policy,
273                                 :source_index        => @source_index,
274                                 :user_install        => @user_install,
275                                 :wrappers            => @wrappers
276 
277       spec = inst.install
278 
279       @installed_gems << spec
280     end
281 
282     @installed_gems
283   end
284 
285 end
286 

Generated on Mon May 10 23:40:28 -0700 2010 with rcov 0.9.8