Class: Yast::PackageSystemClass

Inherits:
Module
  • Object
show all
Defined in:
library/packages/src/modules/PackageSystem.rb

Instance Method Summary collapse

Instance Method Details

#Available(package) ⇒ Object

Is a package available?

Returns:

  • true if yes (nil = no package source available)



308
309
310
311
312
313
314
315
316
317
# File 'library/packages/src/modules/PackageSystem.rb', line 308

def Available(package)
  EnsureSourceInit()

  if !@source_initialized
    # error no source initialized
    return nil
  end

  Pkg.IsAvailable(package)
end

#CheckAndInstallPackages(packages) ⇒ Boolean

Check if packages are installed

Install them if they are not and user approves installation

false otherwise

Parameters:

  • a

    list of packages to check (and install)

Returns:

  • (Boolean)

    true if installation succeeded or packages were installed,



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

def CheckAndInstallPackages(packages)
  packages = deep_copy(packages)
  return true if Mode.config
  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



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'library/packages/src/modules/PackageSystem.rb', line 410

def CheckAndInstallPackagesInteractive(packages)
  packages = deep_copy(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) ⇒ Object



120
121
122
123
# File 'library/packages/src/modules/PackageSystem.rb', line 120

def DoInstall(packages)
  packages = deep_copy(packages)
  DoInstallAndRemove(packages, [])
end

#DoInstallAndRemove(toinstall, toremove) ⇒ Object



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'library/packages/src/modules/PackageSystem.rb', line 289

def DoInstallAndRemove(toinstall, toremove)
  toinstall = deep_copy(toinstall)
  toremove = deep_copy(toremove)
  # remember the current solver flags
  solver_flags = Pkg.GetSolverFlags

  # do not install recommended packages for already installed packages (bnc#445476)
  Pkg.SetSolverFlags("ignoreAlreadyRecommended" => true)

  ret = DoInstallAndRemoveInt(toinstall, toremove)

  # restore the original flags
  Pkg.SetSolverFlags(solver_flags)

  ret
end

#DoInstallAndRemoveInt(toinstall, toremove) ⇒ Object



157
158
159
160
161
162
163
164
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'library/packages/src/modules/PackageSystem.rb', line 157

def DoInstallAndRemoveInt(toinstall, toremove)
  toinstall = deep_copy(toinstall)
  toremove = deep_copy(toremove)
  Builtins.y2debug("toinstall: %1, toremove: %2", toinstall, toremove)
  return false if !PackageLock.Check

  EnsureSourceInit()
  EnsureTargetInit()
  ok = true

  Yast.import "Label"
  Yast.import "Popup"
  Yast.import "PackagesUI"

  # licenses: #35250
  licenses = Pkg.PkgGetLicensesToConfirm(toinstall)
  if Ops.greater_than(Builtins.size(licenses), 0)
    rt_licenses_l = Builtins.maplist(licenses) do |p, l|
      if Mode.commandline
        Builtins.sformat("%1\n%2", p, l)
      else
        Builtins.sformat("<p><b>%1</b></p>\n%2", p, l)
      end
    end

    accepted = false

    if Mode.commandline
      # print the licenses
      CommandLine.Print(Builtins.mergestring(rt_licenses_l, "\n"))
      # print the question
      CommandLine.Print(_("Do you accept this license agreement?"))

      accepted = !CommandLine.YesNo
    else
      accepted = !Popup.AnyQuestionRichText(
        # popup heading, with rich text widget and Yes/No buttons
        _("Do you accept this license agreement?"),
        Builtins.mergestring(rt_licenses_l, "\n"),
        70,
        20,
        Label.YesButton,
        Label.NoButton,
        :focus_none
      )
    end

    Builtins.y2milestone("Licenses accepted: %1", accepted)

    if !accepted
      Builtins.y2milestone("License not accepted: %1", toinstall)
      @last_op_canceled = true
      return false
    end

    # mark licenses as confirmed
    Builtins.foreach(licenses) { |p, _l| Pkg.PkgMarkLicenseConfirmed(p) }
    @last_op_canceled = false
  end

  return false if !SelectPackages(toinstall, toremove)

  if !Pkg.PkgSolve(false)
    Builtins.y2error("Package solve failed: %1", Pkg.LastError)

    # error message, after pressing [OK] the package manager is displayed
    Report.Error(
      _(
        "There are unresolved dependencies which need\nto be solved manually in the software manager."
      )
    )

    # disable repomanagement during installation
    repomgmt = !Mode.installation
    # start the package selector
    ret = PackagesUI.RunPackageSelector(
      "enable_repo_mgr" => repomgmt, "mode" => :summaryMode
    )

    Builtins.y2internal("Package selector returned: %1", ret)

    # do not fix the system
    return false if ret == :cancel || ret == :close
  end

  # is a package or a patch selected for installation?
  any_to_install = Pkg.IsAnyResolvable(:package, :to_install) ||
    Pkg.IsAnyResolvable(:patch, :to_install)

  # [int successful, list failed, list remaining, list srcremaining, list update_messages]
  result = Pkg.PkgCommit(0)
  Builtins.y2debug("PkgCommit: %1", result)
  if result.nil? || Ops.get_list(result, 1, []) != []
    Builtins.y2error(
      "Package commit failed: %1",
      Ops.get_list(result, 1, [])
    )
    return false
  end

  PackagesUI.show_update_messages(result)

  Builtins.foreach(Ops.get_list(result, 2, [])) do |remaining|
    if ok == true
      if Builtins.contains(toinstall, remaining)
        Builtins.y2error("Package remain: %1", remaining)
        ok = false
      end
    end
  end
  return false if ok != true

  # Show popup when new kernel was installed
  # But omit it during installation, one is run at its end.
  # #25071
  Kernel.InformAboutKernelChange if !Stage.initial && !Stage.cont

  # a package or a patch was installed, may be that there is a new yast agent
  if any_to_install
    # register the new agents
    SCR.RegisterNewAgents
  end

  # check if the required packages have been installed
  if !InstalledAll(toinstall)
    Builtins.y2error("Required packages have not been installed")
    return false
  end

  true
