// The flatpak module's tools (novox/hq research 027/02, 026/05): the applications and runtimes in // both installations, the remotes, pending updates, what nothing uses any more and the space it all // takes; and installing, removing and updating. A Go bundle the node's runtime launches over stdio // (ADR 0188, ADR 0193); it runs as the operator account. An act on the system installation goes // through `sudo -n`; one on the account's own installation does not. package main import ( "fmt" "os" stdio "git.novox.be/novox/mesh-sdk/go" ) var providedBy = map[string]string{ "flatpak": "the flatpak package, which this module installs", "du": "the coreutils package", } func main() { if err := stdio.Serve("", tools()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } var installationArg = map[string]any{"type": "string", "enum": []string{"system", "user"}, "description": "the system installation (default), or the account's own"} func installationOf(args map[string]any, def string) (string, error) { i, err := optText(args, "installation", def) if err != nil { return "", err } if i == "" { return "", nil } return i, oneOf("installation", i, "system", "user") } func refArg(args map[string]any, key string) (string, error) { r, err := text(args, key) if err != nil { return "", err } return r, checkRef(r) } func tools() []stdio.Tool { return []stdio.Tool{ { Name: "flatpak_list", Description: "The installed applications, in both installations or one: id, name, version, branch, origin, " + "installation and size. (r)", Input: map[string]any{"installation": installationArg}, Run: func(args map[string]any) (any, error) { inst, err := installationOf(args, "") if err != nil { return nil, err } return List("app", inst) }, }, { Name: "flatpak_runtimes", Description: "The installed runtimes and extensions, in both installations or one: id, branch, origin, installation and size. (r)", Input: map[string]any{"installation": installationArg}, Run: func(args map[string]any) (any, error) { inst, err := installationOf(args, "") if err != nil { return nil, err } return List("runtime", inst) }, }, { Name: "flatpak_remotes", Description: "The remotes of both installations, with how many installed refs come from each, and findings: " + "Flathub missing from the system installation, the same remote in both installations, a remote nothing " + "is installed from. (r)", Input: map[string]any{}, Run: func(map[string]any) (any, error) { return Remotes() }, }, { Name: "flatpak_updates", Description: "What an update would change: each ref with a newer commit on its remote. Asks the remotes, so it needs the network. (r)", Input: map[string]any{"installation": installationArg}, Run: func(args map[string]any) (any, error) { inst, err := installationOf(args, "") if err != nil { return nil, err } return Updates(inst) }, }, { Name: "flatpak_unused", Description: "The runtimes and extensions no installed application needs any more, computed without changing " + "anything: a runtime is used when an application names it as its runtime or SDK, when it fills an " + "extension point of something used, or when it is pinned. With the space each takes. (r)", Input: map[string]any{}, Run: func(map[string]any) (any, error) { return Unused() }, }, { Name: "flatpak_disk_usage", Description: "The space flatpak takes: each installation's directory on disk, and the applications and " + "runtimes by size, largest first. (r)", Input: map[string]any{}, Run: func(map[string]any) (any, error) { return DiskUsage() }, }, { Name: "flatpak_install", Description: "Install an application or runtime from a remote (default flathub), in the system installation " + "(default) or the account's. Answers when finished, or after 18 s with a job to follow with flatpak_job. (a)", Input: map[string]any{ "ref": map[string]any{"type": "string", "description": "an application id such as org.gimp.GIMP, or a full ref"}, "remote": map[string]any{"type": "string", "description": "the remote (default flathub)"}, "installation": installationArg, }, Run: func(args map[string]any) (any, error) { ref, err := refArg(args, "ref") if err != nil { return nil, err } remote, err := optText(args, "remote", "flathub") if err != nil { return nil, err } inst, err := installationOf(args, "system") if err != nil { return nil, err } return Install(ref, remote, inst) }, }, { Name: "flatpak_remove", Description: "Uninstall an application or runtime, keeping its data unless delete_data is set. Answers when finished, or with a job to follow. (a)", Input: map[string]any{ "ref": map[string]any{"type": "string", "description": "the application id or ref"}, "installation": installationArg, "delete_data": map[string]any{"type": "boolean", "description": "remove the application's data in the home too"}, }, Run: func(args map[string]any) (any, error) { ref, err := refArg(args, "ref") if err != nil { return nil, err } inst, err := installationOf(args, "system") if err != nil { return nil, err } del, err := optFlag(args, "delete_data", false) if err != nil { return nil, err } return Remove(ref, inst, del) }, }, { Name: "flatpak_update", Description: "Update one ref, or everything in an installation when no ref is given. Answers when finished, or with a job to follow. (a)", Input: map[string]any{ "ref": map[string]any{"type": "string", "description": "the application id or ref (default all)"}, "installation": installationArg, }, Run: func(args map[string]any) (any, error) { ref, err := optText(args, "ref", "") if err != nil { return nil, err } if ref != "" { if err := checkRef(ref); err != nil { return nil, err } } inst, err := installationOf(args, "system") if err != nil { return nil, err } return Update(ref, inst) }, }, { Name: "flatpak_remove_unused", Description: "Uninstall what flatpak itself finds unused in one installation (system by default). " + "flatpak_unused shows what that is beforehand. Answers when finished, or with a job to follow. (a)", Input: map[string]any{"installation": installationArg}, Run: func(args map[string]any) (any, error) { inst, err := installationOf(args, "system") if err != nil { return nil, err } return RemoveUnused(inst) }, }, { Name: "flatpak_job", Description: "A long act this module started: running or finished, its exit status and the end of its output. Without job, every act this process knows. (r)", Input: map[string]any{"job": map[string]any{"type": "string", "description": "the job id an act answered"}}, Run: func(args map[string]any) (any, error) { id, err := optText(args, "job", "") if err != nil { return nil, err } if id == "" { return map[string]any{"jobs": listJobs()}, nil } return jobByID(id) }, }, } }