Class: Gem::RequestSet

Inherits:
Object
  • Object
show all
Includes:
TSort
Defined in:
lib/rubygems/request_set.rb

Overview

A RequestSet groups a request to activate a set of dependencies.

nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6'
pg = Gem::Dependency.new 'pg', '~> 0.14'

set = Gem::RequestSet.new nokogiri, pg

requests = set.resolve

p requests.map { |r| r.full_name }
#=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"]

Defined Under Namespace

Classes: GemDependencyAPI, Lockfile

Constant Summary collapse

GemDepedencyAPI =

TODO: remove this typo name at RubyGems 3.0

self

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*deps) {|_self| ... } ⇒ RequestSet

Creates a RequestSet for a list of Gem::Dependency objects, deps. You can then #resolve and #install the resolved list of dependencies.

nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6'
pg = Gem::Dependency.new 'pg', '~> 0.14'

set = Gem::RequestSet.new nokogiri, pg

Yields:

  • (_self)

Yield Parameters:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/rubygems/request_set.rb', line 65

def initialize *deps
  @dependencies = deps

  @always_install      = []
  @dependency_names    = {}
  @development         = false
  @git_set             = nil
  @ignore_dependencies = false
  @install_dir         = Gem.dir
  @requests            = []
  @sets                = []
  @soft_missing        = false
  @sorted              = nil
  @specs               = nil
  @vendor_set          = nil

  yield self if block_given?
end

Instance Attribute Details

#always_installObject (readonly)

Array of gems to install even if already installed



24
25
26
# File 'lib/rubygems/request_set.rb', line 24

def always_install
  @always_install
end

#dependenciesObject (readonly)

Returns the value of attribute dependencies



26
27
28
# File 'lib/rubygems/request_set.rb', line 26

def dependencies
  @dependencies
end

#developmentObject

Returns the value of attribute development



28
29
30
# File 'lib/rubygems/request_set.rb', line 28

def development
  @development
end

#git_setObject (readonly)

The set of git gems imported via load_gemdeps.



33
34
35
# File 'lib/rubygems/request_set.rb', line 33

def git_set
  @git_set
end

#ignore_dependenciesObject

When true, dependency resolution is not performed, only the requested gems are installed.



39
40
41
# File 'lib/rubygems/request_set.rb', line 39

def ignore_dependencies
  @ignore_dependencies
end

#setsObject (readonly)

Sets used for resolution



44
45
46
# File 'lib/rubygems/request_set.rb', line 44

def sets
  @sets
end

#soft_missingObject

Treat missing dependencies as silent errors



49
50
51
# File 'lib/rubygems/request_set.rb', line 49

def soft_missing
  @soft_missing
end

#vendor_setObject (readonly)

The set of vendor gems imported via load_gemdeps.



54
55
56
# File 'lib/rubygems/request_set.rb', line 54

def vendor_set
  @vendor_set
end

Instance Method Details

#gem(name, *reqs) ⇒ Object

Declare that a gem of name name with reqs requirements is needed.



87
88
89
90
91
92
93
94
95
# File 'lib/rubygems/request_set.rb', line 87

def gem name, *reqs
  if dep = @dependency_names[name] then
    dep.requirement.concat reqs
  else
    dep = Gem::Dependency.new name, reqs
    @dependency_names[name] = dep
    @dependencies << dep
  end
end

#import(deps) ⇒ Object

Add deps Gem::Dependency objects to the set.



100
101
102
# File 'lib/rubygems/request_set.rb', line 100

def import deps
  @dependencies.concat deps
end

#install(options, &block) ⇒ Object

Installs gems for this RequestSet using the Gem::Installer options.

If a block is given an activation request and installer are yielded. The installer will be nil if a gem matching the request was already installed.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/rubygems/request_set.rb', line 111

def install options, &block # :yields: request, installer
  if dir = options[:install_dir]
    return install_into dir, false, options, &block
  end

  cache_dir = options[:cache_dir] || Gem.dir

  specs = []

  sorted_requests.each do |req|
    if req.installed? then
      req.spec.spec.build_extensions

      if @always_install.none? { |spec| spec == req.spec.spec } then
        yield req, nil if block_given?
        next
      end
    end

    path = req.download cache_dir

    inst = Gem::Installer.new path, options

    yield req, inst if block_given?

    specs << inst.install
  end

  specs
end

