Files
DevFlow/docs/08-用户指南/patch_file使用指南.md
绝尘 998a2f243d 文档: 架构方案文档(意图识别论证+多主题愿景/论证+文档物理分类+边界清晰化)
squash合并:
- 意图识别层论证(8维度+10业界佐证)
- 多主题上下文管理愿景+并存论证+补充论证(多轮agentic)
- 架构设计文档物理分类(四子目录+INDEX+命名规范+引用同步+边界清晰化)
- 前端架构技术债清单归档
2026-06-19 15:04:04 +08:00

108 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# patch_file 使用指南
> 创建: 2026-06-15
> 关联设计: docs/02-架构设计/专项设计/patch_file工具设计-2026-06-15.md
## 使用场景
局部更新文件(替代 read-merge-write 多步流程),精确定位 `old_text` 并替换为 `new_text`
适用于只改文件中某几行的场景:大文件改 3 行无需重发全部内容,避免 `write_file` 全量覆盖的事故风险(参见 FR-S7 记录762 行文件被覆盖为 248 字节)。
## API 参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `path` | 是 | 目标文件路径workspace 内,走 `validate_path` 校验 + 黑名单) |
| `old_text` | 是 | 要替换的精确文本(必须与文件内容完全匹配,含空格/缩进;充当乐观锁) |
| `new_text` | 是 | 替换后的新文本 |
| `line` | 否 | 行号辅助定位(快速跳转 + 去歧增强;有值时优先跳到该行检查 `old_text`,不匹配则降级全文扫描) |
| `expected_hash` | 否 | 文件指纹防脏写,格式 `"{unix_timestamp}_{size}"`(如 `"1718400000_12345"`),由 `read_file` 返回的 `file_hash` 字段携带 |
补充去歧参数(可选):`before_text` / `after_text` —— 当 `old_text` 多处匹配时,作为上下文锚精确锁定目标位置。
## 返回值
```json
{
"success": true,
"patches_applied": 1,
"total_matches": 1,
"lines_changed": 2,
"warnings": [],
"file_hash": "1718400000_12400"
}
```
| 字段 | 含义 |
|------|------|
| `success` | 是否成功 |
| `patches_applied` | 成功替换的 patch 数 |
| `total_matches` | 每个 patch 的总命中数(含未替换的) |
| `lines_changed` | 总行数变化(正=增加,负=减少) |
| `warnings` | 警告信息,如 `["匹配到 3 处,仅替换第 1 处"]` |
| `file_hash` | 操作后的新指纹(下次操作传入 `expected_hash` 用) |
## 安全边界
- **RiskLevel Medium**:修改已有文件,需人工审批
- **自动 `.bak` 备份**:复用 FR-S7 已有逻辑,误操作可恢复
- **old_text 不匹配 → 报错**(不修改文件,避免盲替换)
- **expected_hash 不匹配 → 报错**(防并发脏写,提示「文件已被外部修改,请重新读取」)
- **三层防御**L1 文件级 Mutex防时机冲突+ L2 old_text 精确匹配(防内容错配)+ L3 expected_hash 指纹校验(防版本漂移),底层兜底 `.bak` 备份
## 最佳实践
- **old_text 取足够上下文确保唯一**:避免短串多处匹配,收到「匹配到 N 处」warning 时用 `before_text`/`after_text` 锚定或加长 `old_text` 重试
- **大段修改用多个小 patch 而非一个巨大 patch**:每个 patch 独立校验,失败可定位
- **危险操作前先 `file_info` 确认**:核对路径、大小、是否二进制(含 `\0` 的文件会被拒绝)
- **read → patch 链路带上 hash**`read_file` 返回 `file_hash`,传入 `patch_file``expected_hash` 形成乐观锁闭环
- **多 patch 从文件末尾往前排**:避免行号偏移(工具内部已按此执行)
- **old_text 必须完全匹配**:含空格、缩进、换行,复制粘贴原文最稳妥
## 示例
### 基础替换
```json
{
"path": "src/main.rs",
"old_text": "fn old()",
"new_text": "fn new()"
}
```
### 带 hash 乐观锁
```json
{
"path": "src/main.rs",
"expected_hash": "1718400000_12345",
"patches": [
{ "old_text": "fn old()", "new_text": "fn new()" }
]
}
```
### 多处匹配用 line 锚定
```json
{
"path": "src/main.rs",
"old_text": "return Ok(())",
"new_text": "return Ok(value)",
"line": 42
}
```
## 边界情况
| 情况 | 行为 |
|------|------|
| 文件不存在 | 报错「文件不存在」 |
| 二进制文件(含 `\0` | 报错「不支持二进制文件」 |
| `old_text` 为空串 | 报错「old_text 不能为空」 |
| `new_text` == `old_text` | 成功 + warning「无实际更改」 |
| 路径含 `..` | `validate_path` 黑名单拦截 |
| 目标是 `.bak`/`.tmp` | 拒绝CR-03 噪声文件过滤) |