1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-30 01:22:06 -04:00

system update: general fixes to flatpak parsing

This commit is contained in:
bbedward
2026-04-29 16:14:19 -04:00
parent f76724f7cd
commit 86096db26b
11 changed files with 159 additions and 25 deletions

View File

@@ -45,7 +45,11 @@ func (aptBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine func(
OnLine: onLine,
})
}
argv := []string{"pkexec", "env", "DEBIAN_FRONTEND=noninteractive", "LC_ALL=C", bin, "upgrade", "-y"}
names := pickTargetNames(opts.Targets, "apt", true)
if len(names) == 0 {
return nil
}
argv := append([]string{"pkexec", "env", "DEBIAN_FRONTEND=noninteractive", "LC_ALL=C", bin, "install", "-y", "--only-upgrade"}, names...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}

View File

@@ -45,7 +45,12 @@ func (b dnfBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine fun
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})
names := pickTargetNames(opts.Targets, b.bin, true)
if len(names) == 0 {
return nil
}
argv := append([]string{"pkexec", b.bin, "upgrade", "-y"}, names...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}
func dnfListUpgrades(ctx context.Context, bin string) (string, error) {
@@ -88,14 +93,14 @@ func parseDnfList(text, backendID string, installed map[string]string) []Package
}
nameArch := fields[0]
version := fields[1]
switch nameArch {
case "Available", "Upgrades":
dot := strings.LastIndex(nameArch, ".")
if dot <= 0 {
continue
}
name := nameArch
if dot := strings.LastIndex(nameArch, "."); dot > 0 {
name = nameArch[:dot]
if !looksLikeRpmVersion(version) {
continue
}
name := nameArch[:dot]
pkgs = append(pkgs, Package{
Name: nameArch,
Repo: RepoSystem,
@@ -106,3 +111,15 @@ func parseDnfList(text, backendID string, installed map[string]string) []Package
}
return pkgs
}
func looksLikeRpmVersion(s string) bool {
if s == "" {
return false
}
for _, r := range s {
if r >= '0' && r <= '9' {
return true
}
}
return false
}

View File

@@ -56,12 +56,15 @@ bash.x86_64 5.2.40-1.fc41 updates`,
want: nil,
},
{
name: "package without arch suffix",
input: "noarchpkg 1.2.3 updates",
name: "skips dnf5 banner / column header lines",
input: `Updates available
Last metadata expiration check: 0:01:23 ago on Tue Apr 29 14:00:00 2026.
Package Version Repository Size
bash.x86_64 5.2.40-1.fc41 updates`,
backendID: "dnf",
installed: map[string]string{"noarchpkg": "1.2.0"},
installed: nil,
want: []Package{
{Name: "noarchpkg", Repo: RepoSystem, Backend: "dnf", FromVersion: "1.2.0", ToVersion: "1.2.3"},
{Name: "bash.x86_64", Repo: RepoSystem, Backend: "dnf", FromVersion: "", ToVersion: "5.2.40-1.fc41"},
},
},
}

View File

@@ -70,13 +70,32 @@ type flatpakInstalledEntry struct {
}
func (flatpakBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine func(string)) error {
argv := []string{"flatpak", "update", "-y", "--noninteractive"}
if opts.DryRun {
argv = []string{"flatpak", "update", "--no-deploy", "-y"}
return Run(ctx, []string{"flatpak", "update", "--no-deploy", "-y"}, RunOptions{OnLine: onLine})
}
refs := flatpakTargetRefs(opts.Targets)
if len(refs) == 0 {
return nil
}
argv := append([]string{"flatpak", "update", "-y", "--noninteractive"}, refs...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}
func flatpakTargetRefs(targets []Package) []string {
out := make([]string, 0, len(targets))
for _, p := range targets {
if p.Backend != "flatpak" {
continue
}
ref := p.Ref
if ref == "" {
ref = p.Name
}
out = append(out, ref)
}
return out
}
func parseFlatpakUpdates(text string, installed map[string]flatpakInstalledEntry) []Package {
if text == "" {
return nil
@@ -111,14 +130,25 @@ func parseFlatpakUpdates(text string, installed map[string]flatpakInstalledEntry
key = appID + "//" + branch
}
inst := installed[key]
if inst.commit != "" && commit != "" && strings.HasPrefix(commit, inst.commit) {
continue
}
from, to := flatpakVersionPair(inst.version, inst.commit, version, commit)
ref := appID
if branch != "" {
ref = appID + "//" + branch
}
pkgs = append(pkgs, Package{
Name: display,
Repo: RepoFlatpak,
Backend: "flatpak",
FromVersion: from,
ToVersion: to,
Ref: ref,
})
}
return pkgs

View File

@@ -31,6 +31,7 @@ func TestParseFlatpakUpdates(t *testing.T) {
Backend: "flatpak",
FromVersion: "8b16fa1a",
ToVersion: "43a1e5d2",
Ref: "com.discordapp.Discord//stable",
},
},
},
@@ -47,6 +48,7 @@ func TestParseFlatpakUpdates(t *testing.T) {
Backend: "flatpak",
FromVersion: "1.4.2",
ToVersion: "1.5.0",
Ref: "com.example.App//stable",
},
},
},
@@ -61,6 +63,7 @@ func TestParseFlatpakUpdates(t *testing.T) {
Backend: "flatpak",
FromVersion: "",
ToVersion: "badcd4af",
Ref: "org.gnome.Platform//49",
},
},
},
@@ -74,6 +77,7 @@ func TestParseFlatpakUpdates(t *testing.T) {
Backend: "flatpak",
FromVersion: "",
ToVersion: "2.0",
Ref: "com.example.NoName//stable",
},
},
},
@@ -87,9 +91,18 @@ func TestParseFlatpakUpdates(t *testing.T) {
Backend: "flatpak",
FromVersion: "",
ToVersion: "1.0",
Ref: "org.real.App//stable",
},
},
},
{
name: "skips phantom updates where remote commit matches installed",
input: "com.phantom.App\t\tstable\tabc12345deadbeef\tPhantom",
installed: map[string]flatpakInstalledEntry{
"com.phantom.App//stable": {commit: "abc12345"},
},
want: nil,
},
}
for _, tt := range tests {

View File

@@ -43,7 +43,12 @@ func (b pacmanBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine
if opts.DryRun {
return Run(ctx, []string{"pacman", "-Sup"}, RunOptions{OnLine: onLine})
}
return Run(ctx, []string{"pkexec", "pacman", "-Syu", "--noconfirm"}, RunOptions{OnLine: onLine})
names := pickTargetNames(opts.Targets, b.ID(), opts.IncludeAUR)
if len(names) == 0 {
return nil
}
argv := append([]string{"pkexec", "pacman", "-Sy", "--noconfirm", "--needed"}, names...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}
type archHelperBackend struct {
@@ -53,7 +58,9 @@ type archHelperBackend struct {
func (b archHelperBackend) ID() string { return b.id }
func (b archHelperBackend) Repo() RepoKind { return RepoSystem }
func (b archHelperBackend) NeedsAuth() bool { return true }
func (b archHelperBackend) RunsInTerminal() bool { return true }
func (b archHelperBackend) RunsInTerminal() bool {
return os.Getenv("DMS_FORCE_PKEXEC") != "1"
}
func (b archHelperBackend) IsAvailable(_ context.Context) bool { return commandExists(b.id) }
func (b archHelperBackend) DisplayName() string {
@@ -86,18 +93,37 @@ func (b archHelperBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onL
if opts.DryRun {
return Run(ctx, []string{b.id, "-Sup"}, RunOptions{OnLine: onLine})
}
names := pickTargetNames(opts.Targets, b.id, opts.IncludeAUR)
if len(names) == 0 {
return nil
}
if os.Getenv("DMS_FORCE_PKEXEC") == "1" {
argv := append([]string{"pkexec", b.id, "-Sy", "--noconfirm", "--needed"}, names...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}
term := findTerminal(opts.Terminal)
if term == "" {
return fmt.Errorf("no terminal found (pick one in DMS settings, set $TERMINAL, or install kitty/ghostty/foot/alacritty)")
}
cmd := fmt.Sprintf("%s -Syu", b.id)
if !opts.IncludeAUR {
cmd += " --repo"
}
cmd := fmt.Sprintf("%s -Sy --noconfirm --needed %s", b.id, strings.Join(names, " "))
title := fmt.Sprintf("DMS — System Update (%s)", b.id)
return Run(ctx, wrapInTerminal(term, title, cmd), RunOptions{OnLine: onLine})
}
func pickTargetNames(targets []Package, backendID string, includeAUR bool) []string {
out := make([]string, 0, len(targets))
for _, p := range targets {
if p.Backend != backendID {
continue
}
if !includeAUR && p.Repo == RepoAUR {
continue
}
out = append(out, p.Name)
}
return out
}
func pacmanRepoUpdates(ctx context.Context) (string, error) {
if commandExists("checkupdates") {
return capturePermissive(ctx, "checkupdates")

View File

@@ -74,5 +74,10 @@ func (zypperBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine fu
if opts.DryRun {
return Run(ctx, []string{"zypper", "--non-interactive", "--dry-run", "update"}, RunOptions{OnLine: onLine})
}
return Run(ctx, []string{"pkexec", "zypper", "--non-interactive", "update"}, RunOptions{OnLine: onLine})
names := pickTargetNames(opts.Targets, "zypper", true)
if len(names) == 0 {
return nil
}
argv := append([]string{"pkexec", "zypper", "--non-interactive", "update"}, names...)
return Run(ctx, argv, RunOptions{OnLine: onLine})
}

View File

@@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"sync"
"syscall"
)
type RunOptions struct {
@@ -24,6 +25,13 @@ func Run(ctx context.Context, argv []string, opts RunOptions) error {
if len(opts.Env) > 0 {
cmd.Env = append(cmd.Environ(), opts.Env...)
}
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
if cmd.Process == nil {
return nil
}
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
}
stdout, err := cmd.StdoutPipe()
if err != nil {

View File

@@ -309,6 +309,12 @@ func (m *Manager) runUpgrade(ctx context.Context, opts UpgradeOptions) {
return
}
if len(opts.Targets) == 0 {
m.mu.RLock()
opts.Targets = append([]Package(nil), m.state.Packages...)
m.mu.RUnlock()
}
opID := fmt.Sprintf("op-%d", time.Now().UnixNano())
m.mu.Lock()
m.state.Phase = PhaseUpgrading

View File

@@ -38,6 +38,7 @@ type Package struct {
ToVersion string `json:"toVersion,omitempty"`
SizeBytes int64 `json:"sizeBytes,omitempty"`
ChangelogURL string `json:"changelogUrl,omitempty"`
Ref string `json:"-"`
}
type BackendInfo struct {
@@ -77,6 +78,7 @@ type UpgradeOptions struct {
DryRun bool
CustomCommand string
Terminal string
Targets []Package
}
type RefreshOptions struct {

View File

@@ -1,4 +1,5 @@
import QtQuick
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
@@ -17,6 +18,21 @@ DankPopout {
property bool _reopenAfterUpgrade: false
readonly property bool polkitModalOpen: PopoutService.polkitAuthModal?.visible ?? false
readonly property bool anyModalOpen: polkitModalOpen
backgroundInteractive: !anyModalOpen
customKeyboardFocus: {
if (!shouldBeVisible)
return WlrKeyboardFocus.None;
if (anyModalOpen)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
Connections {
target: SystemUpdateService
function onIsUpgradingChanged() {
@@ -38,7 +54,11 @@ DankPopout {
screen: triggerScreen
shouldBeVisible: false
onBackgroundClicked: close()
onBackgroundClicked: {
if (anyModalOpen)
return;
close();
}
onShouldBeVisibleChanged: {
if (!shouldBeVisible) {
@@ -290,7 +310,7 @@ DankPopout {
}
}
font.pixelSize: Theme.fontSizeMedium
color: SystemUpdateService.hasError ? Theme.errorText : Theme.surfaceText
color: SystemUpdateService.hasError ? Theme.error : Theme.surfaceText
wrapMode: Text.WordWrap
}