Class: Yast::PackageClass

Inherits:
Module
  • Object
show all
Extended by:
Forwardable
Includes:
Logger
Defined in:
library/packages/src/modules/Package.rb

Overview

This module implements support to query, install and remove packages.

Prefer Package to PackageSystem

Depending on the mode, this module decides if it should interact with PackageSystem (libzypp) or PackageAI (AutoYaST). For instance, if you open a module in the AutoYaST UI, calling to #CheckAndInstallPackages does not install the package for real. Instead, it adds the package to the list of packages to include in the profile. However, when running on other modes (normal, installation, etc.), it just installs the package.

Overriding default behavior

There might a scenario where you want to force Package to work with the real packages. For instance, while reading the configuration during a clone_system operation: the mode is still autoinst_config but you are dealing with the underlying system. In those cases, you can force Package to work with PackageSystem.

If you are accessing this module through YCP (for instance, using Perl), you cannot pass the :target option. If you need to specify this option, please consider using PackageSystem or PackageAI functions directly.

See https://bugzilla.suse.com/show_bug.cgi?id=1196963 for further details.

Examples:

Forcing to check for packages on the underlying system

Yast::Package.Installed("firewalld", target: :system)

Instance Method Summary collapse

Instance Method Details

#AskPackages(packs, install) ⇒ Object

Asks the user if the given packages should be installed or removed

It only makes sense in CommandLine mode.

Parameters:

  • packs (Array<String>)

    List of packages to install/remove

  • install (Boolean)

    True to install the packages, false to remove them



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'library/packages/src/modules/Package.rb', line 292

def AskPackages(packs, install)
  packs = deep_copy(packs)
  pkgs = Builtins.mergestring(packs, ", ")
  text = if install
    # the message is followed by list of required packages
    _("These packages need to be installed:")
  else
    # the message is followed by list of required packages
    _("These packages need to be removed:")
  end

  text += " " + pkgs

  CommandLine.Print(text)

  CommandLine.YesNo
end

#Available(package) ⇒ Boolean

Determines whether the package is available or not

This method checks whether any available package provides the given "package".

Parameters:

  • package (String)

    Package name

Returns:

  • (Boolean)

    true if the package is available; false otherwise

See Also:



# File 'library/packages/src/modules/Package.rb', line 76

#AvailableAll(packages) ⇒ Boolean

Are all of these packages available?

Parameters:

  • packages (Array<String>)

    list of packages

Returns:

  • (Boolean)

    true if yes (nil = an error occurred)



231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'library/packages/src/modules/Package.rb', line 231

def AvailableAll(packages)
  packages = deep_copy(packages)
  error = false

  which = Builtins.find(packages) do |p|
    avail = Available(p)
    error = true if avail.nil?
    !avail
  end

  return nil if error

  which.nil?
end

#AvailableAny(packages) ⇒ Boolean

Is any of these packages available?

Parameters:

  • packages (Array<String>)

    list of packages

Returns:

  • (Boolean)

    true if yes (nil = an error occurred)



249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'library/packages/src/modules/Package.rb', line 249

def AvailableAny(packages)
  packages = deep_copy(packages)
  error = false

  which = Builtins.find(packages) do |p|
    avail = Available(p)
    error = true if avail.nil?
    avail
  end

  return nil if error

  !which.nil?
end

#CheckAndInstallPackages(packages) ⇒ Boolean

Check if packages are installed

Install them if they are not and user approves installation

false otherwise

Parameters:

  • packages (Array<String>)

    list of packages to check (and install)

Returns:

  • (Boolean)

    true if installation succeeded or packages were installed,



149
150
151
152
153
154
# File 'library/packages/src/modules/Package.rb', line 149

def CheckAndInstallPackages(packages)
  return true if Mode.config || Stage.initial
  return true if InstalledAll(packages)

  InstallAll(packages)
end

#CheckAndInstallPackagesInteractive(packages) ⇒ Boolean

Check if packages are installed

