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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user