# StigmergyLite Git 安装、检测和处理流程

## 📊 整体架构流程

```
用户运行 stigmergylite
        ↓
    [主安装流程 install()]
        ↓
┌─────────────────────────────────────────────┐
│ 1. 环境检测                          │
│    - 检测操作系统 (detectOS)          │
│    - 检测环境 (detectEnvironment)      │
└─────────────────────────────────────────────┘
        ↓
┌─────────────────────────────────────────────┐
│ 2. Git 检测和安装                     │
│    - 检查 Git 是否已安装              │
│    - 如果未安装，尝试安装               │
│    - 配置 Git Bash 环境变量           │
│    - 持久化 PATH（无权限环境）        │
└─────────────────────────────────────────────┘
        ↓
┌─────────────────────────────────────────────┐
│ 3. Git 配置                           │
│    - 用户名、邮箱（如果提供）          │
│    - 默认分支                           │
│    - 平台特定配置                       │
└─────────────────────────────────────────────┘
        ↓
┌─────────────────────────────────────────────┐
│ 4. 安装其他工具（可选）               │
│    - OpenCode                           │
│    - Bun                                │
│    - Oh My OpenCode                     │
│    - CodeBuddy                          │
│    - iFlow CLI                          │
│    - Qoder CLI                          │
│    - Qwen CLI                           │
└─────────────────────────────────────────────┘
        ↓
    返回安装结果
```

---

## 🔍 步骤 1: 环境检测

### 1.1 操作系统检测 (detectOS)

```javascript
detectOS() {
  const platform = os.platform();
  if (platform === 'win32') return 'windows';
  if (platform === 'darwin') return 'macos';
  if (platform === 'linux') return 'linux';
  return 'unknown';
}
```

**返回值**: `'windows' | 'macos' | 'linux' | 'unknown'`

### 1.2 环境检测 (detectEnvironment)

```javascript
detectEnvironment() {
  return {
    isDocker: 检查 /.dockerenv 或 /proc/self/cgroup,
    hasSudo: 运行 'sudo -n true' 测试,
    osType: detectOS() 结果
  };
}
```

**检测内容**:
- **Docker 环境**: 检查是否存在 `/.dockerenv` 或 `/proc/self/cgroup` 包含 "docker"
- **sudo 权限**: 尝试运行 `sudo -n true`（无密码模式）
- **操作系统类型**: 用于后续选择安装策略

---

## 🔧 步骤 2: Git 检测和安装

### 2.1 Git 检测 (isGitInstalled)

```javascript
async isGitInstalled() {
  try {
    const gitPath = which.sync('git');  // 使用 which 查找 git
    const version = execSync('git --version').trim();
    return {
      installed: true,
      path: gitPath,
      version: version
    };
  } catch (error) {
    return {
      installed: false,
      path: null,
      version: null
    };
  }
}
```

**检测机制**: 使用 `which` 命令在系统 PATH 中查找 `git` 可执行文件

### 2.2 Git 安装决策树

```
Git 是否已安装？
    |
    ├─ 是 → 跳过安装，直接配置
    |
    └─ 否 → 是否启用自动安装 (autoInstall)？
              |
              ├─ 否 → 抛出错误："Git 未安装且自动安装已禁用"
              |
              └─ 是 → 检查环境类型
                        |
                        ├─ Docker 环境？
                        |   ├─ 是 → 抛出错误，提示在 Dockerfile 中预安装
                        |   └─ 否 → 继续
                        |
                        └─ 调用 installGit()
```

### 2.3 Git 安装 (installGit)

```javascript
async installGit() {
  const osType = this.detectOS();

  switch (osType) {
    case 'windows':
      return await this.installGitOnWindows();
    case 'macos':
      return await this.installGitOnMacOS();
    case 'linux':
      return await this.installGitOnLinux();
    default:
      throw new Error(`不支持的操作系统: ${osType}`);
  }
}
```

---

## 💻 Windows 安装流程

### 安装策略（按优先级尝试）