Install them if they are not and user approves installation If installation fails (or wasn't allowed), ask user if he wants to continue

before or user decided to continue, false otherwise

Parameters:

  • packages (Array<String>)

    a list of packages to check (and install)

Returns:

  • (Boolean)

    true if installation succeeded, packages were installed



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'library/packages/src/modules/Package.rb', line 165

def CheckAndInstallPackagesInteractive(packages)
  success = CheckAndInstallPackages(packages)
  return true if success

  if !LastOperationCanceled()
    if Mode.commandline
      # error report
      Report.Error(_("Installing required packages failed."))
    else
      Popup.ContinueCancel(
        # continue/cancel popup
        _(
          "Installing required packages failed. If you continue\n" \
          "without installing required packages,\n" \
          "YaST may not work properly.\n"
        )
      )
    end
  elsif Mode.commandline
    Report.Error(
      # error report
      _("Cannot continue without installing required packages.")
    )
  else
    Popup.ContinueCancel(
      # continue/cancel popup
      _(
        "If you continue without installing required \npackages, YaST may not work properly.\n"
      )
    )
  end
end

#DoInstall(packages) ⇒ Boolean

Installs the given packages

Parameters:

  • packages (Array<String>)

    Name of the packages to install

Returns:

  • (Boolean)

    true if packages were successfully installed



# File 'library/packages/src/modules/Package.rb', line 94

#DoInstallAndRemove(toinstall, toremove) ⇒ Boolean

Install and remove packages in one go

Parameters:

  • toinstall (Array<String>)

    Name of the packages to install

  • toremove (Array<String>)

    Name of the packages to remove

Returns:

  • (Boolean)

    true on success



211
212
213
214
215
216
217
218
219
220
221
# File 'library/packages/src/modules/Package.rb', line 211

def DoInstallAndRemove(toinstall, toremove)
  ret = backend.DoInstallAndRemove(toinstall, toremove)
  return false unless ret

  if !InstalledAll(toinstall)
    log.error("Required packages have not been installed")
    return false
  end

  true
end

#DoRemove(packages) ⇒ Boolean

Removes the given packages

Parameters:

  • packages (Array<String>)

    Name of the packages to remove

Returns:

  • (Boolean)

    true if packages were successfully removed



# File 'library/packages/src/modules/Package.rb', line 99

#Install(package) ⇒ Boolean

Installs a package

Parameters:

  • package (String)

    package to be installed

Returns:

  • (Boolean)

    true on success



403
404
405
# File 'library/packages/src/modules/Package.rb', line 403

def Install(package)
  InstallMsg(package, nil)
end

#InstallAll(packages) ⇒ Boolean

Installs a list of packages

Parameters:

  • packages (Array<String>)

    list of packages to be installed

Returns:

  • (Boolean)

    true on success



411
412
413
414
# File 'library/packages/src/modules/Package.rb', line 411

def InstallAll(packages)
  packages = deep_copy(packages)
  InstallAllMsg(packages, nil)
end

#InstallAllMsg(packages, message) ⇒ Object

Install list of packages with a custom text message

Parameters:

  • packages (Array<String>)

    The list packages to be installed

  • message (String)

    custom text message

Returns:

  • True on success



377
378
379
380
# File 'library/packages/src/modules/Package.rb', line 377

def InstallAllMsg(packages, message)
  packages = deep_copy(packages)
  PackageDialog(packages, true, message)
end

#Installed(package, target: nil) ⇒ Boolean

Determines whether the package is provided or not

This method checks whether any installed package provides the given "package".

Parameters:

  • package (String)

    Package name

  • target (Symbol, nil) (defaults to: nil)

    :autoinst or :system. If it is nil, it guesses the backend depending on the mode.

Returns:

  • (Boolean)

    true if the package exists; false otherwise

See Also:



125
126
127
# File 'library/packages/src/modules/Package.rb', line 125

def Installed(package, target: nil)
  find_backend(target).Installed(package)
end

#InstalledAll(packages, target: nil) ⇒ Boolean

Are all of these packages installed?

Parameters:

  • packages (Array<String>)

    list of packages

  • target (Symbol, nil) (defaults to: nil)

    :autoinst or :system. If it is nil, it guesses the backend depending on the mode.

Returns:

  • (Boolean)

    true if yes



269
270
271
272
273
# File 'library/packages/src/modules/Package.rb', line 269

def InstalledAll(packages, target: nil)
  packages = deep_copy(packages)
  which = Builtins.find(packages) { |p| !Installed(p, target: target) }
  which.nil?
end

#InstalledAny(packages, target: nil) ⇒ Boolean

Is any of these packages installed?

Parameters:

  • packages (Array<String>)

    list of packages

  • target (Symbol, nil) (defaults to: nil)

    :autoinst or :system. If it is nil, it guesses the backend depending on the mode.

Returns:

  • (Boolean)

    true if yes



280
281
282
283
284
# File 'library/packages/src/modules/Package.rb', line 280

def InstalledAny(packages, target: nil)
  packages = deep_copy(packages)
  which = Builtins.find(packages) { |p| Installed(p, target: target) }
  !which.nil?
end

#InstallKernel(kernel_modules) ⇒ Boolean

Installs the given kernel modules

Parameters:

  • kernel_modules (Array<String>)

    Names of the kernel modules to install

Returns:

  • (Boolean)

    true on success



108
109
110
111
112
113
114
# File 'library/packages/src/modules/Package.rb', line 108

def main
  textdomain "base"

  @last_op_canceled = false
  @installed_packages = []
  @removed_packages = []
end

#InstallMsg(package, message) ⇒ Object

Install a package with a custom text message

Parameters:

  • package (String)

    to be installed

  • message (String)

    custom text message

Returns:

  • True on success



369
370
371
# File 'library/packages/src/modules/Package.rb', line 369

def InstallMsg(package, message)
  PackageDialog([package], true, message)
end

#IsTransactionalSystemBoolean

Return if system is transactional and does not support direct package install

Returns:

  • (Boolean)


443
444
445
446
447
448
449
450
451
452
453
454
# File 'library/packages/src/modules/Package.rb', line 443

def IsTransactionalSystem
  return @transactional unless @transactional.nil?

  mounts = SCR.Read(path(".proc.mounts"))
  root = mounts.find { |m| m["file"] == WFM.scr_root }
  log.info "root in mounts #{root.inspect}"

  raise "Failed to find #{WFM.scr_root} at /proc/mounts" unless root

  # check if there are ro keyword in mount
  @transactional = /(?:^|,)ro(?:,|$)/.match?(root["mntops"])
end

#LastOperationCanceledObject

Return result of the last operation Use immediately after calling any Package*:: function

Returns:

  • true if it last operation was canceled



436
437
438
# File 'library/packages/src/modules/Package.rb', line 436

def LastOperationCanceled
  @last_op_canceled
end

#mainObject



108
109
110
111
112
113
114
# File 'library/packages/src/modules/Package.rb', line 108

def main
  textdomain "base"

  @last_op_canceled = false
  @installed_packages = []
  @removed_packages = []
end

#PackageAvailable(package) ⇒ Boolean

Determines whether the package with the given name is available

This method check just the package's name.

Parameters:

  • package (String)

    Package name

Returns:

  • (Boolean)

    true if the package is available; false otherwise

See Also:



# File 'library/packages/src/modules/Package.rb', line 85

#PackageDialog(packages, install, message) ⇒ Object

Main package installatio|removal dialog

Parameters:

  • packages (Array<String>)

    list of packages

  • install (Boolean)

    true if install, false if remove

  • message (String)

    optional installation|removal text (nil -> standard will be used)

Returns:

  • true on success



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'library/packages/src/modules/Package.rb', line 315

def PackageDialog(packages, install, message)
  log.info "Asking for packages: #{packages}"
  packs = Builtins.filter(packages) do |package|
    install ? !Installed(package) : Installed(package)
  end
  log.info "Remaining packages: #{packs}"

  return true if packs.empty?

  check_transactional_system!(packs, install ? :install : :remove)

  # Popup Text
  text = _("These packages need to be installed:") + "<p>"
  # Popup Text
  text = _("These packages need to be removed:") + "<p>" if install == false

  Builtins.foreach(packs) do |p|
    text = Ops.add(text, Builtins.sformat("%1<br>", p))
  end

  text = Builtins.sformat(message, Builtins.mergestring(packs, ", ")) if !message.nil?

  doit = if Mode.commandline
    CommandLine.Interactive ? AskPackages(packs, install) : true
  else
    Popup.AnyQuestionRichText(
      "",
      text,
      40,
      10,
      # labels changed for bug #215195
      #  Label::ContinueButton (), Label::CancelButton (),
      # push button label
      install ? Label.InstallButton : _("&Uninstall"),
      Label.CancelButton,
      :focus_yes
    )
  end

  if doit
    @last_op_canceled = false
    return DoRemove(packs) if install == false

    return DoInstall(packs)
  end

  @last_op_canceled = true
  false
end

#PackageInstalled(package, target: nil) ⇒ Boolean

Determines whether the package is installed or not

This method check just the package's name.

Parameters:

  • package (String)

    Package name

  • target (Symbol, nil) (defaults to: nil)

    :autoinst or :system. If it is nil, it guesses the backend depending on the mode.

Returns:

  • (Boolean)

    true if the package exists; false otherwise

See Also:



138
139
140
# File 'library/packages/src/modules/Package.rb', line 138

def PackageInstalled(package, target: nil)
  find_backend(target).PackageInstalled(package)
end

#Remove(package) ⇒ Boolean

Removes a package

Parameters:

  • package (String)

    package to be removed

Returns:

  • (Boolean)

    true on success



420
421
422
# File 'library/packages/src/modules/Package.rb', line 420

def Remove(package)
  RemoveMsg(package, nil)
end

#RemoveAll(packages) ⇒ Boolean

Removes a list of packages

Parameters:

  • packages (Array<String>)

    list of packages to be removed

Returns:

  • (Boolean)

    true on success



428
429
430
431
# File 'library/packages/src/modules/Package.rb', line 428

def RemoveAll(packages)
  packages = deep_copy(packages)
  RemoveAllMsg(packages, nil)
end

#RemoveAllMsg(packages, message) ⇒ Object

Remove a list of packages with a custom text message

Parameters:

  • packages (Array<String>)

    The list of packages to be removed

  • message (String)

    custom text message

Returns:

  • True on success



394
395
396
397
# File 'library/packages/src/modules/Package.rb', line 394

def RemoveAllMsg(packages, message)
  packages = deep_copy(packages)
  PackageDialog(packages, false, message)
end

#RemoveMsg(package, message) ⇒ Object

Remove a package with a custom text message

Parameters:

  • package (String)

    package to be removed

  • message (String)

    custom text message

Returns:

  • True on success



386
387
388
# File 'library/packages/src/modules/Package.rb', line 386

def RemoveMsg(package, message)
  PackageDialog([package], false, message)
end

#resetObject



223
224
225
226
# File 'library/packages/src/modules/Package.rb', line 223

def reset
  @installed_packages.clear
  @removed_packages.clear
end