LCOV - code coverage report
Current view: top level - pkg/lib - packagemanager.ts Coverage Total Hit
Test: cockpit Lines: 100.0 % 58 58
Test Date: 2026-07-17 07:33:01

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2025 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5              : 
       6          280 : import cockpit from 'cockpit';
       7              : 
       8              : import { PackageManager, InstallProgressType, UnsupportedError, NotFoundError } from './_internal/packagemanager-abstract';
       9              : import { Dnf5DaemonManager } from './_internal/dnf5daemon';
      10              : import { PackageKitManager } from './_internal/packagekit';
      11              : 
      12          280 : let package_manager: PackageManager | null = null;
      13              : 
      14           40 : function debug(...args: unknown[]) {
      15            4 :     if (window.debugging == 'all' || window.debugging?.includes('packagemanager'))
      16            4 :         console.debug('packagemanager', ...args);
      17           40 : }
      18              : 
      19           42 : async function is_immutable_os() {
      20           42 :     try {
      21           42 :         const options = await cockpit.spawn(["findmnt", "-T", "/usr", "-n", "-o", "VFS-OPTIONS"]);
      22           41 :         return options.split(",").indexOf("ro") >= 0;
      23            4 :     } catch (err) {
      24            4 :         debug("Unable to detect immutable OS", err);
      25            4 :         return false;
      26            4 :     }
      27           42 : }
      28              : 
      29           42 : async function detect_dnf5daemon() {
      30           42 :     const client = cockpit.dbus("org.rpm.dnf.v0", { superuser: "try" });
      31           42 :     let detected = false;
      32           42 :     try {
      33           42 :         await client.call("/org/rpm/dnf/v0", "org.freedesktop.DBus.Peer", "Ping", []);
      34           42 :         detected = true;
      35            4 :     } catch (err) {
      36            4 :         debug("dnf5daemon not supported", err);
      37            4 :     }
      38              : 
      39           42 :     client.close();
      40           42 :     return detected;
      41           42 : }
      42              : 
      43           42 : async function detect_packagekit() {
      44           42 :     const client = cockpit.dbus("org.freedesktop.PackageKit", { superuser: "try" });
      45           42 :     let detected = false;
      46           42 :     try {
      47           42 :         await client.call("/org/freedesktop/PackageKit", "org.freedesktop.DBus.Properties",
      48           42 :                           "Get", ["org.freedesktop.PackageKit", "VersionMajor"]);
      49           36 :         detected = true;
      50            4 :     } catch (err) {
      51            8 :         debug("PackageKit not supported", err);
      52            8 :     }
      53              : 
      54           40 :     client.close();
      55           40 :     return detected;
      56           42 : }
      57              : 
      58              : // Cache result for a session
      59              : // HACK: allow overriding the package manager to make the software updates page
      60              : // keep using PackageKit until the dnf5daemon API is sufficient.
      61           42 : export async function getPackageManager(force_packagekit: boolean = false): Promise<PackageManager> {
      62           42 :     if (package_manager !== null)
      63           17 :         return Promise.resolve(package_manager);
      64              : 
      65           42 :     const [unsupported, has_dnf5daemon, has_packagekit] = await Promise.all([is_immutable_os(), detect_dnf5daemon(), detect_packagekit()]);
      66              : 
      67           40 :     if (unsupported)
      68            4 :         throw new UnsupportedError("Cockpit does not support installing additional packages on immutable operating systems");
      69              : 
      70           24 :     if (has_dnf5daemon && !force_packagekit) {
      71           24 :         debug("constructing dnf5daemon");
      72           24 :         package_manager = new Dnf5DaemonManager();
      73           24 :         return Promise.resolve(package_manager);
      74           24 :     }
      75              : 
      76           20 :     if (has_packagekit) {
      77           20 :         debug("constructing packagekit");
      78           20 :         package_manager = new PackageKitManager();
      79           20 :         return Promise.resolve(package_manager);
      80           20 :     }
      81              : 
      82            4 :     throw new NotFoundError("No package manager found");
      83           42 : }
      84              : 
      85              : export { InstallProgressType };
        

Generated by: LCOV version 2.0-1