77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package toolsrv
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// Process represents a running toolsrv subprocess.
|
|
// The session owns this and calls Close() when the session ends.
|
|
type Process struct {
|
|
// Socket is the Unix socket path clients should Dial().
|
|
Socket string
|
|
// Info holds host environment details (platform, git repo status).
|
|
Info HostInfo
|
|
// cleanup shuts down the subprocess and removes the socket.
|
|
cleanup func()
|
|
}
|
|
|
|
// Close shuts down the toolsrv subprocess and removes the socket file.
|
|
func (p *Process) Close() {
|
|
if p.cleanup != nil {
|
|
p.cleanup()
|
|
}
|
|
}
|
|
|
|
// Spawn starts a local ollie-remote subprocess listening on a Unix socket.
|
|
// The returned Process owns the subprocess lifecycle. Callers connect
|
|
// via Dial(LocalAddr(proc.Socket)).
|
|
func Spawn(ctx context.Context, cwd string, opts ...Option) (*Process, error) {
|
|
StreamOutput(ctx, "[toolsrv] spawning local toolsrv...\n")
|
|
|
|
t, err := localDial(ctx, cwd, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Verify the server is responsive via the initial connection.
|
|
conn := NewConnSplit(t.r, t.w, func() {})
|
|
var info HostInfo
|
|
if hi, err := conn.FetchHostInfo(); err == nil {
|
|
info = hi
|
|
}
|
|
|
|
StreamOutput(ctx, fmt.Sprintf("[toolsrv] local ready: %s (socket %s)\n", cwd, t.sockPath))
|
|
|
|
return &Process{
|
|
Socket: t.sockPath,
|
|
Info: info,
|
|
cleanup: t.cleanup,
|
|
}, nil
|
|
}
|
|
|
|
// SpawnRemote starts ollie-remote on a remote host via SSH, sets up Unix
|
|
// socket forwarding, and returns a Process with the local forwarded socket.
|
|
func SpawnRemote(ctx context.Context, cfg RemoteConfig) (*Process, error) {
|
|
StreamOutput(ctx, fmt.Sprintf("[toolsrv] dialing %s (cwd: %s)...\n", cfg.SSHTarget, cfg.CWD))
|
|
|
|
t, err := sshDial(ctx, cfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("spawn remote: %w", err)
|
|
}
|
|
|
|
conn := NewConnSplit(t.r, t.w, func() {})
|
|
var info HostInfo
|
|
if hi, err := conn.FetchHostInfo(); err == nil {
|
|
info = hi
|
|
}
|
|
|
|
StreamOutput(ctx, fmt.Sprintf("[toolsrv] remote ready: %s → %s (%s/%s)\n", cfg.SSHTarget, t.sockPath, info.Platform, info.Arch))
|
|
|
|
return &Process{
|
|
Socket: t.sockPath,
|
|
Info: info,
|
|
cleanup: t.cleanup,
|
|
}, nil
|
|
}
|