mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-30 01:22:06 -04:00
109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
package sysupdate
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
func init() {
|
|
RegisterSystemBackend(func() Backend { return &dnfBackend{bin: "dnf5"} })
|
|
RegisterSystemBackend(func() Backend { return &dnfBackend{bin: "dnf"} })
|
|
}
|
|
|
|
type dnfBackend struct {
|
|
bin string
|
|
}
|
|
|
|
func (b dnfBackend) ID() string { return b.bin }
|
|
func (b dnfBackend) DisplayName() string { return strings.ToUpper(b.bin) }
|
|
func (b dnfBackend) Repo() RepoKind { return RepoSystem }
|
|
func (b dnfBackend) NeedsAuth() bool { return true }
|
|
func (b dnfBackend) RunsInTerminal() bool { return false }
|
|
|
|
func (b dnfBackend) IsAvailable(ctx context.Context) bool {
|
|
if !commandExists(b.bin) {
|
|
return false
|
|
}
|
|
if commandExists("rpm-ostree") && ostreeBooted(ctx) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (b dnfBackend) CheckUpdates(ctx context.Context) ([]Package, error) {
|
|
out, err := dnfListUpgrades(ctx, b.bin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
installed := rpmInstalledVersions(ctx)
|
|
return parseDnfList(out, b.bin, installed), nil
|
|
}
|
|
|
|
func (b dnfBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine func(string)) error {
|
|
if opts.DryRun {
|
|
return Run(ctx, []string{b.bin, "upgrade", "--assumeno"}, RunOptions{OnLine: onLine})
|
|
}
|
|
return Run(ctx, []string{"pkexec", b.bin, "upgrade", "-y"}, RunOptions{OnLine: onLine})
|
|
}
|
|
|
|
func dnfListUpgrades(ctx context.Context, bin string) (string, error) {
|
|
cmd := exec.CommandContext(ctx, bin, "list", "--upgrades", "--quiet")
|
|
out, err := cmd.Output()
|
|
if err == nil {
|
|
return string(out), nil
|
|
}
|
|
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok && exitErr.ExitCode() == 1 {
|
|
return "", nil
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
func rpmInstalledVersions(ctx context.Context) map[string]string {
|
|
out, err := exec.CommandContext(ctx, "rpm", "-qa", "--qf", `%{NAME}\t%{VERSION}-%{RELEASE}\n`).Output()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
m := make(map[string]string)
|
|
for line := range strings.SplitSeq(string(out), "\n") {
|
|
name, ver, ok := strings.Cut(line, "\t")
|
|
if !ok {
|
|
continue
|
|
}
|
|
m[name] = ver
|
|
}
|
|
return m
|
|
}
|
|
|
|
func parseDnfList(text, backendID string, installed map[string]string) []Package {
|
|
if text == "" {
|
|
return nil
|
|
}
|
|
var pkgs []Package
|
|
for line := range strings.SplitSeq(text, "\n") {
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 2 {
|
|
continue
|
|
}
|
|
nameArch := fields[0]
|
|
version := fields[1]
|
|
switch nameArch {
|
|
case "Available", "Upgrades":
|
|
continue
|
|
}
|
|
name := nameArch
|
|
if dot := strings.LastIndex(nameArch, "."); dot > 0 {
|
|
name = nameArch[:dot]
|
|
}
|
|
pkgs = append(pkgs, Package{
|
|
Name: nameArch,
|
|
Repo: RepoSystem,
|
|
Backend: backendID,
|
|
FromVersion: installed[name],
|
|
ToVersion: version,
|
|
})
|
|
}
|
|
return pkgs
|
|
}
|