```
installGitOnWindows()
    |
    ├─ 1. 尝试 winget (需要管理员权限)
    |   └─ winget install --id Git.Git -e --source winget
    |
    ├─ 2. 尝试 chocolatey (需要管理员权限)
    |   └─ choco install git -y
    |
    ├─ 3. 尝试 scoop (需要 Scoop 预安装)
    |   └─ scoop install git
    |
    ├─ 4. 尝试用户级便携版安装 (无管理员权限) ✨ 新增
    |   └─ installGitOnWindowsUser()
    |
    └─ 5. 失败 → 抛出错误，提示手动安装
```

### 用户级安装 (installGitOnWindowsUser) - 无需管理员权限

```javascript
async installGitOnWindowsUser() {
  // 1. 下载 MinGit 便携版
  const gitUrl = 'https://github.com/git-for-windows/git/releases/download/v2.47.0.windows.2/MinGit-2.47.0-64-bit.zip';
  const zipPath = path.join(os.tmpdir(), 'MinGit.zip');
  await this.downloadFile(gitUrl, zipPath);  // 使用 Node.js HTTPS 模块

  // 2. 解压到用户目录
  const userDir = path.join(os.homedir(), 'git-portable');
  execSync(`powershell.exe -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${userDir}' -Force"`);

  // 3. 配置 Git
  const gitBinPath = path.join(userDir, 'mingw64', 'bin');
  process.env.PATH = `${gitBinPath};${process.env.PATH}`;  // 当前进程
  process.env.GIT_INSTALL_ROOT = userDir;

  execSync(`"${gitExePath}" config --global core.autocrlf true`);
  execSync(`"${gitExePath}" config --global core.longpaths true`);
  execSync(`"${gitExePath}" config --global core.quotepath off`);

  // 4. 持久化 PATH 到用户注册表 ✨ 新增
  await this.persistUserPath(gitBinPath, 'windows');
}
```

### Windows PATH 持久化 (persistUserPath - Windows)

```javascript
async persistUserPath(gitBinPath, 'windows') {
  // 1. 读取当前用户 PATH
  const currentPathCommand = `[System.Environment]::GetEnvironmentVariable("Path", "User")`;
  let currentPath = execSync(`powershell.exe -Command "${currentPathCommand}"`, { encoding: 'utf8' }).trim();

  // 2. 检查是否已存在
  if (!currentPath.includes(gitBinPath)) {
    // 3. 添加到 PATH
    const newPath = `${gitBinPath};${currentPath}`;
    const setPathCommand = `[System.Environment]::SetEnvironmentVariable("Path", "${newPath}", "User")`;
    execSync(`powershell.exe -Command "${setPathCommand}"`);

    this.log('已更新用户 PATH 环境变量', 'success');
  }
}
```

**重要**: 修改 `HKEY_CURRENT_USER\Environment` 注册表键，无需管理员权限

---

## 🍎 macOS 安装流程

### 安装策略（按优先级尝试）

```
installGitOnMacOS()
    |
    ├─ 1. 尝试 Homebrew (需要预安装)
    |   └─ brew install git
    |
    ├─ 2. 尝试 Xcode Command Line Tools (需要管理员权限)
    |   └─ xcode-select --install
    |
    ├─ 3. 尝试用户级预编译版本 (无管理员权限) ✨ 新增
    |   └─ installGitOnMacOSUser()
    |
    └─ 4. 失败 → 调用受限环境安装
