From 3b244ba0492fd86fca051713196067f833f34a1b Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 6 Jun 2026 15:36:25 -0500 Subject: feat: add the local transfer execution engine and queue Phase 5 turns the pure transfer-specs from Phase 3 into running transfers. duet--run-transfer spawns the backend over make-process, and a serial queue (duet-max-concurrent-transfers, default 1) holds the rest until a slot frees. Each transfer carries a state machine: queued, running, stalled, cancelling, then a terminal done, failed, or cleanup-unverified. The process filter is the hot path, so it stays cheap: it counts output, bounds it to a trailing window, and schedules one coalesced log render. It never refreshes panes. Pane refresh runs once per batch from the sentinel, also coalesced. A move deletes its sources only after the copy exits 0, so a failed move leaves the source untouched. Cancellation kills the process and, for a backend declaring verifiable cleanup, checks the destination for stray temp files before settling on failed versus cleanup-unverified. The process boundary and the temp-file lister are injectable, so the queue and classification logic test against fake results while real rsync gets its own slow integration file. duet-copy, duet-move, duet-mkdir, and duet-delete are wired to the engine. The viewer actions stay stubs until their phase. In-process TRAMP and both-remote rsync still refuse to run here. They land with Phase 6. 172 tests, duet.el at 100% line coverage, compile/lint/complexity green. --- tests/test-duet-pane.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/test-duet-pane.el') diff --git a/tests/test-duet-pane.el b/tests/test-duet-pane.el index df9866b..433035c 100644 --- a/tests/test-duet-pane.el +++ b/tests/test-duet-pane.el @@ -82,8 +82,10 @@ ;;; Not-yet-implemented action commands (ert-deftest test-duet-pane-unimplemented-actions-error () - "The transfer/file actions announce themselves until their phase lands." - (dolist (cmd '(duet-view duet-edit duet-copy duet-move duet-mkdir duet-delete)) + "The viewer actions announce themselves until the viewer phase lands. +The transfer actions (copy/move/mkdir/delete) are wired to the engine and are +covered in test-duet-transfer-exec.el." + (dolist (cmd '(duet-view duet-edit)) (should-error (funcall cmd) :type 'user-error))) ;;; Launch, quit, and two-window resolution against a real frame -- cgit v1.2.3