end

#DoRemove(packages) ⇒ Object



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

def DoRemove(packages)
  packages = deep_copy(packages)
  DoInstallAndRemove([], packages)
end

#EnsureSourceInitObject

Ensure that Pkg

calls working with the installation sources work



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'library/packages/src/modules/PackageSystem.rb', line 92

def EnsureSourceInit
  PackageLock.Check

  if @source_initialized
    # this way, if somebody closed the cache outside of Package
    # (typically in installation), we will reinitialize
    # it's cheap if cache is already initialized
    Pkg.SourceStartCache(true)
    return
  end

  if !@target_initialized
    # make sure we have the RPM keys imported
    EnsureTargetInit()
  end

  sources = Pkg.SourceStartCache(true)

  if Ops.greater_than(Builtins.size(sources), 0)
    @source_initialized = true
  else
    # all repositories are disabled or no repository defined
    Builtins.y2warning("No package repository available")
  end

  nil
end

#EnsureTargetInitObject

Ensure that Pkg

calls work.

This may become superfluous.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'library/packages/src/modules/PackageSystem.rb', line 74

def EnsureTargetInit
  # do not initialize the target system in the first installation stage when
  # running in instsys, there is no RPM DB in the RAM disk image (bnc#742420)
  if Stage.initial && !Mode.live_installation
    Builtins.y2milestone(
      "Skipping target initialization in first stage installation"
    )
    return
  end

  PackageLock.Check
  # always initizalize target, it should be cheap according to #45356
  @target_initialized = Pkg.TargetInit("/", false)

  nil
end

#InitRPMQueryBinaryObject



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'library/packages/src/modules/PackageSystem.rb', line 319

def InitRPMQueryBinary
  return if @_rpm_query_binary_initialized

  # rpmqpack is a way faster
  if Ops.greater_than(
    SCR.Read(path(".target.size"), "/usr/bin/rpmqpack"),
    -1
  )
    @_rpm_query_binary = "/usr/bin/rpmqpack "
    # than rpm itself
  elsif Ops.greater_than(SCR.Read(path(".target.size"), "/bin/rpm"), -1)
    @_rpm_query_binary = "/bin/rpm -q "
  end

  @_rpm_query_binary_initialized = true

  nil
end

#Installed(package) ⇒ Object

Is a package provided in the system? Is there any installed package providing 'package'?

Returns:

  • true if yes



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'library/packages/src/modules/PackageSystem.rb', line 340

def Installed(package)
  # This is a most commonly called function and so it's
  # important that it's fast, especially in the common
  # case, where all dependencies are satisfied.
  # Unfortunately, initializing Pkg reads the RPM database...
  # so we must avoid it.
  # added --whatprovides due to bug #76181
  0 ==
    Convert.to_integer(
      SCR.Execute(
        path(".target.bash"),
        Ops.add("rpm -q --whatprovides ", package)
      )
    )
  # return Pkg::IsProvided (package);
end

#InstallKernel(kernel_modules) ⇒ Object



444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
# File 'library/packages/src/modules/PackageSystem.rb', line 444

