Skip to content

[Feature] 远程同步:Git 通道支持仓库内子目录前缀(多工具备份同一私有仓库,各自独立) #131

Closed

Description

@LingYingNX

使用场景

Image

我用同一个私有仓库(LingYingNX/backup)集中备份多款工具的配置,按工具分子目录:

  • Hindsight知识库备份/
  • magpie备份/
  • DSH备份/(本次为 DSH 配置同步新建)

这是我长期形成的「一个仓库 + 每个工具一个子目录」的备份习惯,便于统一管理、统一权限、统一查看提交历史。

问题

dsh-config-manager 的 Git 通道只能配置「仓库地址」一个字段,快照固定写到仓库根目录下的 snapshots/、snapshots-encrypted/、blobs/,没有子目录 / 路径前缀选项:

  • src/sync/sync-config.ts:
export interface GitConfig { repoUrl: string }
  • src/sync/git/git-transport.ts:171-187:
const SNAPSHOTS_REL = 'snapshots'
const SNAPSHOTS_ENCRYPTED_REL = 'snapshots-encrypted'
const BLOBS_REL = 'blobs'

上传路径统一拼在工作副本根。结果是:只要在这个仓库里启用 DSH 同步,snapshots/ 等目录就会散落在仓库顶层,与 Hindsight知识库备份/、magpie备份/、DSH备份/ 平级,破坏「每个工具一个独立目录」的结构;如果为了保持整洁而换一个专用仓库,又多出一个仓库要管理。

S3 通道有「对象键前缀」、Gist 通道有「文件名前缀」,说明框架本身支持带前缀的存储布局,只是 Git 通道没有暴露这个能力。

期望方案

给 Git 通道增加一个可选的「仓库内子目录 / 路径前缀」配置项(例如 subdir: "DSH备份"),所有快照写入 subdir/snapshots/、subdir/snapshots-encrypted/、subdir/blobs/,读取、比对、清理、接管历史等逻辑同样以该前缀为根。

参考实现要点:

  1. 配置项:GitConfig 增加可选 subdir(或 pathPrefix),默认空 = 当前行为,保证向后兼容;UI 放在「仓库地址」下一行,标注「可选,留空则写入仓库根目录」。
  2. 路径拼接:git-transport.ts 中所有 ${SNAPSHOTS_REL}/... 统一改为 ${prefix}${SNAPSHOTS_REL}/...,并对前缀做合法性校验(禁止绝对路径、..、反斜杠、以 .git 开头等)。
  3. sparse-checkout:cloneIntoWorkDir() 的 sparse-checkout set --cone snapshots snapshots-encrypted blobs 也要带上前缀(cone 模式下传 subdir/snapshots 这类路径即可)。
  4. adopt 边界:ADOPT_ROOT_ALLOW 的顶层白名单要按前缀调整,避免把带前缀的仓库误判为「另有用途的仓库」而拒绝接管历史。
  5. 兼容与迁移:老配置(无 subdir)行为完全不变;从「根」切到「子目录」时给出提示,说明两侧快照历史不互通(或提供一次性迁移)。

备选方案

  • 保持现状,另建一个专用私有仓库给 DSH 使用:能解决隔离问题,但仓库数量变多,不符合「一个仓库集中管理」的习惯。
  • 改用 WebDAV / S3 通道:这两条通道本来就有子目录 / 前缀,但需要额外的服务端,成本更高。
  • 由插件在 git 层硬编码一个固定子目录(例如统一写 dsh-config-manager/):至少不污染仓库顶层,但仍不可配置,不如做成可选前缀。

补充

仓库现状截图(根目录下按工具划分的多个备份目录):


Triage 诊断(AI)

This was generated by AI during triage.

状态:未实现。诊断完成,4 项设计决策已由维护者拍板;agent brief 已发,票转 ready-for-agent。

现状核对

  • GitConfig 只有 repoUrl,git 通道没有前缀字段。
  • 三处同步目录(明文快照 / 加密快照 / 内容寻址 blob)是模块级常量,上传、下载、删除、GC、远端统计全在仓库根上拼路径。
  • 同一能力在 S3(prefix)与 gist(filePrefix)已有先例,git 缺这一层;诉求成立,分类 enhancement。

变更面

