Class: Gem::Commands::UpdateCommand

Inherits:
Gem::Command show all
Includes:
InstallUpdateOptions, LocalRemoteOptions, VersionOption
Defined in:
lib/rubygems/commands/update_command.rb

Instance Attribute Summary collapse

Attributes inherited from Gem::Command

#command, #defaults, #options, #program_name, #summary

Instance Method Summary collapse

Methods included from VersionOption

#add_platform_option, #add_prerelease_option, #add_version_option, #get_platform_from_requirements

Methods included from LocalRemoteOptions

#accept_uri_http, #add_bulk_threshold_option, #add_clear_sources_option, #add_local_remote_options, #add_proxy_option, #add_source_option, #add_update_sources_option, #both?, #local?, #remote?

Methods included from InstallUpdateOptions

#add_install_update_options, #install_update_defaults_str, #install_update_options

Methods included from SecurityOption

#add_security_option

Methods inherited from Gem::Command

add_common_option, #add_extra_args, #add_option, add_specific_extra_args, #begins?, build_args, build_args=, #check_deprecated_options, common_options, #deprecate_option, #deprecated?, extra_args, extra_args=, #get_all_gem_names, #get_all_gem_names_and_versions, #get_one_gem_name, #get_one_optional_argument, #handle_options, #handles?, #invoke, #invoke_with_build_args, #merge_options, #remove_option, #show_help, #show_lookup_failure, specific_extra_args, specific_extra_args_hash, #when_invoked

Methods included from UserInteraction

#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction, #verbose

Methods included from DefaultUserInteraction

ui, #ui, ui=, #ui=, use_ui, #use_ui

Methods included from Text

#clean_text, #format_text, #levenshtein_distance, #min3, #truncate_text

Constructor Details

#initializeUpdateCommand

Returns a new instance of UpdateCommand.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rubygems/commands/update_command.rb', line 21

def initialize
  options = {
    :force => false,
  }

  options.merge!(install_update_options)

  super 'update', 'Update installed gems to the latest version', options

  add_install_update_options

  Gem::OptionParser.accept Gem::Version do |value|
    Gem::Version.new value

    value
  end

  add_option('--system [VERSION]', Gem::Version,
             'Update the RubyGems system software') do |value, options|
    value = true unless value

    options[:system] = value
  end

  add_local_remote_options
  add_platform_option
  add_prerelease_option "as update targets"

  @updated   = []
  @installer = nil
end

Instance Attribute Details

#installerObject (readonly)

:nodoc:



17
18
19
# File 'lib/rubygems/commands/update_command.rb', line 17

def installer
  @installer
end

#updatedObject (readonly)

:nodoc:



19
20
21
# File 'lib/rubygems/commands/update_command.rb', line 19

def updated
  @updated
end

Instance Method Details

#argumentsObject

:nodoc:



53
54
55
# File 'lib/rubygems/commands/update_command.rb', line 53

def arguments # :nodoc:
  "GEMNAME       name of gem to update"
end

#check_latest_rubygems(version) ⇒ Object

:nodoc:



75
76
77
78
79
80
# File 'lib/rubygems/commands/update_command.rb', line 75

def check_latest_rubygems(version) # :nodoc:
  if Gem.rubygems_version == version
    say "Latest version already installed. Done."
    terminate_interaction
  end
end

#check_oldest_rubygems(version) ⇒ Object

:nodoc:



82
83
84
85
86
87
# File 'lib/rubygems/commands/update_command.rb', line 82

def check_oldest_rubygems(version) # :nodoc:
  if oldest_supported_version > version
    alert_error "rubygems #{version} is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is #{oldest_supported_version}"
    terminate_interaction 1
  end
end

#check_update_argumentsObject

:nodoc:



89
90
91
92
93
94
# File 'lib/rubygems/commands/update_command.rb', line 89

def check_update_arguments # :nodoc:
  unless options[:args].empty?
    alert_error "Gem names are not allowed with the --system option"
    terminate_interaction 1
  end
