From 808a66a670d4456b69b60437173e4899fc11a38e Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 23 Aug 2026 16:23:05 +0200 Subject: [PATCH] Add tmog-bin, the TMOG system monitor TMOG ships no source and no AUR package, so this repackages the vendor's Linux tarball. That artifact is 7.9 MB against the system Qt, where the AppImage is 55 MB carrying a second copy of the Qt the shell already installs. Every release is served from one versionless URL, so .omarchy/upstream.sh reads /version.txt, computes the checksum from the artifact, and checks the tarball's own directory name to confirm the mutable path really served the version it announced. The beta licence forbids public redistribution, so publishing this needs the publisher's permission; .omarchy/README.md records that. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011K4ra2oZTtzUQZJ2kwP3io --- pkgbuilds/tmog-bin/.omarchy/README.md | 75 ++++++++++++++++++++++++ pkgbuilds/tmog-bin/.omarchy/package.json | 3 + pkgbuilds/tmog-bin/.omarchy/upstream.sh | 54 +++++++++++++++++ pkgbuilds/tmog-bin/PKGBUILD | 71 ++++++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 pkgbuilds/tmog-bin/.omarchy/README.md create mode 100644 pkgbuilds/tmog-bin/.omarchy/package.json create mode 100755 pkgbuilds/tmog-bin/.omarchy/upstream.sh create mode 100644 pkgbuilds/tmog-bin/PKGBUILD diff --git a/pkgbuilds/tmog-bin/.omarchy/README.md b/pkgbuilds/tmog-bin/.omarchy/README.md new file mode 100644 index 0000000..9c862f3 --- /dev/null +++ b/pkgbuilds/tmog-bin/.omarchy/README.md @@ -0,0 +1,75 @@ +# tmog-bin - repackaging a vendor tarball from a versionless URL + +## Overview + +[TMOG](https://tmog.org/) is a Qt 6 system monitor from Plummers' Software LLC. +There is no source release, no AUR package, and the GitHub repository its +AppStream metadata names (`PlummersSoftwareLLC/TMOG`) is not public, so this +package repackages the vendor's own Linux tarball. + +## Why the tarball and not the AppImage + +Upstream publishes three Linux artifacts at the same version. The tarball is +7.9 MB and links against the system Qt; the AppImage is 55 MB because it carries +its own copy of Qt, which Omarchy already installs for the shell. The `.deb` +holds the same tree as the tarball under Debian's layout. The tarball is the +same binary at a seventh of the download, so that is what this builds from. + +Its layout is already FHS-shaped (`bin/`, `share/applications`, `share/icons`, +`share/metainfo`), so `package()` is a copy rather than a reconstruction. Only +the licence texts move: upstream files them under `share/doc/`, which is +Debian's convention, and on Arch they belong in `share/licenses/`. + +## Before this ships publicly + +The beta licence in `share/doc/taskmanagerog/copyright` says: + +> You may not sell, sublicense, publicly redistribute, or represent the +> software as your own. + +Building this package on pkgs.omarchy.org and serving it to users is public +redistribution, so the package needs Plummers' Software's permission before it +is published, not merely a working build. The same file also describes itself as +"a release-candidate document [that] must be approved by the publisher before +public distribution", so the terms themselves may still move. + +Nothing in the packaging depends on the answer -- it is a question for the +publisher, and it is recorded here so it is not mistaken for settled. + +## The versionless download URL + +Every TMOG release is served from one path: + +```text +https://tmog.org/downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz +``` + +Nothing in it identifies a version, and `downloads/release.json` -- the manifest +the macOS updater verifies -- describes the DMG only. So the Linux side has no +manifest to read a checksum out of, and `.omarchy/upstream.sh` computes one from +the artifact. That download is 7.9 MB and happens only when `/version.txt` +reports something other than the checked-in `pkgver`, so the six-hourly check +normally costs a single small request. + +Two details follow from the path being mutable: + +- **The `?v=-free` query string** in `source=()` is upstream's own + cache key; tmog.org appends it to its Linux download links for the same + reason, so a CDN holding an older object under this path cannot answer for a + new release. +- **The hook checks the tarball's top-level directory**, which upstream names + `TaskManagerOG--linux-x86_64`. It is the only evidence available that + the bytes that arrived are the release `/version.txt` announced. On a mismatch + the hook reports no update and leaves the package alone, which is the right + answer whether the cause is a half-published release or a stale object. + +`sha256sums` is reported under the key `any` rather than `x86_64`: upstream +publishes no aarch64 build, so the package has one plain `source=()` array, and +`any` is `bin/sync-upstream`'s name for the unsuffixed checksum array. + +## Testing + +```bash +bin/sync-upstream tmog-bin +bin/repo build --package tmog-bin +``` diff --git a/pkgbuilds/tmog-bin/.omarchy/package.json b/pkgbuilds/tmog-bin/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/tmog-bin/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/tmog-bin/.omarchy/upstream.sh b/pkgbuilds/tmog-bin/.omarchy/upstream.sh new file mode 100755 index 0000000..4635f63 --- /dev/null +++ b/pkgbuilds/tmog-bin/.omarchy/upstream.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# TMOG publishes no manifest for its Linux builds -- release.json describes the +# macOS DMG only -- so the version comes from /version.txt and the checksum has +# to be computed from the artifact itself. That is 8 MB, and only when the +# version has actually moved, so the six-hourly check normally costs one tiny +# request. +# +# The download path carries no version, which makes it worth proving that what +# arrived is what was announced: the tarball's top-level directory is named for +# the release, and a mismatch means the object served is not the one +# /version.txt describes. Reporting no update leaves the checked-in package +# alone and lets the next run try again, which is the right answer whether the +# cause is a half-published release or a stale CDN object. +set -euo pipefail + +BASE_URL="https://tmog.org" + +current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") + +version=$(curl -fsSL "$BASE_URL/version.txt" | tr -d '[:space:]') +if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Unusable version from $BASE_URL/version.txt: '$version'" >&2 + exit 1 +fi + +if [[ $version == "$current" ]]; then + echo '{}' + exit 0 +fi + +tarball=$(mktemp) +trap 'rm -f "$tarball"' EXIT + +curl -fsSL -o "$tarball" \ + "$BASE_URL/downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz?v=${version}-free" + +# Every entry is listed rather than just the first: `head -1` would close the +# pipe under `tar` and take the whole hook down with SIGPIPE, and reading them +# all also catches a tarball that unpacks more than one top-level directory. +expected_dir="TaskManagerOG-${version}-linux-x86_64" +served_dir=$(tar tzf "$tarball" | cut -d/ -f1 | sort -u) +if [[ $served_dir != "$expected_dir" ]]; then + echo "Download holds $served_dir, but /version.txt announced $version; skipping" >&2 + echo '{}' + exit 0 +fi + +# "any" is bin/sync-upstream's name for the unsuffixed sha256sums array, which +# is the one this package has: upstream publishes x86_64 alone, so there is a +# single plain source=() rather than per-architecture arrays. +jq -n \ + --arg pkgver "$version" \ + --arg sha256 "$(sha256sum "$tarball" | cut -d' ' -f1)" \ + '{pkgver: $pkgver, sha256sums: {any: [$sha256]}}' diff --git a/pkgbuilds/tmog-bin/PKGBUILD b/pkgbuilds/tmog-bin/PKGBUILD new file mode 100644 index 0000000..9856cb4 --- /dev/null +++ b/pkgbuilds/tmog-bin/PKGBUILD @@ -0,0 +1,71 @@ +# Maintainer: David Heinemeier Hansson + +# TMOG publishes no source and no AUR package, so this repackages the vendor's +# Linux tarball. That tarball is 8 MB against the system Qt, where the AppImage +# is 55 MB of bundled Qt -- the same binary, minus a second copy of what +# Omarchy already installs. +# +# The download URL carries no version: tmog.org serves every release from the +# same path. .omarchy/upstream.sh rewrites the pkgver and sha256 below when +# /version.txt moves, and checks the tarball's own directory name to be sure +# the mutable URL really served the version it announced. + +pkgname=tmog-bin +pkgver=0.1.1 +pkgrel=1 +pkgdesc="Native system monitor and task manager" +arch=('x86_64') +url="https://tmog.org/" +license=('LicenseRef-proprietary') + +depends=( + 'gcc-libs' + 'glibc' + 'hicolor-icon-theme' + 'qt6-base' + 'qt6-multimedia' + 'qt6-svg' + # Omarchy is a Wayland desktop, so the Wayland platform plugin is what this + # actually runs on; without it Qt falls back to xcb under XWayland. + 'qt6-wayland' + 'systemd-libs' +) + +provides=('tmog') +conflicts=('tmog') + +# Upstream ships a stripped release build and no debug symbols to split out. +options=('!debug' '!strip') + +_srcdir="TaskManagerOG-${pkgver}-linux-x86_64" + +# The query string is upstream's own cache key -- tmog.org appends it to the +# Linux links for the same reason, so a CDN holding an older object under this +# mutable path cannot answer for a new release. +source=("${pkgname}-${pkgver}.tar.gz::${url}downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz?v=${pkgver}-free") +sha256sums=('4d319d3d27f513e83801daeec8eb64cb78ddec1f6483bbe90d57d11e607af39d') + +package() { + cd "${_srcdir}" + + install -Dm755 bin/tmog-task-manager "${pkgdir}/usr/bin/tmog-task-manager" + + install -Dm644 share/applications/com.tmog.taskmanager.desktop \ + "${pkgdir}/usr/share/applications/com.tmog.taskmanager.desktop" + install -Dm644 share/metainfo/com.tmog.taskmanager.metainfo.xml \ + "${pkgdir}/usr/share/metainfo/com.tmog.taskmanager.metainfo.xml" + install -Dm644 share/pixmaps/tmog-task-manager.png \ + "${pkgdir}/usr/share/pixmaps/tmog-task-manager.png" + + local icon + for icon in share/icons/hicolor/*/apps/tmog-task-manager.png; do + install -Dm644 "$icon" "${pkgdir}/usr/${icon}" + done + + # Upstream files its licence texts under share/doc, which is Debian's layout. + # On Arch they belong with the package's licences. + local doc + for doc in share/doc/tmog/* share/doc/taskmanagerog/copyright; do + install -Dm644 "$doc" "${pkgdir}/usr/share/licenses/${pkgname}/${doc##*/}" + done +}