路径常量与拼接、sparse 面(SYNC_ROOT_DIRS)、adopt 判据(ADOPT_ROOT_ALLOW)、GitTransportOptions 与 host 装配、sync-config 的 v2 解析与写入、通道配置 UI、对外契约 docs/contracts/sync-channel-v1.md 的通道布局表。

定案(2026-11-09 维护者拍板)

  1. 前缀变更 → 强制重建工作副本:复用既有 relink / adopt / reclone 入口;前缀纳入工作副本身份判定,不符即报「需重建」,不做静默迁移。
  2. adopt 改判 <subdir>/ 子树:只要求该子树下只出现三类同步目录,仓库顶层允许有别的目录(多工具备份仓库的正常形态);子树内出现陌生条目仍拒绝。
  3. 不做快照迁移:根 ↔ 子目录切换只提示「两侧历史不互通」。
  4. 前缀口径:允许 UTF-8(中文目录)与嵌套;拒绝绝对路径、..、反斜杠、空段、首尾斜杠、.git 段。

下一步:AFK agent 按 brief 实施;完成后按 issue-intake-response 回访报告者。

进度

  • 进度:100%(2026-11-09T22:06:23+01:00):已实现并本地验证通过(typecheck / npm test 5525 通过 / build 全绿),尚未发版

