新闻详情

新闻详情

首页 / 资讯中心 / 详情

Lore 修改文件跟踪(Dirty Tracking)设计解析:从 Merkle 树标志位到 `lore status --scan` 的完整实现

发布时间:2026/9/25 7:15:05来源:尧图网络
Lore 修改文件跟踪(Dirty Tracking)设计解析:从 Merkle 树标志位到 `lore status --scan` 的完整实现
版本控制后端【免费下载链接】loreLore is a next-generation, open source version control system项目地址https://gitcode.com/gh_mirrors/lore6/lore点击查看免费下载导读本文以 Lore 官方增强提案《Modified File Tracking》docs/proposals/2026-05-03-modified-file-tracking.md为主体讲解 Lore 如何在不做全量文件系统扫描的前提下把磁盘上有哪些文件被修改作为一等仓库概念进行跟踪。你将理解 Merkle 树节点上新增的Dirty标志位如何定义与传播、lore file dirty如何为 IDE/VFS/文件系统监视器提供轻量上报 API、lore status如何默认展示脏文件、以及--scan如何在按需扫描时持久化结果——全部附当前仓库源码证据。1. 背景与动机为什么lore status需要一次改造Lore 是一个下一代开源版本控制系统见 README.md。在引入修改文件跟踪之前Lore 只有两种方式获知文件系统变更lore status默认只显示已暂存staged的变更对本地修改视而不见lore status --unstaged会触发一次全递归扫描逐文件对比内容哈希与已提交修订版本。对于大型仓库后者耗时数秒到数分钟根本无法在日常交互中使用提案 Motivation 原文。这带来三个问题状态默认是盲的——用户看不到未暂存的本地修改除非显式跑一次昂贵的扫描没有通知通道——IDE、文件系统监视器、构建系统、VFS 提供方明明通过操作系统事件知道哪些文件变了却没有途径告诉 Lore只能要么过度提交全部 stage要么漏报等用户扫描跟踪逻辑重复——每个需要修改状态的应用程序都要各自实现一套跟踪行为发散、边界情况各异、无法与 Lore 共享状态。更深层的原因是--unstaged把扫描文件系统昂贵 I/O和展示已知变更廉价状态读取这两件事混在了同一个标志里。提案的核心洞察是把变更的检测detection与变更的跟踪tracking分离。检测是集成方的责任它们本来就通过 OS 事件知道变化而跟踪是 Lore 的责任持久化状态、树传播、与暂存/提交等操作交互所有消费者从唯一权威来源读取。2. 目标与非目标Goals提案目标把修改文件跟踪作为一等仓库概念Lore 无需扫描即可知道磁盘上有哪些文件被修改且该知识跨操作持久存在让外部集成能够上报修改通过轻量 API无需暂存告知 Lore 文件变化默认展示修改lore status默认显示本地修改文件无需标志或全量爬取扫描与展示分离按需扫描的结果被持久化后续 status 调用能即时展示已知变更修改状态贯穿暂存/提交生命周期暂存不清除修改跟踪只有提交才清除未纳入提交的文件保留修改状态。Non-Goals明确不做不做内容级变更跟踪只跟踪哪些文件变了不跟踪文件内部变了什么不做变更检测本提案只提供跟踪设施文件系统监视、VFS 集成、IDE 变更检测都是集成方的事dirty 跟踪 API 只是它们的公共目标不做按生命周期状态拆分动作Dirty 与 Staged 在每个节点上共享同一动作类型不支持staged 为 modify 而 dirty 为 delete这种独立动作组合。3. 核心设计Merkle 树节点上的Dirty标志位提案把修改跟踪作为仓库状态中的一等公民。数据结构的落点是 Merkle 树节点上新增的一个正交标志位。3.1 位布局V1 的 bit 3 与 V2 的 bit 15NodeFlagsV1u16此前 bit 3 名为Unused1NodeFlagsV2V2u32此前 bit 15 未定义。提案将它们分别赋予Dirty语义。这在当前源码中已经完整落地见 node.rs// V1 (u16) const File 0b1; const Link 0b10; const ExternalNameDeprecated 0b100; /// Node has been modified on the filesystem (dirty tracking) const Dirty 0b1000; // bit 3原 Unused1 /// Node is staged for commit const Staged 0b10000; // bit 4 // ... /// Action bits shared between Dirty and Staged (Modify, Add, Delete, Move, Copy) const ActionBits 0b1111100000; // bits 5-9 // ... const DirtyModify 0b101000; // Dirty Modify const DirtyAdd 0b1001000; // Dirty Add const DirtyDelete 0b10001000; // Dirty Delete const DirtyMove 0b100001000; // Dirty Move const DirtyCopy 0b1000001000;// Dirty Copy /// All dirty flags (Dirty base ActionBits) const DirtyBits 0b1111101000;V2 侧对应定义node.rs// V2 (u32) /// Node has been modified on the filesystem (dirty tracking) const Dirty 0b1000000000000000; // bit 15原未定义关键语义Dirty 与 Staged 正交Dirtybit 3位于StagedBitsV1 为0b111111111110000即 bits 4-14之外二者互不干扰共享动作位Dirty 与 Staged 共用 bits 5-9 的 Modify/Add/Delete/Move/Copy 动作位。一个节点在任何时刻只有一个动作类型无论它处于哪个生命周期状态。于是变更节点有且仅有四种合法组合dirty only、staged only、dirtystaged、clean源码中有专门测试断言这些约束node.rsassert_eq!(NodeFlags::Dirty.bits(), 0b1000); assert_eq!(NodeFlags::Dirty.bits() NodeFlags::Staged.bits(), 0); assert_eq!(NodeFlagsV2::Dirty.bits(), 1 15);V2 转 V1 时Dirty按直接位映射处理与File、Link、Discarded的既有转换模式一致见 node.rs 附近的 V2→V1 转换逻辑。3.2 传播node_mark_dirty()与 early-out 优化Dirty 标志沿 Merkle 树向上传播到父目录采用与既有 staged 传播node_mark相同的早退优化父节点已经 dirty 就停止向上。核心原语是State::node_mark_dirtystate.rs目标节点被标记为给定的 dirty 标志含动作位父目录只获得基础 Dirty 位bit 3无动作位——因为父目录的脏只是表示其下存在脏子节点不需要动作语义当mark_dirty为 false 且节点已具备目标标志时提前返回early-out设置新 dirty 位前先清除既有DirtyBits即最新动作胜出latest wins同时保留 Staged 与 Merge 位一路向上直到根块根块也被标记为脏。配套的查询原语State::node_has_dirty_childrenstate.rs遍历某父节点的子节点判断是否存在带 Dirty 标志的后代——这是父目录脏标志清理、以及跳过无脏子树的子树遍历的关键。4. 轻量上报 APIlore file dirty命令族外部进程IDE、文件系统监视器、VFS 提供方、构建系统通过新的lore file dirty命令把哪些文件变了推给 Lore而无需暂存、无需读取内容。命令族如下提案原文 file.rs 中的 CLI 定义命令语义lore file dirty paths按文件系统存在性不校验内容分类动作文件存在且在当前修订中 → modify文件存在但不在修订中 → add文件缺失但在修订中 → delete文件缺失且不在修订中 → 忽略。目录则递归其子节点lore file dirty move from to标记文件为移动不做文件系统验证调用方可信lore file dirty copy from to标记文件为复制不做文件系统验证lore file dirty --targets file从 targets 文件批量标记CLI 参数结构在 file.rs 中可见FileDirtyArgs扁平化两个参数组——路径组paths可变数量 --targets批量文件与子命令组Move/Copymove/copy各自携带from/to两个位置参数。注意路径组在顶层并不强制因为 move/copy 有各自的路径参数其必填性在 handler 层当未使用子命令时校验。dirty 状态持久化在既有的 staged anchor中——不引入新的 anchor 类型因此也不引入新的序列化格式。API 尊重与 stage API 相同的 ignore 与 view 过滤器实现中可见对FilterMode/FilterStates、is_path_under_layer_mask/route_layer_paths的复用见 dirty.rs。同时提供顶层快捷键lore dirty镜像既有lore stage快捷键。dirty.rs 的实现注释也印证了其设计意图Detected changes are marked dirty and staged in a single pass、lore dirty paths或运行lore status --scan以在整棵树范围内对账 dirty 标志见 file.rs。典型集成场景VFS 提供方VFS 提供方从内核拦截 write/rename/delete 回调把每个回调翻译成一次对应的file dirty调用就能在零文件系统扫描的情况下维护精确的 dirty 状态。同样的 API 服务于 IDE 集成、构建系统以及任何能观察到文件变化的过程——这正是提案 Goal 2 的落点。5. 状态展示lore status默认显示脏文件lore status的输出结构变化新增Dirty files (not staged for commit)区块位于 staged 区块与现已降级的unstaged 区块之间dirtystaged的文件仍出现在 staged 区块程序化输出C struct 与 JSON 事件新增flag_dirty字段。FFI 侧新字段flag_dirty追加到lore_repository_status_file_event_data_tC 结构体的flag_conflict_theirs之后保持既有字段的布局兼容。源码中对应字段为pub flag_dirty: u8由change.flags.is_dirty().into()填充见 status.rs。迁移提示此前通过flag_staged false识别 unstaged 文件的消费者应改为检查flag_dirty true。为了让 dirty 文件在驱动状态展示的 diff 输出中浮现diff 引擎diff_subtree_node()被扩展即使节点的内容哈希与比较状态一致只要带 Dirty 标志也要在 diff 中报出提案 Status display 一节。从源码看状态输出引擎同时支持基于状态树的 diff与文件系统扫描 diff两种来源并引入show_scan标志来区分哪些变更应由状态 diff 报出、哪些留给扫描去重检测见 status.rs 中reported_by_state_diff的注释A change that is neither staged nor dirty is not a working-tree change. One a scan will re-detect from the filesystem, settling its flags inline, is left to the scan。6. 按需扫描lore status --scan与 scan_dirty 模式--unstaged的另一个问题是被降级了新增lore status --scan触发一次文件系统爬取复用既有diff_filesystem()基础设施扫描比较文件系统与staged 状态因为 stage 与 dirty 标记都不会更新内容staged 状态的内容哈希就等于已提交修订的哈希--unstaged变为--scan 的隐藏别名内部StatusOptions.unstaged字段更名为scan源码中可见pub scan: bool及配套的--check-dirty选项见 status.rs。diff_filesystem遍历器被扩展出scan_dirty 模式核心实现位于 os_diff.rs入口为diff_filesystem_subtree_impl/diff_filesystem_directory等一组函数遍历过程中内联地对修改过的文件设置 Dirty、对保留匹配的文件清除过期 Dirty零额外树遍历开销父目录清理清除已无任何脏子节点目录上的 Dirty在 retain 点内联完成状态 diff 与文件系统扫描可以并行执行并通过任务计数器折叠出按动作分组的汇总事件status.rs 注释Accumulates per-action dirty counts across the parallel staged/scan walks; emitted as a single summary event for--scan/--check-dirty。从并发实现看diff 遍历还受信号量约束diff_filesystem_task_semaphoreos_diff.rs避免大型仓库扫描时任务数量失控。7. 操作交互Dirty 状态如何在生命周期中存活提案明确了 dirty 标志与各项既有操作的关系Operation interactions 一节这也是贯穿暂存/提交生命周期目标Goal 5的落地规则操作对 Dirty 的影响Stage添加 Staged 标志不清除 Dirty清标志操作在 Dirty 已设置时保留 Dirty 与动作位Unstage清除 Staged 后重新检查文件系统文件与已提交修订一致则清除 Dirty仍不一致则保留 Dirty父目录向上清理无脏子节点则清脏若 unstage 后仍有 dirty-only 节点则保留 staged anchorReset对 dirty-only 文件恢复文件内容并清除 Dirty含父目录清理对 staged 或 dirtystaged 文件继续拒绝行为不变Commit提交的文件同时清除 Dirty 与 Stageddirty-only 文件跨提交保留。提交后若仍有 dirty-only 节点staged 状态被重新挂到新修订并持久化为新 staged anchor若无脏节点anchor 被删除Sync不删除 staged anchorDirty 标志跨 sync 存活到新修订Branch switch普通切换保留 staged anchor含 dirty 标志强制切换--reset删除 staged anchor清空全部 dirty 状态Merge / cherry-pick / revert通过加法式标志操作保留既有标志Dirty 在这些操作后存活源码中State::node_mark_dirty的清除 DirtyBits 但保留 Staged/Merge 位行为、以及State上配套的清 dirty 原语node_has_dirty_children的反向操作见 state.rs 注释正是这些交互的底层支撑。相关调用点遍布 stage.rs、file/reset.rs、file/unstage.rs 与 commit.rs。8. 兼容性、安全与迁移兼容性Wire 格式不涉及。Dirty 标志只存在于本地 staged anchor从不传输给远端对端客户端/服务端协议不涉及。file dirty与--scan都是本地操作无新增 RPC磁盘格式Dirty 占 V1 bit 3原Unused1与 V2 bit 15原未定义两处都是保留未用位。旧客户端读取新客户端写入的 staged 状态时会把 dirty 位当作 flags 字段中的未知位由于旧客户端不解释 bit 3、且该位在StagedBits掩码bits 4-14之外不会影响 staged 标志的解析又因为节点 flags 字段作为不透明整数读写dirty 位会在旧客户端的读写周期中被静默保留CLI 与公开 API新增lore file dirty、lore dirty快捷键与lore status --scan--unstaged保留为隐藏别名flag_dirty追加在 C 结构体末尾保持既有字段布局。安全与隐私安全Dirty 标志是仅本地元数据存于 staged anchor从不传输、不进提交修订file dirty不读文件内容只检查存在性以分类动作信任模型不变本地用户对自己的仓库状态拥有完整访问权隐私Dirty 记录的是文件路径本就属于仓库树与动作类型modify/add/delete/move/copy无新增用户标识或元数据dirty 状态仅本地永不离开客户端机器。迁移无破坏性变更无需迁移。--unstaged作为隐藏别名保留flag_dirty追加到结构体末尾不破坏既有字段。9. 非功能属性并发、内存、确定性与风险并发模型file dirty操作作用于 staged anchor——这是一个单写者资源与stage/unstage相同的并发模型。多进程并发 dirty 通知在没有外部协调的情况下不安全这与既有暂存操作的模型一致Non-Functional Considerations 原文。内存与性能Dirty 是既有 Merkle 树节点上的单个位不分配任何新数据结构scan_dirty模式在遍历中内联设置/清除标志不额外缓冲collect_dirty_file_nodes()辅助函数只遍历脏子树不带 Dirty 标志的目录直接跳过保证查询效率状态无进程内存驻留dirty 状态持久化在 staged anchor磁盘文件跨操作只经过标准的反序列化/序列化周期确定性相同的文件系统状态产生相同的 dirty 标志file dirty对相同输入路径 存在性确定--scan对相同文件系统状态与已提交修订确定。已知风险与应对共享动作位导致动作覆盖stage 一个 modify 后再file dirty标记为 delete会把 staged 动作改成 delete。这是文档化的 latest action wins 语义——动作反映当前文件系统现实而非历史意图用户 stage 后又删除了文件理应看到删除动作扫描中断的原子性scan_dirty会在读导向操作lore status中修改 staged 状态。缓解staged anchor 在完整扫描完成后原子更新扫描中途崩溃时旧 anchor 保持完整file dirty的即时持久化产生的部分 dirty 状态也不比一次被中断的lore stage更糟存在性检查的竞态窗口file dirty通过文件系统存在性分类动作存在调用方检测与 Lore 存在性检查之间文件快速变化的竞态。move/copy子命令通过完全信任调用方来规避这一点。代价DrawbacksDirty 与 Staged 共享动作位无法同时表示两个生命周期状态的不同动作如staged 为 modifydirty 为 deletefile dirty的一次同步存在性检查引入了轻微系统调用开销与竞态窗口staged anchor 随 dirty 跟踪文件数增长dirty 状态与 staged 状态共处同一 Merkle 树但被仓库文件总数所界定且沿用 staged 状态同一套基于块的序列化成本随既有基础设施线性扩展。10. 备选方案回顾为什么放弃三种更简单的设计提案明确评估并否决了三个备选方案独立 dirty anchoranchor-dirty单独存储 dirty 状态。否决理由每次 status 都要加载并 diff 两棵状态树序列化/反序列化成本翻倍单 anchor 模型避免了双树同步问题并完整复用既有基础设施——dirty 标志作为同一节点上的附加位是更自然的选择扁平路径集合hash set / 排序列表在 Merkle 树之外维护扁平 dirty 路径表。否决理由丢失与树遍历和 diff 基础设施的集成基于路径的查找无法利用 Merkle 树的层次结构做高效的子树操作此目录下是否有任何文件是脏的且每次 status 都要将扁平集合与树对账徒增复杂度而无性能收益file dirty时做内容哈希验证读取并哈希文件内容来确认文件真的变了。否决理由内容哈希违背轻量通知通道的设计初衷——调用方IDE/监视器已经知道文件变了再读文件又重新引入了 dirty 跟踪 API 本要避免的 I/O 成本。需要内容级验证时用户可以用--scan。11. 与既有 VCS 的对照Prior Art提案把 Lore 的方案放在 VCS 谱系中定位Git用 index暂存区跟踪工作树状态git status每次对比工作树与 index、index 与 HEAD做全量文件系统扫描用 fsmonitor 扩展钩住 OS 级变更通知macOS 的 FSEvents、Windows 的 ReadDirectoryChangesW来跳过未修改子树VFS for Git前 GVFS维护一份由投影文件系统提供方填充的 modified-paths 列表。Lore 的file dirty扮演相似角色——外部进程与 VFS 提供方上报变更——但把结果集成进既有 Merkle 树而非使用单独的 watch 位图或旁路文件Perforce通过显式 checkout 跟踪文件状态文件默认只读直到p4 edit才标记为打开编辑并变为可写——完全不隐式检测变更的反向极端。Lore 介于两者之间既支持显式通知file dirty也支持按需扫描--scanMercurial用 dirstate 记录每个被跟踪文件的预期 size/mtime/modehg status先用文件系统元数据比对定位变更、仅当元数据不一致时才回退到内容比较。Lore 的快速路径与之同源——见file_modification函数state.rs先比 sizeModifiedBySize再比记录的 mtimeUnmodifiedByMtime最后才哈希内容。Mercurial 的 Rust 重写rhg也加入了与 Git fsmonitor 精神类似的文件系统监视器集成。12. 遗留未决问题提案在收尾时保留了三个未决问题供后续实现继续打磨file dirty在未指定动作子命令时应验证内容与已提交修订一致还是仅靠文件系统存在性即可分类动作--scan如何处理 dirty-moved 但目标文件缺失的节点备选在树中还原 move把节点恢复到提交位置或转换为 dirty-delete--scan如何处理 dirty-added零内容哈希但文件已从磁盘删除的节点备选若未暂存则整节点丢弃若已暂存则仅清除 dirty 标志。13. 从提案到代码当前仓库的落地状态在本文撰写时的当前仓库中该提案的主体已经落地可以作为交叉验证的源码证据链标志位定义与测试node.rsV1Dirty 0b1000、DirtyBits、DirtyModify/Add/Delete/Move/Copy、node.rsV2Dirty 1 15位不变式断言在 node.rs传播原语state.rsnode_mark_dirty父节点仅基础 Dirty 位 early-out、state.rsnode_has_dirty_children命令实现file/dirty.rsDirtyError错误集、modify/add/delete/move/copy 各分类路径上的node_mark_dirty调用、file.rsFileDirtyArgs/--targets/move/copyCLI 参数状态展示与扫描repository/status.rsflag_dirty字段、scan选项、show_scan区分状态 diff 与扫描 diff、并行扫描汇总、state/os_diff.rsdiff_filesystem基础设施与扫描并发控制快速路径state.rsfile_modificationsize → mtime → hash 三级判定。总体而言Modified File Tracking 提案为 Lore 补齐了修改状态这一 VCS 交互中的关键拼图用 Merkle 树上的一个正交标志位把变更检测交给集成方与变更跟踪交给仓库彻底分离让lore status从默认盲目变为默认知情同时保留--scan作为按需的、结果可持久化的全量对账手段。赞分享版本控制后端【免费下载链接】loreLore is a next-generation, open source version control system项目地址https://gitcode.com/gh_mirrors/lore6/lore点击查看免费下载相关推荐Linux 内核 Si4713 FM 无线电发射器驱动深度解析V4L2 控制、RDS 与 RNL 测量实战指南Linux 内核 Si4713 FM 无线电发射器驱动深度解析V4L2 控制、RDS 与 RNL 测量实战指南 导读 本文以内核文档 Documentatio版本控制后端Lore 日志体系全解tracing 与 Lore 宏的双轨架构、级别门控与日志文件轮转Lore 日志体系全解tracing 与 Lore 宏的双轨架构、级别门控与日志文件轮转 Lore 代码库中存在两套并行的日志系统面向服务端和工具链的 tr版本控制后端gh_mirrors/co/completion核心功能解析代码补全、定义跳转与文档查看全攻略gh_mirrors/co/completion核心功能解析代码补全、定义跳转与文档查看全攻略 GitHub 加速计划 / co / completion 是版本控制后端上一篇终极开源项目影响力评估指南star-history工具深度评测下一篇gh_mirrors/sh1/sh的发布准备文档准备清单与检查项创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