```

### 用户级安装 (installGitOnMacOSUser) - 无需管理员权限

```javascript
async installGitOnMacOSUser() {
  // 1. 根据架构选择合适的预编译版本
  if (arch === 'x64') {
    gitUrl = 'https://github.com/git/git/releases/download/v2.47.0/git-2.47.0-x86_64-apple-darwin.tar.gz';
  } else if (arch === 'arm64') {
    gitUrl = 'https://github.com/git/git/releases/download/v2.47.0/git-2.47.0-arm64-apple-darwin.tar.gz';
  }

  // 2. 使用 curl 下载
  const tarPath = path.join(os.tmpdir(), 'git.tar.gz');
  execSync(`curl -L -o "${tarPath}" "${gitUrl}"`);

  // 3. 解压到用户目录
  const extractPath = path.join(os.homedir(), 'git-user');
  execSync(`tar -xzf "${tarPath}" -C "${extractPath}" --strip-components=1`);

  // 4. 配置 Git
  process.env.PATH = `${extractPath}:${process.env.PATH}`;
  process.env.GIT_INSTALL_ROOT = extractPath;

  execSync(`${gitBinPath}/git config --global core.autocrlf input`);
  execSync(`${gitBinPath}/git config --global core.longpaths true`);
  execSync(`${gitBinPath}/git config --global core.quotepath off`);

  // 5. 持久化 PATH 到配置文件 ✨ 新增
  await this.persistUserPath(gitBinPath, 'macos');
}
```

### macOS PATH 持久化 (persistUserPath - macOS)

```javascript
async persistUserPath(gitBinPath, 'macos') {
  const bashrcPath = path.join(os.homedir(), '.bashrc');
  const zshrcPath = path.join(os.homedir(), '.zshrc');
  const exportLine = `\n# Git from stigmergylite\nexport PATH="${gitBinPath}:$PATH"\n`;

  // 1. 更新 ~/.bashrc
  if (fs.existsSync(bashrcPath)) {
    const bashrcContent = fs.readFileSync(bashrcPath, 'utf-8');
    if (!bashrcContent.includes(gitBinPath)) {
      fs.appendFileSync(bashrcPath, exportLine);
      this.log('已更新 ~/.bashrc', 'success');
    }
  } else {
    fs.writeFileSync(bashrcPath, exportLine);
    this.log('已创建 ~/.bashrc', 'success');
  }

  // 2. 更新 ~/.zshrc (macOS 默认使用 zsh)
  if (fs.existsSync(zshrcPath)) {
    const zshrcContent = fs.readFileSync(zshrcPath, 'utf-8');
    if (!zshrcContent.includes(gitBinPath)) {
      fs.appendFileSync(zshrcPath, exportLine);
      this.log('已更新 ~/.zshrc', 'success');
    }
  } else {
    fs.writeFileSync(zshrcPath, exportLine);
    this.log('已创建 ~/.zshrc', 'success');
  }
}
```

---

## 🐧 Linux 安装流程

### 安装策略（按优先级尝试）

```
installGitOnLinux()
    |
    ├─ 1. 尝试 apt-get (需要 sudo 权限)
    |   └─ sudo apt-get update && sudo apt-get install -y git-all
    |
    ├─ 2. 尝试 dnf (需要 sudo 权限)
    |   └─ sudo dnf install -y git-all
    |
    ├─ 3. 尝试 yum (需要 sudo 权限)
    |   └─ sudo yum install -y git-all
    |
    ├─ 4. 尝试 pacman (需要 sudo 权限)
    |   └─ sudo pacman -S --noconfirm git
    |
    ├─ 5. 尝试用户级预编译版本 (无 sudo 权限) ✨ 新增
    |   └─ installGitOnLinuxUser()
    |
    └─ 6. 失败 → 调用受限环境安装
