Code Reader
首页
帮助
设计文档
首页
帮助
设计文档
  • Snapshot

Snapshot

Snapshot 提供文件系统快照和差异比较功能。

概述

Snapshot 使用 Git 作为底层存储,在不影响工作目录的情况下创建代码快照。支持创建快照、计算差异、回滚和历史记录等功能。

定义位置

packages/opencode/src/snapshot/index.ts:78-195

主要对象

Patch

补丁信息,表示从某个快照到当前状态的变更。

属性名类型必填说明
hashstring是快照哈希
filesstring[]是变更的文件列表

FileDiff

文件差异详情,包含修改前后的完整内容。

属性名类型必填说明
filestring是文件路径
beforestring是修改前内容
afterstring是修改后内容
additionsnumber是新增行数
deletionsnumber是删除行数

TypeScript 类型定义

export type Patch = {
  hash: string
  files: string[]
}

export type FileDiff = {
  file: string
  before: string
  after: string
  additions: number
  deletions: number
}

存储位置

快照存储在以下位置:

~/.opencode/data/snapshot/<project-id>/.git/

这使用的是独立的 Git 仓库,不影响项目的主 Git 仓库。

典型使用场景

1. 创建快照

// 跟踪当前工作目录并创建快照
const hash = await Snapshot.track()

console.log(hash) // Git tree hash,如 "a1b2c3d4..."

2. 获取补丁(变更文件列表)

const patch = await Snapshot.patch(hash)

console.log(`Changed files: ${patch.files.length}`)
console.log(`Files: ${patch.files.join(", ")}`)

3. 获取完整差异

const diff = await Snapshot.diff(hash)

console.log(diff) // Git diff 输出

4. 获取详细差异(FileDiff)

const diffs = await Snapshot.diffFull(fromHash, toHash)

for (const diff of diffs) {
  console.log(`File: ${diff.file}`)
  console.log(`  Additions: ${diff.additions}`)
  console.log(`  Deletions: ${diff.deletions}`)
  console.log(`  Before length: ${diff.before.length}`)
  console.log(`  After length: ${diff.after.length}`)
}

5. 回滚到快照

// 将工作目录恢复到指定快照状态
await Snapshot.restore(snapshotHash)

6. 选择性回滚

// 回滚特定文件
const patches = [
  {
    hash: snapshotHash,
    files: ["/path/to/file1.js", "/path/to/file2.ts"],
  },
]

await Snapshot.revert(patches)

7. 清理旧快照

// 由调度器自动运行,修剪 7 天前的快照
await Snapshot.cleanup()

快照生命周期

工作流程

Session 中使用快照

存储配置

Git 配置

快照仓库使用以下 Git 配置:

git config core.autocrlf false

这确保跨平台的一致性。

修剪策略

默认修剪策略:

const prune = "7.days" // 修剪 7 天前的快照

由调度器每小时运行一次。

二进制文件处理

快照会检测并正确处理二进制文件:

// 从 git diff --numstat 中检测
const isBinaryFile = additions === "-" && deletions === "-"

if (isBinaryFile) {
  // 不读取二进制文件内容
  result.push({
    file,
    before: "",
    after: "",
    additions: 0,
    deletions: 0,
  })
}

性能考虑

快照创建

  • 时间: O(n),其中 n 是变更的文件数
  • 空间: 仅存储变更,不复制整个工作目录

差异计算

  • 时间: O(m),其中 m 是变更的文件数
  • 空间: FileDiff 存储完整文件内容

回滚操作

  • 时间: O(k),其中 k 是要回滚的文件数
  • 空间: 原地修改

错误处理

Git 失败

快照操作失败时记录警告但不会抛出异常:

const result = await $`git command`.quiet().nothrow()

if (result.exitCode !== 0) {
  log.warn("operation failed", {
    exitCode: result.exitCode,
    stderr: result.stderr.toString(),
  })
  return defaultValue
}

变更历史

版本变更内容日期
v1初始 Snapshot 实现-
v1.1添加 FileDiff 详细差异支持-
v1.2添加二进制文件检测-

相关文档

  • Session - 会话对象
  • Part - 消息部分
  • Storage - 存储架构