end

#defaults_strObject

:nodoc:



57
58
59
60
# File 'lib/rubygems/commands/update_command.rb', line 57

def defaults_str # :nodoc:
  "--no-force --install-dir #{Gem.dir}\n" +
  install_update_defaults_str
end

#descriptionObject

:nodoc:



62
63
64
65
66
67
68
69
# File 'lib/rubygems/commands/update_command.rb', line 62

def description # :nodoc:
  <<-EOF
The update command will update your gems to the latest version.

The update command does not remove the previous version. Use the cleanup
command to remove old versions.
  EOF
end

#executeObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rubygems/commands/update_command.rb', line 96

def execute
  if options[:system]
    update_rubygems
    return
  end

  gems_to_update = which_to_update(
    highest_installed_gems,
    options[:args].uniq
  )

  if options[:explain]
    say "Gems to update:"

    gems_to_update.each do |name_tuple|
      say "  #{name_tuple.full_name}"
    end

    return
  end

  say "Updating installed gems"

  updated = update_gems gems_to_update

  updated_names = updated.map {|spec| spec.name }
  not_updated_names = options[:args].uniq - updated_names

  if updated.empty?
    say "Nothing to update"
  else
    say "Gems updated: #{updated_names.join(' ')}"
    say "Gems already up-to-date: #{not_updated_names.join(' ')}" unless not_updated_names.empty?
  end
end

#fetch_remote_gems(spec) ⇒ Object

:nodoc:



132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/rubygems/commands/update_command.rb', line 132

def fetch_remote_gems(spec) # :nodoc:
  dependency = Gem::Dependency.new spec.name, "> #{spec.version}"
  dependency.prerelease = options[:prerelease]

  fetcher = Gem::SpecFetcher.fetcher

  spec_tuples, errors = fetcher.search_for_dependency dependency

  error = errors.find {|e| e.respond_to? :exception }

  raise error if error

  spec_tuples
end

#highest_installed_gemsObject

:nodoc:



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/rubygems/commands/update_command.rb', line 147

def highest_installed_gems # :nodoc:
  hig = {} # highest installed gems

  # Get only gem specifications installed as --user-install
  Gem::Specification.dirs = Gem.user_dir if options[:user_install]

  Gem::Specification.each do |spec|
    if hig[spec.name].nil? or hig[spec.name].version < spec.version
      hig[spec.name] = spec
    end
  end

  hig
end

#highest_remote_name_tuple(spec) ⇒ Object

:nodoc:



162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/rubygems/commands/update_command.rb', line 162

def highest_remote_name_tuple(spec) # :nodoc:
  spec_tuples = fetch_remote_gems spec

  matching_gems = spec_tuples.select do |g,_|
    g.name == spec.name and g.match_platform?
  end

  highest_remote_gem = matching_gems.max

  highest_remote_gem ||= [Gem::NameTuple.null]

  highest_remote_gem.first
end

#install_rubygems(version) ⇒ Object

:nodoc:



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/rubygems/commands/update_command.rb', line 176

def install_rubygems(version) # :nodoc:
  args = update_rubygems_arguments

  update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"

  Dir.chdir update_dir do
    say "Installing RubyGems #{version}" unless options[:silent]

    installed = preparing_gem_layout_for(version) do
      system Gem.ruby, '--disable-gems', 'setup.rb', *args
    end

    say "RubyGems system software updated" if installed unless options[:silent]
  end
end

#preparing_gem_layout_for(version) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/rubygems/commands/update_command.rb', line 192

def preparing_gem_layout_for(version)
  if Gem::Version.new(version) >= Gem::Version.new("3.2.a")
    yield
  else
    require "tmpdir"
    tmpdir = Dir.mktmpdir
    FileUtils.mv Gem.plugindir, tmpdir

    status = yield

    if status
      FileUtils.rm_rf tmpdir
    else
      FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugindir
    end

    status
  end
end

#rubygems_target_versionObject



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/rubygems/commands/update_command.rb', line 212

