mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
iOS port M0b: extract Transport + ServerContext to ScarfCore
Second of four M0 sub-PRs. Moves the remaining cross-cutting
infrastructure — the ServerTransport protocol and its two implementations
(LocalTransport, SSHTransport), plus ServerContext and its helpers —
into ScarfCore so both Mac and (future) iOS targets share one codebase.
Files moved (5):
- scarf/Core/Transport/ServerTransport.swift (+ FileStat, ProcessResult, WatchEvent)
- scarf/Core/Transport/LocalTransport.swift
- scarf/Core/Transport/SSHTransport.swift
- scarf/Core/Transport/TransportErrors.swift
- scarf/Core/Models/ServerContext.swift (+ SSHConfig, ServerKind, ServerID, UserHomeCache)
Split out of ServerContext.swift into a new Mac-target sibling file
scarf/Core/Models/ServerContext+Mac.swift:
- runHermes(_:timeout:stdin:) — depends on HermesFileService
- openInLocalEditor(_:) — depends on AppKit.NSWorkspace
These methods can't live in ScarfCore itself because ScarfCore must not
depend on main-target services or AppKit. iOS will provide a sibling
ServerContext+iOS.swift in M2+.
Removed: scarf/Core/Models/HermesPaths+Deprecated.swift.
Zero callers in-tree; its only justification was that ServerContext
used to be in the Mac target. With ServerContext in ScarfCore now,
the deprecated forwarders are both unreachable AND dead code.
Breaking the ScarfCore → main-target circular dep in SSHTransport:
The old SSHTransport.sshSubprocessEnvironment() called
HermesFileService.enrichedEnvironment() to harvest SSH_AUTH_SOCK from
the user's login shell. Replaced with a local #if os(macOS) helper
SSHTransport.macLoginShellSSHAgent() that probes /bin/zsh for only
the two SSH agent vars (no PATH/credentials — that's still in
HermesFileService for ACP subprocess use). Behavior-identical on
macOS; no-op on iOS/Linux.
Platform guards added in ScarfCore (runtime targets still macOS/iOS):
- `#if canImport(os)` around os.Logger (definition + every call site,
except the large Darwin-dependent ensureControlDir block).
- `#if canImport(Darwin)` around LocalTransport.watchPaths (FSEvents)
and SSHTransport.ensureControlDir (Darwin.stat/lstat). Linux gets
a no-op empty stream and a best-effort FileManager.createDirectory
fallback — neither is exercised at runtime on Linux, only compiled.
- `#if canImport(SwiftUI)` around ServerContext's EnvironmentKey.
- `#if canImport(AppKit)` inside the new ServerContext+Mac.swift
extension.
Bug fixed: M0a's sed transform accidentally added `public` to protocol
requirements in ServerTransport.swift, e.g. `public nonisolated var
contextID: ServerID { get }`. Swift forbids access modifiers on
protocol requirements — stripped.
54 additional consumer files in the Mac target gained `import ScarfCore`.
Test coverage: 18 new tests in ScarfCoreTests/M0bTransportTests.swift.
Runs on Linux via
docker run --rm -v $PWD/scarf/Packages/ScarfCore:/work -w /work swift:6.0 swift test
Total suite: 34 / 34 passing (M0a's 16 + M0b's 18).
Updated scarf/docs/IOS_PORT_PLAN.md progress log with the shipped M0b
state and the Platform-guard patterns future phases should reuse.
https://claude.ai/code/session_019yMRP6mwZWfzVrPTqevx2y
This commit is contained in:
@@ -224,7 +224,85 @@ $PWD/scarf/Packages/ScarfCore:/work -w /work swift:6.0 swift test`.
|
||||
`nonisolated` to new ScarfCore APIs pre-emptively; match the
|
||||
surrounding conventions.
|
||||
|
||||
### M0b — pending
|
||||
### M0b — shipped
|
||||
|
||||
**Shipped:**
|
||||
|
||||
- 4 Transport files moved to `Packages/ScarfCore/Sources/ScarfCore/Transport/`:
|
||||
`ServerTransport.swift`, `LocalTransport.swift`, `SSHTransport.swift`,
|
||||
`TransportErrors.swift`.
|
||||
- `ServerContext.swift` moved to `Packages/ScarfCore/Sources/ScarfCore/Models/`.
|
||||
The `runHermes(_:timeout:stdin:)` and `openInLocalEditor(_:)` extension
|
||||
methods — the only two that depend on main-target `HermesFileService` or
|
||||
on AppKit's `NSWorkspace` — are split out into a new main-target file
|
||||
`scarf/Core/Models/ServerContext+Mac.swift`.
|
||||
- `HermesFileService.enrichedEnvironment()` reference inside
|
||||
`SSHTransport.sshSubprocessEnvironment()` replaced with a local
|
||||
`#if os(macOS)` helper `macLoginShellSSHAgent()` that does a narrow
|
||||
`zsh -l -c` probe for only `SSH_AUTH_SOCK` / `SSH_AGENT_PID` (instead
|
||||
of the broader PATH + credentials harvest that still lives in
|
||||
`HermesFileService`). This breaks the Mac-target dependency from
|
||||
ScarfCore. Behavior-identical on macOS; a no-op on iOS (where the SSH
|
||||
agent comes from Citadel in M4, not the user's shell) and on Linux CI.
|
||||
- `HermesPaths+Deprecated.swift` deleted. Its only justification was that
|
||||
`ServerContext` was in the Mac target; with `ServerContext` in ScarfCore
|
||||
now, the deprecated forwarders are both unreachable AND unused (zero
|
||||
callers). Good riddance.
|
||||
- Added `import ScarfCore` to 54 more consumer files that reference
|
||||
Transport types or `ServerContext` but weren't already importing
|
||||
ScarfCore from M0a. `scarfTests/scarfTests.swift` also gets the import
|
||||
— its `ControlPathTests` now hits the public `SSHTransport` via
|
||||
ScarfCore.
|
||||
|
||||
**Platform guards applied in ScarfCore:**
|
||||
|
||||
- `#if canImport(os)` — Apple's `os.Logger` (`import os` + every call
|
||||
site). Linux gets silent logging. **Exception:** the large block in
|
||||
`SSHTransport.ensureControlDir()` uses `Darwin.stat` / `lstat` / `mkdir`
|
||||
/ `chmod` alongside its Logger calls — the whole method body is wrapped
|
||||
in `#if canImport(Darwin)` with a simple `FileManager.createDirectory`
|
||||
fallback for Linux (stubbed because SSH isn't exercised at runtime on
|
||||
Linux anyway).
|
||||
- `#if canImport(Darwin)` — `Darwin.open`/`Darwin.close` + FSEvents-based
|
||||
`DispatchSourceFileSystemObject` in `LocalTransport.watchPaths`. Linux
|
||||
gets a no-op empty stream.
|
||||
- `#if canImport(SwiftUI)` — `EnvironmentKey` / `EnvironmentValues`
|
||||
plumbing in `ServerContext.swift`.
|
||||
- `#if canImport(AppKit)` — only in the split-out
|
||||
`ServerContext+Mac.swift`, where `NSWorkspace.shared.open` lives. iOS
|
||||
will provide its own equivalent (`UIApplication.open(_:)`) when the
|
||||
target lands in M2.
|
||||
|
||||
**Bug fixed while moving:** the sed transform in M0a accidentally promoted
|
||||
`protocol ServerTransport` requirements to `public nonisolated var contextID ...`.
|
||||
Protocol requirements inherit the protocol's access level and **must
|
||||
not** carry an explicit modifier — that's a Swift compile error. Fixed
|
||||
in this PR's ServerTransport.swift.
|
||||
|
||||
**Test coverage (`M0bTransportTests`):** 18 new tests that construct
|
||||
`SSHConfig` with and without defaults, round-trip it through Codable,
|
||||
verify `ServerKind` pattern-matching, pin `ServerContext.local`'s
|
||||
hard-coded UUID, assert local-vs-remote path derivation, verify
|
||||
`makeTransport()` dispatches to the right impl, exercise `FileStat` /
|
||||
`ProcessResult` / `WatchEvent` / `TransportError` shapes + error-classifier
|
||||
stderr patterns, and round-trip an actual local file through
|
||||
`LocalTransport` (write → read → stat → remove).
|
||||
|
||||
**Rules next phases can rely on:**
|
||||
|
||||
- `ServerContext` is the canonical multi-server entry point. Any new
|
||||
service added in M0c or later takes a `ServerContext` in its init.
|
||||
- `ServerContext+Mac.swift` is the pattern for Mac-only methods on
|
||||
ScarfCore types. iOS will have a sibling `ServerContext+iOS.swift`
|
||||
when the iOS target lands. Keep platform-specific methods out of
|
||||
ScarfCore itself and in these sibling files.
|
||||
- Logger pattern: `#if canImport(os) ... #endif` around each call site.
|
||||
If there are 3+ sites in one method, consider wrapping the whole method
|
||||
body in `#if canImport(Darwin)` with a Linux-safe fallback.
|
||||
- SSH env enrichment is now self-contained in `SSHTransport.swift`. When
|
||||
iOS's Citadel-based transport lands (M4), it will provide its own env
|
||||
story — the existing macOS helper stays untouched.
|
||||
|
||||
### M0c — pending
|
||||
### M0d — pending
|
||||
### M1 — pending
|
||||
|
||||
Reference in New Issue
Block a user