def InstallKernel(kernel_modules)
  kernel_modules = deep_copy(kernel_modules)
  # this function may be responsible for the horrible startup time
  Builtins.y2milestone("want: %1", kernel_modules)
  if kernel_modules == []
    return true # nothing to do
  end

  # check whether tag "kernel" is provided
  # do not initialize the package manager if it's not necessary
  rpm_command = "/bin/rpm -q --whatprovides kernel"
  Builtins.y2milestone("Starting RPM query: %1", rpm_command)
  output = Convert.to_map(
    SCR.Execute(path(".target.bash_output"), rpm_command)
  )
  Builtins.y2debug("result of the query: %1", output)

  if Ops.get_integer(output, "exit", -1) == 0
    packages = Builtins.splitstring(
      Ops.get_string(output, "stdout", ""),
      "\n"
    )
    packages = Builtins.filter(packages) { |pkg| pkg != "" }
    Builtins.y2milestone("Packages providing tag 'kernel': %1", packages)

    return true if Ops.greater_than(Builtins.size(packages), 0)

    Builtins.y2milestone("Huh? Kernel is not installed??")
  else
    Builtins.y2warning("RPM query failed, quering the package manager...")
  end

  EnsureTargetInit()

  provides = Pkg.PkgQueryProvides("kernel")
  Builtins.y2milestone("provides: %1", provides)

  kernels = Builtins.filter(provides) do |l|
    Ops.get_symbol(l, 1, :NONE) == :BOTH ||
      Ops.get_symbol(l, 1, :NONE) == Ops.get_symbol(l, 2, :NONE)
  end

  if Builtins.size(kernels) != 1
    Builtins.y2error("not exactly one package provides tag kernel")
  end

  kernel = Ops.get_string(kernels, [0, 0], "none")
  packs = [kernel]

  EnsureSourceInit() if !Pkg.IsProvided(kernel)

  # TODO: for 9.2, we always install all packages, but
  # we could only install those really needed (#44394)
  InstallAll(packs)
end

#mainObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'library/packages/src/modules/PackageSystem.rb', line 39

def main
  Yast.import "Pkg"
  textdomain "base"

  Yast.import "Kernel"
  Yast.import "Mode"
  Yast.import "PackageCallbacks"
  Yast.import "PackageLock"
  Yast.import "Report"
  Yast.import "Stage"
  Yast.import "CommandLine"

  # Was last operation canceled?
  #
  # Used to enhance the exit status to distinguish between package
  # installation fail and installation canceled by user, as in the second
  # case doesn't make much sense to display any error
  # Is set to true when user canceled package installation, from
  # PackageSystem::* functions
  @last_op_canceled = false

  # Has Pkg::TargetInit run?
  @target_initialized = false

  # Has Pkg::SourceStartCache run?
  @source_initialized = false

  Yast.include self, "packages/common.rb"

  @_rpm_query_binary_initialized = false
  @_rpm_query_binary = "rpm"
end

#PackageAvailable(package) ⇒ Object

Is a package available? Checks only package name, not list of provides.

Returns:

  • true if yes (nil = no package source available)



376
377
378
379
380
381
382
383
384
385
# File 'library/packages/src/modules/PackageSystem.rb', line 376

def PackageAvailable(package)
  EnsureSourceInit()

  if !@source_initialized
    # error no source initialized
    return nil
  end

  Pkg.PkgAvailable(package)
end

#PackageInstalled(package) ⇒ Object

Is a package installed? Checks only the package name in contrast to Installed() function.

Returns:

  • true if yes



359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'library/packages/src/modules/PackageSystem.rb', line 359

def PackageInstalled(package)
  InitRPMQueryBinary()

  # This is commonly called function and so it's
  # important that it's fast, especially in the common
  # case, where all dependencies are satisfied.
  0 ==
    Convert.to_integer(
      SCR.Execute(
        path(".target.bash"),
        Ops.add(@_rpm_query_binary, package)
      )
    )
end

#SelectPackages(toinstall, toremove) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'library/packages/src/modules/PackageSystem.rb', line 130

def SelectPackages(toinstall, toremove)
  toinstall = deep_copy(toinstall)
  toremove = deep_copy(toremove)
  ok = true

  Builtins.foreach(toinstall) do |p|
    if ok == true
      if Pkg.PkgInstall(p) != true
        Builtins.y2error("Package %1 install failed: %2", p, Pkg.LastError)
        ok = false
      end
    end
  end
  return false if ok != true

  Builtins.foreach(toremove) do |p|
    if ok == true
      if Pkg.PkgDelete(p) != true
        Builtins.y2error("Package %1 delete failed: %2", p, Pkg.LastError)
        ok = false
      end
    end
  end

  ok
end