修改代码注释为中文
This commit is contained in:
@@ -29,13 +29,13 @@ func newCaptureCmd() *cobra.Command {
|
||||
return fmt.Errorf("必须指定 Pack 名称 (--name)")
|
||||
}
|
||||
fmt.Printf("📦 Capturing environment \"%s\"...\n", name)
|
||||
// TODO: Implement capture logic
|
||||
// 1. Load profile
|
||||
// 2. Run collectors
|
||||
// 3. Write data to temp directory
|
||||
// 4. Generate manifest
|
||||
// 5. Encrypt sensitive data (if enabled)
|
||||
// 6. Create pack
|
||||
// TODO: 实现捕获逻辑
|
||||
// 1. 加载 Profile 配置
|
||||
// 2. 运行采集器
|
||||
// 3. 将数据写入临时目录
|
||||
// 4. 生成 Manifest 清单
|
||||
// 5. 加密敏感数据(如果启用)
|
||||
// 6. 创建 Pack 文件
|
||||
fmt.Printf("✅ Pack created: %s\n", name)
|
||||
fmt.Printf("\nRun 'devpack export %s -o %s.devpack' to export.\n", name, name)
|
||||
return nil
|
||||
|
||||
@@ -30,8 +30,8 @@ func newDiffCmd() *cobra.Command {
|
||||
return fmt.Errorf("请指定对比目标: --current 或 --with <pack-name>")
|
||||
}
|
||||
|
||||
// TODO: Implement diff logic
|
||||
fmt.Println("(diff not yet implemented)")
|
||||
// TODO: 实现差异对比逻辑
|
||||
fmt.Println("(差异对比功能尚未实现)")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func newExportCmd() *cobra.Command {
|
||||
output = packName + ".devpack"
|
||||
}
|
||||
fmt.Printf("📤 Exporting \"%s\" to %s...\n", packName, output)
|
||||
// TODO: Implement export logic
|
||||
// TODO: 实现导出逻辑
|
||||
fmt.Printf("✅ Exported: %s\n", output)
|
||||
return nil
|
||||
},
|
||||
@@ -45,7 +45,7 @@ func newImportCmd() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
filePath := args[0]
|
||||
fmt.Printf("📥 Importing %s...\n", filePath)
|
||||
// TODO: Implement import logic
|
||||
// TODO: 实现导入逻辑
|
||||
fmt.Println("✅ Import complete!")
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -19,12 +19,12 @@ func newInitCmd() *cobra.Command {
|
||||
Long: `初始化 DevPack,创建配置目录和默认配置文件。`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Println("🚀 Initializing DevPack...")
|
||||
// TODO: Implement init logic
|
||||
// 1. Create ~/.devpack/ directory
|
||||
// 2. Create config.yaml
|
||||
// 3. Create profiles/ directory
|
||||
// 4. Create packs/ directory
|
||||
// 5. Create logs/ directory
|
||||
// TODO: 实现初始化逻辑
|
||||
// 1. 创建 ~/.devpack/ 目录
|
||||
// 2. 创建 config.yaml 配置文件
|
||||
// 3. 创建 profiles/ 目录
|
||||
// 4. 创建 packs/ 目录
|
||||
// 5. 创建 logs/ 目录
|
||||
fmt.Println("✅ DevPack initialized successfully!")
|
||||
fmt.Println("\nRun 'devpack scan' to scan your current environment.")
|
||||
return nil
|
||||
|
||||
@@ -26,15 +26,15 @@ func newListCmd() *cobra.Command {
|
||||
switch subCmd {
|
||||
case "packs":
|
||||
fmt.Println("📦 Local Packs:")
|
||||
// TODO: List packs
|
||||
// TODO: 列出所有 Pack
|
||||
fmt.Println(" (none)")
|
||||
case "profiles":
|
||||
fmt.Println("📋 Profiles:")
|
||||
// TODO: List profiles
|
||||
// TODO: 列出所有 Profile
|
||||
fmt.Println(" (none)")
|
||||
case "collectors":
|
||||
fmt.Println("🔌 Available Collectors:")
|
||||
// TODO: List collectors
|
||||
// TODO: 列出所有采集器
|
||||
fmt.Println(" (none)")
|
||||
default:
|
||||
return fmt.Errorf("未知的子命令: %s (可选: packs, profiles, collectors)", subCmd)
|
||||
|
||||
@@ -13,7 +13,7 @@ func newProfileCmd() *cobra.Command {
|
||||
Long: `创建、编辑、删除和管理 Profile 配置方案。`,
|
||||
}
|
||||
|
||||
// Subcommands
|
||||
// 注册子命令
|
||||
cmd.AddCommand(newProfileCreateCmd())
|
||||
cmd.AddCommand(newProfileShowCmd())
|
||||
cmd.AddCommand(newProfileListCmd())
|
||||
@@ -33,7 +33,7 @@ func newProfileCreateCmd() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
fmt.Printf("📋 Creating profile \"%s\"...\n", name)
|
||||
// TODO: Create profile
|
||||
// TODO: 创建 Profile 配置文件
|
||||
fmt.Printf("✅ Profile \"%s\" created.\n", name)
|
||||
fmt.Printf("Edit with: devpack profile edit %s\n", name)
|
||||
return nil
|
||||
@@ -53,7 +53,7 @@ func newProfileShowCmd() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
fmt.Printf("📋 Profile: %s\n", name)
|
||||
// TODO: Show profile content
|
||||
// TODO: 显示 Profile 内容
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func newProfileListCmd() *cobra.Command {
|
||||
Short: "列出所有 Profile",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Println("📋 Profiles:")
|
||||
// TODO: List profiles
|
||||
// TODO: 列出所有 Profile
|
||||
fmt.Println(" (none)")
|
||||
return nil
|
||||
},
|
||||
@@ -80,7 +80,7 @@ func newProfileDeleteCmd() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
fmt.Printf("🗑️ Deleting profile \"%s\"...\n", name)
|
||||
// TODO: Delete profile
|
||||
// TODO: 删除 Profile 文件
|
||||
fmt.Printf("✅ Profile \"%s\" deleted.\n", name)
|
||||
return nil
|
||||
},
|
||||
@@ -95,7 +95,7 @@ func newProfileUseCmd() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
fmt.Printf("✅ Default profile set to \"%s\".\n", name)
|
||||
// TODO: Set default profile
|
||||
// TODO: 设置默认 Profile
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,20 +28,20 @@ func newRestoreCmd() *cobra.Command {
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("🔍 Dry Run — Restore Plan for \"%s\"\n\n", packName)
|
||||
// TODO: Generate and display restore plan
|
||||
fmt.Println("⚠ This is a dry run. No changes were made.")
|
||||
fmt.Println("Run without --dry-run to apply these changes.")
|
||||
// TODO: 生成并展示还原计划
|
||||
fmt.Println("⚠ 这是一次干运行,未做任何实际更改。")
|
||||
fmt.Println("去掉 --dry-run 参数以执行实际还原。")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("🚀 Restoring environment from \"%s\"...\n", packName)
|
||||
// TODO: Implement restore logic
|
||||
// 1. Load and verify pack
|
||||
// 2. Check platform compatibility
|
||||
// 3. Detect conflicts
|
||||
// 4. Create restore point
|
||||
// 5. Execute restore plan
|
||||
// 6. Verify results
|
||||
// TODO: 实现还原逻辑
|
||||
// 1. 加载并校验 Pack 文件
|
||||
// 2. 检查平台兼容性
|
||||
// 3. 检测冲突
|
||||
// 4. 创建还原点
|
||||
// 5. 执行还原计划
|
||||
// 6. 验证还原结果
|
||||
fmt.Println("✅ Environment restored successfully!")
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@ var (
|
||||
noColor bool
|
||||
)
|
||||
|
||||
// rootCmd represents the base command
|
||||
// rootCmd 根命令定义
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "devpack",
|
||||
Short: "DevPack - 开发环境打包迁移工具",
|
||||
@@ -29,7 +29,7 @@ var rootCmd = &cobra.Command{
|
||||
Version: version.GetVersionString(),
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// Execute 将所有子命令添加到根命令并执行
|
||||
func Execute() error {
|
||||
return rootCmd.Execute()
|
||||
}
|
||||
@@ -37,14 +37,14 @@ func Execute() error {
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
// Global flags
|
||||
// 全局参数
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (默认: ~/.devpack/config.yaml)")
|
||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "详细输出")
|
||||
rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "静默模式")
|
||||
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "日志级别 (trace|debug|info|warn|error)")
|
||||
rootCmd.PersistentFlags().BoolVar(&noColor, "no-color", false, "禁用彩色输出")
|
||||
|
||||
// Add subcommands
|
||||
// 注册子命令
|
||||
rootCmd.AddCommand(newInitCmd())
|
||||
rootCmd.AddCommand(newScanCmd())
|
||||
rootCmd.AddCommand(newCaptureCmd())
|
||||
@@ -75,6 +75,6 @@ func initConfig() {
|
||||
viper.SetEnvPrefix("DEVPACK")
|
||||
viper.AutomaticEnv()
|
||||
|
||||
// Read config file (ignore error if not found)
|
||||
// 读取配置文件(文件不存在时忽略错误)
|
||||
_ = viper.ReadInConfig()
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ func newScanCmd() *cobra.Command {
|
||||
Long: `扫描当前系统的开发环境,检测已安装的工具、配置和设置。`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Println("🔍 Scanning development environment...")
|
||||
// TODO: Implement scan logic
|
||||
// 1. Load profile (if specified)
|
||||
// 2. Determine which collectors to run
|
||||
// 3. Run collectors in parallel
|
||||
// 4. Aggregate results
|
||||
// 5. Display results
|
||||
// TODO: 实现扫描逻辑
|
||||
// 1. 加载 Profile(如果指定了)
|
||||
// 2. 确定需要运行哪些采集器
|
||||
// 3. 并行运行采集器
|
||||
// 4. 汇总扫描结果
|
||||
// 5. 展示结果
|
||||
fmt.Println("✅ Scan complete!")
|
||||
return nil
|
||||
},
|
||||
|
||||
962
docs/DEVELOPMENT-PLAN.md
Normal file
962
docs/DEVELOPMENT-PLAN.md
Normal file
@@ -0,0 +1,962 @@
|
||||
# DevPack 后续开发详细计划
|
||||
|
||||
> 基于 ROADMAP.md 路线图,细化到每个文件及其所需第三方库 / 标准库
|
||||
> 更新日期:2026-03-03
|
||||
|
||||
---
|
||||
|
||||
## 依赖库总览
|
||||
|
||||
下表列出后续开发中需要引入的**所有第三方库**(go get 命令):
|
||||
|
||||
| 库 | Import Path | 用途 | 引入阶段 |
|
||||
|---|---|---|---|
|
||||
| zerolog | `github.com/rs/zerolog` | 结构化日志 | M1 |
|
||||
| go-yaml | `gopkg.in/yaml.v3` | Profile YAML 解析 | M1 |
|
||||
| uuid | `github.com/google/uuid` | Pack ID 生成 | M1 |
|
||||
| color | `github.com/fatih/color` | 终端彩色输出 | M1 |
|
||||
| tablewriter | `github.com/olekukonenko/tablewriter` | 终端表格渲染 | M1 |
|
||||
| progressbar | `github.com/schollz/progressbar/v3` | 终端进度条 | M3 |
|
||||
| survey | `github.com/AlecAivazis/survey/v2` | 交互式终端提示 | M4 |
|
||||
| testify | `github.com/stretchr/testify` | 测试断言与 Mock | M1 |
|
||||
| archiver | `github.com/mholt/archiver/v4` | tar.gz 高级归档(可选,也可用标准库) | M3 |
|
||||
| x/crypto | `golang.org/x/crypto` | Argon2id 密钥派生 | v0.3.0 |
|
||||
|
||||
> 注意:`cobra` 和 `viper` 已在 go.mod 中,无需再添加。
|
||||
|
||||
---
|
||||
|
||||
## M1: 项目基础架构(第 1-2 周)
|
||||
|
||||
### 任务 1.1 — 日志系统
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/logging/logger.go` | 全局 Logger 封装、日志级别控制、文件 + 控制台双输出 |
|
||||
| `internal/logging/logger_test.go` | 日志系统单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/rs/zerolog — 核心日志引擎
|
||||
|
||||
标准库:
|
||||
os — 日志文件创建
|
||||
io — MultiWriter (控制台+文件)
|
||||
time — 时间戳格式
|
||||
fmt — 格式化
|
||||
path/filepath — 日志文件路径
|
||||
```
|
||||
|
||||
**实现要点:**
|
||||
- 导出全局 `Logger` 实例
|
||||
- 支持 `--verbose` / `--quiet` / `--log-level` 全局标志
|
||||
- 支持 `--log-file` 输出到文件
|
||||
- 集成到 `cmd/devpack/commands/root.go` 的 `PersistentPreRun`
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `cmd/devpack/commands/root.go` | 在 `PersistentPreRunE` 中初始化 Logger,传递 verbose/quiet/log-level/log-file 标志 |
|
||||
| `go.mod` | 添加 `github.com/rs/zerolog` 依赖 |
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.2 — 配置系统
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/config/config.go` | 配置结构体定义 (AppConfig)、加载/保存/默认值逻辑 |
|
||||
| `internal/config/config_test.go` | 配置系统单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/spf13/viper — 配置文件读取(已有)
|
||||
gopkg.in/yaml.v3 — YAML 序列化/反序列化
|
||||
|
||||
标准库:
|
||||
os — 文件操作
|
||||
path/filepath — 路径拼接
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `internal/config/paths.go` | 增加 `ConfigFilePath()` 方法返回 config.yaml 路径 |
|
||||
| `go.mod` | 添加 `gopkg.in/yaml.v3` 依赖 |
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.3 — Profile 系统核心
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/profile/profile.go` | Profile 结构体、加载/保存/验证/列出/默认模板 |
|
||||
| `internal/profile/profile_test.go` | Profile 单元测试 |
|
||||
| `internal/profile/templates.go` | 预设模板: minimal / standard / full |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
gopkg.in/yaml.v3 — Profile YAML 解析与生成
|
||||
|
||||
标准库:
|
||||
os — 文件操作
|
||||
path/filepath — Profile 文件路径
|
||||
fmt — 错误信息
|
||||
strings — 字符串处理
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.4 — 平台适配层完善
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `internal/platform/platform.go` | 添加 `InstallFont()` 和 `RunAsAdmin()` 方法签名 | `os/exec` |
|
||||
| `internal/platform/windows.go` | 实现 `InstallFont()` (注册表写入)、`RunAsAdmin()` (runas 动词)、完善 `SetEnvVar` (使用 `golang.org/x/sys/windows/registry`) | `os/exec`, `golang.org/x/sys/windows/registry` |
|
||||
| `internal/platform/darwin.go` | 实现 `InstallFont()` (~/Library/Fonts)、`RunAsAdmin()` (osascript) | `os/exec`, `os` |
|
||||
| `internal/platform/linux.go` | 实现 `InstallFont()` (~/.local/share/fonts)、`RunAsAdmin()` (pkexec/sudo) | `os/exec`, `os` |
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/platform/platform_test.go` | 平台层单元测试 (使用 build tags 分平台) |
|
||||
|
||||
**额外库(仅 Windows 构建时需要):**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
golang.org/x/sys/windows/registry — Windows 注册表操作 (设置环境变量、安装字体)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.5 — init 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/init.go` | 实现完整的 init 逻辑:创建目录、写入默认 config.yaml、创建默认 Profile、支持 `--template` / `--profile` / `--force` | `internal/config`, `internal/profile`, `internal/logging` |
|
||||
|
||||
**依赖的内部包:**
|
||||
|
||||
```
|
||||
internal/config — DefaultPaths(), EnsureDirs()
|
||||
internal/profile — 创建默认/模板 Profile
|
||||
internal/logging — 日志记录
|
||||
|
||||
标准库:
|
||||
os — 文件/目录创建
|
||||
fmt — 用户输出
|
||||
path/filepath — 路径
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.6 — 终端 UI 工具
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/ui/printer.go` | 统一输出工具:Success/Error/Warn/Info 打印、Verbose 判断 |
|
||||
| `internal/ui/table.go` | 表格渲染封装 (基于 tablewriter) |
|
||||
| `internal/ui/spinner.go` | 加载动画封装 (用于扫描等操作) |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/fatih/color — 终端颜色 (绿色✓、红色✗、黄色⚠ 等)
|
||||
github.com/olekukonenko/tablewriter — 终端表格
|
||||
|
||||
标准库:
|
||||
fmt — 格式化输出
|
||||
os — Stdout/Stderr
|
||||
io — Writer 接口
|
||||
strings — 字符串处理
|
||||
time — 动画定时
|
||||
sync — Spinner 并发控制
|
||||
```
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `go.mod` | 添加 `github.com/fatih/color`、`github.com/olekukonenko/tablewriter` |
|
||||
|
||||
---
|
||||
|
||||
### 任务 1.7 — 错误处理系统
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/errors/errors.go` | DevPackError 结构体、ErrorLevel 枚举、CollectorError、格式化输出 |
|
||||
| `internal/errors/errors_test.go` | 错误处理单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
fmt — 错误格式化
|
||||
errors — errors.Is / errors.As 兼容
|
||||
strings — 消息拼接
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## M2: 核心采集器(第 3-5 周)
|
||||
|
||||
### 任务 2.1 — Go 运行时采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/runtime/go_collector.go` | Go 采集器: 扫描版本、GOPATH、GOROOT、go env、GOPATH/bin 下的工具 |
|
||||
| `internal/collector/runtime/go_collector_test.go` | Go 采集器单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `go version`、`go env -json`、`go install`
|
||||
encoding/json — 解析 `go env -json` 输出
|
||||
context — 命令超时控制
|
||||
path/filepath — GOPATH/bin 扫描
|
||||
os — 文件遍历
|
||||
strings — 输出解析
|
||||
runtime — 获取当前 Go 信息
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`: `go version` 获取版本,`go env -json` 获取环境,遍历 `GOPATH/bin` 获取安装的工具
|
||||
- `Capture()`: 将 metadata.json (版本+env) + go-tools.json (工具列表) 写入目标目录
|
||||
- `Restore()`: 检测 Go 是否安装 → 安装缺失工具 (`go install xxx@latest`)
|
||||
- `Verify()`: 验证 Go 版本和工具是否存在
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.2 — Node.js 运行时采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/runtime/node_collector.go` | Node.js 采集器: 扫描 node/npm/nvm 版本、全局包 |
|
||||
| `internal/collector/runtime/node_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `node --version`、`npm --version`、`npm list -g --json`
|
||||
encoding/json — 解析 npm list JSON
|
||||
context — 超时
|
||||
strings — 版本解析
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`: `node --version`、`npm --version`、`npm list -g --json` 获取全局包
|
||||
- `Capture()`: 写入 metadata.json + global-packages.json
|
||||
- `Restore()`: `npm install -g <package>@<version>` 逐个安装
|
||||
- `Verify()`: 验证 node 版本和全局包
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.3 — Python 运行时采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/runtime/python_collector.go` | Python 采集器: 版本、pip 包、virtualenv 配置 |
|
||||
| `internal/collector/runtime/python_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `python --version`、`pip list --format=json`
|
||||
encoding/json — 解析 pip list JSON
|
||||
context — 超时
|
||||
strings — 解析
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`: `python --version`、`pip --version`、`pip list --format=json`
|
||||
- `Capture()`: 写入 metadata.json + pip-packages.json
|
||||
- `Restore()`: `pip install <package>==<version>` 逐个安装
|
||||
- `Verify()`: 验证安装
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.4 — VS Code 编辑器采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/editor/vscode_collector.go` | VS Code 采集器: 版本、扩展列表、settings.json、keybindings.json、代码片段 |
|
||||
| `internal/collector/editor/vscode_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `code --version`、`code --list-extensions --show-versions`、`code --install-extension`
|
||||
encoding/json — 解析/生成 settings.json
|
||||
os — 读取 settings.json、keybindings.json 文件
|
||||
path/filepath — VS Code 配置文件路径 (不同平台不同)
|
||||
context — 超时
|
||||
strings — 扩展列表解析
|
||||
io — 文件复制
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`:
|
||||
- `code --version` 获取版本
|
||||
- `code --list-extensions --show-versions` 获取扩展列表
|
||||
- 读取 `%APPDATA%/Code/User/settings.json` (Windows) 或 `~/Library/Application Support/Code/User/settings.json` (macOS)
|
||||
- 读取 keybindings.json、snippets 目录
|
||||
- `Capture()`: 复制 settings.json / keybindings.json / snippets/ + 写入 extensions.json
|
||||
- `Restore()`: `code --install-extension <id>@<version>` 逐个安装扩展、复制配置文件
|
||||
- `Verify()`: 验证扩展已安装
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.5 — PowerShell Shell 采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/shell/powershell_collector.go` | PowerShell 采集器: 版本、已安装模块、Profile 脚本 |
|
||||
| `internal/collector/shell/powershell_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `pwsh -Command "Get-Module -ListAvailable | ConvertTo-Json"`
|
||||
encoding/json — 解析 PowerShell JSON 输出
|
||||
os — 读取 $PROFILE 文件
|
||||
path/filepath — Profile 路径
|
||||
context — 超时
|
||||
strings — 解析
|
||||
io — 文件复制
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`: PowerShell 版本、`Get-Module -ListAvailable`、Profile 路径
|
||||
- `Capture()`: 写入 metadata.json + modules.json + profile 文件内容
|
||||
- `Restore()`: `Install-Module -Name <name> -Force` 安装模块 + 写入 Profile
|
||||
- `Verify()`: 验证模块和 Profile
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.6 — Scoop 包管理器采集器 (Windows)
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/package/scoop_collector.go` | Scoop 采集器: 已安装包、bucket 列表 |
|
||||
| `internal/collector/package/scoop_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `scoop list`、`scoop bucket list`、`scoop install`
|
||||
encoding/json — 解析 scoop export JSON
|
||||
context — 超时
|
||||
strings — 输出解析
|
||||
os — Scoop 目录检测
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
**实现逻辑:**
|
||||
- `Scan()`: `scoop export` (JSON)、`scoop bucket list`
|
||||
- `Capture()`: 写入 packages.json + buckets.json
|
||||
- `Restore()`: 先 `scoop bucket add`,再 `scoop install <pkg>`
|
||||
- `Verify()`: 验证包是否已安装
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.7 — Git 配置采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/git/git_collector.go` | Git 采集器: 全局配置、别名 |
|
||||
| `internal/collector/git/git_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os/exec — 执行 `git config --global --list`、`git config --global <key> <value>`
|
||||
context — 超时
|
||||
strings — key=value 解析
|
||||
bufio — 逐行读取 .gitconfig
|
||||
os — 读取 ~/.gitconfig 文件
|
||||
path/filepath — 路径
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.8 — 环境变量采集器
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/env/env_collector.go` | 环境变量采集器: 按 Profile 中定义的 include/exclude pattern 过滤 |
|
||||
| `internal/collector/env/env_collector_test.go` | 单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os — os.Environ() 获取所有环境变量
|
||||
strings — key=value 拆分、pattern 匹配
|
||||
path/filepath — filepath.Match 用于 glob 匹配
|
||||
context — 超时
|
||||
fmt — 格式化
|
||||
encoding/json — 序列化
|
||||
|
||||
内部依赖:
|
||||
internal/platform — SetEnvVar() 设置环境变量 (不同平台不同)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.9 — 采集器自动注册
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `internal/collector/registry.go` | 无需修改,现有注册机制已可用 | — |
|
||||
| `cmd/devpack/main.go` | 添加 `registerCollectors()` 函数,创建 Registry 实例并注册所有内置采集器 | 所有 `internal/collector/*` 子包 |
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/collector/register.go` | `RegisterBuiltins(registry)` — 一次性注册所有内置采集器,集中管理 |
|
||||
|
||||
---
|
||||
|
||||
### 任务 2.10 — scan 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/scan.go` | 实现完整扫描逻辑:解析 flags → 加载 Profile → 选择采集器 → 并发扫描 → 格式化输出 (table/json/yaml) | `internal/collector`, `internal/profile`, `internal/ui`, `internal/logging` |
|
||||
|
||||
**依赖的内部包:**
|
||||
|
||||
```
|
||||
internal/collector — Registry.ScanAll() / ListByCategory()
|
||||
internal/profile — 加载 Profile 确定启用的采集器
|
||||
internal/ui — 表格渲染、颜色输出
|
||||
internal/logging — 日志
|
||||
internal/config — 路径
|
||||
|
||||
标准库:
|
||||
encoding/json — --output json
|
||||
context — 超时控制
|
||||
fmt — 输出
|
||||
strings — 逗号分隔解析
|
||||
time — 扫描耗时
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## M3: 打包引擎(第 6-7 周)
|
||||
|
||||
### 任务 3.1 — Pack 引擎核心
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/pack/engine.go` | PackEngine 结构体:创建 Pack 的核心流程控制 |
|
||||
| `internal/pack/engine_test.go` | Pack 引擎单元测试 |
|
||||
| `internal/pack/archive.go` | tar.gz 打包/解包实现 |
|
||||
| `internal/pack/archive_test.go` | 归档单元测试 |
|
||||
| `internal/pack/checksum.go` | SHA-256 校验和计算与验证 |
|
||||
| `internal/pack/checksum_test.go` | 校验和单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/google/uuid — 生成 Pack UUID
|
||||
|
||||
标准库:
|
||||
archive/tar — tar 格式写入/读取
|
||||
compress/gzip — gzip 压缩/解压
|
||||
crypto/sha256 — SHA-256 校验和
|
||||
encoding/hex — 校验和 hex 编码
|
||||
encoding/json — manifest.json 写入
|
||||
io — 数据流复制
|
||||
os — 文件操作
|
||||
path/filepath — 路径遍历
|
||||
time — 时间戳
|
||||
fmt — 格式化
|
||||
strings — 路径处理
|
||||
```
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `pkg/manifest/manifest.go` | 添加 `Validate()` 方法、`NewManifest()` 构造函数 |
|
||||
| `go.mod` | 添加 `github.com/google/uuid`、`github.com/schollz/progressbar/v3` |
|
||||
|
||||
---
|
||||
|
||||
### 任务 3.2 — capture 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/capture.go` | 实现完整捕获流程:解析 flags → 加载 Profile → 创建临时目录 → 并发运行 Capture() → 生成 Manifest → 打包 → 输出结果 | `internal/pack`, `internal/collector`, `internal/profile`, `internal/ui`, `internal/logging` |
|
||||
|
||||
**依赖的内部包:**
|
||||
|
||||
```
|
||||
internal/pack — PackEngine.CreatePack()
|
||||
internal/collector — Registry + 各采集器
|
||||
internal/profile — 加载 Profile
|
||||
internal/ui — 进度条、表格
|
||||
internal/logging — 日志
|
||||
internal/config — 路径 (Packs 目录)
|
||||
pkg/manifest — Manifest 构建
|
||||
|
||||
标准库:
|
||||
os — 临时目录、文件
|
||||
path/filepath — 路径
|
||||
context — 超时
|
||||
fmt — 输出
|
||||
time — 时间戳
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 3.3 — export / import 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/export.go` | export: 从内部 Packs 目录复制 .devpack 到指定路径; import: 从外部路径复制 .devpack 到 Packs 目录并验证 | `internal/pack`, `internal/config`, `internal/ui` |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
os — 文件复制
|
||||
io — 数据流
|
||||
path/filepath — 路径
|
||||
fmt — 输出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 3.4 — 进度条组件
|
||||
|
||||
**新建文件或修改:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/ui/progress.go` | 基于 progressbar 库的进度条封装、适配打包/还原等长时操作 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/schollz/progressbar/v3 — 进度条渲染
|
||||
|
||||
标准库:
|
||||
os — Stderr 输出
|
||||
fmt — 格式化
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## M4: 还原引擎(第 8-10 周)
|
||||
|
||||
### 任务 4.1 — 还原引擎核心
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/restore/engine.go` | RestoreEngine: 解包 → 校验 → 解析 Manifest → 平台检查 → 冲突检测 → 执行还原 → 验证 → 报告 |
|
||||
| `internal/restore/engine_test.go` | 还原引擎单元测试 |
|
||||
| `internal/restore/plan.go` | RestorePlan: 还原计划生成、依赖排序 (拓扑排序) |
|
||||
| `internal/restore/plan_test.go` | 还原计划单元测试 |
|
||||
| `internal/restore/conflict.go` | 冲突检测器: 版本对比、已存在检测、策略应用 |
|
||||
| `internal/restore/conflict_test.go` | 冲突检测单元测试 |
|
||||
| `internal/restore/report.go` | 还原报告: 成功/失败/跳过/警告 的汇总和输出 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/AlecAivazis/survey/v2 — 冲突时交互式提示 (ConflictPrompt 策略)
|
||||
|
||||
标准库:
|
||||
archive/tar — 解包
|
||||
compress/gzip — 解压
|
||||
crypto/sha256 — 校验和验证
|
||||
encoding/hex — hex 解码
|
||||
encoding/json — Manifest 解析
|
||||
os — 文件操作
|
||||
path/filepath — 路径
|
||||
context — 超时
|
||||
fmt — 格式化
|
||||
sort — 依赖排序
|
||||
strings — 版本对比
|
||||
time — 时间
|
||||
sync — 并发控制
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 4.2 — 干运行模式
|
||||
|
||||
**涉及文件:**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `internal/restore/engine.go` | 在 `Restore()` 中根据 `DryRun` 标志只模拟操作、输出计划但不执行 |
|
||||
| `internal/restore/report.go` | DryRun 专用报告格式 |
|
||||
|
||||
**所需库:** 无额外依赖,使用已有标准库
|
||||
|
||||
---
|
||||
|
||||
### 任务 4.3 — restore 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/restore.go` | 实现完整还原流程:解析 flags → 加载 Pack → 调用 RestoreEngine → 处理冲突 → 输出报告 | `internal/restore`, `internal/pack`, `internal/ui`, `internal/logging`, `internal/collector` |
|
||||
|
||||
**依赖的内部包:**
|
||||
|
||||
```
|
||||
internal/restore — RestoreEngine
|
||||
internal/pack — Pack 解包、校验和验证
|
||||
internal/collector — 各采集器 Restore() / Verify()
|
||||
internal/ui — 进度条、表格、确认提示
|
||||
internal/logging — 日志
|
||||
internal/config — 路径
|
||||
internal/profile — Profile 加载
|
||||
pkg/manifest — Manifest 解析
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 4.4 — 各采集器的 Restore 逻辑
|
||||
|
||||
此阶段需**回到每个采集器文件**实现完整的 `Restore()` 和 `Verify()` 方法:
|
||||
|
||||
| 文件 | Restore 逻辑 | 所需命令 |
|
||||
|---|---|---|
|
||||
| `internal/collector/runtime/go_collector.go` | `go install <tool>@latest` 安装工具 | `os/exec` |
|
||||
| `internal/collector/runtime/node_collector.go` | `npm install -g <pkg>@<ver>` 安装全局包 | `os/exec` |
|
||||
| `internal/collector/runtime/python_collector.go` | `pip install <pkg>==<ver>` 安装包 | `os/exec` |
|
||||
| `internal/collector/editor/vscode_collector.go` | `code --install-extension <id>` + 复制配置文件 | `os/exec`, `io`, `os` |
|
||||
| `internal/collector/shell/powershell_collector.go` | `Install-Module -Name <mod>` + 写入 Profile | `os/exec`, `os` |
|
||||
| `internal/collector/package/scoop_collector.go` | `scoop bucket add` + `scoop install` | `os/exec` |
|
||||
| `internal/collector/git/git_collector.go` | `git config --global <key> <value>` | `os/exec` |
|
||||
| `internal/collector/env/env_collector.go` | 调用 `platform.SetEnvVar()` | `internal/platform` |
|
||||
|
||||
---
|
||||
|
||||
## M5: 配置与打磨(第 11-12 周)
|
||||
|
||||
### 任务 5.1 — profile 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/profile.go` | 实现 create/show/list/delete/use 五个子命令的完整逻辑 | `internal/profile`, `internal/config`, `internal/ui`, `internal/logging` |
|
||||
|
||||
**依赖的内部包:**
|
||||
|
||||
```
|
||||
internal/profile — Profile CRUD 操作
|
||||
internal/config — 路径
|
||||
internal/ui — 表格、颜色输出
|
||||
internal/logging — 日志
|
||||
|
||||
标准库:
|
||||
fmt — 输出
|
||||
os — 文件操作
|
||||
path/filepath — 路径
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 5.2 — list 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/list.go` | 实现 packs/profiles/collectors 列表展示,支持 `--format` 标志 | `internal/pack`, `internal/profile`, `internal/collector`, `internal/ui` |
|
||||
|
||||
**所需标准库:**
|
||||
|
||||
```
|
||||
encoding/json — --format json 输出
|
||||
fmt — 格式化
|
||||
path/filepath — 扫描 Packs 目录
|
||||
os — 读取目录
|
||||
time — Pack 创建时间
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 5.3 — diff 命令实现
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/diff.go` | 实现环境对比逻辑:Pack vs 当前环境 / Pack vs Pack | `internal/pack`, `internal/collector`, `internal/ui` |
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/diff/differ.go` | 差异计算引擎:逐项对比、输出 added/removed/changed |
|
||||
| `internal/diff/differ_test.go` | 差异引擎单元测试 |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
标准库:
|
||||
encoding/json — 数据加载
|
||||
fmt — 输出
|
||||
strings — 版本对比
|
||||
sort — 排序
|
||||
|
||||
内部依赖:
|
||||
internal/ui — 彩色差异输出 (红色-/绿色+/黄色~)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 5.4 — 测试覆盖率提升
|
||||
|
||||
**新建文件:**
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `internal/pack/engine_integration_test.go` | Pack 引擎集成测试:完整的打包→解包流程 |
|
||||
| `internal/restore/engine_integration_test.go` | 还原引擎集成测试 |
|
||||
| `test/e2e/capture_restore_test.go` | 端到端测试:capture → export → import → restore |
|
||||
|
||||
**所需库:**
|
||||
|
||||
```
|
||||
第三方库:
|
||||
github.com/stretchr/testify/assert — 断言
|
||||
github.com/stretchr/testify/require — 必要条件断言
|
||||
github.com/stretchr/testify/mock — Mock (模拟外部命令)
|
||||
|
||||
标准库:
|
||||
testing — Go 测试框架
|
||||
os — 临时目录
|
||||
path/filepath — 路径
|
||||
io/fs — 文件遍历
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 任务 5.5 — version 命令增强
|
||||
|
||||
**需修改的现有文件:**
|
||||
|
||||
| 文件 | 改动 | 所需库 |
|
||||
|---|---|---|
|
||||
| `cmd/devpack/commands/version.go` | 添加 `--check-update` 标志,从 GitHub API 检查最新版本 | `net/http`, `encoding/json` |
|
||||
| `pkg/version/version.go` | 添加 `CheckLatest()` 方法 | `net/http`, `encoding/json`, `fmt` |
|
||||
|
||||
---
|
||||
|
||||
## 文件总览与新增文件清单
|
||||
|
||||
### 新建文件列表 (按模块分组)
|
||||
|
||||
```
|
||||
internal/
|
||||
├── logging/
|
||||
│ ├── logger.go # zerolog 封装
|
||||
│ └── logger_test.go
|
||||
├── config/
|
||||
│ ├── config.go # AppConfig 配置结构
|
||||
│ └── config_test.go
|
||||
├── profile/
|
||||
│ ├── profile.go # Profile CRUD
|
||||
│ ├── profile_test.go
|
||||
│ └── templates.go # 预设模板
|
||||
├── ui/
|
||||
│ ├── printer.go # 统一输出工具
|
||||
│ ├── table.go # 表格渲染
|
||||
│ ├── spinner.go # 加载动画
|
||||
│ └── progress.go # 进度条
|
||||
├── errors/
|
||||
│ ├── errors.go # 错误类型
|
||||
│ └── errors_test.go
|
||||
├── collector/
|
||||
│ ├── register.go # RegisterBuiltins()
|
||||
│ ├── runtime/
|
||||
│ │ ├── go_collector.go
|
||||
│ │ ├── go_collector_test.go
|
||||
│ │ ├── node_collector.go
|
||||
│ │ ├── node_collector_test.go
|
||||
│ │ ├── python_collector.go
|
||||
│ │ └── python_collector_test.go
|
||||
│ ├── editor/
|
||||
│ │ ├── vscode_collector.go
|
||||
│ │ └── vscode_collector_test.go
|
||||
│ ├── shell/
|
||||
│ │ ├── powershell_collector.go
|
||||
│ │ └── powershell_collector_test.go
|
||||
│ ├── package/
|
||||
│ │ ├── scoop_collector.go
|
||||
│ │ └── scoop_collector_test.go
|
||||
│ ├── git/
|
||||
│ │ ├── git_collector.go
|
||||
│ │ └── git_collector_test.go
|
||||
│ └── env/
|
||||
│ ├── env_collector.go
|
||||
│ └── env_collector_test.go
|
||||
├── pack/
|
||||
│ ├── engine.go # PackEngine
|
||||
│ ├── engine_test.go
|
||||
│ ├── engine_integration_test.go
|
||||
│ ├── archive.go # tar.gz 归档
|
||||
│ ├── archive_test.go
|
||||
│ ├── checksum.go # SHA-256 校验和
|
||||
│ └── checksum_test.go
|
||||
├── restore/
|
||||
│ ├── engine.go # RestoreEngine
|
||||
│ ├── engine_test.go
|
||||
│ ├── engine_integration_test.go
|
||||
│ ├── plan.go # 还原计划
|
||||
│ ├── plan_test.go
|
||||
│ ├── conflict.go # 冲突检测
|
||||
│ ├── conflict_test.go
|
||||
│ └── report.go # 还原报告
|
||||
├── diff/
|
||||
│ ├── differ.go # 差异引擎
|
||||
│ └── differ_test.go
|
||||
├── platform/
|
||||
│ └── platform_test.go # 平台层测试
|
||||
test/
|
||||
└── e2e/
|
||||
└── capture_restore_test.go # 端到端测试
|
||||
```
|
||||
|
||||
**新增文件总计:约 45 个**
|
||||
|
||||
---
|
||||
|
||||
## go.mod 最终依赖
|
||||
|
||||
完成 MVP 后,`go.mod` 应包含以下直接依赖:
|
||||
|
||||
```go
|
||||
require (
|
||||
// CLI 框架 (已有)
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.18.2
|
||||
|
||||
// 日志
|
||||
github.com/rs/zerolog v1.32.0
|
||||
|
||||
// 终端 UI
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/olekukonenko/tablewriter v0.0.5
|
||||
github.com/schollz/progressbar/v3 v3.14.2
|
||||
|
||||
// 交互式提示
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||
|
||||
// 数据格式
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
// 工具
|
||||
github.com/google/uuid v1.6.0
|
||||
|
||||
// 测试
|
||||
github.com/stretchr/testify v1.9.0
|
||||
)
|
||||
```
|
||||
|
||||
v0.3.0 版本额外添加:
|
||||
|
||||
```go
|
||||
require (
|
||||
golang.org/x/crypto v0.21.0 // Argon2id 密钥派生
|
||||
golang.org/x/sys v0.18.0 // Windows 注册表操作
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 开发顺序建议
|
||||
|
||||
```
|
||||
Week 1-2: M1 (logging → config → profile → ui → errors → init → 平台完善)
|
||||
↓
|
||||
Week 3-5: M2 (go → node → python → vscode → powershell → scoop → git → env → scan)
|
||||
↓
|
||||
Week 6-7: M3 (archive → checksum → pack engine → capture → export/import)
|
||||
↓
|
||||
Week 8-10: M4 (plan → conflict → restore engine → 各采集器 restore → restore cmd)
|
||||
↓
|
||||
Week 11-12: M5 (profile cmd → list → diff → tests → 打磨)
|
||||
```
|
||||
|
||||
每完成一个模块就跑 `go test ./...` 确保不引入回归。
|
||||
@@ -11,13 +11,13 @@ func TestRegistry_Register(t *testing.T) {
|
||||
mock := &mockCollector{name: "test"}
|
||||
err := r.Register(mock)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
t.Fatalf("注册时不应出错: %v", err)
|
||||
}
|
||||
|
||||
// Duplicate registration should fail
|
||||
// 重复注册应该失败
|
||||
err = r.Register(mock)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for duplicate registration")
|
||||
t.Fatal("重复注册应该返回错误")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,15 +29,15 @@ func TestRegistry_Get(t *testing.T) {
|
||||
|
||||
c, ok := r.Get("test")
|
||||
if !ok {
|
||||
t.Fatal("expected to find collector")
|
||||
t.Fatal("应该能找到已注册的采集器")
|
||||
}
|
||||
if c.Name() != "test" {
|
||||
t.Fatalf("expected name 'test', got '%s'", c.Name())
|
||||
t.Fatalf("期望名称为 'test',实际为 '%s'", c.Name())
|
||||
}
|
||||
|
||||
_, ok = r.Get("nonexistent")
|
||||
if ok {
|
||||
t.Fatal("expected not to find collector")
|
||||
t.Fatal("不应该找到未注册的采集器")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,16 +50,16 @@ func TestRegistry_List(t *testing.T) {
|
||||
|
||||
all := r.List()
|
||||
if len(all) != 3 {
|
||||
t.Fatalf("expected 3 collectors, got %d", len(all))
|
||||
t.Fatalf("期望 3 个采集器,实际为 %d 个", len(all))
|
||||
}
|
||||
|
||||
runtime := r.ListByCategory(CategoryRuntime)
|
||||
if len(runtime) != 2 {
|
||||
t.Fatalf("expected 2 runtime collectors, got %d", len(runtime))
|
||||
t.Fatalf("期望 2 个运行时采集器,实际为 %d 个", len(runtime))
|
||||
}
|
||||
}
|
||||
|
||||
// mockCollector implements Collector for testing
|
||||
// mockCollector 用于测试的模拟采集器
|
||||
type mockCollector struct {
|
||||
name string
|
||||
category Category
|
||||
@@ -68,7 +68,7 @@ type mockCollector struct {
|
||||
|
||||
func (m *mockCollector) Name() string { return m.name }
|
||||
func (m *mockCollector) DisplayName() string { return m.name }
|
||||
func (m *mockCollector) Description() string { return "mock collector" }
|
||||
func (m *mockCollector) Description() string { return "模拟采集器" }
|
||||
func (m *mockCollector) Category() Category { return m.category }
|
||||
func (m *mockCollector) IsAvailable(ctx context.Context) bool {
|
||||
return m.available
|
||||
|
||||
@@ -18,7 +18,7 @@ func NewDarwinPlatform() *DarwinPlatform {
|
||||
}
|
||||
|
||||
func (p *DarwinPlatform) OS() string { return "darwin" }
|
||||
func (p *DarwinPlatform) Arch() string { return "amd64" } // TODO: detect properly
|
||||
func (p *DarwinPlatform) Arch() string { return "amd64" } // TODO: 正确检测架构
|
||||
func (p *DarwinPlatform) HomeDir() string { return p.homeDir }
|
||||
|
||||
func (p *DarwinPlatform) ConfigDir() string {
|
||||
@@ -34,13 +34,13 @@ func (p *DarwinPlatform) GetEnvVar(key string) string {
|
||||
}
|
||||
|
||||
func (p *DarwinPlatform) SetEnvVar(ctx context.Context, key, value string) error {
|
||||
// On macOS, set via launchctl and shell profile
|
||||
// 在 macOS 上通过 launchctl 和 Shell 配置文件设置
|
||||
cmd := exec.CommandContext(ctx, "launchctl", "setenv", key, value)
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func (p *DarwinPlatform) AddToPath(ctx context.Context, dir string) error {
|
||||
// TODO: Add to shell profile
|
||||
// TODO: 添加到 Shell 配置文件
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ func NewLinuxPlatform() *LinuxPlatform {
|
||||
}
|
||||
|
||||
func (p *LinuxPlatform) OS() string { return "linux" }
|
||||
func (p *LinuxPlatform) Arch() string { return "amd64" } // TODO: detect properly
|
||||
func (p *LinuxPlatform) Arch() string { return "amd64" } // TODO: 正确检测架构
|
||||
func (p *LinuxPlatform) HomeDir() string { return p.homeDir }
|
||||
|
||||
func (p *LinuxPlatform) ConfigDir() string {
|
||||
@@ -40,12 +40,12 @@ func (p *LinuxPlatform) GetEnvVar(key string) string {
|
||||
}
|
||||
|
||||
func (p *LinuxPlatform) SetEnvVar(ctx context.Context, key, value string) error {
|
||||
// TODO: Add to shell profile
|
||||
// TODO: 写入 Shell 配置文件以持久化
|
||||
return os.Setenv(key, value)
|
||||
}
|
||||
|
||||
func (p *LinuxPlatform) AddToPath(ctx context.Context, dir string) error {
|
||||
// TODO: Add to shell profile
|
||||
// TODO: 添加到 Shell 配置文件
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ func Detect() Platform {
|
||||
case "linux":
|
||||
return NewLinuxPlatform()
|
||||
default:
|
||||
// Fallback to Linux
|
||||
// 默认回退到 Linux 实现
|
||||
return NewLinuxPlatform()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (p *WindowsPlatform) AddToPath(ctx context.Context, dir string) error {
|
||||
}
|
||||
|
||||
func (p *WindowsPlatform) IsAdmin() bool {
|
||||
// Check if running as administrator on Windows
|
||||
// 检查 Windows 上是否以管理员身份运行
|
||||
cmd := exec.Command("net", "session")
|
||||
err := cmd.Run()
|
||||
return err == nil
|
||||
@@ -77,7 +77,7 @@ func (p *WindowsPlatform) PackageManagers() []string {
|
||||
|
||||
func (p *WindowsPlatform) DefaultShell() string {
|
||||
if _, err := exec.LookPath("pwsh"); err == nil {
|
||||
return "pwsh" // PowerShell 7+
|
||||
return "pwsh" // PowerShell 7+ 版本
|
||||
}
|
||||
return "powershell" // Windows PowerShell 5.1
|
||||
}
|
||||
|
||||
@@ -5,19 +5,19 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// These variables are set at build time via ldflags.
|
||||
// 以下变量在构建时通过 ldflags 注入
|
||||
var (
|
||||
Version = "dev"
|
||||
Commit = "unknown"
|
||||
Date = "unknown"
|
||||
)
|
||||
|
||||
// GetVersionString returns a short version string.
|
||||
// GetVersionString 返回简短的版本号字符串
|
||||
func GetVersionString() string {
|
||||
return Version
|
||||
}
|
||||
|
||||
// GetFullVersionInfo returns complete version information.
|
||||
// GetFullVersionInfo 返回完整的版本信息
|
||||
func GetFullVersionInfo() string {
|
||||
return fmt.Sprintf(
|
||||
"DevPack %s\n Commit: %s\n Built: %s\n Go: %s\n OS/Arch: %s/%s",
|
||||
|
||||
Reference in New Issue
Block a user