def rubygems_target_version
  version = options[:system]
  update_latest = version == true

  if update_latest
    version     = Gem::Version.new     Gem::VERSION
    requirement = Gem::Requirement.new ">= #{Gem::VERSION}"
  else
    version     = Gem::Version.new     version
    requirement = Gem::Requirement.new version
  end

  rubygems_update         = Gem::Specification.new
  rubygems_update.name    = 'rubygems-update'
  rubygems_update.version = version

  hig = {
    'rubygems-update' => rubygems_update,
  }

  gems_to_update = which_to_update hig, options[:args], :system
  up_ver = gems_to_update.first.version

  target = if update_latest
             up_ver
           else
             version
           end

  return target, requirement
end

#update_gem(name, version = Gem::Requirement.default) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rubygems/commands/update_command.rb', line 244

def update_gem(name, version = Gem::Requirement.default)
  return if @updated.any? {|spec| spec.name == name }

  update_options = options.dup
  update_options[:prerelease] = version.prerelease?

  @installer = Gem::DependencyInstaller.new update_options

  say "Updating #{name}" unless options[:system] && options[:silent]
  begin
    @installer.install name, Gem::Requirement.new(version)
  rescue Gem::InstallError, Gem::DependencyError => e
    alert_error "Error installing #{name}:\n\t#{e.message}"
  end

  @installer.installed_gems.each do |spec|
    @updated << spec
  end
end

#update_gems(gems_to_update) ⇒ Object



264
265
266
267
268
269
270
# File 'lib/rubygems/commands/update_command.rb', line 264

def update_gems(gems_to_update)
  gems_to_update.uniq.sort.each do |name_tuple|
    update_gem name_tuple.name, name_tuple.version
  end

  @updated
end

#update_rubygemsObject

Update RubyGems software to the latest version.



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/rubygems/commands/update_command.rb', line 275

def update_rubygems
  if Gem.disable_system_update_message
    alert_error Gem.disable_system_update_message
    terminate_interaction 1
  end

  check_update_arguments

  version, requirement = rubygems_target_version

  check_latest_rubygems version

  check_oldest_rubygems version

  installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement
  installed_gems = update_gem('rubygems-update', version) if installed_gems.empty?
  return if installed_gems.empty?

  version = installed_gems.first.version

  install_rubygems version
end

#update_rubygems_argumentsObject

:nodoc:



298
299
300
301
302
303
304
305
306
307
308
# File 'lib/rubygems/commands/update_command.rb', line 298

def update_rubygems_arguments # :nodoc:
  args = []
  args << '--silent' if options[:silent]
  args << '--prefix' << Gem.prefix if Gem.prefix
  args << '--no-document' unless options[:document].include?('rdoc') || options[:document].include?('ri')
  args << '--no-format-executable' if options[:no_format_executable]
  args << '--previous-version' << Gem::VERSION if
    options[:system] == true or
      Gem::Version.new(options[:system]) >= Gem::Version.new(2)
  args
end

#usageObject

:nodoc:



71
72
73
# File 'lib/rubygems/commands/update_command.rb', line 71

def usage # :nodoc:
  "#{program_name} GEMNAME [GEMNAME ...]"
end

#which_to_update(highest_installed_gems, gem_names, system = false) ⇒ Object



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/rubygems/commands/update_command.rb', line 310

def which_to_update(highest_installed_gems, gem_names, system = false)
  result = []

  highest_installed_gems.each do |l_name, l_spec|
    next if not gem_names.empty? and
            gem_names.none? {|name| name == l_spec.name }

    highest_remote_tup = highest_remote_name_tuple l_spec
    highest_remote_ver = highest_remote_tup.version
    highest_installed_ver = l_spec.version

    if system or (highest_installed_ver < highest_remote_ver)
      result << Gem::NameTuple.new(l_spec.name, [highest_installed_ver, highest_remote_ver].max, highest_remote_tup.platform)
    end
  end

  result
end