# repostack pull

> 

根据 stack 配置与锁文件，clone 本地缺失的 repo。

```bash
repostack pull
```

## 执行流程

<steps level="4">

#### **加载配置**- 读取 `repostack.yaml` 和 `.repostackrc`（如果启用了用户配置）。





#### **遍历 repos**- 先筛出本地缺失的 repo，再按 `settings.concurrency` 并发执行 clone。
- 目标路径**已存在**的 repo 会直接跳过。
- 对每一个待拉取 repo：

  - 计算目标路径：`join(root, repo.path)`。
  - 如果目标路径**不存在**，默认使用 `repostack.yaml` 中的 `source`。
  - 只有当 `source` 仍然是旧的占位路径值（例如与 `path` 相同）时，才会回退使用 `repostack.lock.yaml` 中该 repo 的 `source`。
  - 最终执行 `git clone <source> <destination>`。





#### **失败重试**- 单个 repo 的 clone 失败时会自动重试，默认最多 **3 次尝试**（首次 + 2 次重试）。
- 每次失败后，如果目标目录已被 Git 部分创建，会先清理再重试。





#### **进度输出**- TTY 环境下会显示 spinner 进度，并在结束后输出稳定结果。
- 常见文案包括：

  - `Cloning <repo>...`
  - `Retrying <repo>... (2/3)`
  - `Cloned <repo>`
  - `Cloned <repo> (3 attempts)`
  - `Clone failed: <repo> — <message>`





</steps>

## 涉及文件

| 文件                    | 操作                 |
| --------------------- | ------------------ |
| `repostack.yaml`      | 读取                 |
| `repostack.lock.yaml` | 读取（如存在）            |
| `.repostackrc`        | 读取（如启用用户）          |
| `<repo.path>` 目录      | 创建（通过 `git clone`） |

## Git 操作

- `git clone <source> <destination>`（仅针对缺失目录，旧占位 `source` 可由 lock 纠正）

## 错误与边界情况

- 如果 `repostack.yaml` 中定义了 `users` 但当前未选择用户，命令立即中断。
- 如果 lock 文件存在且 checksum 不匹配，命令立即中断。
- `git clone` 连续 3 次都失败时会抛出异常。
- **已存在的目录不做任何验证**：即使里面是一个空文件夹或错误的仓库，也会直接跳过。

## 适用场景

- 新成员首次设置开发环境
- 恢复缺失的 repo

## 示例

```bash
repostack pull
```
