mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-30 17:42:06 -04:00
system updater: complete overhaul
Move system update flow to GO, with a CLI (convenient AIO tool) and server integration. All lifecycle, scheduling, execution occurs on backend side. Run some backends via pkexec, some via terminal like paru/yay. Incorporate flatpak as an option to update. Add terminal override setting in GUI, in addition to $TERMINAL env variable. fixes #2307 fixes #822 fixes #1102 fixes #1812 fixes #1087 fixes #1743
This commit is contained in:
108
core/internal/server/sysupdate/backend_dnf.go
Normal file
108
core/internal/server/sysupdate/backend_dnf.go
Normal file
@@ -0,0 +1,108 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user