硬件电路设计经典模块实战:防反接、MOS管开关与BUCK电路详解 2026/9/25 7:44:26

硬件电路设计经典模块实战:防反接、MOS管开关与BUCK电路详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
LibreOffice安装配置与服务器端转换实战指南 2026/9/25 7:44:26

LibreOffice安装配置与服务器端转换实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32驱动DHT11温湿度传感器:时序、驱动与排坑详解 2026/9/25 7:44:26

STM32驱动DHT11温湿度传感器:时序、驱动与排坑详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32嵌入式开发入门:架构、外设与工程实战指南 2026/9/25 7:44:26

STM32嵌入式开发入门:架构、外设与工程实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
汽车之家语音POC测试:从播放音频到服务可靠 2026/9/25 7:44:26

汽车之家语音POC测试:从播放音频到服务可靠

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Atlas 300V 24G推理加速卡实战:从模型转换到YOLO部署全解析 2026/9/25 7:44:20

Atlas 300V 24G推理加速卡实战:从模型转换到YOLO部署全解析

“atlas 300v 24g 是运算加速卡吗”,这个搜索词我太熟悉了。去年给自己找推理卡的时候,我几乎把Atlas 300V 24G的相关资料翻了个遍,后来干脆直接拿它部署YOLO模型,一跑就是大半年。在AI推理这个圈子里,华为Atlas系列已…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