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-06-16 14:09:37

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

Generated by: LCOV version 2.0-1