# lib/git → KenShell gRPC 迁移说明与待办 ## 0. 当前状态(已完成) - 新增 crate `lib/kenshell`:`proto/kenshell/**` 与 `proto/gitken/v1/{lint,shared,cleanup,conflicts}.proto` 从 `KenShell/proto` 原样复制;`build.rs` 只生成 client;`KenShellClient` 暴露全部 `kenshell.v1` 与 `kenshell.internal.v1` 服务客户端,并统一 64 MiB 消息上限与 `x-request-id`。 - 配置写在 `[git]` 段:`kenshell_endpoint`、`kenshell_rpc_key`、`kenshell_timeout_secs`。 - `lib/git` 不再包含任何 `gix`、不再 spawn `git`: - 删除 `lib/gitbaby`(整个 crate)与 workspace 依赖 `gix`、`russh`、`ssh-key`、`sha1`。 - 删除 `src/smart/**`、`src/ssh/**`、`src/graphql/**`、`src/share/git_env.rs`、 `src/service/gitcmd.rs`、`src/lfs/{object,handle}.rs`。 - `src/sync/` 只保留 Redis 队列与事件类型(`queue`/`event`/`error`),worker 删除。 - `GitService` 持有 `KenShellClient`;`GitContext` 由「本地路径 + gix 仓库」改为 「`RepositoryRef` + KenShell 客户端」。 - `src/rpcgit/` 是 KenShell 的薄封装:保留原 `gitbaby` 的公开数据类型与 `GitBaby` 方法签名,内部全部映射到 gRPC;业务层(service/handler)改用 `crate::rpcgit::...`。 - 已切到 RPC 的能力:tree/file 列表与解析、blob 元数据/内容/LFS 指针、commit 列表/详情/ 统计/blame/rev-parse/is-ancestor、diff(raw/range/shortstat/numstat/changed-paths/ compare/diff-tree)、refs/branches/tags 读写、conflict 检查与明细、analysis 读、 archive 创建与查询、remote 增删查与 import/fetch/push(异步 Job 轮询)、 repository 存在性/体积、commit status 回写、code comment 的 revision 解析。 - `app/githost` 退役(smart HTTP/SSH 由 KenShell 提供);`charts` 与 `scripts/dev.*` 移除 githost、改由 `kenshell.*` 配置注入 `/git` 环境变量。 ## 1. 架构边界 | 关注点 | 归属 | | --- | --- | | Git 对象库、引用、pack、LFS 对象、smart HTTP、SSH | KenShell | | 仓库/分支/标签/提交/PR/评论/星标等元数据 | KenApi 数据库 | | LFS 锁 | KenApi 数据库(KenShell 无锁协议) | | 页面渲染(maud HTML 片段、PDF 分页) | KenApi | | 定时任务 | 已移除 | `GitContext` 只描述「哪个仓库」: ```rust GitContext { model, cache, database, space_name, repo_root, ks } ``` `space_name` 是组织 slug,`model.name` 是仓库名,二者组成 KenShell 的 `RepositoryRef`。 **前提**:KenShell 必须能按 `(org slug, repo name)` 解析到自己的仓库行。 ## 2. KenShell 已覆盖、且已完成对接 | API / 能力 | KenShell RPC | | --- | --- | | `GET /tree/{rev}`、`/html/*` 目录读取 | `TreeService/GetTree`、`ListFiles`、`ResolveTreePath` | | `GET /blobs/{oid}/metadata`、`/content` | `BlobService/GetBlobMetadata`、`GetBlobContent` | | `GET /lfs-pointers` | `BlobService/ListLfsPointers` | | `GET /commits`、`/commits/{rev}`、`/commits/stats`、`/commits/ancestor`、`/rev/{rev}` | `CommitService/ListCommits`、`GetCommit`、`GetCommitStats`、`IsAncestor`、`RevParse` | | `GET /blame` | `CommitService/ListBlame` | | `GET /diff`、`/diff/raw`、`/diff/for-commit`、`/diff/range` | `DiffService/CompareCommits`、`GetRawDiff`、`ListChangedPaths`、`ListDiffTree`、`GetRangeDiff`、`GetDiffShortStat`、`ListDiffNumStats` | | `GET /conflicts`、`/conflicts/detail` | `ConflictService/CheckConflicts`、`GetConflictDetail` | | `GET /analysis/{languages,contributors,code-activity}` | `AnalysisService/GetLanguages`、`ListContributors`、`GetCodeActivity` | | `POST /archives`、`GET /archives/{rev}`、`/archives/bundle` | `ArchiveService/StartArchive`、`GetArchiveArtifact`、`StartArchiveBundle`(Job 轮询) | | `GET /remotes`、`PUT/DELETE /remotes/{name}` | `RemoteService/ListRemotes`、`UpsertRemote`、`RemoveRemote` | | `POST /remotes/{import,fetch,push}` | `RemoteService/StartRemoteImport|StartRemoteFetch|StartRemotePush`(Job 轮询) | | `GET/POST /branches`、`GET/DELETE/PATCH /branches/{name}`、`{name}/default` | `RefService/*`、`CommandService/*` | | `GET/POST /tags`、`GET/DELETE /tags/{name}` | `RefService/ListTags|GetTag`、`CommandService/CreateTag|DeleteTag` | | `GET /path-log` | `CommitService/ListCommits(path=...)`(近似,见 §4) | | 仓库创建 | `CommandService/CreateRepository` | ### 语义变化(调用方已适配) 1. **远端导入/拉取/推送**:由同步返回结果改为启动 Job 并轮询 `JobService/GetJob`。 HTTP 响应字段保持兼容(`default_branch`/`commit_count`/`updated`/`new`/`pushed`/`rejected`)。 2. **归档**:KenShell 生成产物后返回 `storage_key` + `download_url`,KenApi 不再自己打包、 不再写入自己的 S3。 3. **仓库创建**:只创建裸库和默认分支,**不再写入初始提交/README**(见 §4)。 4. **Tag 详情**:`TagView` 没有 tag 对象的 oid,`GitBaby` 用 `target_sha` 填充 `TagInfo.sha`,前端展示不受影响;若需要区分 tag 对象 oid,需 KenShell 补字段。 5. **Blame**:以 `BlameLineView` 逐行返回,KenApi 按连续相同 commit 聚合成 hunk; `previous_sha`/`previous_path`/`orig_start_line` 固定为空(原实现有值)。 ## 3. 保留在 KenApi 的本地能力(不依赖 git 对象库) | 能力 | 说明 | | --- | --- | | LFS 锁(`/lfs/locks*`) | `git_lfs_lock` 表;KenShell 只有对象与 LFS HTTP 协议 | | 分支/标签保护、白名单 | KenApi 数据库;写操作时前置校验 | | releases / stars / watch / topics | KenApi 数据库 | | code comments(含 resolve/parent/outdated) | KenApi 数据库;KenShell 的 `CodeCommentService` 字段不足 | | HTML 片段(readme/tree/blob-pages/languages 等) | maud 渲染,数据来自 RPC | | PDF 分页 | `hayro`,输入来自 `BlobService` | | `POST /utils/patch/parse` | 纯文本解析 | | `POST /utils/commit-signature` | 读取用户身份,无 git | ## 4. 未覆盖能力(当前返回 `501 Not Implemented`) 统一错误:`GitError::Unimplemented` → HTTP 501。路由与 OpenAPI 声明保留,便于后续补齐。 | 接口 / 能力 | 现状 | 需要的 KenShell 能力 | | --- | --- | --- | | `POST /pulls/{id}/merge`、`POST /pulls/{id}/update-branch`、`/gate` 的合并判定 | 不可用(`merge_plan`/`merge_execute` 直接返回 501) | `MergeService`:merge-base、merge-tree(含冲突树)、fast-forward、squash/rebase、任意 ref 更新 | | `GET /patch/generate` | 可用(`DiffService/GetRawDiff`) | — | | `POST /patch/apply` | 501 | `PatchService/ApplyPatch`(3-way) | | `GET /packs/stats`、`POST /packs/ingest`、`POST /packs/repack` | 501 | `PackService`(或明确由 KenShell 内部管理并删除接口) | | `POST /maintenance/prune`、`/fsck` | 501 | `MaintenanceService` | | `GET /signatures/commit/{sha}`、`/signatures/tag/{name}` | 501 | `SignatureService/VerifyCommit`、`VerifyTag` | | `GET /submodules`、`/submodules/resolve` | 501 | `SubmoduleService`(或解析 `.gitmodules` 的 RPC) | | `POST /hooks/{script}` | 501 | `HookService/Execute`(或确认废弃) | | `POST /contents/blobs`、`/trees`、`/commits` | 501 | `ContentWriteService`(写对象 + 建提交) | | `POST /lfs/cleanup` | 501 | `LfsAdminService/UnreferenceObject` 的批量版本 | | 仓库创建时的初始提交 / README | 不再执行 | `ContentWriteService` 或 `CommandService.CreateRepository(initial_commit)` | | 分支/标签删除的 hook 事件回写 | 不再触发(原 `sync` worker 负责) | KenShell 事件推送(§6) | | 任意 ref 写入/删除(`PATCH/DELETE /refs/{name}`、`refs/notes/*`、`refs/pull/*`) | 仅支持 `refs/heads/*` | `CommandService/UpdateRef|DeleteRef` 泛化 | | `GET /graphql` | **已移除**(前端未使用;字段逐步被 REST 覆盖) | 若要恢复:用 service 层重写,并补 `pack_stats`/`submodules`/`patch_generate` | | search 索引 | 已移除 | — | ## 5. 进程与部署变化 - **删除** `app/githost`:smart HTTP / SSH 由 KenShell 提供。`charts/core` 移除 `githost` Deployment、Service、IngressRoute 与相关 values;`scripts/dev.*` 与 `justfile` 同步移除。 - **删除** `app/synchost`、`app/searchhost`、`app/webhook`、`app/runner`: 同步/导入、搜索索引、CI 与 webhook 均已移除;`git::sync::SyncWorker` 已删除。 - 剩余进程:`apihost`、`im`、`migrate`、`openapi`。 - 克隆地址改为指向 KenShell:`git.http_clone_base_url`、`git.ssh_clone_*`; Helm 通过 `kenshell.*` values 注入 `APP_GIT__KENSHELL_ENDPOINT`/`RPC_KEY`/`TIMEOUT_SECS`/`HTTP_CLONE_BASE_URL`/`SSH_CLONE_*`。 ## 6. 建议 KenShell 补充的协议 1. `MergeService` - `GetMergeBase(repository, a, b) -> oid` - `MergeTrees(base, ours, theirs, opts) -> {tree_oid, conflicts[]}` - `Merge(base_ref, head, strategy, message, actor) -> {method, new_sha, rewritten[]}` - `UpdateRef(ref_name, new_oid, expected_old_oid, force)` 2. `PatchService`:`GeneratePatch`、`ApplyPatch(3-way)` 3. `SignatureService`:`VerifyCommit`、`VerifyTag` 4. `SubmoduleService`:`ListSubmodules`、`ResolveSubmodule` 5. `PackService`:`GetPackStats`、`IngestPack(stream)`、`Repack` 6. `MaintenanceService`:`Prune`、`Fsck` 7. `ContentWriteService`:`WriteBlob`、`WriteTree`、`CreateCommit`(含初始提交) 8. `HookService`:`ExecuteHook(script, args, stdin)` 9. `LfsLockService`(可选):`ListLocks`/`Lock`/`Unlock`/`VerifyLocks` 10. `CommandService`:`UpdateRef`/`DeleteRef` 泛化到任意 ref 11. `BlobService/GetBlobContent`:支持 `stream`,避免 64 MiB 单消息上限 12. `RefService/TagView`:补 tag 对象 `sha` 与 `peeled` 13. 事件通道:写入完成(push/command)后向 KenApi 推送事件,替代已删除的 sync worker 14. `RepositoryService`:补齐展示字段,或明确 KenApi 为仓库元数据唯一来源 ## 7. 前端受影响清单 来自 `web/src/shared/api/apiDefinitions.ts`(已按新 openapi 重新生成): | 前端接口 | 迁移后 | | --- | --- | | `GET /repos/{space}/{repo}/tree/{rev}`、`/blobs/*`、`/commits*`、`/blame`、`/diff*` | 正常(RPC) | | `GET/POST /branches*`、`/tags*`、`/remotes*` | 正常(RPC;远端操作改异步 Job,轮询在服务端完成) | | `GET/POST /analysis/*`、`/archives*` | 正常(创建为 Job + 轮询) | | `GET /html/{tree,readme,blob-content,blob-pages,languages}` | 正常 | | `GET /lfs/locks*`、`/lfs/locks/verify` | 正常(KenApi DB) | | `GET /patch/generate` | 正常(raw diff) | | `GET /pulls/{id}/files`、`/commits`、`/patch` | 列表与 patch 正常;**合并动作不可用** | | `GET /lfs-pointers` | 正常(只返回 oid/size,`file_oid` 字段置零) | | `GET /submodules*`、`/signatures/*`、`/path-log` | submodules/signatures 501;path-log 近似可用 | | `/graphql` | 已从 OpenAPI 与前端生成代码移除 | | 其余 DB 接口(star/watch/topics/releases/protection/whitelists/code-comments) | 正常 | ## 8. 后续执行顺序 1. 与 KenShell 对齐 `MergeService` + `ContentWriteService`,恢复 PR 合并与建库初始提交。 2. 补 `SignatureService`、`SubmoduleService`、`PatchService`,替换对应 501。 3. 补反射/事件通道,替换已删除的 sync worker(分支/标签/提交镜像与 webhook 触发)。 4. search worker 改为 RPC 驱动。 5. 清理 `GitContext.repo_root`、`git.repo_root`/`objects_root` 与相关 chart 挂载。