| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
| |
The bug fixes raised line coverage on duet.el to 92.3%. This closes the rest. The new tests exercise the branches a review would want locked down before execution and UI build on this core: each arm of the minimal failure normalizer (missing executable, stall, signal cancellation, unknown-without-exit), a :match predicate rather than a regexp, the rsync normalizer mapping known stderr to permission/space/protocol classes, the capability-tier contract check, an explicit :async override, the case-collision path through the safety composite's injected predicates, and redaction of a pattern with no capture group.
Line coverage on duet.el is now 100%. The one deliberately trivial case left is the entry command, a not-yet-implemented stub that errors. Its test asserts that and will change when the pane layout lands.
|
| |
|
|
|
|
|
|
|
|
| |
duet--rsync-command built one direct rsync argv for every pair, rendering each remote endpoint as host:path. That is right when at most one endpoint is remote, but rsync refuses a source and destination that are both remote, so the argv was unexecutable for every remote-to-remote route, not just the round-trip.
Now rsync builds a single argv only for :local and :local-remote, the routes it can run in one invocation. A both-remote pair returns a deferred spec: nil argv, an :exec-mode marker, and the route. Phase 6 reads the route to run rsync on a host (same-host), route through this machine (round-trip), or go direct host-to-host when the override is set.
transfer-spec now carries the classified :src-endpoint and :dst-endpoint alongside the route, so execution has the structured endpoints and never has to reinterpret an argv string. The runnable-shape check from the in-process-mode fix extends to accept :exec-mode, so a deferred spec reads as a real plan rather than a broken nil-argv command.
Tests cover local-to-remote and remote-to-local argv shapes including a port, and the same-host, round-trip, and direct routes each producing a deferred spec.
|
| |
|
|
|
|
|
|
| |
Two coupled holes surfaced in the Phase 0-3 review. duet--transfer-spec copied only :argv, :default-directory, and :process-environment out of a backend's command result, dropping the :tramp marker, so a TRAMP-routed spec arrived as :argv nil with nothing telling the executor to copy in process. And duet--check-command leaned on listp, where nil is a list in Elisp, so a command builder returning nil or a bare :argv nil passed the minimum tier.
Both turn on the same idea, so they share a fix. duet--command-spec-executable-p defines a runnable spec: a non-empty plist with either a non-empty :argv of strings (a CLI backend) or a declared in-process mode such as :tramp. The contract checker rejects anything else, and transfer-spec now carries :tramp through, so the TRAMP fallback has a positive execution signal rather than an ambiguous nil argv.
The legitimate TRAMP backend keeps passing because it declares its mode. A broken backend that forgets argv no longer slips through.
|
|
|
duet--transfer-spec classifies both endpoints, selects a backend through the registry, determines the route, and delegates argv construction to the backend (Phase 3 in the design spec). It returns the plist the executor will run: sources, destination, backend, route, argv, and async flag.
The route is decided independently of backend by duet--transfer-route: local, local-remote, remote-same-host, remote-direct, or remote-roundtrip. Different remote hosts default to the round-trip through this machine. Direct host-to-host runs only when a per-connection override asks for it, never automatically, because a direct route can silently fail where a round-trip always works.
This phase also registers the two stage-1 backends through the same duet-register-backend seam a plugin uses: rsync for local and ssh-reachable endpoints, TRAMP as the universal fallback that costs more so rsync wins whenever it applies. rsync receives its source and destination as separate argv elements, so a filename with spaces or shell metacharacters stays inert.
The two planners are pure and prompt-free, so the dangerous decisions are testable before a byte moves. duet--plan-conflicts resolves overwrite/skip/rename per file with an apply-to-all that stops asking, taking the existence check and the resolver as injected functions. duet--plan-move pairs each source's copy with a delete gated on that source's copy success, so a failed copy can never delete its source.
Remote-to-remote execution (honoring the round-trip route as a two-step through local) and TRAMP's in-process copy land in Phase 6. Here transfer-spec records the route and the rsync path the executor will use.
|