From ce835729946615f71e23cca34cb565297490a464 Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 13 Aug 2026 14:29:48 -0600 Subject: [PATCH] remove hampack app --- desktop/icons/ham.png | Bin 4729 -> 0 bytes hampack-src/go.mod | 8 - hampack-src/main.go | 637 ------------------------------------ hampackremove | 2 - install.sh | 24 +- updates.d/170-hampack-build | 35 -- 6 files changed, 1 insertion(+), 705 deletions(-) delete mode 100644 desktop/icons/ham.png delete mode 100644 hampack-src/go.mod delete mode 100644 hampack-src/main.go delete mode 100644 updates.d/170-hampack-build diff --git a/desktop/icons/ham.png b/desktop/icons/ham.png deleted file mode 100644 index 59c8999c9110fa9c4873952e1d168f19beb251ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4729 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 diff --git a/hampack-src/go.mod b/hampack-src/go.mod deleted file mode 100644 index 37e28f5..0000000 --- a/hampack-src/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module hampack - -go 1.22 - -require ( - github.com/diamondburned/gotk4-adwaita/pkg v0.0.0-20250703085708-8e7f01e2c815 - github.com/diamondburned/gotk4/pkg v0.3.2-0.20250703063411-16654385f59a -) diff --git a/hampack-src/main.go b/hampack-src/main.go deleted file mode 100644 index a4b89be..0000000 --- a/hampack-src/main.go +++ /dev/null @@ -1,637 +0,0 @@ -package main - -import ( - "bufio" - "encoding/json" - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "regexp" - "sort" - "strings" - - "github.com/diamondburned/gotk4-adwaita/pkg/adw" - "github.com/diamondburned/gotk4/pkg/gdk/v4" - "github.com/diamondburned/gotk4/pkg/glib/v2" - "github.com/diamondburned/gotk4/pkg/gtk/v4" -) - -// ── Helpers ──────────────────────────────────────────────────────────────────── - -func homeDir() string { - d, _ := os.UserHomeDir() - return d -} - -func hampackDir() string { - if d := os.Getenv("HAMPACK_DIR"); d != "" { - return d - } - return filepath.Join(homeDir(), ".local/share/HamPack") -} - -func stateFilePath() string { - return filepath.Join(homeDir(), ".local/state/HamPack/selections.json") -} - -func expand(v string) string { - return strings.ReplaceAll(v, "$HOME", homeDir()) -} - -var windowsItems = [][2]string{ - {"VARA HF", filepath.Join(homeDir(), ".wine/drive_c/VARA")}, - {"VARA FM", filepath.Join(homeDir(), ".wine/drive_c/VARA FM")}, - {"VARA Terminal", filepath.Join(homeDir(), ".wine/drive_c/VARA Terminal")}, - {"Winlink Express", filepath.Join(homeDir(), ".wine/drive_c/RMS Express")}, -} - -// ── Config parsing ───────────────────────────────────────────────────────────── - -func parseINI(path string) map[string]map[string]string { - entries := make(map[string]map[string]string) - data, err := os.ReadFile(path) - if err != nil { - return entries - } - var cur string - for _, line := range strings.Split(string(data), "\n") { - line = strings.TrimSpace(line) - if line == "" || strings.HasPrefix(line, "#") { - continue - } - if len(line) > 2 && line[0] == '[' && line[len(line)-1] == ']' { - cur = line[1 : len(line)-1] - entries[cur] = make(map[string]string) - continue - } - if cur == "" { - continue - } - if k, v, ok := strings.Cut(line, "="); ok { - entries[cur][strings.TrimSpace(k)] = strings.TrimSpace(v) - } - } - return entries -} - -func parsePackages() (utils, apps []string) { - path := filepath.Join(hampackDir(), "packages.conf") - cmd := exec.Command("bash", "-c", fmt.Sprintf( - `source '%s' && printf '%%s\n' ${UTILITIES[@]} && echo '---' && printf '%%s\n' ${APPLICATIONS[@]}`, - path)) - out, err := cmd.Output() - if err != nil { - return - } - inApps := false - for _, line := range strings.Split(string(out), "\n") { - line = strings.TrimSpace(line) - if line == "---" { - inApps = true - } else if line != "" { - if inApps { - apps = append(apps, line) - } else { - utils = append(utils, line) - } - } - } - return -} - -func parseFlatpaks() []string { - path := filepath.Join(hampackDir(), "install-flatpaks.sh") - data, err := os.ReadFile(path) - if err != nil { - return nil - } - re := regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*(\.[a-zA-Z][a-zA-Z0-9_-]*){2,}$`) - var ids []string - for _, line := range strings.Split(string(data), "\n") { - s := strings.Trim(strings.TrimSpace(line), `"'`) - if re.MatchString(s) { - ids = append(ids, s) - } - } - return ids -} - -// ── State ────────────────────────────────────────────────────────────────────── - -// installedPacmanPackages returns a set of all installed pacman package names. -func installedPacmanPackages() map[string]bool { - out, err := exec.Command("pacman", "-Q").Output() - if err != nil { - return map[string]bool{} - } - installed := make(map[string]bool) - for _, line := range strings.Split(string(out), "\n") { - if fields := strings.Fields(line); len(fields) > 0 { - installed[fields[0]] = true - } - } - return installed -} - -// installedFlatpaks returns a set of all installed Flatpak application IDs. -func installedFlatpaks() map[string]bool { - out, err := exec.Command("flatpak", "list", "--app", "--columns=application").Output() - if err != nil { - return map[string]bool{} - } - installed := make(map[string]bool) - for _, line := range strings.Split(string(out), "\n") { - if s := strings.TrimSpace(line); s != "" { - installed[s] = true - } - } - return installed -} - -// detectInitialState checks actual installation status for every item. -func detectInitialState( - utils, apps, flatpaks []string, - compiled, binaries map[string]map[string]string, -) map[string]bool { - pacman := installedPacmanPackages() - flatpak := installedFlatpaks() - state := make(map[string]bool) - - for _, name := range utils { - state["utility:"+name] = pacman[name] - } - for _, name := range apps { - state["application:"+name] = pacman[name] - } - for _, id := range flatpaks { - state["flatpak:"+id] = flatpak[id] - } - for name, fields := range compiled { - path := expand(fields["install"]) - _, err := os.Stat(path) - state["compiled:"+name] = err == nil - } - for name, fields := range binaries { - path := expand(fields["install"]) - _, err := os.Stat(path) - state["binary:"+name] = err == nil - } - for _, item := range windowsItems { - _, err := os.Stat(item[1]) - state["windows:"+item[0]] = err == nil - } - - return state -} - -func saveState(state map[string]bool) { - os.MkdirAll(filepath.Dir(stateFilePath()), 0755) - data, _ := json.MarshalIndent(state, "", " ") - os.WriteFile(stateFilePath(), data, 0644) -} - - -// ── Operations ──────────────────────────────────────────────────────────────── - -type Op struct { - Label string - Cmds [][]string - Env []string // nil means inherit os.Environ() - Tmp string // temp file to clean up after the op -} - -func writeTempINI(name string, fields map[string]string) string { - f, err := os.CreateTemp("", "hampack-*.conf") - if err != nil { - return "" - } - defer f.Close() - fmt.Fprintf(f, "[%s]\n", name) - for k, v := range fields { - fmt.Fprintf(f, "%s=%s\n", k, v) - } - return f.Name() -} - -func sortedKeys(m map[string]map[string]string) []string { - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -} - -func computeOps( - oldState, newState map[string]bool, - compiled, binaries map[string]map[string]string, -) []Op { - allKeys := make(map[string]bool) - for k := range oldState { - allKeys[k] = true - } - for k := range newState { - allKeys[k] = true - } - keys := make([]string, 0, len(allKeys)) - for k := range allKeys { - keys = append(keys, k) - } - sort.Strings(keys) - - var ops []Op - windowsInstallAdded := false - - for _, key := range keys { - was := oldState[key] - now := newState[key] - if was == now { - continue - } - parts := strings.SplitN(key, ":", 2) - if len(parts) != 2 { - continue - } - cat, name := parts[0], parts[1] - - if now { // ── install ────────────────────────────────────────────────── - switch cat { - case "utility", "application": - ops = append(ops, Op{ - Label: "Install " + name, - Cmds: [][]string{{"yay", "-S", "--noconfirm", name}}, - }) - case "flatpak": - ops = append(ops, Op{ - Label: "Install " + name, - Cmds: [][]string{{"flatpak", "install", "--noninteractive", "flathub", name}}, - }) - case "compiled": - if fields, ok := compiled[name]; ok { - tmp := writeTempINI(name, fields) - ops = append(ops, Op{ - Label: "Build " + name, - Cmds: [][]string{{"bash", filepath.Join(hampackDir(), "install-compiled.sh")}}, - Env: append(os.Environ(), "HAMPACK_COMPILE_CONF="+tmp), - Tmp: tmp, - }) - } - case "binary": - if fields, ok := binaries[name]; ok { - tmp := writeTempINI(name, fields) - ops = append(ops, Op{ - Label: "Install " + name, - Cmds: [][]string{{"bash", filepath.Join(hampackDir(), "install-binaries.sh")}}, - Env: append(os.Environ(), "HAMPACK_BINARIES_CONF="+tmp), - Tmp: tmp, - }) - } - case "windows": - if !windowsInstallAdded { - ops = append(ops, Op{ - Label: "Install Windows Apps (Wine)", - Cmds: [][]string{{"bash", filepath.Join(hampackDir(), "install-windows-apps.sh")}}, - }) - windowsInstallAdded = true - } - } - } else { // ── uninstall ──────────────────────────────────────────────── - switch cat { - case "utility", "application": - ops = append(ops, Op{ - Label: "Remove " + name, - Cmds: [][]string{{"sudo", "pacman", "-Rns", "--noconfirm", name}}, - }) - case "flatpak": - ops = append(ops, Op{ - Label: "Remove " + name, - Cmds: [][]string{{"flatpak", "uninstall", "--noninteractive", name}}, - }) - case "compiled": - if fields, ok := compiled[name]; ok { - installPath := expand(fields["install"]) - desktopSrc := expand(fields["desktop"]) - cmds := [][]string{{"rm", "-f", installPath}} - if desktopSrc != "" { - cmds = append(cmds, []string{"rm", "-f", desktopSrc}) - } - cmds = append(cmds, []string{"rm", "-f", - filepath.Join(homeDir(), ".local/share/applications", name+".desktop")}) - ops = append(ops, Op{Label: "Remove " + name, Cmds: cmds}) - } - case "binary": - if fields, ok := binaries[name]; ok { - installPath := expand(fields["install"]) - ops = append(ops, Op{ - Label: "Remove " + name, - Cmds: [][]string{ - {"rm", "-f", installPath}, - {"rm", "-f", filepath.Join(homeDir(), ".local/share/applications", name+".desktop")}, - }, - }) - } - case "windows": - for _, item := range windowsItems { - if item[0] == name { - ops = append(ops, Op{ - Label: "Remove " + name, - Cmds: [][]string{{"rm", "-rf", item[1]}}, - }) - break - } - } - } - } - } - return ops -} - -// ── Output window ───────────────────────────────────────────────────────────── - -type outputWin struct { - *gtk.Window - buf *gtk.TextBuffer - tv *gtk.TextView - endMark *gtk.TextMark - closeBtn *gtk.Button -} - -func newOutputWin(ops []Op, onDone func()) *outputWin { - w := &outputWin{Window: gtk.NewWindow()} - w.SetTitle("Applying Changes") - w.SetDefaultSize(680, 500) - - toolbar := adw.NewToolbarView() - w.SetChild(toolbar) - - header := adw.NewHeaderBar() - header.SetShowEndTitleButtons(false) - toolbar.AddTopBar(header) - - w.closeBtn = gtk.NewButtonWithLabel("Close") - w.closeBtn.SetSensitive(false) - w.closeBtn.ConnectClicked(func() { w.Close() }) - header.PackEnd(w.closeBtn) - - scroll := gtk.NewScrolledWindow() - scroll.SetPolicy(gtk.PolicyAutomatic, gtk.PolicyAlways) - scroll.SetVExpand(true) - scroll.SetHExpand(true) - - w.buf = gtk.NewTextBuffer(nil) - endIter := w.buf.EndIter() - w.endMark = w.buf.CreateMark("end", endIter, false) - - w.tv = gtk.NewTextView() - w.tv.SetBuffer(w.buf) - w.tv.SetEditable(false) - w.tv.SetCursorVisible(false) - w.tv.SetMonospace(true) - w.tv.SetLeftMargin(12) - w.tv.SetRightMargin(12) - w.tv.SetTopMargin(8) - w.tv.SetBottomMargin(8) - w.tv.SetWrapMode(gtk.WrapWordChar) - scroll.SetChild(w.tv) - toolbar.SetContent(scroll) - - go w.run(ops, onDone) - return w -} - -func (w *outputWin) append(text string) { - glib.IdleAdd(func() bool { - iter := w.buf.EndIter() - w.buf.Insert(iter, text) - w.tv.ScrollToMark(w.endMark, 0, false, 0, 1) - return false - }) -} - -func (w *outputWin) runCmd(cmd, env []string) bool { - w.append(fmt.Sprintf("$ %s\n", strings.Join(cmd, " "))) - - c := exec.Command(cmd[0], cmd[1:]...) - c.Dir = hampackDir() - if env != nil { - c.Env = env - } - - pr, pw := io.Pipe() - c.Stdout = pw - c.Stderr = pw - - scanDone := make(chan struct{}) - go func() { - defer close(scanDone) - scanner := bufio.NewScanner(pr) - for scanner.Scan() { - w.append(scanner.Text() + "\n") - } - }() - - if err := c.Start(); err != nil { - pw.Close() - <-scanDone - pr.Close() - w.append(fmt.Sprintf("Error: %v\n", err)) - return false - } - - err := c.Wait() - pw.Close() - <-scanDone - pr.Close() - - if err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - w.append(fmt.Sprintf("[exit %d]\n", exitErr.ExitCode())) - } - return false - } - return true -} - -func (w *outputWin) run(ops []Op, onDone func()) { - success := true - for _, op := range ops { - w.append(fmt.Sprintf("\n── %s ──\n", op.Label)) - for _, cmd := range op.Cmds { - if !w.runCmd(cmd, op.Env) { - success = false - } - } - if op.Tmp != "" { - os.Remove(op.Tmp) - } - } - if success { - w.append("\n── Done ──\n") - } else { - w.append("\n── Completed with errors ──\n") - } - glib.IdleAdd(func() bool { - w.closeBtn.SetSensitive(true) - onDone() - return false - }) -} - -// ── Main window ─────────────────────────────────────────────────────────────── - -type mainWin struct { - *adw.ApplicationWindow - compiled map[string]map[string]string - binaries map[string]map[string]string - state map[string]bool - rows map[string]*gtk.Switch - applyBtn *gtk.Button - updateBtn *gtk.Button -} - -func newMainWin(app *adw.Application) *mainWin { - compiled := parseINI(filepath.Join(hampackDir(), "compile.conf")) - binaries := parseINI(filepath.Join(hampackDir(), "binaries.conf")) - utils, apps := parsePackages() - flatpaks := parseFlatpaks() - - w := &mainWin{ - ApplicationWindow: adw.NewApplicationWindow(&app.Application), - compiled: compiled, - binaries: binaries, - state: detectInitialState(utils, apps, flatpaks, compiled, binaries), - rows: make(map[string]*gtk.Switch), - } - w.SetTitle("HamPack Manager") - w.SetDefaultSize(600, 720) - - toolbar := adw.NewToolbarView() - w.SetContent(toolbar) - - header := adw.NewHeaderBar() - toolbar.AddTopBar(header) - - w.applyBtn = gtk.NewButtonWithLabel("Apply Changes") - w.applyBtn.AddCSSClass("suggested-action") - w.applyBtn.ConnectClicked(func() { w.onApply() }) - header.PackEnd(w.applyBtn) - - w.updateBtn = gtk.NewButtonWithLabel("Run Update") - w.updateBtn.ConnectClicked(func() { w.onUpdate() }) - header.PackStart(w.updateBtn) - - page := adw.NewPreferencesPage() - toolbar.SetContent(page) - - windows := make([]string, len(windowsItems)) - for i, item := range windowsItems { - windows[i] = item[0] - } - - w.makeGroup(page, "System Utilities", "utility", utils) - w.makeGroup(page, "AUR Applications", "application", apps) - w.makeGroup(page, "Flatpaks", "flatpak", flatpaks) - w.makeGroup(page, "Compiled from Source", "compiled", sortedKeys(w.compiled)) - w.makeGroup(page, "Pre-built Binaries", "binary", sortedKeys(w.binaries)) - w.makeGroup(page, "Windows Apps (Wine)", "windows", windows) - - return w -} - -func (w *mainWin) makeGroup(page *adw.PreferencesPage, title, cat string, names []string) { - if len(names) == 0 { - return - } - group := adw.NewPreferencesGroup() - group.SetTitle(title) - page.Add(group) - - var actionRows []*adw.ActionRow - for _, name := range names { - key := cat + ":" + name - row := adw.NewActionRow() - row.SetTitle(name) - sw := gtk.NewSwitch() - sw.SetVAlign(gtk.AlignCenter) - sw.SetActive(w.state[key]) - row.AddSuffix(sw) - row.SetActivatableWidget(sw) - group.Add(row) - w.rows[key] = sw - actionRows = append(actionRows, row) - } - - expanded := true - chevron := gtk.NewImageFromIconName("pan-down-symbolic") - toggleBtn := gtk.NewButton() - toggleBtn.SetChild(chevron) - toggleBtn.AddCSSClass("flat") - toggleBtn.ConnectClicked(func() { - expanded = !expanded - for _, row := range actionRows { - row.SetVisible(expanded) - } - if expanded { - chevron.SetFromIconName("pan-down-symbolic") - } else { - chevron.SetFromIconName("pan-end-symbolic") - } - }) - group.SetHeaderSuffix(toggleBtn) -} - -func (w *mainWin) onApply() { - newState := make(map[string]bool, len(w.rows)) - for k, sw := range w.rows { - newState[k] = sw.Active() - } - - ops := computeOps(w.state, newState, w.compiled, w.binaries) - - if len(ops) == 0 { - dlg := adw.NewAlertDialog("No changes", "Nothing to install or remove.") - dlg.AddResponse("ok", "OK") - dlg.Present(w) - return - } - - w.applyBtn.SetSensitive(false) - - out := newOutputWin(ops, func() { - w.state = newState - saveState(w.state) - w.applyBtn.SetSensitive(true) - }) - out.Present() -} - -func (w *mainWin) onUpdate() { - w.updateBtn.SetSensitive(false) - w.applyBtn.SetSensitive(false) - - ops := []Op{{ - Label: "Run Update", - Cmds: [][]string{{"bash", "-c", "wget -qO- https://gitea.young.computer/david/hampack/raw/branch/main/install.sh | bash"}}, - Env: append(os.Environ(), "TERM=xterm"), - }} - - newOutputWin(ops, func() { - w.updateBtn.SetSensitive(true) - w.applyBtn.SetSensitive(true) - }).Present() -} - -// ── Main ────────────────────────────────────────────────────────────────────── - -func main() { - app := adw.NewApplication("computer.young.HamPack", 0) - app.ConnectActivate(func() { - iconTheme := gtk.IconThemeGetForDisplay(gdk.DisplayGetDefault()) - iconTheme.AddSearchPath(filepath.Join(hampackDir(), "desktop", "icons")) - gtk.WindowSetDefaultIconName("computer.young.HamPack") - newMainWin(app).Present() - }) - os.Exit(app.Run(os.Args)) -} diff --git a/hampackremove b/hampackremove index d3c08bc..f7a97a1 100755 --- a/hampackremove +++ b/hampackremove @@ -64,7 +64,6 @@ echo "Removing HamPack scripts and binaries..." rm -f ~/.local/bin/hampackrefresh rm -f ~/.local/bin/hampackupdate rm -f ~/.local/bin/hampackcheck -rm -f ~/.local/bin/hampack rm -f ~/.local/bin/dx.py # Uninstall not1mm @@ -160,7 +159,6 @@ rm -rf "$HOME/.wine/drive_c/RMS Express" # Remove desktop files echo "Removing desktop files..." -rm -f ~/.local/share/applications/hampack.desktop rm -f ~/.local/share/applications/js8call.desktop rm -f ~/.local/share/applications/yaac.desktop rm -f ~/.local/share/applications/potacat.desktop diff --git a/install.sh b/install.sh index 1b2c5da..b33aa5b 100755 --- a/install.sh +++ b/install.sh @@ -86,30 +86,8 @@ echo "Installing dx.py..." wget -q https://raw.githubusercontent.com/HB9VQQ/dx.py/main/dx.py -O "$HOME/.local/bin/dx.py" chmod +x "$HOME/.local/bin/dx.py" -echo "Building HamPack..." -cd ~/.local/share/HamPack/hampack-src -go get github.com/diamondburned/gotk4-adwaita/pkg/adw@latest -go get github.com/diamondburned/gotk4/pkg/gtk/v4@latest -go mod tidy -go build -o ~/.local/bin/hampack . -cd ~/.local/share/HamPack - -echo "Installing HamPack desktop file..." -mkdir -p ~/.local/share/applications -mkdir -p ~/.local/share/HamPack/desktop/icons/hicolor/256x256/apps -cp ~/.local/share/HamPack/desktop/icons/ham.png \ - ~/.local/share/HamPack/desktop/icons/hicolor/256x256/apps/computer.young.HamPack.png -cat > ~/.local/share/applications/hampack.desktop << EOF -[Desktop Entry] -Type=Application -Name=HamPack -Exec=$HOME/.local/bin/hampack -Icon=$HOME/.local/share/HamPack/desktop/icons/ham.png -Comment=Manage HamPack amateur radio software -Categories=HamRadio; -EOF - echo "Installing JS8Call desktop file..." +mkdir -p ~/.local/share/applications sed "s|\$HOME|$HOME|g" ~/.local/share/HamPack/desktop/js8call.desktop \ > ~/.local/share/applications/js8call.desktop diff --git a/updates.d/170-hampack-build b/updates.d/170-hampack-build deleted file mode 100644 index d2e90f2..0000000 --- a/updates.d/170-hampack-build +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# /etc/coredesktop/updaters.d/170-hampack-build - -HAMPACK_DIR="$HOME/.local/share/HamPack" - -is_installed() { - [[ -d "$HAMPACK_DIR/hampack-src" ]] && command -v go &>/dev/null -} - -run_update() { - echo "→ Rebuilding HamPack..." - cd "$HAMPACK_DIR/hampack-src" - go get github.com/diamondburned/gotk4-adwaita/pkg/adw@latest - go get github.com/diamondburned/gotk4/pkg/gtk/v4@latest - go mod tidy - go build -o "$HOME/.local/bin/hampack" . - cd "$HAMPACK_DIR" - - echo "→ Updating desktop files..." - mkdir -p "$HOME/.local/share/applications" - cat > "$HOME/.local/share/applications/hampack.desktop" << EOF -[Desktop Entry] -Type=Application -Name=HamPack -Exec=$HOME/.local/bin/hampack -Icon=$HOME/.local/share/HamPack/desktop/icons/ham.png -Comment=Manage HamPack amateur radio software -Categories=HamRadio; -EOF - sed "s|\$HOME|$HOME|g" "$HAMPACK_DIR/desktop/js8call.desktop" \ - > "$HOME/.local/share/applications/js8call.desktop" - update-desktop-database "$HOME/.local/share/applications/" - - echo "✓ HamPack built and desktop files updated." -}