diff --git a/pkgbuilds/omarchy-task-manager/.omarchy/package.json b/pkgbuilds/omarchy-task-manager/.omarchy/package.json index 8b66e2d..df4a9fb 100644 --- a/pkgbuilds/omarchy-task-manager/.omarchy/package.json +++ b/pkgbuilds/omarchy-task-manager/.omarchy/package.json @@ -1,11 +1,11 @@ { "source": "local", - "channels": ["edge"], "upstream": { "watch": { "github": "tcballard/omarchy-task-manager", "pattern": "v(?P[0-9]+\\.[0-9]+\\.[0-9]+)", "allow_prerelease": true } - } + }, + "release_ring": "fast" } diff --git a/pkgbuilds/omarchy-task-manager/PKGBUILD b/pkgbuilds/omarchy-task-manager/PKGBUILD index 94f01cd..0da9895 100644 --- a/pkgbuilds/omarchy-task-manager/PKGBUILD +++ b/pkgbuilds/omarchy-task-manager/PKGBUILD @@ -1,8 +1,8 @@ # Canonical recipe. scripts/package-source.sh fills the release source checksum. # Maintainer: Tom Ballard (tcballard) pkgname=omarchy-task-manager -pkgver=0.0.3 -pkgrel=3 +pkgver=0.0.4 +pkgrel=1 url='https://github.com/tcballard/omarchy-task-manager' pkgdesc='Floating native task manager for Omarchy (preview)' arch=('x86_64') @@ -11,19 +11,8 @@ depends=('qt6-base' 'qt6-declarative' 'qt6-wayland' 'qt6-svg' 'hicolor-icon-them optdepends=('gdb: live process core dumps' 'nvidia-utils: NVIDIA device telemetry') makedepends=('cmake' 'ninja' 'rust' 'cargo') checkdepends=('python' 'desktop-file-utils') -source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz" - "pause-resume-test.patch" - "worker-shutdown.patch") -sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85' - 'ce191fc8dc7e4f7018193aa4982d58fd463f66b37e3129b3acce46b7a1c9a89e' - '1142aaedf8739bf2ed1cb823a03ed7e406d7ff59d7dfb72748815cc81cfda96b') - -# Backport upstream PR #11 (sample observation) and PR #12 (worker shutdown). -prepare() { - cd "$srcdir/$pkgname-$pkgver" - patch -Np1 -i "$srcdir/pause-resume-test.patch" - patch -Np1 -i "$srcdir/worker-shutdown.patch" -} +source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz") +sha256sums=('a8be937c6df43a01893c0955dfa53953a9ef06660144b1562445dacf64bbbbfb') build() { cmake -S "$srcdir/$pkgname-$pkgver" -B build -G Ninja \ diff --git a/pkgbuilds/omarchy-task-manager/pause-resume-test.patch b/pkgbuilds/omarchy-task-manager/pause-resume-test.patch deleted file mode 100644 index e256547..0000000 --- a/pkgbuilds/omarchy-task-manager/pause-resume-test.patch +++ /dev/null @@ -1,63 +0,0 @@ -diff --git a/tests/bridge_test.cpp b/tests/bridge_test.cpp -index bab79f2..9bed7be 100644 ---- a/tests/bridge_test.cpp -+++ b/tests/bridge_test.cpp -@@ -79,37 +79,53 @@ private slots: - const auto before = bridge.history().size(); - QTest::qWait(1100); - QCOMPARE(bridge.history().size(), before); -- QSignalSpy samples(&bridge, &Bridge::snapshotChanged); -+ // Capture at emission: QTRY processes events, so another timer sample can -+ // replace bridge.snapshot() before the waiting assertion runs. -+ QVariantList samples; -+ QList historySizes; -+ QObject sampleObserver; // Disconnect before the captured lists are destroyed. -+ connect(&bridge, &Bridge::snapshotChanged, &sampleObserver, [&] { -+ samples.append(bridge.snapshot()); -+ historySizes.append(bridge.history().size()); -+ }); - bridge.setPaused(false); - QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); -- QVERIFY(!bridge.snapshot() -+ QVERIFY(!samples.first().toMap() - .value("system") - .toMap() - .value("continuous") - .toBool()); -- QCOMPARE(bridge.history().size(), 1); -+ QCOMPARE(historySizes.first(), 1); - bridge.active(false); - QTest::qWait(600); - samples.clear(); -+ historySizes.clear(); - bridge.active(true); - QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); -- QVERIFY(!bridge.snapshot() -+ QVERIFY(!samples.first().toMap() - .value("system") - .toMap() - .value("continuous") - .toBool()); - QTRY_VERIFY_WITH_TIMEOUT(!bridge.busy(), 8000); - samples.clear(); -+ historySizes.clear(); - bridge.refresh(); - QVERIFY(bridge.busy()); - bridge.setPaused(true); - bridge.setPaused(false); - QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); -- QVERIFY(!bridge.snapshot() -+ QVERIFY(!samples.first().toMap() - .value("system") - .toMap() - .value("continuous") - .toBool()); -+ QCOMPARE(historySizes.first(), 1); -+ // Keep automatic refresh enabled. The baseline must be followed by a -+ // continuous sample; inspecting only the latest snapshot misses this order. -+ QTRY_VERIFY_WITH_TIMEOUT(samples.count() >= 2, 8000); -+ QVERIFY(samples.at(1).toMap().value("system").toMap() -+ .value("continuous").toBool()); - QTRY_VERIFY_WITH_TIMEOUT(!bridge.busy(), 8000); - QVERIFY(bridge.prepareManagement({{"category", "startup"}}).isEmpty()); - QVERIFY( diff --git a/pkgbuilds/omarchy-task-manager/worker-shutdown.patch b/pkgbuilds/omarchy-task-manager/worker-shutdown.patch deleted file mode 100644 index d71f21b..0000000 --- a/pkgbuilds/omarchy-task-manager/worker-shutdown.patch +++ /dev/null @@ -1,90 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index c940e5e..d1cd40f 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -29,7 +29,8 @@ if(BUILD_TESTING) - target_include_directories(bridge-test PRIVATE ui) - target_link_libraries(bridge-test PRIVATE Qt6::Core Qt6::Gui Qt6::Test) - add_dependencies(bridge-test core) -- add_test(NAME bridge COMMAND bridge-test) -+ add_test(NAME bridge COMMAND bridge-test -nocrashhandler) -+ set_tests_properties(bridge PROPERTIES TIMEOUT 60) - endif() - if(BUILD_TESTING) - qt_add_executable(ui-test tests/ui_test.cpp ui/bridge.cpp ui/bridge.h) -@@ -37,5 +38,6 @@ if(BUILD_TESTING) - qt_add_resources(ui-test test_qml PREFIX "/" FILES ${TASK_MANAGER_QML}) - target_link_libraries(ui-test PRIVATE Qt6::Core Qt6::Gui Qt6::Quick Qt6::Qml Qt6::QuickControls2 Qt6::Test) - add_dependencies(ui-test core) -- add_test(NAME ui COMMAND ui-test) -+ add_test(NAME ui COMMAND ui-test -nocrashhandler) -+ set_tests_properties(ui PROPERTIES TIMEOUT 60) - endif() -diff --git a/tests/bridge_test.cpp b/tests/bridge_test.cpp -index 9bed7be..d6737a4 100644 ---- a/tests/bridge_test.cpp -+++ b/tests/bridge_test.cpp -@@ -3,9 +3,46 @@ - #include - #include - #include -+#include -+#include - class BridgeTest : public QObject { - Q_OBJECT - private slots: -+ void shutdownDoesNotPublish_data() { -+ QTest::addColumn("inFlight"); -+ QTest::addColumn("stopped"); -+ QTest::newRow("idle") << false << false; -+ QTest::newRow("sample-in-flight") << true << false; -+ QTest::newRow("stopped-worker") << true << true; -+ } -+ void shutdownDoesNotPublish() { -+ QFETCH(bool, inFlight); -+ QFETCH(bool, stopped); -+ auto bridge = std::make_unique(); -+ QTRY_VERIFY_WITH_TIMEOUT(!bridge->snapshot().isEmpty(), 8000); -+ bridge->m_timer.stop(); -+ QTRY_VERIFY_WITH_TIMEOUT(!bridge->busy(), 8000); -+ // Stop only the disposable worker owned by this bridge, forcing shutdown -+ // through terminate/kill rather than the normal stdin-EOF exit. -+ if (stopped) { -+ const auto workerPid = bridge->m_worker.processId(); -+ QVERIFY(workerPid > 0); -+ QCOMPARE(::kill(workerPid, SIGSTOP), 0); -+ } -+ if (inFlight) { -+ bridge->refresh(); -+ QVERIFY(bridge->busy()); -+ } -+ QSignalSpy snapshots(bridge.get(), &Bridge::snapshotChanged); -+ QSignalSpy statuses(bridge.get(), &Bridge::statusChanged); -+ QSignalSpy busy(bridge.get(), &Bridge::busyChanged); -+ // Closing the app must not publish late samples or worker-exit errors while -+ // its bridge and UI are being destroyed. Spies outlive the bridge on purpose. -+ bridge.reset(); -+ QCOMPARE(snapshots.count(), 0); -+ QCOMPARE(statuses.count(), 0); -+ QCOMPARE(busy.count(), 0); -+ } - void inspectionErrorsAndDismissal() { - Bridge bridge; - QTRY_VERIFY_WITH_TIMEOUT(!bridge.snapshot().isEmpty(), 8000); -diff --git a/ui/bridge.cpp b/ui/bridge.cpp -index 86b5b47..b1fb303 100644 ---- a/ui/bridge.cpp -+++ b/ui/bridge.cpp -@@ -82,7 +82,12 @@ Bridge::Bridge(QObject *p) : QObject(p), m_rows(this) { - m_clock.start(); - } - Bridge::~Bridge() { -+ // waitForFinished() can emit readyRead/error/finished synchronously. Quiesce -+ // callbacks before waiting, including if QProcess outlives our final wait and -+ // emits from its destructor after the other Bridge members are gone. - m_timer.stop(); -+ m_timeout.stop(); -+ m_worker.disconnect(this); - m_worker.closeWriteChannel(); - if (!m_worker.waitForFinished(600)) { - m_worker.terminate();