Documentation
¶
Overview ¶
Package workspace 定义执行环境工具用的工作区:按路径读写文件、启动进程。 本机实现基于 os、os.Root 和真实 bash;SSH 实现经 SFTP 读写文件、在远端 bash 里运行命令;虚拟实现基于 go-bash 的内存文件系统和解释器。 路径都是工作区里的绝对路径;读取不限范围,WriteFile 等写入只能在工作区根目录之内,命令不受这个限制。 流式的 OpenFileReader、CreateFileWriter 和 CopyFile 还接受相对根目录的路径,写入也不限于根目录。
Index ¶
- Variables
- func CopyDirectory(ctx context.Context, source Workspace, sourcePath string, target Workspace, ...) error
- func CopyFile(ctx context.Context, source Workspace, sourcePath string, target Workspace, ...) error
- func GetFileText(ctx context.Context, source Workspace, path string) (string, error)
- func QuoteShellWord(word string) string
- type AgentsInstructionFile
- type DirectoryEntry
- type DirectoryFile
- type FileContent
- type FileMetadata
- type LocalWorkspaceOpt
- type Process
- type ProcessRequest
- type SSHWorkspace
- type SSHWorkspaceOpt
- type VirtualFile
- type VirtualWorkspaceOpt
- type Workspace
Constants ¶
This section is empty.
Variables ¶
var ( // ErrOutsideWorkspace 表示写操作的目标不在工作区根目录内。 ErrOutsideWorkspace = errors.New("path is outside the workspace root") // ErrNotRegularFile 表示读取目标不是普通文件。 ErrNotRegularFile = errors.New("path is not a regular file") // ErrTTYUnsupported 表示这个工作区不能在终端里运行命令。 ErrTTYUnsupported = errors.New("this workspace does not support interactive commands") // ErrTTYInputUnsupported 表示向不在终端里运行的命令写终端输入。 ErrTTYInputUnsupported = errors.New("this command is not running in a terminal") // ErrTTYStdinUnsupported 表示 TTY 命令的请求带了 Stdin;TTY 命令的输入只能经 Process.WriteTerminalInput 写入。 ErrTTYStdinUnsupported = errors.New("interactive commands take input through the terminal, not Stdin") )
Functions ¶
func CopyDirectory ¶
func CopyDirectory(ctx context.Context, source Workspace, sourcePath string, target Workspace, targetPath string, skippedNames []string) error
CopyDirectory 跨工作区复制完整目录。
func CopyFile ¶
func CopyFile(ctx context.Context, source Workspace, sourcePath string, target Workspace, targetPath string) error
CopyFile 跨工作区流式复制普通文件并保留权限。
func GetFileText ¶
GetFileText 分块读取文件全文并返回文本。
Types ¶
type AgentsInstructionFile ¶
type AgentsInstructionFile struct {
// Path 是这份 AGENTS.md 清理后的绝对路径。
Path string
// Text 是文件全文。
Text string
}
AgentsInstructionFile 是从工作区读到的一份 AGENTS.md。
func GetFileAgentsInstructions ¶
func GetFileAgentsInstructions(ctx context.Context, work Workspace, path string) ([]AgentsInstructionFile, error)
GetFileAgentsInstructions 按从工作区根目录到文件所在目录的顺序读取沿途的 AGENTS.md。
func GetWorkspaceAgentsInstructions ¶
func GetWorkspaceAgentsInstructions(ctx context.Context, work Workspace) ([]AgentsInstructionFile, error)
GetWorkspaceAgentsInstructions 从工作区根目录往上找最近的 Git 根目录,按从 Git 根目录到工作区根目录的顺序读取沿途的 AGENTS.md。
type DirectoryEntry ¶
DirectoryEntry 是目录中的一个直接子项。
type DirectoryFile ¶
type DirectoryFile struct {
// RelativePath 是相对遍历根目录的路径,用 / 分隔。
RelativePath string
// Mode 是跟随符号链接后的权限位。
Mode fs.FileMode
IsDirectory bool
}
DirectoryFile 是 ListDirectoryFiles 收集到的一项。
func ListDirectoryFiles ¶
func ListDirectoryFiles(ctx context.Context, source Workspace, root string, skippedNames []string) ([]DirectoryFile, error)
ListDirectoryFiles 遍历目录并按相对路径排序返回目录和普通文件。
type FileContent ¶
type FileContent struct {
Content []byte
// Size 是文件报告的大小;/proc 等文件可能为 0。
Size int64
// EOF 这次读取是否已经读到文件末尾?
EOF bool
}
FileContent 是 ReadFile 读到的一段内容。
type FileMetadata ¶
type FileMetadata struct {
IsDirectory bool
// IsFile 是不是普通文件?
IsFile bool
IsSymlink bool
Size int64
Mode fs.FileMode
ModifiedAt time.Time
}
FileMetadata 描述一个路径的类型、大小、权限位与修改时间。
type LocalWorkspaceOpt ¶
type LocalWorkspaceOpt struct {
// RootDirectory 是工作区根目录,必须是绝对路径。
RootDirectory string
// Environment 是执行命令用的环境变量,格式同 os.Environ;为 nil 时继承当前进程的环境。
Environment []string
}
LocalWorkspaceOpt 保存本机工作区的根目录和命令环境变量。
func NewLocalWorkspaceOpt ¶
func NewLocalWorkspaceOpt(rootDirectory string) *LocalWorkspaceOpt
NewLocalWorkspaceOpt 保存本机工作区根目录。
func (*LocalWorkspaceOpt) WithEnvironment ¶
func (o *LocalWorkspaceOpt) WithEnvironment(environment []string) *LocalWorkspaceOpt
WithEnvironment 设置命令环境变量并返回本配置。
type Process ¶
type Process interface {
// Wait 等待命令结束并返回退出码;返回时输出已全部写入请求中的 Writer。被 Terminate 结束时退出码为 -1。
Wait() (int, error)
// Terminate 结束命令所在的整个进程组;没能确认结束时返回错误,可以重试;进程组已不存在时返回 nil。
Terminate() error
// WriteTerminalInput 把 data 原样写进 TTY 命令的终端,返回实际写入的字节数;
// 非 TTY 命令返回 ErrTTYInputUnsupported,命令已结束时返回写入错误。
WriteTerminalInput(data []byte) (int, error)
// ResizeTerminal 修改 TTY 命令的终端行列数;非 TTY 命令返回 ErrTTYInputUnsupported,virtual 命令返回 ErrTTYUnsupported。
ResizeTerminal(rows, cols uint16) error
// Close 放手这条命令:关闭本地这一端,让 Wait 尽快返回。SSH 关闭命令的会话,不证明远端已停止,Wait 随后返回错误;
// 本机和 virtual 等同于 Terminate。只在不能无限等待的收尾路径上、Terminate 失败之后调用。
Close() error
}
Process 是 StartProcess 启动的一条命令。
type ProcessRequest ¶
type ProcessRequest struct {
// Command 是交给 bash -c 执行的命令文本。
Command string
// Directory 是命令的工作目录,绝对路径。
Directory string
// TTY 是否在终端里运行命令?在终端里运行时输出全部写入 Stdout。
TTY bool
// Rows、Cols 是 TTY 命令的初始终端行列数;为零时按 24×80。
Rows, Cols uint16
// Stdin 是非 TTY 命令的一次性输入,nil 时读到空输入;TTY 命令的输入用 Process.WriteTerminalInput,传 Stdin 返回错误。
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
ProcessRequest 描述一条要启动的 bash 命令。
type SSHWorkspace ¶
type SSHWorkspace interface {
Workspace
// Close 关闭当前连接;之后的调用返回 net.ErrClosed。可重复调用。
Close() error
}
SSHWorkspace 是经 SSH 访问的远端工作区:文件操作走 SFTP,命令在 exec 会话中由远端 bash 执行; 连接在首次调用时建立,断开后由下一次调用重新建立。
func NewSSHWorkspace ¶
func NewSSHWorkspace(opt *SSHWorkspaceOpt) (SSHWorkspace, error)
NewSSHWorkspace 校验根目录并解析 SSH 地址,保存工作区配置。
type SSHWorkspaceOpt ¶
type SSHWorkspaceOpt struct {
// RootDirectory 是远端工作区根目录的绝对路径。
RootDirectory string
// Address 是 [user@]host[:port];省略 user 时使用本机用户名,省略 port 时为 22。
Address string
// IdentityFile 是本机私钥路径,可为空。
IdentityFile string
// Telemetry 是遥测管道,用于连接建立、断开与保活失败的日志;nil 时使用全局兜底。
Telemetry *telemetry.Telemetry
}
SSHWorkspaceOpt 是 SSH 工作区的远端根目录与连接参数。
func NewSSHWorkspaceOpt ¶
func NewSSHWorkspaceOpt(rootDirectory, address, identityFile string) *SSHWorkspaceOpt
NewSSHWorkspaceOpt 保存远端根目录、地址和私钥路径。
type VirtualFile ¶
type VirtualFile struct {
// Content 是现成的文件内容。
Content []byte
// Load 在第一次读取时调用一次,返回文件内容。
Load func(ctx context.Context) ([]byte, error)
}
VirtualFile 是虚拟工作区的一个初始文件。
type VirtualWorkspaceOpt ¶
type VirtualWorkspaceOpt struct {
// RootDirectory 是工作区在虚拟文件系统中的绝对路径,省略时为 /workspace。
RootDirectory string
// Files 是创建时写入的文件,键为绝对路径,父目录自动创建。
Files map[string]*VirtualFile
}
VirtualWorkspaceOpt 保存虚拟工作区的根目录和初始文件。
func NewVirtualWorkspaceOpt ¶
func NewVirtualWorkspaceOpt(rootDirectory string, files map[string]*VirtualFile) *VirtualWorkspaceOpt
NewVirtualWorkspaceOpt 保存虚拟根目录和初始文件列表。
type Workspace ¶
type Workspace interface {
// GetRootDirectory 返回工作区根目录的绝对路径,工具以它为相对路径的基准。
GetRootDirectory() string
// GetHomeDirectory 返回工作区所在机器上当前用户的主目录:本机是 serve 进程的用户(os.UserHomeDir),
// SSH 是登录用户(SFTP 的初始目录,sftp.Client.Getwd);virtual 没有主目录,返回 errors.ErrUnsupported。
GetHomeDirectory(ctx context.Context) (string, error)
// ReadFile 跟随符号链接,从 offset 起读取最多 limit 字节,不足时读到文件末尾;目标不是普通文件时返回 ErrNotRegularFile。
ReadFile(ctx context.Context, path string, offset int64, limit int) (*FileContent, error)
// WriteFile 写入完整内容,父目录须已存在;目标在工作区外时返回 ErrOutsideWorkspace;
// createOnly 且目标已存在时返回满足 fs.ErrExist 的错误。
WriteFile(ctx context.Context, path string, content []byte, mode fs.FileMode, createOnly bool) error
// OpenFileReader 打开文件顺序读取,跟随符号链接,不限于工作区根目录;path 为相对根目录的路径或绝对路径。
// 文件不存在时返回满足 fs.ErrNotExist 的错误;读完由调用方 Close。ctx 只约束打开。
OpenFileReader(ctx context.Context, path string) (io.ReadCloser, error)
// CreateFileWriter 创建或覆盖一个文件并返回写入端,权限位为 mode(不受 umask 影响);
// path 为相对根目录的路径或绝对路径,可以在根目录外;父目录不存在时创建;Close 返回 nil 才算写完。ctx 只约束创建。
CreateFileWriter(ctx context.Context, path string, mode fs.FileMode) (io.WriteCloser, error)
// GetMetadata 返回路径的元数据;followSymlinks 为 false 时描述符号链接本身;不存在时返回满足 fs.ErrNotExist 的错误。
GetMetadata(ctx context.Context, path string, followSymlinks bool) (*FileMetadata, error)
// ReadDirectory 按名称顺序返回目录的直接子项,不跟随符号链接。
ReadDirectory(ctx context.Context, path string) ([]*DirectoryEntry, error)
// CreateDirectory 递归创建工作区内的目录,已存在时成功。
CreateDirectory(ctx context.Context, path string) error
// Remove 删除工作区内的一个文件或空目录。
Remove(ctx context.Context, path string) error
// StartProcess 在 request.Directory 启动一条 bash 命令;ctx 只约束启动,结束命令使用 Process.Terminate。
// request.Stdin 非 nil 时,调用方不再写入后要关闭它的写端,命令才能结束读取。
StartProcess(ctx context.Context, request *ProcessRequest) (Process, error)
// Dial 从工作区所在的机器建立一条网络连接:本机直接连;SSH 经这条 SSH 连接转发,由远端发起,
// 地址也在远端解析;virtual 返回 errors.ErrUnsupported。
Dial(ctx context.Context, network, address string) (net.Conn, error)
// GetHTTPProxy 返回从工作区所在机器发出 HTTP 请求时要经过的代理,签名同 http.Transport.Proxy:
// 本机按 serve 进程的 HTTPS_PROXY、HTTP_PROXY、NO_PROXY(http.ProxyFromEnvironment);
// SSH 拿不到远端 shell 的代理设置,返回 nil 表示直连;virtual 返回 nil。
GetHTTPProxy(request *http.Request) (*url.URL, error)
}
Workspace 是一个 Executor 的工作区,工具按路径读写文件、启动命令;实现可被多个工具并发调用。
func NewLocalWorkspace ¶
func NewLocalWorkspace(opt *LocalWorkspaceOpt) (Workspace, error)
NewLocalWorkspace 校验并保存本机工作区配置。
func NewVirtualWorkspace ¶
func NewVirtualWorkspace(opt *VirtualWorkspaceOpt) (Workspace, error)
NewVirtualWorkspace 创建内存工作区及初始文件。