#install_from_gemdeps(options, &block) ⇒ Object

Installs from the gem dependencies files in the :gemdeps option in options, yielding to the block as in #install.

If :without_groups is given in the options, those groups in the gem dependencies file are not used. See Gem::Installer for other options.



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rubygems/request_set.rb', line 149

def install_from_gemdeps options, &block
  gemdeps = options[:gemdeps]

  @install_dir = options[:install_dir] || Gem.dir

  load_gemdeps gemdeps, options[:without_groups]

  resolve

  if options[:explain]
    puts "Gems to install:"

    specs.map { |s| s.full_name }.sort.each do |s|
      puts "  #{s}"
    end

    if Gem.configuration.really_verbose
      @resolver.stats.display
    end
  else
    installed = install options, &block

    lockfile = Gem::RequestSet::Lockfile.new self, gemdeps
    lockfile.write

    installed
  end
end

#install_into(dir, force = true, options = {}) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/rubygems/request_set.rb', line 178

def install_into dir, force = true, options = {}
  gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir

  existing = force ? [] : specs_in(dir)
  existing.delete_if { |s| @always_install.include? s }

  dir = File.expand_path dir

  installed = []

  options[:install_dir] = dir
  options[:only_install_dir] = true

  sorted_requests.each do |request|
    spec = request.spec

    if existing.find { |s| s.full_name == spec.full_name } then
      yield request, nil if block_given?
      next
    end

    spec.install options do |installer|
      yield request, installer if block_given?
    end

    installed << request
  end

  installed
ensure
  ENV['GEM_HOME'] = gem_home
end

#load_gemdeps(path, without_groups = []) ⇒ Object

Load a dependency management file.



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/rubygems/request_set.rb', line 214

def load_gemdeps path, without_groups = []
  @git_set    = Gem::Resolver::GitSet.new
  @vendor_set = Gem::Resolver::VendorSet.new

  @git_set.root_dir = @install_dir

  lockfile = Gem::RequestSet::Lockfile.new self, path
  lockfile.parse

  gf = Gem::RequestSet::GemDependencyAPI.new self, path
  gf.without_groups = without_groups if without_groups
  gf.load
end

#resolve(set = Gem::Resolver::BestSet.new) ⇒ Object

Resolve the requested dependencies and return an Array of Specification objects to be activated.



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/rubygems/request_set.rb', line 232

def resolve set = Gem::Resolver::BestSet.new
  @sets << set
  @sets << @git_set
  @sets << @vendor_set

  set = Gem::Resolver.compose_sets(*@sets)

  resolver = Gem::Resolver.new @dependencies, set
  resolver.development         = @development
  resolver.ignore_dependencies = @ignore_dependencies
  resolver.soft_missing        = @soft_missing

  @resolver = resolver

  @requests = resolver.resolve
end

#resolve_currentObject

Resolve the requested dependencies against the gems available via Gem.path and return an Array of Specification objects to be activated.



253
254
255
# File 'lib/rubygems/request_set.rb', line 253

def resolve_current
  resolve Gem::Resolver::CurrentSet.new
end

#sorted_requestsObject



257
258
259
# File 'lib/rubygems/request_set.rb', line 257

def sorted_requests
  @sorted ||= strongly_connected_components.flatten
end

#specsObject



261
262
263
# File 'lib/rubygems/request_set.rb', line 261

def specs
  @specs ||= @requests.map { |r| r.full_spec }
end

#specs_in(dir) ⇒ Object



265
266
267
268
269
# File 'lib/rubygems/request_set.rb', line 265

def specs_in dir
  Dir["#{dir}/specifications/*.gemspec"].map do |g|
    Gem::Specification.load g
  end
end

#tsort_each_child(node) ⇒ Object

:nodoc:



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/rubygems/request_set.rb', line 275

def tsort_each_child node # :nodoc:
  node.spec.dependencies.each do |dep|
    next if dep.type == :development and not @development

    match = @requests.find { |r| dep.match? r.spec.name, r.spec.version }
    if match
      begin
        yield match
      rescue TSort::Cyclic
      end
    else
      unless @soft_missing
        raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})"
      end
    end
  end
end

#tsort_each_node(&block) ⇒ Object

:nodoc:



271
272
273
# File 'lib/rubygems/request_set.rb', line 271

def tsort_each_node &block # :nodoc:
  @requests.each(&block)
end