Skip to content
dsh.fish
Bundle

dsh-auto-git

dsh profile bundle: git init every newly registered Workspace so the git-graph branch chip works in every workspace

Source
zhitiaojun
License
MIT
Updated
Updated 2 hours ago

Readme

# dsh-auto-git

为**每个新注册的 DSH 工作区**自动 `git init`,让 git 相关插件(如 `@linxin666/dsh-client-ui-git-graph` 的分支胶囊 / Git 图谱)在每个工作区都能出现。

## 为什么需要它

git-graph 插件的 host 侧 `/git/*` 路由有两道门(见其 `src/index.ts` 的 `createWorkspaceGate` 与 `src/host/git-service.ts`):

1. 请求路径的 realpath 必须**恰好等于**某个已注册工作区路径(`workspace.path === canonical`,不接受子目录、不接受任意目录);
2. 该路径必须是 git 仓库(`git rev-parse --show-toplevel` 成功),否则 `status` 返回 `null`。

前端 `BranchChip` 在 `repo === null` 时直接 `return null` —— 于是"非 git 工作区"里这个插件完全没有 UI。所以想让 git 功能"每个工作区都有",唯一办法是让工作区目录本身是仓库。

## 它做什么

- **注册时**:监听 `domain/changed`(`domain === 'workspace' && table === 'workspaces' && operation === 'put'`),对新工作区根目录执行 `git init -b main`。
- **启动时**:对启动前已注册的工作区做一次同样的扫描(可用 `sweepExisting: false` 关掉)。
- **默认补一个空提交**(`git commit --allow-empty`):仓库在"未出生 HEAD"状态下 `git rev-parse --abbrev-ref HEAD` 会失败,分支胶囊会退化成显示 `detached`;有首个提交才有正常分支名。不会把任何现有文件纳入提交,不会写 `.gitignore`,不碰远程。
- **不会嵌套仓库**:先探测 `git rev-parse --is-inside-work-tree`,已在某个工作树内(父目录已是仓库、或本身就是 `git worktree` 检出)就跳过。
- **幂等**:同一路径在一个 host 进程内只处理一次;已存在的仓库一律跳过。

## 配置

安装后由 profile 的 bundle patch(`cordis.patch.yml`)提供行配置,改完重启 `dsh web` 生效:

| 字段 | 默认 | 含义 |
|---|---|---|
| `enabled` | `true` | 总开关,`false` 时插件什么都不装 |
| `branch` | `main` | 初始分支名(`git init -b <branch>`,老版本 git 回退到 `git symbolic-ref`) |
| `initialCommit` | `true` | 是否补一个空提交(关闭则新仓库分支名可能显示为 detached) |
| `sweepExisting` | `true` | 是否也处理**已注册**的工作区;`false` 则只处理以后新注册的 |
| `timeoutMs` | `30000` | 每条 git 命令的超时 |

## 安装

从 GitHub 安装(推荐):

```powershell
dsh plugin --profile web add github:zhitiaojun/dsh-auto-git
```

或在 DSH 插件市场 / [目录站](https://awesome-dsh-plugin.com) 里搜 `dsh-auto-git` 点安装。

本仓库的包没有 `prepare`/构建脚本,`github:` 安装不需要往 profile 的 `pnpm-workspace.yaml` 的 `allowBuilds` 里加任何 key。

本地开发用 `link:` 指向 checkout:

```powershell
dsh plugin --profile web add link:D:/Project/1/dsh-auto-git
```

`link:` 指向本地目录(用正斜杠),改代码后重启即生效,无需重装。两种方式都**必须重启 `dsh web`** 才会装进 host 进程。

## 验证

1. 不进 DSH 也能验证核心行为:

   ```powershell
   node D:\Project\1\dsh-auto-git\test\smoke.mjs
   ```

   它会用真实 git 在临时目录里跑:新建仓库、二次调用幂等、跳过已在工作树内的目录、自定义分支名、不建提交的模式、以及 `apply()` 的 boot 扫描 / `domain/changed` 钩子 / `enabled:false` / `sweepExisting:false`。

2. 安装后:`~/.dsh/profiles/web/.dsh-market/log.ndjson` 应有该包的 `install` 与随后的 `restart` 记录。

3. 运行时:host 日志里出现 `auto-git: initialized: <path>`;或选一个新目录加入工作区,随后

   ```powershell
   git -C <新目录> log --oneline      # 应看到 chore: initial commit
   ```

4. 端到端(可选):在空白会话里看分支胶囊是否出现(host 侧 SSE 每 30s 推送一次工作区状态,或切走窗口再切回来触发 focus 刷新)。

## 卸载

```powershell
dsh plugin --profile web remove dsh-auto-git
```

卸载只移除插件,**不会**回滚已经建好的仓库。

## 安装前须知

`sweepExisting` 默认 `true`:装上并重启后,当前所有**还不是仓库**的已注册工作区都会被 `git init`(本机当时为 `D:\Project\1`、`D:\Project`、`D:\Project\控制`、`D:\Project\我就要洗衣`、`D:\Project\race`、`D:\Project\race\before`、`D:\Project\race\nerv`)。如果只想影响以后新建的工作区,把 `cordis.patch.yml` 里的 `sweepExisting` 改成 `false`。

## 实现要点

- 纯 host 侧插件,无 `dsh.client` 声明 → 不向浏览器贡献任何代码。
- 零运行时依赖:只用 `node:child_process` / `node:fs/promises`。
- 包根声明 `dsh.bundle.patch`,profile 组合时把 `auto-git-init` 这一行插进插件树(与 git-graph 等社区 bundle 同机制)。
- 用 `ctx.inject(['workspaceRegistry'], scope => …)` 拿服务、`scope.effect(...)` 管生命周期、`scope.on('domain/changed', ...)` 挂在工作区表的写入事件上。

Install

dsh plugin --profile web add github:zhitiaojun/dsh-auto-git#e0a4eeb54de562cf92f3eb47367a6e154a289009

Profile: web

Source