```

### 用户级安装 (installGitOnLinuxUser) - 无需 sudo 权限

```javascript
async installGitOnLinuxUser() {
  // 1. 根据架构选择合适的预编译版本
  if (arch === 'x64') {
    gitUrl = 'https://github.com/git/git/releases/download/v2.47.0/git-2.47.0-x86_64.tar.gz';
  } else if (arch === 'arm64') {
    gitUrl = 'https://github.com/git/git/releases/download/v2.47.0/git-2.47.0-aarch64.tar.gz';
  }

  // 2. 使用 curl 或 wget 下载
  const tarPath = path.join(os.tmpdir(), 'git.tar.gz');
  if (this.commandExists('curl')) {
    execSync(`curl -L -o "${tarPath}" "${gitUrl}"`);
  } else if (this.commandExists('wget')) {
    execSync(`wget -O "${tarPath}" "${gitUrl}"`);
  } else {
    throw new Error('需要 curl 或 wget 来下载 Git');
  }

  // 3. 解压到用户目录
  const extractPath = path.join(os.homedir(), 'git-user');
  execSync(`tar -xzf "${tarPath}" -C "${extractPath}" --strip-components=1`);

  // 4. 配置 Git
  process.env.PATH = `${extractPath}:${process.env.PATH}`;
  process.env.GIT_INSTALL_ROOT = extractPath;

  execSync(`${gitBinPath}/git config --global core.autocrlf input`);
  execSync(`${gitBinPath}/git config --global core.longpaths true`);
  execSync(`${gitBinPath}/git config --global core.quotepath off`);

  // 5. 持久化 PATH 到配置文件 ✨ 新增
  await this.persistUserPath(gitBinPath, 'linux');
}
```

### Linux PATH 持久化 (persistUserPath - Linux)

```javascript
async persistUserPath(gitBinPath, 'linux') {
  const bashrcPath = path.join(os.homedir(), '.bashrc');
  const exportLine = `\n# Git from stigmergylite\nexport PATH="${gitBinPath}:$PATH"\n`;

  // 更新 ~/.bashrc
  if (fs.existsSync(bashrcPath)) {
    const bashrcContent = fs.readFileSync(bashrcPath, 'utf-8');
    if (!bashrcContent.includes(gitBinPath)) {
      fs.appendFileSync(bashrcPath, exportLine);
      this.log('已更新 ~/.bashrc', 'success');
    }
  } else {
    fs.writeFileSync(bashrcPath, exportLine);
    this.log('已创建 ~/.bashrc', 'success');
  }
}
```

---

## 🔄 步骤 3: Git Bash 配置

### configureGitBashEnv()

```javascript
async configureGitBashEnv() {
  const bashPath = this.findGitBashPath();
  const osType = this.detectOS();

  // Windows: Git Bash 是必需的
  if (osType === 'windows' && !bashPath) {
    this.log('无法配置 Git Bash：Windows系统需要 Git Bash', 'error');
    return false;
  }

  // 非Windows: 只要有 Git 命令即可
  if (osType !== 'windows') {
    if (!(await this.validateGitAvailability())) {
      return false;
    }
  }

  // 设置环境变量（当前进程）
  process.env.GIT_BASH_PATH = bashPath;
  process.env.GIT_INSTALL_ROOT = gitRoot;

  return true;
}
```

### Git Bash 路径检测 (findGitBashPath)

#### Windows 搜索路径
```
C:\Program Files\Git\bin\bash.exe
C:\Program Files\Git\usr\bin\bash.exe
C:\Program Files (x86)\Git\bin\bash.exe
C:\Program Files (x86)\Git\usr\bin\bash.exe
E:\PortableGit\bin\bash.exe
%USERPROFILE%\AppData\Local\Programs\Git\bin\bash.exe
从 git.exe 路径推断: dirname(git.exe) + '/bash.exe'
```

#### macOS/Linux
```
默认使用系统 /bin/bash
或从 git.exe 路径推断
```

---

## ⚙️ 步骤 4: Git 配置

### configureGit(config)

```javascript
async configureGit(config) {
  const { userName, userEmail, defaultBranch = 'main' } = config;

  // 1. 用户名和邮箱
  if (userName) {
    execSync(`git config --global user.name "${userName}"`);
  }
  if (userEmail) {
    execSync(`git config --global user.email "${userEmail}"`);
  }

  // 2. 默认分支
  execSync(`git config --global init.defaultbranch ${defaultBranch}`);

  // 3. Windows 特定配置
  if (this.detectOS() === 'windows') {
    execSync('git config --global core.autocrlf true');
    execSync('git config --global core.longpaths true');
    execSync('git config --global core.quotepath off');
  }
}
```

---

## 📦 步骤 5: CLI 工具安装

### 安装模式（所有 CLI 工具都遵循相同模式）

```javascript
async installXxxCLI() {
  // 1. 检查是否已安装
  if (this.commandExists('xxxcli')) {
    this.log('XXX CLI 已安装', 'success');
    return true;
  }

  // 2. 执行安装命令
  execSync('npm install -g @xxx/xxxcli', {
    stdio: this.options.silent ? 'pipe' : 'inherit',
    timeout: 300000
  });

  // 3. 验证安装
  const version = execSync('xxxcli --version', { encoding: 'utf-8' });
  this.log(`XXX CLI 安装成功: ${version.trim()}`, 'success');

  return true;
}
```

### 支持的 CLI 工具

| 工具 | 命令 | 安装包 |
|------|------|---------|
| CodeBuddy | codebuddy | @tencent-ai/codebuddy-code |
| iFlow CLI | iflow | @iflow-ai/iflow-cli |
| Qoder CLI | qodercli | @qoder-ai/qodercli |
| Qwen CLI | qwen | @qwen-code/qwen-code |
| OpenCode | opencode | opencode-ai |
| Bun | bun | bun |
| Oh My OpenCode | - | bunx oh-my-opencode |

---

## 🎯 关键特性

### ✅ 无权限环境支持

1. **Windows**: 便携版 + 用户注册表
   - 使用 Node.js HTTPS 下载
   - PowerShell Expand-Archive 解压
   - 修改 HKEY_CURRENT_USER\Environment

2. **Linux**: 预编译二进制 + ~/.bashrc
   - 使用 curl/wget 下载
   - tar 解压
   - 修改 ~/.bashrc

3. **macOS**: 预编译二进制 + ~/.bashrc + ~/.zshrc
   - 使用 curl 下载
   - tar 解压
   - 修改 ~/.bashrc 和 ~/.zshrc

### ✅ PATH 持久化

- **立即生效**: 当前 Node.js 进程可以立即使用 Git
- **持久化**: PATH 写入用户级配置（注册表或配置文件）
- **其他进程**: 新启动的进程可以自动检测到 Git
- **CLI 工具**: Qoder、CodeBuddy 等工具启动时自动找到 Git

### ✅ 架构检测

自动检测并下载对应架构的版本：
- Windows: x64
- Linux: x64, ARM64
- macOS: x64 (Intel), ARM64 (Apple Silicon)

### ✅ 下载功能

```javascript
downloadFile(url, destPath) {
  // 1. 支持 HTTP/HTTPS
  // 2. 处理重定向（302, 301）
  // 3. 显示下载进度
  // 4. 超时控制
}
```

---

## 🚀 使用示例

### API 使用

```javascript
const GitAutoInstaller = require('stigmergylite');