Activity

  1. github-actions commented on Nov 9, 2026

    @github-actions
    Contributor

    感谢反馈!🙏 我通常会在 48 小时内回复;这条已加上 needs-triage,进度会体现在标签上。

    Thanks for the report! I usually reply within 48h. This issue is labeled needs-triage; progress shows up in the labels.

    如果还没写,补上这几项能少好几轮来回 / Adding these saves round trips:

    • 截图 / 录屏 Screenshot —— 直接把图片拖进编辑框,或 Ctrl+V 粘贴
    • 控制台报错 Console —— F12 → Console,复制文本或截图
    • 环境 Environment —— 插件版本(设置 → 备份与迁移 → 关于,可一键复制)、DSH 版本、系统、浏览器版本、显示缩放与浏览器缩放、深色/浅色

    ⚠️ 请务必抹掉 API Key / Token / 密码等敏感信息(包括截图里的)。
    Never paste real secrets — including inside screenshots.

  2. added
    enhancementNew feature or request
    needs-triage等待维护者分类与确认(awaiting maintainer triage)
    on Nov 9, 2026
  3. xiajiajun516 commented on Nov 9, 2026

    @xiajiajun516
    Owner

    This was generated by AI during triage.

    Agent Brief

    Category: enhancement
    Summary: git 同步通道增加可选的「仓库内子目录前缀」,让多工具共用一个备份仓库时各自独立。

    Current behavior:
    git 通道的配置只有仓库地址(GitConfig 只有 repoUrl)。三处同步目录——明文快照目录、加密快照目录、内容寻址 blob 目录——是模块级常量,上传、下载、删除、GC、远端快照统计都直接拼在工作副本根上。首次 clone 的 sparse-checkout 面与 adopt 模式的顶层白名单也由同一组常量派生。结果是:在一个已按工具分好子目录的备份仓库里启用 DSH 同步,这三个目录会落在仓库顶层,破坏「一个工具一个目录」的结构。

    Desired behavior:

    1. git 通道配置新增可选前缀(建议字段名 subdir,语义对齐 S3 的 prefix):缺省或空 = 现有行为(写仓库根);配置后所有同步目录都落到 <subdir>/ 之下,读写、比对、删除、GC、远端统计、sparse 面、adopt 判据全部以该前缀为根。
    2. 前缀校验允许 UTF-8(中文目录必须能用)与嵌套(a/b);拒绝绝对路径、..、反斜杠、空段、首尾斜杠、.git 段。校验失败回结构化错误码,不静默丢弃该值。
    3. 前缀变更 = 工作副本布局变了:必须能判定「当前工作副本是按哪个前缀建的」,不符时报「需重建工作副本」并引导走既有的 relink / adopt / reclone 入口。不得静默复用旧工作副本——sparse 面只在首次 clone 生效,旧副本里没有新前缀那棵树,否则用户看到的是「远端没有快照」。
    4. 不做快照迁移:根 ↔ 子目录切换时明确告知两侧快照历史不互通。
    5. adopt 在设了前缀时改判 <subdir>/ 子树:只要求该子树下只出现三类同步目录;仓库顶层允许出现别的目录(多工具备份仓库的正常形态)。子树下出现陌生条目仍然拒绝。
    6. UI 在仓库地址下一行加可选输入,标注「可选,留空则写入仓库根目录」;文案进字典(zh 逐字保留 + en 补齐),不得硬编码。
    7. 对外契约的通道布局表补上 git 的前缀形态。

    Key interfaces:

    • GitConfig:新增可选前缀字段。v2 命名空间的解析与写入都必须显式搬运它——当前解析只构造 { repoUrl },不显式搬字段会被静默丢掉。
    • GitTransportOptions:新增同一前缀字段,由 host 装配处从配置传入。
    • 前缀校验:复用 validateCloudPrefix 的口径(禁绝对路径、..、反斜杠、空段),扩展为允许 UTF-8 与嵌套段,并补 .git 段与首尾斜杠拒绝;错误码并入同族的既有错误码集合。
    • 三处目录常量及其派生(sparse 面 SYNC_ROOT_DIRS、adopt 白名单 ADOPT_ROOT_ALLOW):改为按前缀派生,不再在模块顶层固化。
    • 工作副本身份:当前工作副本目录与 repoUrl / 前缀都无关,需要新增「这个副本是按哪个前缀建的」的判定依据(落盘标记或配置指纹均可),判不出时不得静默复用。

    Acceptance criteria:

    • 未配置前缀时 git 通道行为与现在一致:仓库根布局不变,既有测试全绿
    • 配置 subdir: "DSH备份" 后 push 的快照落在 DSH备份/snapshots/…、DSH备份/snapshots-encrypted/…、DSH备份/blobs/…,仓库顶层不出现这三个目录
    • 同一配置下 list / download / delete / GC / 远端统计都能从带前缀的位置读回刚 push 的内容
    • 带前缀首次 clone 的 sparse-checkout 面包含 <subdir>/ 下三个目录,且不 materialize 仓库里其它工具目录
    • 带前缀时 adopt 在多工具仓库(顶层含别的工具目录)上成功;<subdir>/ 下出现陌生条目仍被拒绝
    • 前缀从空改成非空(或反之)后,状态/自检给出「需重建工作副本」的明确错误,不表现为「远端没有快照」
    • 前缀校验:中文与嵌套 a/b 通过;绝对路径、..、反斜杠、空段、首尾斜杠、.git 段被拒并回错误码
    • 配置往返:写入后读回字段不丢;旧 v2 配置文件(无该字段)读出来等于「根」
    • UI 输入为空或非法时给出可操作提示,非法值不落盘
    • 契约文档的通道布局表已更新;CHANGELOG.md 的 ## [Unreleased] 有用户可见条目

    Out of scope:

    • 把根目录已有快照一次性迁移到子目录(明确不做)
    • 给 webdav 通道加前缀(它本来就有路径前缀,行为不动)
    • 改 gist / s3 的前缀语义
    • 自动静默重建工作副本(只提示,走既有重建入口)
  4. added
    ready-for-agent完全描述清楚、可直接交给 AFK agent(fully specified, ready for an AFK agent)
    sync远程同步 / 传输通道(Git、WebDAV、一键同步、自动同步)
    and removed
    needs-triage等待维护者分类与确认(awaiting maintainer triage)
    on Nov 9, 2026
  5. xiajiajun516 commented on Nov 9, 2026

    @xiajiajun516
    Owner

    已在 v0.7.0 修复并发布。

    Git 通道现在可以在同步设置里填一个仓库内子目录前缀(例如 DSH备份/),快照就落在这个子目录下;留空仍是原来的仓库根布局,行为不变。

    升级:dsh plugin --profile web add dsh-config-manager@latest(桌面版在插件页更新后重启)。

    自证三步:

    1. 同步设置 → Git 通道 → 子目录前缀填 DSH备份/,保存;
    2. 手动同步一次,仓库里应出现 DSH备份/snapshots/… 而不是根目录下的 snapshots/;
    3. 把前缀清空再同步一次,应回到根布局(旧快照不受影响)。
  6. added
    fixed已在某个版本中修复(fixed in a release)
    and removed
    ready-for-agent完全描述清楚、可直接交给 AFK agent(fully specified, ready for an AFK agent)
    on Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfixed已在某个版本中修复(fixed in a release)sync远程同步 / 传输通道(Git、WebDAV、一键同步、自动同步)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions