1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-14 16:22:46 -04:00

refactor(SysUpdate): Flatpak & Cli command handling

This commit is contained in:
purian23
2026-05-07 16:16:10 -04:00
parent 5df2b5fc33
commit 7fb4b6e0d9
3 changed files with 154 additions and 182 deletions
@@ -2,6 +2,7 @@ package sysupdate
import (
"context"
"errors"
"os/exec"
"strings"
)
@@ -20,17 +21,44 @@ func (flatpakBackend) RunsInTerminal() bool { return false }
func (flatpakBackend) IsAvailable(_ context.Context) bool { return commandExists("flatpak") }
func (flatpakBackend) CheckUpdates(ctx context.Context) ([]Package, error) {
cmd := exec.CommandContext(ctx, "flatpak", "remote-ls", "--updates", "--columns=application,version,branch,commit,name")
// Run `flatpak update`
cmd := exec.CommandContext(ctx, "flatpak", "update")
cmd.Stdin = strings.NewReader("n\nn\n") // decline up to 2 installation prompts
out, err := cmd.Output()
if err != nil {
return nil, err
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok && exitErr.ExitCode() == 1 && len(out) > 0 {
} else if len(out) == 0 {
return nil, err
}
}
installed := flatpakInstalled(ctx)
return parseFlatpakUpdates(string(out), installed), nil
return parseFlatpakUpdateOutput(string(out), installed), nil
}
type flatpakInstalledEntry struct {
version string
branch string
}
func flatpakInstalled(ctx context.Context) map[string]flatpakInstalledEntry {
out, err := exec.CommandContext(ctx, "flatpak", "list", "--columns=application,version,branch,active").Output()
m := flatpakListInstalled(ctx, false)
if m == nil {
m = make(map[string]flatpakInstalledEntry)
}
for k, v := range flatpakListInstalled(ctx, true) {
if _, exists := m[k]; !exists {
m[k] = v
}
}
return m
}
func flatpakListInstalled(ctx context.Context, system bool) map[string]flatpakInstalledEntry {
args := []string{"flatpak", "list", "--columns=application,version,branch"}
if system {
args = append(args, "--system")
}
out, err := exec.CommandContext(ctx, args[0], args[1:]...).Output()
if err != nil {
return nil
}
@@ -51,9 +79,6 @@ func flatpakInstalled(ctx context.Context) map[string]flatpakInstalledEntry {
if len(fields) > 2 {
entry.branch = fields[2]
}
if len(fields) > 3 {
entry.commit = fields[3]
}
key := appID
if entry.branch != "" {
key = appID + "//" + entry.branch
@@ -63,12 +88,6 @@ func flatpakInstalled(ctx context.Context) map[string]flatpakInstalledEntry {
return m
}
type flatpakInstalledEntry struct {
version string
branch string
commit string
}
func (flatpakBackend) Upgrade(ctx context.Context, opts UpgradeOptions, onLine func(string)) error {
if opts.DryRun {
return Run(ctx, []string{"flatpak", "update", "--no-deploy", "-y"}, RunOptions{OnLine: onLine})
@@ -83,74 +102,71 @@ func flatpakUpgradeArgv() []string {
return []string{"flatpak", "update", "-y", "--noninteractive"}
}
func parseFlatpakUpdates(text string, installed map[string]flatpakInstalledEntry) []Package {
if text == "" {
return nil
}
func parseFlatpakUpdateOutput(text string, installed map[string]flatpakInstalledEntry) []Package {
var pkgs []Package
seen := make(map[string]bool)
for line := range strings.SplitSeq(text, "\n") {
if line == "" {
p := parseFlatpakUpdateRow(strings.TrimRight(line, "\r"), installed)
if p == nil || seen[p.Ref] {
continue
}
fields := strings.Split(line, "\t")
if len(fields) == 0 || fields[0] == "" {
continue
}
appID := fields[0]
version, branch, commit := "", "", ""
if len(fields) > 1 {
version = fields[1]
}
if len(fields) > 2 {
branch = fields[2]
}
if len(fields) > 3 {
commit = fields[3]
}
display := appID
if len(fields) > 4 && fields[4] != "" {
display = fields[4]
}
key := appID
if branch != "" {
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,
})
seen[p.Ref] = true
pkgs = append(pkgs, *p)
}
return pkgs
}
func flatpakVersionPair(installedVer, installedCommit, remoteVer, remoteCommit string) (from, to string) {
if remoteVer != "" {
return installedVer, remoteVer
func parseFlatpakUpdateRow(line string, installed map[string]flatpakInstalledEntry) *Package {
// Row format: " N.\t<name>\t<appID>\t<branch>\t<op>\t<remote>\t<size>"
fields := strings.Split(line, "\t")
if len(fields) < 5 {
return nil
}
// First field must look like " N." (optional whitespace, digits, period)
rowField := strings.TrimSpace(fields[0])
if len(rowField) < 2 || rowField[len(rowField)-1] != '.' {
return nil
}
for _, c := range rowField[:len(rowField)-1] {
if c < '0' || c > '9' {
return nil
}
}
return shortCommit(installedCommit), shortCommit(remoteCommit)
}
func shortCommit(c string) string {
if len(c) > 8 {
return c[:8]
appID := strings.TrimSpace(fields[2])
branch := strings.TrimSpace(fields[3])
op := strings.TrimSpace(fields[4])
if appID == "" || op == "" {
return nil
}
switch op {
case "i", "u", "r": // install, update, reinstall
default:
return nil
}
ref := appID
if branch != "" {
ref = appID + "//" + branch
}
name := strings.TrimSpace(fields[1])
if name == "" {
name = appID
}
var from string
if op != "i" {
if inst, ok := installed[ref]; ok {
from = inst.version
}
}
return &Package{
Name: name,
Repo: RepoFlatpak,
Backend: "flatpak",
FromVersion: from,
Ref: ref,
}
return c
}