
Tolaria 非 Git 库支持设计解析ADR-0085 如何让普通 Markdown 文件夹直接可用【免费下载链接】tolariaDesktop app to manage markdown knowledge bases项目地址: https://gitcode.com/GitHub_Trending/to/tolaria本文围绕 Tolaria 仓库中的架构决策记录 ADR-0085 展开讲解非 Git 库non-git vault作为受支持状态而非错误状态这一设计如何取代早期强制 Git策略并结合useGitSetupState状态机、init_git_repo后端命令与冒烟测试说明用户从打开普通文件夹到事后启用 Git 的完整技术链路。读完后你将理解 Tolaria 的 Git 能力是如何按每个库各自的状态做功能门控的以及初始化 Git 时后端实际执行了哪些安全校验与提交步骤。从硬前置条件到受支持状态ADR-0085 的产生背景ADR-0085 的 frontmatter 声明了它的基本身份type: ADR id: 0085 title: Non-git vaults open with explicit later Git initialization status: active date: 2026-04-26 supersedes: 0034它明确取代了 ADR-0034。ADR-0034 曾把 Git 设为打开库的硬前置条件当时 Git 支撑的缓存、历史、变更与同步流程在用户打开纯 Markdown 文件夹时会静默失败——缓存算不出 commit hash、Pulse/Changes 面板为空、commit/push 命令报错且这些失败对用户不可见。ADR-0034 的做法是当库目录下没有.git时用一个阻塞式模态框阻止一切使用直到用户一键初始化 Git 仓库或换一个库检查由轻量的is_git_repoTauri 命令完成只检查.git是否存在不校验 remote 或提交历史浏览器/开发模式下该检查直接跳过。这种保护 Git 功能的做法挡住了最常见的采用路径从 Obsidian、iCloud、Dropbox 或手工维护的笔记目录中打开一个现有文件夹。ADR-0085 因此反转了默认值——浏览和编辑 Markdown 应当立即可用Git 只是用户可以显式开启的能力用于历史、同步、提交或协作。核心决策非 Git 库是受支持状态不是错误状态ADR-0085 的决策原文可以归纳为三层行为约定即使不是 Git 仓库也打开现有 Markdown 文件夹。打开时 Tolaria 会询问是否初始化 Git如果用户关闭提示应用继续正常工作状态栏会持续显示Git disabled警告。重新进入设置的两个入口点击该警告或从命令面板执行Initialize Git for Current Vault都能重新打开初始化动作。库处于非 Git 状态期间的能力边界Git 历史、变更、提交、同步、冲突与 remote 相关操作被隐藏或禁用后台自动同步Auto-sync和 AutoGit 检查点不再运行Markdown 扫描、笔记浏览、笔记编辑、搜索以及其他非 Git 功能照常工作。ADR 同时强调init_git_repo是事后启用 Git 的唯一后端命令——它创建仓库、写入 Tolaria 的默认.gitignore、暂存整个库并创建一个无签名的初始化提交。ADR 还列出了被否决的两个替代方案理解它们能看清设计权衡Option A采纳受支持的非 Git 模式 显式事后初始化。采用路径最顺Git 能力保持可见但不阻塞基础笔记流程。Option B保留 ADR-0034 的阻塞模态框。能防止 Git 功能语义模糊但拒绝了合法的纯文件夹工作流。Option C打开普通文件夹时自动初始化 Git。摩擦最低但对不希望 Tolaria 修改文件夹元数据的用户来说行为出人意料。前端状态机useGitSetupState如何驱动询问—关闭—重开循环文档中打开时询问、关闭后持续警告、点击警告重开的交互在渲染进程中由 useGitSetupState 实现。这个 Hook 维护一个三态状态机export type GitRepoState checking | missing | ready其关键机制包括状态探测checkGitRepo在 Tauri 环境调用invoke(is_git_repo, { vaultPath })浏览器/开发环境走mockInvoke结果映射为ready是 Git 仓库或missing不是。探测失败时按ready处理即检查失败向放行方向失败避免探测异常卡死启动流程。是否弹窗shouldShowGitSetupDialog的判定逻辑是——处于windowMode或状态不是missing时不弹用户手动打开过则强制显示否则要求gitSetupPreference ! never且该路径未曾被关闭过dismissedGitSetupPath ! resolvedPath。关闭与永不再问dismissGitSetupDialog只记录当前路径不再提示neverForVaultGitSetupDialog则把偏好设为never从此该库不再自动弹出但仍可手动重开。手动重开openGitSetupDialog把manuallyOpened置为 true 并清除关闭记录——这就是点击状态栏警告 / 从命令面板执行后能再次看到设置界面的实现来源。初始化成功后的状态收束handleInitGitRepo调用init_git_repo命令后执行markGitRepoReady()、把偏好重置回prompt、清除手动与关闭标记并弹出Git initialized for this vault的 Toast。状态栏文案Git disabled来自本地化资源 en.json 中的status.git.disabled键测试 StatusBar.test.tsx 也断言了该文案的渲染。init_git_repo唯一的事后启用 Git 后端命令后端实现位于 commands/git.rs。is_git_repo命令委托给is_inside_work_tree判断路径是否在 Git 工作树内含父仓库场景而init_git_repo在执行初始化前先经过一层validate_git_init_target防护目标路径必须存在且是目录否则分别报Choose an existing vault folder before initializing Git/Choose a folder before initializing Git如果目标是 Desktop、Documents、Downloads 等宽泛的个人文件夹且不含 Tolaria 库标记文件AGENTS.md、CLAUDE.md、type.md、note.md任一文件或attachments、type、views任一目录会被拒绝错误信息会建议改用如路径/Tolaria的子文件夹——防止在用户整个文档目录下执行git init如果路径已经处于某个 Git 工作树内且自身没有直接 Git 元数据也直接拒绝错误信息说明 Tolaria 会使用父仓库而非创建嵌入式仓库。通过校验后init_git_repo调用 git/mod.rs 中的init_repo其执行顺序固定为四步run_git(dir, [init])?; // 1. 创建仓库 ensure_author_config(dir)?; // 2. 确保提交者身份尊重已有全局身份缺失时补回退值 ensure_gitignore(dir)?; // 3. 写入默认 .gitignore已存在则不动 run_git(dir, [add, .])?; // 4. 暂存全库 commit_initial_vault_setup(dir); // 5. 创建初始化提交其中初始化提交显式禁用 GPG 签名-c commit.gpgsignfalse commit -m Initial vault setup对应 ADR 所说的无签名的 setup commit——用户可能尚未配置任何提交身份ensure_author_config负责兜底。默认.gitignore内容DEFAULT_GITIGNORE常量刻意排除机器相关与平台元数据文件# Tolaria app files (machine-specific, never commit) .laputa/settings.json # macOS .DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Editors .vscode/ .idea/ *.swp *.swo并且ensure_gitignore的语义是文件已存在则完全不修改保证不会覆盖用户手工维护的.gitignore。值得注意的是移动端编译下这些命令是返回错误信息的桩实现如Git history is not available on mobile即完整 Git 流程依赖桌面端构建。能力门控命令注册与状态栏随库状态切换ADR 的 Consequences 部分要求UI 表面必须把 Git 能力当作每个库各自的状态而不是应用级不变量。这一点在 gitCommands.ts 的命令注册函数中体现得非常直接export function buildGitCommands(config: GitCommandsConfig): CommandAction[] { if (config.gitFeaturesEnabled false) return [] if (config.isGitVault false) return buildInitializeGitCommand(config) return buildGitVaultCommands(config) }全局 Git 功能关闭Git 组命令为空当前库非 GitGit 组只注册Initialize Git for Current Vault关键词含git、initialize、enable、history、syncpull、commit、changes、conflict、remote 等命令全部不出现当前库是 Git 仓库注册完整的命令集包括Commit Push仅在modifiedCount 0时可用、Generate Commit Message from Diff、Add Remote to Current Vault、拉取、Resolve Conflicts、View Pending Changes等。ARCHITECTURE.md 对同一行为的描述是当库不是 Git 仓库时Tolaria 把 Git 视为不可用而非降级——状态栏用Git disabled警告替换掉 changes、commit、sync、remote、conflict、history 控件除非用户对该库选择了不再自动提示useAutoSync对非 Git 库被禁用应用不会针对普通文件夹发起任何后台 Git 命令。ABSTRACTIONS.md 中的状态表也把Non-git列为一种命名状态库路径是普通文件夹Markdown 扫描、编辑、搜索、导航可用Git 相关的状态栏控件与命令面板条目被Git disabledInitialize Git for Current Vault替代。验证链路冒烟测试覆盖打开—关闭—事后初始化ADR 要求测试需要同时覆盖 Git 库与非 Git 库。Playwright 冒烟测试 non-git-vault-init.spec.ts 正是这条链路的端到端验证完整走一遍用户旅程用createFixtureVaultCopy复制一个夹具库并以isGitRepo: false的方式打开断言笔记列表可见Alpha Project出现证明非 Git 状态下核心浏览功能正常断言出现Enable Git for this vault?标题的初始化对话框按Escape关闭对话框断言对话框消失且状态栏status-missing-git显示Git disabled——对应 ADR 中关闭后应用继续工作 持续警告打开命令面板执行Initialize Git对话框再次出现聚焦Initialize Git按钮回车确认断言对话框消失、Git disabled警告消失、status-pulsePulse 面板入口出现——证明 Git 能力Pulse 等在初始化后恢复。此外commands/git.rs 自带的 Rust 单测还覆盖了初始化校验的边界情况例如init_git_repo_rejects_broad_personal_folders拒绝宽泛个人文件夹、init_git_repo_allows_named_vault_subfolder_under_documents允许 Documents 下带名称的库子目录、is_git_repo_accepts_vault_nested_inside_parent_worktree嵌套在父工作树中的库视为 Git 库等与前端状态机的三态判定形成前后端一致的语义。决策后果与适用边界ADR-0085 列出的四条后果结合仓库现状可以这样理解既有 Git 库行为不变历史、提交、同步、remote 流程与之前完全一致非 Git 模式只是新增的合法起点Git 能力是按库的状态量UI 各表面状态栏、命令面板、自动同步都必须依据当前库的 Git 状态注册功能不能假设整个应用都有 Git双态测试覆盖成为常态要求浏览器 mockmock-tauri的mockInvoke路径与原生 QA 都要同时覆盖 Git 与非 Git 库约束未来功能任何新增的 Git 依赖功能都必须先检查当前库的 Git 状态才能注册命令或运行后台任务——这也是buildGitCommands这种按状态选命令集模式存在的原因。适用前提方面需要注意完整流程依赖桌面端Tauri构建移动端对 Git 命令返回不可用错误is_git_repo的探测在异常时按通过处理所以它只是一个轻量存在性检查不做 remote 或历史校验而打开时是否自动弹窗还受gitSetupPreferenceprompt/never控制用户可以按库选择永不再被自动询问但随时能通过状态栏警告或命令面板手动重新启用 Git。【免费下载链接】tolariaDesktop app to manage markdown knowledge bases项目地址: https://gitcode.com/GitHub_Trending/to/tolaria创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考