const installer = new GitAutoInstaller({
  autoInstall: true,
  configureGitBash: true,
  gitConfig: {
    userName: 'Your Name',
    userEmail: 'your.email@example.com'
  }
});

const result = await installer.install();
// {
//   success: true,
//   git: { installed: true, path: '...', version: '...' },
//   gitBashPath: '...',
//   opencode: true,
//   bun: true,
//   codebuddy: true,
//   ...
// }
```

### CLI 使用

```bash
# 完整安装
stigmergylite

# 仅安装 Git，不安装 CLI 工具
stigmergylite --no-opencode --no-bun --no-oh-my-opencode --no-iflow --no-qoder --no-qwen --no-codebuddy

# 静默模式
stigmergylite --silent

# 仅检测，不安装
stigmergylite --no-auto-install
```

---

## 📊 总结

### 安装流程

1. **环境检测** → 识别操作系统、权限、Docker
2. **Git 检测** → 检查是否已安装
3. **Git 安装** → 根据环境和权限选择合适的安装方法
4. **PATH 持久化** → 确保其他进程可以检测到 Git
5. **Git 配置** → 用户名、邮箱、默认分支等
6. **CLI 工具安装** → 可选安装其他开发工具

### 关键改进

✅ **无权限环境支持**: Windows/Linux/macOS 都有用户级安装方案
✅ **PATH 自动持久化**: 其他进程和 CLI 工具可以自动检测到 Git
✅ **架构感知**: 自动选择正确的二进制版本
✅ **下载功能**: 内置 HTTP/HTTPS 下载，支持进度显示
✅ **清晰的提示**: 告知用户如何使 PATH 生效

### 用户受益

- 🎯 无需管理员/sudo 权限即可安装 Git
- 🎯 其他 CLI 工具自动检测到 Git
- 🎯 跨平台统一体验
- 🎯 自动化配置，减少手动操作
