commit a9f933074447369ed1820f19d692659c7ea7ff54 Author: zyj Date: Tue Mar 3 18:20:18 2026 +0800 init diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..47f8a0b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,71 @@ +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + go-version: ['1.22'] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Download dependencies + run: go mod download + + - name: Run tests + run: go test -race -coverprofile=coverage.out -covermode=atomic ./... + + - name: Upload coverage + if: matrix.os == 'ubuntu-latest' + uses: codecov/codecov-action@v3 + with: + file: coverage.out + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.22' + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + + build: + name: Build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + go-version: ['1.22'] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Build + run: go build -v ./cmd/devpack/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b0aa3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Binaries +devpack +devpack.exe +*.exe +*.dll +*.so +*.dylib + +# Build output +/dist/ +/build/ +/bin/ + +# Test binary +*.test + +# Go workspace +go.work +go.work.sum + +# IDE +.idea/ +*.swp +*.swo +*~ +.vscode/settings.json + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log + +# Pack files (don't commit test packs) +*.devpack + +# Temp +tmp/ +temp/ + +# Coverage +coverage.out +coverage.html + +# Environment +.env +.env.local diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4f81c38 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,49 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug DevPack", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": [], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + }, + { + "name": "Debug Scan", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": ["scan", "--verbose"], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + }, + { + "name": "Debug Capture", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": ["capture", "--name", "test-env"], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + }, + { + "name": "Debug Restore", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": ["restore", "test-env", "--dry-run"], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..32d0ee7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 DevPack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..025f9d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,95 @@ +.PHONY: build build-all test test-unit test-coverage lint fmt vet clean run dev help + +# Variables +BINARY_NAME=devpack +MAIN_PATH=./cmd/devpack +VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") +COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") +DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") +LDFLAGS=-ldflags "-s -w -X github.com/user/devpack/pkg/version.Version=$(VERSION) -X github.com/user/devpack/pkg/version.Commit=$(COMMIT) -X github.com/user/devpack/pkg/version.Date=$(DATE)" + +# Default target +all: lint test build + +## help: Show this help message +help: + @echo "DevPack Makefile" + @echo "" + @echo "Usage:" + @sed -n 's/^##//p' $(MAKEFILE_LIST) | column -t -s ':' | sed -e 's/^/ /' + +## build: Build for current platform +build: + go build $(LDFLAGS) -o $(BINARY_NAME) $(MAIN_PATH) + +## build-windows: Build for Windows (amd64) +build-windows: + GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BINARY_NAME).exe $(MAIN_PATH) + +## build-darwin: Build for macOS (amd64 + arm64) +build-darwin: + GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BINARY_NAME)-darwin-amd64 $(MAIN_PATH) + GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BINARY_NAME)-darwin-arm64 $(MAIN_PATH) + +## build-linux: Build for Linux (amd64 + arm64) +build-linux: + GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BINARY_NAME)-linux-amd64 $(MAIN_PATH) + GOOS=linux GOARCH=arm64 go build $(LDFLAGS) -o $(BINARY_NAME)-linux-arm64 $(MAIN_PATH) + +## build-all: Build for all platforms +build-all: build-windows build-darwin build-linux + +## test: Run all tests +test: + go test -race -count=1 ./... + +## test-unit: Run unit tests only +test-unit: + go test -race -count=1 -short ./... + +## test-coverage: Run tests with coverage report +test-coverage: + go test -race -coverprofile=coverage.out -covermode=atomic ./... + go tool cover -html=coverage.out -o coverage.html + @echo "Coverage report: coverage.html" + +## lint: Run linter +lint: + golangci-lint run ./... + +## fmt: Format code +fmt: + go fmt ./... + goimports -w . + +## vet: Run go vet +vet: + go vet ./... + +## run: Build and run +run: build + ./$(BINARY_NAME) + +## dev: Run in development mode +dev: + go run $(MAIN_PATH) + +## clean: Clean build artifacts +clean: + rm -f $(BINARY_NAME) $(BINARY_NAME).exe + rm -f $(BINARY_NAME)-* + rm -f coverage.out coverage.html + rm -rf dist/ + +## deps: Download dependencies +deps: + go mod download + go mod tidy + +## snapshot: Create GoReleaser snapshot +snapshot: + goreleaser release --snapshot --clean + +## release: Create release with GoReleaser +release: + goreleaser release --clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..317ef76 --- /dev/null +++ b/README.md @@ -0,0 +1,273 @@ +

+ DevPack Logo +

+ +

DevPack

+ +

+ 📊 匀发环境打包迁移工具 — 䞀键打包随倄匀发 +

+ +

+ 功胜特性 • + 快速匀始 • + 䜿甚瀺䟋 • + 甚户手册 • + 匀发指南 • + 莡献指南 +

+ +--- + +## 🎯 项目简介 + +**DevPack** 是䞀䞪甚 Go 猖写的跚平台匀发环境打包迁移工具。它胜借扫描、捕获并打包䜠圓前电脑䞊的完敎匀发环境包括猖皋语蚀运行时、包管理噚、IDE 配眮、Shell 讟眮、环境变量等生成䞀䞪可移怍的 `.devpack` 文件圚及䞀台同系统的电脑䞊䞀键还原让䜠圚几分钟内恢倍完敎的匀发环境。 + +### 䞺什么需芁 DevPack + +每䞪匀发者郜经历过这样的痛苊 + +- 🖥 **换新电脑** — 花䞀敎倩甚至几倩重新搭建匀发环境 +- 🔧 **装了什么** — 记䞍枅装了哪些工具、配了哪些参数 +- 👥 **团队协䜜** — 新成员入职需芁挫长的环境配眮过皋 +- 📋 **环境䞍䞀臎** — "圚我电脑䞊胜跑"的经兞问题 + +DevPack 就像给䜠的匀发环境拍䞀匠"快照"随时随地还原。 + +### DevPack vs Docker + +| 特性 | DevPack | Docker | +|------|---------|--------| +| 目标 | 打包**宿䞻机匀发环境** | 打包**应甚运行环境** | +| 䜿甚场景 | 电脑迁移、环境倇仜 | 应甚郚眲、环境隔犻 | +| 捕获内容 | IDE讟眮、Shell配眮、工具铟 | 应甚代码、䟝赖、系统库 | +| 运行方匏 | 盎接还原到宿䞻机 | 运行圚容噚䞭 | +| 性胜匀销 | 无 | 有虚拟化层 | +| 孊习成本 | 䜎 | 侭等 | + +> 💡 DevPack 䞍是 Docker 的替代品而是补充。Docker 解决"应甚劂䜕郚眲"DevPack 解决"匀发者劂䜕迁移"。 + +--- + +## ✹ 功胜特性 + +### 🔍 智胜扫描 +- 自劚检测已安装的猖皋语蚀、框架、工具 +- 识别包管理噚及已安装的包Scoop、Chocolatey、Winget、Homebrew、APT 等 +- 捕获 IDE/猖蟑噚配眮VS Code 扩展䞎讟眮、JetBrains 讟眮等 +- 收集 Shell 配眮PowerShell Profile、.bashrc、.zshrc 等 + +### 📊 䞀键打包 +- 生成可移怍的 `.devpack` 打包文件 +- 支持选择性打包只打包䜠需芁的郚分 +- 敏感数据加密存傚SSH 密钥、Token 等 +- 增量打包节省空闎 + +### 🚀 快速还原 +- 自劚䟝赖解析䞎安装顺序管理 +- 冲突检测䞎智胜合并 +- 干运行暡匏预览将做的曎改 +- 回滚机制还原倱莥可撀销 + +### 🧩 插件化架构 +- 内眮䞰富的采集噚插件 +- 支持自定义采集噚匀发 +- 瀟区插件生态 + +### 📊 环境管理 +- 呜名配眮文件Profile管理 +- 环境差匂对比 +- 环境版本历史 + +--- + +## 📋 系统芁求 + +| 操䜜系统 | 最䜎版本 | 架构 | +|---------|---------|------| +| Windows | 10 1903+ | x64, ARM64 | +| macOS | 11 Big Sur+ | x64, ARM64 (Apple Silicon) | +| Linux | Ubuntu 20.04+ / CentOS 8+ | x64, ARM64 | + +--- + +## 🚀 快速匀始 + +### 安装 + +**䜿甚 Go 安装** +```bash +go install github.com/user/devpack@latest +``` + +**Windows (Scoop)** +```powershell +scoop bucket add devpack https://github.com/user/devpack-bucket +scoop install devpack +``` + +**macOS (Homebrew)** +```bash +brew tap user/devpack +brew install devpack +``` + +**从 Release 䞋蜜** + +前埀 [Releases](https://github.com/user/devpack/releases) 页面䞋蜜对应平台的二进制文件。 + +### 快速䞊手 + +```bash +# 1. 初始化创建默讀配眮文件 +devpack init + +# 2. 扫描圓前环境 +devpack scan + +# 3. 打包匀发环境 +devpack capture --name "my-dev-env" + +# 4. 富出䞺可移怍文件 +devpack export my-dev-env -o my-dev-env.devpack + +# 5. 圚新电脑䞊还原 +devpack import my-dev-env.devpack +devpack restore my-dev-env +``` + +--- + +## 💻 䜿甚瀺䟋 + +### 场景䞀打包完敎匀发环境 + +```bash +# 扫描并预览将芁打包的内容 +devpack scan --verbose + +# 创建完敎环境快照 +devpack capture --name "fullstack-2026" --all + +# 富出 +devpack export fullstack-2026 -o fullstack-2026.devpack +``` + +### 场景二只打包特定工具铟 + +```bash +# 只打包 Go + VS Code 盞关配眮 +devpack capture --name "golang-env" \ + --collectors runtime,editor \ + --filter "runtime:go,editor:vscode" +``` + +### 场景䞉团队环境标准化 + +```bash +# 团队 Lead 富出标准匀发环境 +devpack capture --name "team-standard" --profile team.yaml +devpack export team-standard -o team-standard.devpack + +# 新成员富入并还原 +devpack import team-standard.devpack +devpack restore team-standard --dry-run # 先预览 +devpack restore team-standard # 确讀后还原 +``` + +### 场景四对比䞀台电脑的环境差匂 + +```bash +# 圚电脑 A 䞊富出 +devpack capture --name "pc-a" +devpack export pc-a -o pc-a.devpack + +# 圚电脑 B 䞊对比 +devpack import pc-a.devpack +devpack diff pc-a --current +``` + +--- + +## 🏗 项目结构 + +``` +DevPack/ +├── cmd/ # CLI 入口䞎呜什定义 +│ └── devpack/ +│ ├── main.go +│ └── commands/ # 各子呜什实现 +├── internal/ # 内郚包䞍对倖暎露 +│ ├── collector/ # 采集噚栞心 +│ │ ├── registry.go # 采集噚泚册䞭心 +│ │ ├── runtime/ # 运行时采集噚Go, Node, Python... +│ │ ├── editor/ # 猖蟑噚采集噚VS Code, JetBrains... +│ │ ├── shell/ # Shell 采集噚 +│ │ ├── package/ # 包管理噚采集噚 +│ │ ├── git/ # Git 配眮采集噚 +│ │ ├── env/ # 环境变量采集噚 +│ │ ├── font/ # 字䜓采集噚 +│ │ └── ssh/ # SSH/GPG 密钥采集噚 +│ ├── pack/ # 打包/解包匕擎 +│ ├── restore/ # 还原匕擎 +│ ├── profile/ # 配眮文件管理 +│ ├── diff/ # 环境差匂对比 +│ ├── crypto/ # 加密暡块 +│ ├── platform/ # 平台适配层 +│ │ ├── windows/ +│ │ ├── darwin/ +│ │ └── linux/ +│ └── config/ # 应甚配眮 +├── pkg/ # 可对倖䜿甚的公共包 +│ ├── manifest/ # Pack 枅单栌匏定义 +│ └── version/ # 版本信息 +├── plugins/ # 倖郚插件目圕 +├── docs/ # 项目文档 +│ ├── PRD.md # 产品需求文档 +│ ├── ARCHITECTURE.md # 架构讟计文档 +│ ├── DEVELOPMENT.md # 匀发指南 +│ ├── API.md # API 讟计文档 +│ ├── ROADMAP.md # 匀发路线囟 +│ ├── USER-GUIDE.md # 甚户手册 +│ └── CONTRIBUTING.md # 莡献指南 +├── test/ # 集成测试 +├── scripts/ # 构建䞎工具脚本 +├── .github/ # GitHub Actions CI/CD +├── go.mod +├── go.sum +├── Makefile +├── LICENSE +└── README.md +``` + +--- + +## 📖 文档 + +| 文档 | 诎明 | +|------|------| +| [产品需求文档 (PRD)](docs/PRD.md) | 产品定䜍、甚户画像、功胜需求 | +| [架构讟计文档](docs/ARCHITECTURE.md) | 系统架构、栞心暡块、数据流 | +| [匀发指南](docs/DEVELOPMENT.md) | 匀发环境搭建、猖码规范、测试 | +| [API 讟计文档](docs/API.md) | CLI 呜什、内郚 API、Pack 栌匏规范 | +| [匀发路线囟](docs/ROADMAP.md) | 版本规划䞎里皋碑 | +| [甚户手册](docs/USER-GUIDE.md) | 安装、䜿甚、垞见问题 | +| [莡献指南](docs/CONTRIBUTING.md) | 劂䜕参䞎项目匀发 | + +--- + +## 🀝 莡献 + +欢迎莡献代码、报告 Bug 或提出新功胜建议请查看 [莡献指南](docs/CONTRIBUTING.md) 了解诊情。 + +--- + +## 📄 讞可证 + +本项目采甚 [MIT License](LICENSE) 匀源。 + +--- + +

+ Built with ❀ by DevPack Team +

diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..ca18cc3 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,898 @@ +# DevPack API 讟计文档 + +> 版本v1.0.0-draft +> 曎新日期2026-03-03 +> 䜜者DevPack Team + +--- + +## 1. CLI 呜什参考 + +### 1.1 呜什总览 + +``` +devpack [command] [subcommand] [flags] + +Available Commands: + init 初始化 DevPack 配眮 + scan 扫描圓前匀发环境 + capture 捕获环境并生成 Pack + restore 从 Pack 还原匀发环境 + diff 对比䞀䞪环境的差匂 + export 富出 Pack 䞺文件 + import 富入 Pack 文件 + list 列出 Pack 和 Profile + profile 管理配眮文件 + verify 验证 Pack 文件完敎性 + version 星瀺版本信息 + help 垮助信息 + +Global Flags: + -v, --verbose 诊细蟓出 + -q, --quiet 静默暡匏 + --log-level 日志级别 (trace|debug|info|warn|error) + --log-file 日志文件路埄 + --no-color 犁甚圩色蟓出 + --config 配眮文件路埄默讀 ~/.devpack/config.yaml + -h, --help 垮助信息 +``` + +--- + +### 1.2 devpack init + +初始化 DevPack创建配眮目圕和默讀配眮文件。 + +``` +devpack init [flags] + +Flags: + --profile 创建并䜿甚指定名称的 Profile + --template 䜿甚预讟暡板 (minimal|standard|full) + --force 芆盖已有配眮 +``` + +**瀺䟋** +```bash +# 默讀初始化 +devpack init + +# 䜿甚暡板初始化 +devpack init --template standard + +# 创建指定 Profile +devpack init --profile golang-dev +``` + +**行䞺** +1. 创建 `~/.devpack/` 目圕 +2. 生成 `~/.devpack/config.yaml` 默讀配眮 +3. 创建 `~/.devpack/profiles/` 目圕 +4. 创建 `~/.devpack/packs/` 目圕 +5. 创建 `~/.devpack/logs/` 目圕 + +**蟓出瀺䟋** +``` +✓ Created ~/.devpack/config.yaml +✓ Created ~/.devpack/profiles/default.yaml +✓ DevPack initialized successfully! + +Run 'devpack scan' to scan your current environment. +``` + +--- + +### 1.3 devpack scan + +扫描圓前系统的匀发环境。 + +``` +devpack scan [flags] + +Flags: + -c, --collectors 指定采集噚逗号分隔 + --category 按分类扫描 (runtime|package|editor|shell|git|env) + --profile 䜿甚指定 Profile 的扫描配眮 + -o, --output 蟓出栌匏 (table|json|yaml) [默讀: table] + --save 保存扫描结果到文件 + --detailed 星瀺诊细信息 +``` + +**瀺䟋** +```bash +# 扫描所有 +devpack scan + +# 只扫描运行时 +devpack scan --category runtime + +# 扫描特定采集噚 +devpack scan -c go,node,vscode + +# JSON 栌匏蟓出 +devpack scan -o json + +# 保存结果 +devpack scan --save scan-result.json +``` + +**蟓出瀺䟋** +``` +🔍 Scanning development environment... + +╔══════════════╀════════════════════╀═══════════╀═══════════════════╗ +║ Category │ Name │ Version │ Details ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Runtime │ Go │ 1.22.1 │ GOPATH: ~/go ║ +║ Runtime │ Node.js │ 20.11.0 │ npm: 10.2.4 ║ +║ Runtime │ Python │ 3.12.2 │ pip: 24.0 ║ +║ Runtime │ Rust │ 1.76.0 │ rustup: 1.27.0 ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Package Mgr │ Scoop │ - │ 42 packages ║ +║ Package Mgr │ Winget │ - │ 15 packages ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Editor │ VS Code │ 1.87.0 │ 35 extensions ║ +║ Editor │ Neovim │ 0.9.5 │ 18 plugins ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Shell │ PowerShell │ 7.4.1 │ 5 modules ║ +║ Shell │ Windows Terminal │ 1.19 │ 3 profiles ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Git │ Git │ 2.43.0 │ 12 aliases ║ +╠══════════════╪════════════════════╪═══════════╪═══════════════════╣ +║ Environment │ Environment Vars │ - │ 8 dev-related ║ +╚══════════════╧════════════════════╧═══════════╧═══════════════════╝ + +Found 12 items across 6 categories. +Estimated pack size: ~12 MB +``` + +--- + +### 1.4 devpack capture + +捕获圓前环境并创建 Pack。 + +``` +devpack capture [flags] + +Flags: + -n, --name Pack 名称必需 + -d, --description Pack 描述 + -p, --profile 䜿甚指定 Profile + -c, --collectors 指定采集噚逗号分隔 + --filter 过滀衚蟟匏 + --all 捕获所有可甚采集噚 + --encrypt 加密敏感数据 + --password 加密密码䞍建议呜什行䌠入 + --exclude 排陀暡匏逗号分隔 + --tag 标筟逗号分隔 + -y, --yes 跳过确讀提瀺 +``` + +**瀺䟋** +```bash +# 䜿甚默讀 Profile 捕获 +devpack capture --name "my-env-2026" + +# 捕获所有内容 +devpack capture --name "full-env" --all + +# 䜿甚指定 Profile +devpack capture --name "golang-env" --profile golang-dev + +# 选择性捕获 +devpack capture --name "vscode-only" -c vscode + +# 加密捕获 +devpack capture --name "secure-env" --all --encrypt + +# 垊过滀噚 +devpack capture --name "web-dev" \ + -c go,node,vscode \ + --filter "runtime:go,runtime:node,editor:vscode" +``` + +**蟓出瀺䟋** +``` +📊 Capturing environment "my-env-2026"... + +Collecting: + ✓ Go Runtime (1.22.1, 3 tools) [2.1 MB] + ✓ Node.js Runtime (20.11.0, 12 global pkgs) [1.5 MB] + ✓ VS Code (35 extensions, settings) [4.2 MB] + ✓ PowerShell (profile, 5 modules) [0.3 MB] + ✓ Scoop (42 packages) [0.1 MB] + ✓ Git (config, 12 aliases) [0.01 MB] + ✓ Environment Variables (8 variables) [0.001 MB] + ⚠ SSH Keys skipped (use --encrypt) + +Pack created: my-env-2026 + Items: 7 collectors, 115 items + Size: 8.2 MB (compressed) + Pack ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + +Run 'devpack export my-env-2026 -o my-env-2026.devpack' to export. +``` + +--- + +### 1.5 devpack restore + +从 Pack 还原匀发环境。 + +``` +devpack restore [flags] + +Flags: + --dry-run 预览曎改䞍实际执行 + --conflict 冲突倄理策略 (skip|overwrite|merge|prompt|newest) + --no-rollback 䞍创建还原点 + -c, --collectors 只还原指定采集噚 + --exclude 排陀指定采集噚 + --password 解密密码 + --parallel 并行还原数默讀: 4 + -y, --yes 跳过确讀提瀺 + --force 区制还原応略平台䞍匹配 +``` + +**瀺䟋** +```bash +# 干运行预览 +devpack restore my-env-2026 --dry-run + +# 正垞还原 +devpack restore my-env-2026 + +# 跳过冲突 +devpack restore my-env-2026 --conflict skip + +# 只还原猖蟑噚配眮 +devpack restore my-env-2026 -c vscode + +# 还原加密 Pack +devpack restore secure-env --password +``` + +**干运行蟓出瀺䟋** +``` +🔍 Dry Run — Restore Plan for "my-env-2026" + +Source: DESKTOP-ABC123 (Windows 11, amd64) +Target: LAPTOP-XYZ789 (Windows 11, amd64) ✓ Compatible + +Plan: + ┌────────────────────┬────────────┬──────────────────────────────┐ + │ Item │ Action │ Details │ + ├────────────────────┌────────────┌─────────────────────────────── + │ Go 1.22.1 │ INSTALL │ Download from golang.org │ + │ Node.js 20.11.0 │ SKIP │ Already installed (20.11.0) │ + │ Python 3.12.2 │ UPGRADE │ Current: 3.11.7 → 3.12.2 │ + │ VS Code Extensions │ INSTALL 12 │ 23 already present │ + │ VS Code Settings │ MERGE │ Conflict in 3 settings │ + │ PowerShell Profile │ OVERWRITE │ Backup: profile.bak │ + │ Scoop Packages │ INSTALL 8 │ 34 already present │ + │ Git Config │ MERGE │ Add 5 aliases │ + │ Env Variables │ SET 3 │ GOPATH, GOROOT, NODE_HOME │ + └────────────────────┮────────────┮──────────────────────────────┘ + + Install: 3 items | Upgrade: 1 | Merge: 2 | Skip: 1 | Overwrite: 1 + +⚠ This is a dry run. No changes were made. +Run without --dry-run to apply these changes. +``` + +--- + +### 1.6 devpack diff + +对比䞀䞪环境的差匂。 + +``` +devpack diff [flags] + +Flags: + --current 䞎圓前环境对比 + --with 䞎及䞀䞪 Pack 对比 + -c, --collectors 只对比指定采集噚 + -o, --output 蟓出栌匏 (table|json|yaml) +``` + +**瀺䟋** +```bash +# 䞎圓前环境对比 +devpack diff my-env-2026 --current + +# 䞀䞪 Pack 对比 +devpack diff env-v1 --with env-v2 +``` + +--- + +### 1.7 devpack export / import + +富出和富入 Pack 文件。 + +``` +# 富出 +devpack export [flags] + +Flags: + -o, --output 蟓出文件路埄默讀: .devpack + +# 富入 +devpack import [flags] + +Flags: + -n, --name 富入后的名称默讀䜿甚 Pack 原名 + --verify 富入前验证文件完敎性 +``` + +--- + +### 1.8 devpack list + +列出本地的 Pack 和 Profile。 + +``` +devpack list [subcommand] [flags] + +Subcommands: + packs 列出所有 Pack + profiles 列出所有 Profile + collectors 列出所有可甚采集噚 + +Flags: + -o, --output 蟓出栌匏 (table|json|yaml) + --detailed 星瀺诊细信息 +``` + +--- + +### 1.9 devpack profile + +管理 Profile 配眮文件。 + +``` +devpack profile [subcommand] [flags] + +Subcommands: + create 创建新 Profile + edit 猖蟑 Profile + delete 删陀 Profile + show 星瀺 Profile 内容 + list 列出所有 Profile + use 讟眮默讀 Profile +``` + +--- + +### 1.10 devpack verify + +验证 Pack 文件的完敎性。 + +``` +devpack verify [flags] + +Flags: + --checksum 验证校验和 + --structure 验证目圕结构 + --deep 深床验证检查所有采集噚数据 +``` + +--- + +## 2. 内郚 API + +### 2.1 Collector 接口 + +```go +package collector + +import ( + "context" + "time" +) + +// Collector 所有采集噚的统䞀接口 +type Collector interface { + // 基本信息 + Name() string + DisplayName() string + Description() string + Category() Category + + // 可甚性检查 + IsAvailable(ctx context.Context) bool + + // 栞心操䜜 + Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) + Capture(ctx context.Context, targetDir string, opts CaptureOptions) error + Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error + Verify(ctx context.Context) (*VerifyResult, error) +} + +// ScanOptions 扫描选项 +type ScanOptions struct { + Detailed bool // 是吊返回诊细信息 + Filters map[string]string // 过滀条件 + Timeout time.Duration // è¶…æ—¶æ—¶é—Ž +} + +// CaptureOptions 捕获选项 +type CaptureOptions struct { + IncludePatterns []string // 包含暡匏 + ExcludePatterns []string // 排陀暡匏 + Encrypt bool // 是吊加密 +} + +// RestoreOptions 还原选项 +type RestoreOptions struct { + ConflictStrategy ConflictStrategy // 冲突策略 + DryRun bool // 干运行 + Force bool // 区制 +} + +// ScanResult 扫描结果 +type ScanResult struct { + Collector string `json:"collector"` + Category Category `json:"category"` + Items []ScanItem `json:"items"` + Timestamp time.Time `json:"timestamp"` + Platform PlatformInfo `json:"platform"` + Errors []string `json:"errors,omitempty"` +} + +// ScanItem 扫描项 +type ScanItem struct { + Name string `json:"name"` + Version string `json:"version,omitempty"` + Path string `json:"path,omitempty"` + Type string `json:"type,omitempty"` // binary, config, package + Properties map[string]string `json:"properties,omitempty"` + Size int64 `json:"size,omitempty"` + Sensitive bool `json:"sensitive,omitempty"` // 是吊包含敏感数据 + Children []ScanItem `json:"children,omitempty"` +} + +// VerifyResult 验证结果 +type VerifyResult struct { + Success bool `json:"success"` + Items []VerifyItem `json:"items"` +} + +type VerifyItem struct { + Name string `json:"name"` + Status string `json:"status"` // ok, missing, version_mismatch, error + Message string `json:"message,omitempty"` +} +``` + +### 2.2 Pack Engine API + +```go +package pack + +import ( + "context" + "io" + + "github.com/user/devpack/pkg/manifest" +) + +// Packer 打包噚 +type Packer struct { + // ... +} + +// NewPacker 创建打包噚 +func NewPacker(opts PackerOptions) *Packer + +// PackerOptions 打包噚选项 +type PackerOptions struct { + Name string + Description string + Author string + Compression CompressionType // gzip, zstd, none + Encryption bool + Password string +} + +// Pack 执行打包 +func (p *Packer) Pack(ctx context.Context, sourceDir string, output io.Writer) (*manifest.Manifest, error) + +// Unpacker 解包噚 +type Unpacker struct { + // ... +} + +// NewUnpacker 创建解包噚 +func NewUnpacker() *Unpacker + +// Unpack 执行解包 +func (u *Unpacker) Unpack(ctx context.Context, input io.Reader, targetDir string) (*manifest.Manifest, error) + +// Verify 验证 Pack 文件 +func (u *Unpacker) Verify(ctx context.Context, input io.Reader) (*VerifyResult, error) +``` + +### 2.3 Restore Engine API + +```go +package restore + +import ( + "context" + + "github.com/user/devpack/internal/collector" + "github.com/user/devpack/pkg/manifest" +) + +// Engine 还原匕擎 +type Engine struct { + registry *collector.Registry + platform platform.Platform + // ... +} + +// NewEngine 创建还原匕擎 +func NewEngine(registry *collector.Registry, platform platform.Platform) *Engine + +// Plan 生成还原计划 +func (e *Engine) Plan(ctx context.Context, m *manifest.Manifest, opts PlanOptions) (*RestorePlan, error) + +// Execute 执行还原计划 +func (e *Engine) Execute(ctx context.Context, plan *RestorePlan) (*RestoreReport, error) + +// Rollback 回滚还原 +func (e *Engine) Rollback(ctx context.Context, restorePointID string) error + +// RestorePlan 还原计划 +type RestorePlan struct { + PackName string `json:"pack_name"` + Items []RestorePlanItem `json:"items"` + Conflicts []ConflictItem `json:"conflicts"` + TotalSteps int `json:"total_steps"` +} + +// RestorePlanItem 还原计划项 +type RestorePlanItem struct { + Collector string `json:"collector"` + ItemName string `json:"item_name"` + Action RestoreAction `json:"action"` // install, upgrade, merge, skip, overwrite + Current string `json:"current,omitempty"` + Target string `json:"target"` + Details string `json:"details,omitempty"` + Order int `json:"order"` // 执行顺序 +} + +// RestoreAction 还原劚䜜 +type RestoreAction string + +const ( + ActionInstall RestoreAction = "install" + ActionUpgrade RestoreAction = "upgrade" + ActionMerge RestoreAction = "merge" + ActionSkip RestoreAction = "skip" + ActionOverwrite RestoreAction = "overwrite" +) + +// RestoreReport 还原报告 +type RestoreReport struct { + Success int `json:"success"` + Failed int `json:"failed"` + Skipped int `json:"skipped"` + Items []ReportItem `json:"items"` + Duration time.Duration `json:"duration"` + RestorePointID string `json:"restore_point_id,omitempty"` +} +``` + +--- + +## 3. Pack 文件栌匏规范 + +### 3.1 文件结构 + +``` +.devpack # tar.gz 園档 +│ +├── manifest.json # Pack 枅单必需 +├── checksum.sha256 # 校验和文件必需 +│ +├── collectors/ # 采集噚数据目圕 +│ ├── / # 分类目圕 +│ │ └── / # 采集噚目圕 +│ │ ├── metadata.json # 采集噚元数据 +│ │ └── data/ # 采集噚数据 +│ │ └── ... # 具䜓数据文件 +│ └── ... +│ +└── encrypted/ # 加密数据目圕可选 + └── / + └── data.enc # 加密数据 +``` + +### 3.2 manifest.json 完敎规范 + +```json +{ + "version": "0.1.0", + "format_ver": "1", + "pack_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "my-dev-env", + "description": "My full development environment", + "author": "developer@example.com", + "created_at": "2026-03-03T10:30:00Z", + "tags": ["golang", "fullstack"], + + "source": { + "hostname": "DESKTOP-ABC123", + "os": "windows", + "os_version": "10.0.22631", + "arch": "amd64", + "username": "developer", + "devpack_version": "0.1.0" + }, + + "collectors": [ + { + "name": "go", + "category": "runtime", + "display_name": "Go Runtime", + "item_count": 4, + "data_path": "collectors/runtime/go", + "data_size": 2148576, + "checksum": "sha256:abc123..." + }, + { + "name": "vscode", + "category": "editor", + "display_name": "Visual Studio Code", + "item_count": 36, + "data_path": "collectors/editor/vscode", + "data_size": 4412928, + "checksum": "sha256:def456..." + } + ], + + "encryption": { + "algorithm": "AES-256-GCM", + "kdf": "argon2id", + "kdf_params": { + "time": 1, + "memory": 65536, + "threads": 4 + }, + "encrypted_collectors": ["ssh"] + }, + + "checksum": "sha256:789abc..." +} +``` + +### 3.3 metadata.json 规范 + +每䞪采集噚目圕䞋的元数据文件 + +```json +{ + "collector": "go", + "category": "runtime", + "captured_at": "2026-03-03T10:30:00Z", + "platform": { + "os": "windows", + "arch": "amd64" + }, + "items": [ + { + "name": "go", + "version": "1.22.1", + "type": "binary", + "install_method": "direct", + "install_url": "https://go.dev/dl/go1.22.1.windows-amd64.msi", + "properties": { + "GOPATH": "C:\\Users\\dev\\go", + "GOROOT": "C:\\Program Files\\Go", + "GOPROXY": "https://goproxy.cn,direct" + } + }, + { + "name": "gopls", + "version": "0.15.1", + "type": "tool", + "install_method": "go_install", + "install_command": "go install golang.org/x/tools/gopls@v0.15.1" + }, + { + "name": "golangci-lint", + "version": "1.56.2", + "type": "tool", + "install_method": "go_install", + "install_command": "go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.2" + } + ], + "files": [ + { + "source": "data/go-env.json", + "description": "Go environment variables" + } + ] +} +``` + +--- + +## 4. 配眮文件规范 + +### 4.1 党局配眮 (~/.devpack/config.yaml) + +```yaml +# DevPack 党局配眮 +version: "1" + +# 存傚讟眮 +storage: + packs_dir: "~/.devpack/packs" # Pack 存傚目圕 + profiles_dir: "~/.devpack/profiles" # Profile 目圕 + logs_dir: "~/.devpack/logs" # 日志目圕 + temp_dir: "" # 䞎时目圕空则䜿甚系统默讀 + +# 默讀行䞺 +defaults: + profile: "default" # 默讀 Profile + compression: "gzip" # 压猩方匏 (gzip|zstd|none) + conflict_strategy: "prompt" # 冲突策略 + create_restore_point: true # 还原前创建还原点 + parallel_restore: 4 # 并行还原数 + +# 日志讟眮 +logging: + level: "info" # 日志级别 + format: "text" # 日志栌匏 (text|json) + file: "~/.devpack/logs/devpack.log" # 日志文件 + +# 眑络讟眮甚于䞋蜜安装噚 +network: + timeout: 300 # 䞋蜜超时秒 + proxy: "" # HTTP 代理 + retries: 3 # 重试次数 + +# UI 讟眮 +ui: + color: true # 圩色蟓出 + progress_bar: true # 进床条 + interactive: true # 亀互匏提瀺 + +# 安党讟眮 +security: + default_encrypt: false # 默讀是吊加密 + scan_for_secrets: true # 扫描敏感数据并譊告 + exclude_patterns: # 党局排陀暡匏 + - "*_KEY" + - "*_SECRET" + - "*_TOKEN" + - "*_PASSWORD" +``` + +### 4.2 Profile 配眮文件规范 + +```yaml +# Profile 配眮文件 +name: "default" +description: "Default development environment profile" +version: "1" + +collectors: + # 运行时采集噚配眮 + runtime: + enabled: true + include: [] # 空列衚 = 党郚非空 = 只包含列出的 + exclude: [] # 排陀列衚 + options: {} # 采集噚特定选项 + + # 包管理噚采集噚配眮 + package: + enabled: true + include: [] + exclude: [] + options: + scoop: + include_buckets: true + exclude_packages: [] + chocolatey: + exclude_packages: [] + + # 猖蟑噚采集噚配眮 + editor: + enabled: true + include: ["vscode"] + options: + vscode: + capture_extensions: true + capture_settings: true + capture_keybindings: true + capture_snippets: true + exclude_extensions: [] + + # Shell 采集噚配眮 + shell: + enabled: true + include: [] + options: {} + + # Git 采集噚配眮 + git: + enabled: true + options: + capture_config: true + capture_aliases: true + capture_hooks: false + + # 环境变量采集噚配眮 + env: + enabled: true + options: + include_patterns: [] + exclude_patterns: + - "*_KEY" + - "*_SECRET" + + # SSH/GPG 采集噚配眮 + ssh: + enabled: false # 默讀犁甚 + options: + encrypt: true # 必须加密 + + # 字䜓采集噚配眮 + font: + enabled: false + options: + include_fonts: [] # 空 = 自劚检测匀发字䜓 + +# 还原选项 +restore: + conflict_strategy: "prompt" + create_restore_point: true + dry_run_first: false + +# 自定义钩子高级 +hooks: + pre_capture: "" # 捕获前执行的呜什 + post_capture: "" # 捕获后执行的呜什 + pre_restore: "" # 还原前执行的呜什 + post_restore: "" # 还原后执行的呜什 +``` + +--- + +## 5. 退出码 + +| 退出码 | 含义 | +|--------|------| +| 0 | 成功 | +| 1 | 䞀般性错误 | +| 2 | 呜什行参数错误 | +| 3 | 配眮错误 | +| 10 | Pack 文件损坏或无效 | +| 11 | 平台䞍兌容 | +| 12 | 版本䞍兌容 | +| 20 | 还原倱莥 | +| 21 | 还原郚分成功 | +| 22 | 冲突需芁甚户介入 | +| 30 | 权限䞍足 | +| 40 | 眑络错误 | +| 50 | 加密/解密错误 | + +--- + +## 6. 环境变量 + +| 变量 | 诎明 | 默讀倌 | +|------|------|--------| +| `DEVPACK_HOME` | DevPack 䞻目圕 | `~/.devpack` | +| `DEVPACK_LOG_LEVEL` | 日志级别 | `info` | +| `DEVPACK_LOG_FILE` | 日志文件路埄 | `~/.devpack/logs/devpack.log` | +| `DEVPACK_CONFIG` | 配眮文件路埄 | `~/.devpack/config.yaml` | +| `DEVPACK_NO_COLOR` | 犁甚圩色蟓出 | `false` | +| `DEVPACK_PROFILE` | 默讀 Profile | `default` | +| `DEVPACK_HTTP_PROXY` | HTTP 代理 | - | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..fd245a5 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,751 @@ +# DevPack 架构讟计文档 + +> 版本v1.0.0-draft +> 曎新日期2026-03-03 +> 䜜者DevPack Team + +--- + +## 1. 架构抂览 + +### 1.1 讟计原则 + +| 原则 | 诎明 | +|------|------| +| **单䞀二进制** | 猖译䞺无䟝赖的单䞀可执行文件 | +| **插件化** | 采集噚通过接口抜象支持扩展 | +| **安党䌘先** | 敏感数据加密操䜜可回滚 | +| **平台适配** | 通过平台适配层倄理 OS 差匂 | +| **幂等性** | 同䞀 Pack 倚次还原结果䞀臎 | +| **最小䟵入** | 只修改甚户级配眮䞍修改系统级讟眮陀非明确授权 | + +### 1.2 高层架构囟 + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ CLI Layer (Cobra) │ +│ ┌──────┐ ┌───────┐ ┌─────────┐ ┌────────┐ ┌──────┐ ┌────────┐ │ +│ │ init │ │ scan │ │ capture │ │restore │ │ diff │ │export/ │ │ +│ │ │ │ │ │ │ │ │ │ │ │import │ │ +│ └──┬───┘ └───┬───┘ └────┬────┘ └───┬────┘ └──┬───┘ └───┬────┘ │ +└─────┌─────────┌──────────┌──────────┌─────────┌─────────┌──────┘ + │ │ │ │ │ │ +┌─────┮─────────┮──────────┮──────────┮─────────┮─────────┮──────┐ +│ Core Engine Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ +│ │ Collector │ │ Pack Engine │ │ Restore Engine │ │ +│ │ Registry │ │ │ │ │ │ +│ └──────┬───────┘ └──────┬───────┘ └────────────┬─────────────┘ │ +│ │ │ │ │ +│ ┌──────┮───────┐ ┌──────┮───────┐ ┌────────────┮─────────────┐ │ +│ │ Profile │ │ Crypto │ │ Dependency Resolver │ │ +│ │ Manager │ │ Module │ │ │ │ +│ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ +└─────────────────────────┬───────────────────────────────────────┘ + │ +┌─────────────────────────┮───────────────────────────────────────┐ +│ Platform Abstraction Layer │ +│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ +│ │ Windows │ │ macOS │ │ Linux │ │ +│ │ Adapter │ │ Adapter │ │ Adapter │ │ +│ └────────────┘ └────────────┘ └────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ +┌─────────────────────────┮───────────────────────────────────────┐ +│ Collector Plugins │ +│ ┌─────────┐ ┌─────────┐ ┌────────┐ ┌───────┐ ┌─────┐ ┌─────┐ │ +│ │ Runtime │ │ Package │ │ Editor │ │ Shell │ │ Git │ │ Env │ │ +│ └─────────┘ └─────────┘ └────────┘ └───────┘ └─────┘ └─────┘ │ +│ ┌─────────┐ ┌─────────┐ │ +│ │ Font │ │ SSH/GPG │ │ +│ └─────────┘ └─────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. 栞心暡块讟计 + +### 2.1 采集噚系统 (Collector System) + +采集噚是 DevPack 的栞心莟莣扫描和收集环境信息。所有采集噚实现统䞀的接口。 + +#### 2.1.1 Collector 接口 + +```go +// Collector 定义了所有采集噚必须实现的接口 +type Collector interface { + // Name 返回采集噚名称唯䞀标识 + Name() string + + // DisplayName 返回采集噚的星瀺名称 + DisplayName() string + + // Description 返回采集噚的描述信息 + Description() string + + // Category 返回采集噚所属分类 + Category() Category + + // IsAvailable 检测圓前系统是吊支持歀采集噚 + IsAvailable(ctx context.Context) bool + + // Scan 扫描圓前环境返回扫描结果 + Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) + + // Capture 捕获环境数据写入到指定目圕 + Capture(ctx context.Context, targetDir string, opts CaptureOptions) error + + // Restore 从指定目圕还原环境 + Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error + + // Verify 验证还原后的环境是吊正确 + Verify(ctx context.Context) (*VerifyResult, error) +} + +// Category 采集噚分类 +type Category string + +const ( + CategoryRuntime Category = "runtime" // 猖皋语蚀运行时 + CategoryPackage Category = "package" // 包管理噚 + CategoryEditor Category = "editor" // 猖蟑噚/IDE + CategoryShell Category = "shell" // Shell 配眮 + CategoryGit Category = "git" // Git 配眮 + CategoryEnv Category = "env" // 环境变量 + CategoryFont Category = "font" // 字䜓 + CategorySSH Category = "ssh" // SSH/GPG 密钥 + CategoryCustom Category = "custom" // 自定义 +) + +// ScanResult 扫描结果 +type ScanResult struct { + Collector string `json:"collector"` + Category Category `json:"category"` + Items []ScanItem `json:"items"` + Timestamp time.Time `json:"timestamp"` + Platform PlatformInfo `json:"platform"` +} + +// ScanItem 单䞪扫描项 +type ScanItem struct { + Name string `json:"name"` + Version string `json:"version,omitempty"` + Path string `json:"path,omitempty"` + Properties map[string]string `json:"properties,omitempty"` + Size int64 `json:"size,omitempty"` + Children []ScanItem `json:"children,omitempty"` +} +``` + +#### 2.1.2 采集噚泚册䞭心 + +```go +// Registry 采集噚泚册䞭心 +type Registry struct { + collectors map[string]Collector + mu sync.RWMutex +} + +// Register 泚册䞀䞪采集噚 +func (r *Registry) Register(c Collector) error + +// Get 获取指定名称的采集噚 +func (r *Registry) Get(name string) (Collector, bool) + +// List 列出所有已泚册的采集噚 +func (r *Registry) List() []Collector + +// ListByCategory 按分类列出采集噚 +func (r *Registry) ListByCategory(cat Category) []Collector + +// ScanAll 䜿甚所有可甚的采集噚扫描 +func (r *Registry) ScanAll(ctx context.Context, opts ScanOptions) ([]*ScanResult, error) +``` + +#### 2.1.3 内眮采集噚实现瀺䟋 + +以 Go 运行时采集噚䞺䟋 + +```go +type GoCollector struct{} + +func (c *GoCollector) Name() string { return "go" } +func (c *GoCollector) DisplayName() string { return "Go Runtime" } +func (c *GoCollector) Category() Category { return CategoryRuntime } + +func (c *GoCollector) Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) { + result := &ScanResult{ + Collector: c.Name(), + Category: c.Category(), + } + + // 检测 Go 版本 + version, err := exec.CommandContext(ctx, "go", "version").Output() + // ... 解析版本信息 + + // 获取 go env 信息 + envJSON, err := exec.CommandContext(ctx, "go", "env", "-json").Output() + // ... 解析环境变量 + + // 获取党局安装的工具 + // ... 扫描 GOPATH/bin + + return result, nil +} +``` + +### 2.2 打包匕擎 (Pack Engine) + +#### 2.2.1 Pack 文件栌匏 + +`.devpack` 文件本莚䞊是䞀䞪经过组织的 tar.gz 園档文件 + +``` +my-env.devpack (tar.gz) +├── manifest.json # Pack 枅单元数据 +├── checksum.sha256 # 文件校验和 +├── collectors/ # 各采集噚数据 +│ ├── runtime/ +│ │ ├── go/ +│ │ │ ├── metadata.json # Go 环境元数据 +│ │ │ └── data/ # Go 盞关数据文件 +│ │ ├── node/ +│ │ │ ├── metadata.json +│ │ │ └── data/ +│ │ └── python/ +│ │ ├── metadata.json +│ │ └── data/ +│ ├── editor/ +│ │ └── vscode/ +│ │ ├── metadata.json +│ │ ├── extensions.json # 扩展列衚 +│ │ └── data/ # 讟眮文件 +│ │ ├── settings.json +│ │ ├── keybindings.json +│ │ └── snippets/ +│ ├── shell/ +│ │ ├── powershell/ +│ │ │ ├── metadata.json +│ │ │ └── data/ +│ │ └── bash/ +│ │ ├── metadata.json +│ │ └── data/ +│ ├── package/ +│ │ └── scoop/ +│ │ ├── metadata.json +│ │ └── data/ +│ ├── git/ +│ │ ├── metadata.json +│ │ └── data/ +│ └── env/ +│ ├── metadata.json +│ └── data/ +└── encrypted/ # 加密数据可选 + └── ssh/ + └── data.enc # 加密的 SSH 密钥 +``` + +#### 2.2.2 Manifest 结构 + +```go +// Manifest Pack 枅单 +type Manifest struct { + // 元信息 + Version string `json:"version"` // DevPack 版本 + FormatVer string `json:"format_ver"` // Pack 栌匏版本 + Name string `json:"name"` // Pack 名称 + Description string `json:"description"` // 描述 + Author string `json:"author"` // 䜜者 + CreatedAt time.Time `json:"created_at"` // 创建时闎 + PackID string `json:"pack_id"` // 唯䞀 ID (UUID) + + // 源环境信息 + Source SourceInfo `json:"source"` + + // 采集噚数据玢匕 + Collectors []CollectorEntry `json:"collectors"` + + // 加密信息 + Encryption *EncryptionInfo `json:"encryption,omitempty"` + + // 校验信息 + Checksum string `json:"checksum"` // 敎包校验和 +} + +// SourceInfo 源环境信息 +type SourceInfo struct { + Hostname string `json:"hostname"` + OS string `json:"os"` // windows, darwin, linux + OSVersion string `json:"os_version"` + Arch string `json:"arch"` // amd64, arm64 + Username string `json:"username"` +} + +// CollectorEntry 采集噚条目 +type CollectorEntry struct { + Name string `json:"name"` + Category Category `json:"category"` + ItemCount int `json:"item_count"` + DataPath string `json:"data_path"` + DataSize int64 `json:"data_size"` + Checksum string `json:"checksum"` +} +``` + +#### 2.2.3 打包流皋 + +``` +甚户执行 capture 呜什 + │ + â–Œ +┌─────────────────┐ +│ 加蜜 Profile │ ─── 确定需芁运行哪些采集噚 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 运行采集噚 │ ─── 并行扫描 → 收集数据 → 写入䞎时目圕 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 生成 Manifest │ ─── 创建枅单文件、计算校验和 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 加密敏感数据 │ ─── 对标记䞺敏感的数据进行加密可选 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 压猩園档 │ ─── tar.gz 打包 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 蟓出 .devpack │ ─── 写入最终文件 +└─────────────────┘ +``` + +### 2.3 还原匕擎 (Restore Engine) + +#### 2.3.1 还原流皋 + +``` +甚户执行 restore 呜什 + │ + â–Œ +┌─────────────────┐ +│ 校验 Pack 文件 │ ─── 检查完敎性、版本兌容性 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 解析 Manifest │ ─── 读取枅单确定还原内容 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 平台兌容检查 │ ─── 确讀目标平台䞎源平台匹配 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 冲突检测 │ ─── 检测䞎现有环境的冲突 +└────────┬────────┘ + │ + â–Œ +┌─────────────────────┐ +│ 创建还原点可选 │ ─── 倇仜圓前环境甚于回滚 +└────────┬────────────┘ + │ + â–Œ +┌─────────────────┐ +│ 䟝赖排序 │ ─── 按䟝赖关系排序安装顺序 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ ┌──────────────┐ +│ 执行还原 │ ──▶ │ 逐项安装/配眮 │ +└────────┬────────┘ └──────────────┘ + │ + â–Œ +┌─────────────────┐ +│ 验证还原结果 │ ─── 运行各采集噚的验证逻蟑 +└────────┬────────┘ + │ + â–Œ +┌─────────────────┐ +│ 生成还原报告 │ ─── 成功/倱莥/跳过的项目枅单 +└─────────────────┘ +``` + +#### 2.3.2 冲突倄理策略 + +```go +// ConflictStrategy 冲突倄理策略 +type ConflictStrategy int + +const ( + ConflictSkip ConflictStrategy = iota // 跳过保留现有 + ConflictOverwrite // 芆盖䜿甚 Pack 䞭的 + ConflictMerge // 合并 + ConflictPrompt // 询问甚户 + ConflictNewest // 䜿甚蟃新版本 +) + +// ConflictItem 冲突项 +type ConflictItem struct { + Collector string + ItemName string + CurrentVer string + PackVer string + Type ConflictType // VersionMismatch, AlreadyExists, DependencyConflict +} +``` + +### 2.4 配眮文件管理 (Profile Manager) + +#### 2.4.1 Profile 栌匏 + +䜿甚 YAML 栌匏定义 Profile + +```yaml +# ~/.devpack/profiles/golang-dev.yaml +name: golang-dev +description: "Go 党栈匀发环境" +version: "1.0" + +# 采集噚配眮 +collectors: + runtime: + enabled: true + include: + - go + - node + exclude: [] + options: + go: + capture_gopath_bin: true # 捕获 GOPATH/bin 䞋的工具 + capture_go_env: true # 捕获 go env 配眮 + + editor: + enabled: true + include: + - vscode + options: + vscode: + capture_extensions: true + capture_settings: true + capture_keybindings: true + capture_snippets: true + # 排陀的扩展 + exclude_extensions: + - "ms-vsliveshare.vsliveshare" + + shell: + enabled: true + include: + - powershell + - bash + + package: + enabled: true + include: + - scoop + + git: + enabled: true + options: + capture_aliases: true + capture_hooks: false + + env: + enabled: true + options: + # 只捕获匹配的环境变量 + include_patterns: + - "GOPATH" + - "GOROOT" + - "PATH" + - "NODE_*" + exclude_patterns: + - "*_KEY" + - "*_SECRET" + - "*_TOKEN" + + ssh: + enabled: false + +# 还原选项 +restore: + conflict_strategy: prompt # skip, overwrite, merge, prompt, newest + create_restore_point: true + dry_run_first: false +``` + +### 2.5 平台适配层 (Platform Abstraction Layer) + +```go +// Platform 平台适配接口 +type Platform interface { + // OS 返回操䜜系统标识 + OS() string + + // Arch 返回架构标识 + Arch() string + + // HomeDir 返回甚户䞻目圕 + HomeDir() string + + // ConfigDir 返回配眮文件目圕 + ConfigDir() string + + // DataDir 返回数据目圕 + DataDir() string + + // GetEnvVar 获取环境变量 + GetEnvVar(key string) string + + // SetEnvVar 讟眮甚户级环境变量 + SetEnvVar(key, value string) error + + // AddToPath 添加目圕到 PATH + AddToPath(dir string) error + + // IsAdmin 是吊以管理员身仜运行 + IsAdmin() bool + + // PackageManagers 返回可甚的包管理噚 + PackageManagers() []string + + // DefaultShell 返回默讀 Shell + DefaultShell() string + + // InstallFont 安装字䜓文件 + InstallFont(fontPath string) error + + // RunAsAdmin 以管理员权限运行呜什 + RunAsAdmin(cmd string, args ...string) error +} +``` + +各平台实现 + +```go +// Windows 平台实现 +type WindowsPlatform struct{} + +func (p *WindowsPlatform) OS() string { return "windows" } +func (p *WindowsPlatform) HomeDir() string { return os.Getenv("USERPROFILE") } +func (p *WindowsPlatform) ConfigDir() string { return os.Getenv("APPDATA") } +func (p *WindowsPlatform) DefaultShell() string { return "powershell" } +func (p *WindowsPlatform) PackageManagers() []string { + var pms []string + if _, err := exec.LookPath("scoop"); err == nil { pms = append(pms, "scoop") } + if _, err := exec.LookPath("choco"); err == nil { pms = append(pms, "chocolatey") } + if _, err := exec.LookPath("winget"); err == nil { pms = append(pms, "winget") } + return pms +} + +// macOS 平台实现 +type DarwinPlatform struct{} + +// Linux 平台实现 +type LinuxPlatform struct{} +``` + +### 2.6 加密暡块 (Crypto Module) + +```go +// Encryptor 加密噚接口 +type Encryptor interface { + // Encrypt 䜿甚密码加密数据 + Encrypt(data []byte, password string) ([]byte, error) + + // Decrypt 䜿甚密码解密数据 + Decrypt(encrypted []byte, password string) ([]byte, error) +} + +// AESGCMEncryptor AES-256-GCM 加密实现 +type AESGCMEncryptor struct{} + +// 密钥掟生䜿甚 Argon2id +func deriveKey(password string, salt []byte) []byte { + return argon2.IDKey([]byte(password), salt, 1, 64*1024, 4, 32) +} +``` + +--- + +## 3. 数据流 + +### 3.1 扫描 → 打包数据流 + +``` +┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ +│ 甚户系统 │ ──▶ │ Collectors │ ──▶ │ ScanResult │ ──▶ │ 䞎时目圕 │ +│ (实际环境) │ │ (扫描采集) │ │ (结构化数据)│ │ (文件数据)│ +└────────────┘ └────────────┘ └────────────┘ └────┬─────┘ + │ + ┌────────────┐ ┌────────────┐ │ + │ .devpack │ ◀── │ Pack 匕擎 │ ◀────────┘ + │ (園档文件) │ │ (压猩打包) │ + └────────────┘ └────────────┘ +``` + +### 3.2 富入 → 还原数据流 + +``` +┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ +│ .devpack │ ──▶ │ 解压校验 │ ──▶ │ Manifest │ ──▶ │ 还原计划 │ +│ (園档文件) │ │ │ │ 解析 │ │ 生成 │ +└────────────┘ └────────────┘ └────────────┘ └────┬─────┘ + │ + ┌────────────┐ ┌────────────┐ │ + │ 目标系统 │ ◀── │ Restore │ ◀────────┘ + │ (已还原) │ │ Engine │ + └────────────┘ └────────────┘ +``` + +--- + +## 4. 技术选型 + +### 4.1 栞心䟝赖 + +| 䟝赖 | 甹途 | 选型理由 | +|------|------|---------| +| [cobra](https://github.com/spf13/cobra) | CLI 框架 | Go 生态最流行的 CLI 框架 | +| [viper](https://github.com/spf13/viper) | 配眮管理 | 支持倚种配眮栌匏 | +| [zerolog](https://github.com/rs/zerolog) | 日志 | 高性胜结构化日志 | +| [color](https://github.com/fatih/color) | 终端着色 | 矎化 CLI 蟓出 | +| [progressbar](https://github.com/schollz/progressbar) | 进床条 | 长时操䜜反銈 | +| [survey](https://github.com/AlecAivazis/survey) | 亀互匏提瀺 | 甚户亀互 | +| [archiver](https://github.com/mholt/archiver) | 压猩園档 | 支持倚种園档栌匏 | +| [go-yaml](https://github.com/go-yaml/yaml) | YAML 解析 | Profile 文件解析 | +| [uuid](https://github.com/google/uuid) | UUID 生成 | Pack ID 生成 | +| [golang.org/x/crypto](https://golang.org/x/crypto) | 加密库 | Argon2, AES | + +### 4.2 构建工具 + +| 工具 | 甹途 | +|------|------| +| Go 1.22+ | 猖皋语蚀 | +| Make / Task | 构建脚本 | +| GoReleaser | 倚平台发垃 | +| golangci-lint | 代码检查 | +| GitHub Actions | CI/CD | + +--- + +## 5. 错误倄理策略 + +### 5.1 错误分级 + +```go +// ErrorLevel 错误级别 +type ErrorLevel int + +const ( + ErrorFatal ErrorLevel = iota // 臎呜错误必须终止 + ErrorCritical // 䞥重错误圓前采集噚倱莥 + ErrorWarning // 譊告可继续䜆需告知甚户 + ErrorInfo // 信息记圕䜆䞍圱响流皋 +) + +// CollectorError 采集噚错误 +type CollectorError struct { + Collector string + Level ErrorLevel + Message string + Cause error + Hint string // 给甚户的建议 +} +``` + +### 5.2 错误倄理原则 + +1. **采集阶段** — 单䞪采集噚倱莥䞍圱响其他采集噚 +2. **打包阶段** — 倱莥的采集噚数据䞍包含圚 Pack 䞭䜆 Pack 仍然生成 +3. **还原阶段** — 根据策略决定是继续还是终止 +4. **所有操䜜** — 诊细日志记圕甚户友奜的错误信息 + +--- + +## 6. 安党讟计 + +### 6.1 敏感数据识别 + +| 数据类型 | 敏感级别 | 倄理方匏 | +|---------|---------|---------| +| SSH 私钥 | 高 | AES-256 加密 | +| GPG 私钥 | 高 | AES-256 加密 | +| API Token | 高 | AES-256 加密或排陀 | +| 环境变量䞭的密码 | 高 | 默讀排陀 | +| Git 凭证 | 高 | 默讀排陀 | +| IDE 讟眮 | 䜎 | 明文存傚 | +| Shell 配眮 | äž­ | 扫描并譊告内嵌 Token | + +### 6.2 加密流皋 + +``` +甚户密码 ──▶ Argon2id ──▶ 掟生密钥 (256-bit) + │ + â–Œ +敏感数据 ──▶ AES-256-GCM 加密 ──▶ 加密数据 + Nonce + Salt + │ + â–Œ + 存入 encrypted/ 目圕 +``` + +--- + +## 7. 可扩展性讟计 + +### 7.1 插件系统远期规划 + +未来计划支持倖郚插件 + +```go +// Plugin 倖郚插件接口 +type Plugin interface { + Collector + + // PluginInfo 返回插件元信息 + PluginInfo() PluginMeta +} + +type PluginMeta struct { + Name string `json:"name"` + Version string `json:"version"` + Author string `json:"author"` + MinDevPack string `json:"min_devpack_version"` +} +``` + +插件发现机制 +1. `~/.devpack/plugins/` 目圕䞋的可执行文件 +2. 通过 Go Plugin 机制加蜜 `.so` / `.dll` +3. 通过 gRPC/JSON-RPC 䞎倖郚进皋通信掚荐跚语蚀 + +--- + +## 8. 测试策略 + +### 8.1 测试层级 + +| 层级 | 范囎 | 工具 | +|------|------|------| +| 单元测试 | 各暡块独立逻蟑 | Go testing + testify | +| 集成测试 | 暡块闎协䜜 | Go testing | +| 端到端测试 | 完敎的 capture → restore 流皋 | 脚本 + Docker/VM | +| 平台测试 | 各操䜜系统适配 | GitHub Actions Matrix | + +### 8.2 测试环境 + +- CI 环境䜿甚 GitHub Actions 矩阵构建Windows/macOS/Linux +- 端到端测试䜿甚虚拟机或容噚暡拟真实环境 +- Mock 框架甚于隔犻倖郚䟝赖劂包管理噚 diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..6eb2184 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,196 @@ +# DevPack 莡献指南 + +> 感谢䜠对 DevPack 的兎趣我们欢迎各种圢匏的莡献。 + +--- + +## 劂䜕莡献 + +### 🐛 报告 Bug + +1. 搜玢 [已有的 Issues](https://github.com/user/devpack/issues)确讀没有重倍 +2. 创建新 Issue包含以䞋信息 + - DevPack 版本`devpack version` + - 操䜜系统和版本 + - 倍现步骀 + - 期望行䞺 vs 实际行䞺 + - 日志信息`--log-level debug` + +### 💡 功胜建议 + +1. 搜玢已有 Issues确讀没有类䌌建议 +2. 创建 Feature Request Issue +3. 描述䜿甚场景和期望行䞺 +4. 解释䞺什么这䞪功胜对甚户有价倌 + +### 🔧 提亀代码 + +#### 环境准倇 + +```bash +# 1. Fork 项目 + +# 2. Clone 䜠的 Fork +git clone https://github.com/YOUR_USERNAME/devpack.git +cd devpack + +# 3. 添加䞊枞仓库 +git remote add upstream https://github.com/user/devpack.git + +# 4. 安装䟝赖 +go mod download + +# 5. 安装匀发工具 +go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +# 6. 验证环境 +make test +make lint +``` + +#### 匀发流皋 + +```bash +# 1. 同步䞊枞 +git fetch upstream +git checkout develop +git merge upstream/develop + +# 2. 创建分支 +git checkout -b feature/your-feature + +# 3. 猖码 +# ... 猖写代码和测试 + +# 4. 运行检查 +make fmt # 栌匏化代码 +make lint # 代码检查 +make test # 运行测试 + +# 5. 提亀 +git add . +git commit -m "feat(scope): description" + +# 6. 掚送 +git push origin feature/your-feature + +# 7. 创建 Pull Request +``` + +#### Pull Request 规范 + +- **标题** 遵埪 Conventional Commits 栌匏 +- **描述** 诎明改了什么、䞺什么改、怎么测试的 +- **关联 Issue** 劂果有对应的 Issue请关联 +- **测试** 确保新代码有对应的测试 +- **文档** 劂果改变了甚户可见行䞺曎新对应文档 + +#### PR 暡板 + +```markdown +## 描述 + +简述这䞪 PR 做了什么。 + +## 改劚类型 + +- [ ] Bug fix +- [ ] New feature +- [ ] Refactoring +- [ ] Documentation +- [ ] Test + +## 关联 Issue + +Fixes #123 + +## 测试 + +描述劂䜕测试这䞪改劚。 + +## 检查枅单 + +- [ ] 代码通过 `make lint` +- [ ] 添加了对应的单元测试 +- [ ] 所有测试通过 `make test` +- [ ] 曎新了盞关文档 +``` + +--- + +## 猖码规范 + +### Go 代码规范 + +- 遵埪 [Effective Go](https://golang.org/doc/effective_go) +- 䜿甚 `gofmt` 栌匏化代码 +- 通过 `golangci-lint` 检查 +- 公匀 API 必须有文档泚释 +- 错误必须包含䞊䞋文信息 + +### 提亀规范 + +䜿甚 [Conventional Commits](https://www.conventionalcommits.org/) + +``` +feat(collector): add Docker runtime collector +fix(restore): handle version conflict correctly +docs(readme): update installation instructions +test(pack): add pack/unpack round-trip test +refactor(platform): simplify Windows adapter +chore(ci): add macOS build matrix +``` + +### 测试规范 + +- 所有新功胜必须有单元测试 +- 测试文件䞎源码圚同䞀包䞋 +- 䜿甚 `testify` 断蚀库 +- 平台特定逻蟑需芁条件跳过 + +```go +func TestWindowsSpecific(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("Windows-only test") + } + // ... +} +``` + +--- + +## 添加新采集噚 + +劂果䜠想䞺 DevPack 添加䞀䞪新的采集噚请参考以䞋步骀 + +1. 圚 `internal/collector/` 䞋创建新的包 +2. 实现 `Collector` 接口的所有方法 +3. 圚 `registry.go` 䞭泚册 +4. 猖写单元测试 +5. 曎新文档PRD.md 和 USER-GUIDE.md + +诊细指南请参考 [匀发指南 - 添加新采集噚](DEVELOPMENT.md#5-添加新采集噚指南)。 + +--- + +## 瀟区准则 + +- 友善和尊重 +- 建讟性的讚论 +- 接受䞍同意见 +- 关泚事实和技术 + +--- + +## 获取垮助 + +- 📖 [甚户手册](USER-GUIDE.md) +- 🏗 [架构讟计](ARCHITECTURE.md) +- 💻 [匀发指南](DEVELOPMENT.md) +- ❓ [GitHub Discussions](https://github.com/user/devpack/discussions) + +--- + +## 讞可证 + +莡献的代码将按照项目的 [MIT License](../LICENSE) 发垃。 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..b1d79d1 --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,638 @@ +# DevPack 匀发指南 + +> 版本v1.0.0-draft +> 曎新日期2026-03-03 +> 䜜者DevPack Team + +--- + +## 1. 匀发环境搭建 + +### 1.1 前眮芁求 + +| 工具 | 最䜎版本 | 安装方匏 | +|------|---------|---------| +| Go | 1.22+ | [golang.org](https://golang.org/dl/) | +| Git | 2.30+ | [git-scm.com](https://git-scm.com/) | +| Make | 3.81+ | 系统包管理噚Windows 掚荐甚 `choco install make` | +| golangci-lint | 1.55+ | `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest` | + +### 1.2 获取代码 + +```bash +git clone https://github.com/user/devpack.git +cd devpack +``` + +### 1.3 安装䟝赖 + +```bash +go mod download +``` + +### 1.4 验证环境 + +```bash +# 运行测试 +go test ./... + +# 构建 +go build -o devpack ./cmd/devpack/ + +# 代码检查 +golangci-lint run +``` + +--- + +## 2. 项目结构诊解 + +``` +DevPack/ +├── cmd/ # 应甚入口 +│ └── devpack/ +│ ├── main.go # 䞻入口 +│ └── commands/ # CLI 呜什 +│ ├── root.go # 根呜什 +│ ├── init.go # devpack init +│ ├── scan.go # devpack scan +│ ├── capture.go # devpack capture +│ ├── restore.go # devpack restore +│ ├── diff.go # devpack diff +│ ├── export.go # devpack export +│ ├── import.go # devpack import +│ ├── list.go # devpack list +│ ├── profile.go # devpack profile +│ └── version.go # devpack version +│ +├── internal/ # 内郚包 +│ ├── collector/ # 采集噚栞心 +│ │ ├── collector.go # Collector 接口定义 +│ │ ├── registry.go # 采集噚泚册䞭心 +│ │ ├── options.go # 扫描/捕获/还原选项 +│ │ ├── result.go # 结果类型定义 +│ │ │ +│ │ ├── runtime/ # 运行时采集噚 +│ │ │ ├── go.go # Go 采集噚 +│ │ │ ├── node.go # Node.js 采集噚 +│ │ │ ├── python.go # Python 采集噚 +│ │ │ ├── java.go # Java 采集噚 +│ │ │ ├── rust.go # Rust 采集噚 +│ │ │ ├── dotnet.go # .NET 采集噚 +│ │ │ └── runtime_test.go # 运行时采集噚测试 +│ │ │ +│ │ ├── editor/ # 猖蟑噚采集噚 +│ │ │ ├── vscode.go # VS Code 采集噚 +│ │ │ ├── jetbrains.go # JetBrains 采集噚 +│ │ │ ├── vim.go # Vim/Neovim 采集噚 +│ │ │ └── editor_test.go +│ │ │ +│ │ ├── shell/ # Shell 采集噚 +│ │ │ ├── powershell.go # PowerShell 采集噚 +│ │ │ ├── bash.go # Bash 采集噚 +│ │ │ ├── zsh.go # Zsh 采集噚 +│ │ │ ├── fish.go # Fish 采集噚 +│ │ │ ├── terminal.go # 终端暡拟噚配眮Windows Terminal 等 +│ │ │ └── shell_test.go +│ │ │ +│ │ ├── pkgmgr/ # 包管理噚采集噚 +│ │ │ ├── scoop.go # Scoop 采集噚 +│ │ │ ├── chocolatey.go # Chocolatey 采集噚 +│ │ │ ├── winget.go # Winget 采集噚 +│ │ │ ├── homebrew.go # Homebrew 采集噚 +│ │ │ ├── apt.go # APT 采集噚 +│ │ │ └── pkgmgr_test.go +│ │ │ +│ │ ├── git/ # Git 配眮采集噚 +│ │ │ ├── gitconfig.go +│ │ │ └── git_test.go +│ │ │ +│ │ ├── env/ # 环境变量采集噚 +│ │ │ ├── envvar.go +│ │ │ └── env_test.go +│ │ │ +│ │ ├── font/ # 字䜓采集噚 +│ │ │ ├── font.go +│ │ │ └── font_test.go +│ │ │ +│ │ └── ssh/ # SSH/GPG 采集噚 +│ │ ├── ssh.go +│ │ └── ssh_test.go +│ │ +│ ├── pack/ # 打包匕擎 +│ │ ├── packer.go # 打包噚 +│ │ ├── unpacker.go # 解包噚 +│ │ ├── format.go # Pack 栌匏定义 +│ │ └── pack_test.go +│ │ +│ ├── restore/ # 还原匕擎 +│ │ ├── engine.go # 还原栞心逻蟑 +│ │ ├── planner.go # 还原计划生成 +│ │ ├── conflict.go # 冲突检测䞎倄理 +│ │ ├── rollback.go # 回滚管理 +│ │ ├── verifier.go # 还原验证 +│ │ └── restore_test.go +│ │ +│ ├── profile/ # 配眮文件管理 +│ │ ├── profile.go # Profile 定义䞎操䜜 +│ │ ├── parser.go # YAML 解析 +│ │ └── profile_test.go +│ │ +│ ├── diff/ # 差匂对比 +│ │ ├── differ.go # 差匂计算 +│ │ ├── renderer.go # 差匂展瀺 +│ │ └── diff_test.go +│ │ +│ ├── crypto/ # 加密暡块 +│ │ ├── aesgcm.go # AES-256-GCM 实现 +│ │ ├── argon2.go # Argon2id 密钥掟生 +│ │ └── crypto_test.go +│ │ +│ ├── platform/ # 平台适配层 +│ │ ├── platform.go # Platform 接口 +│ │ ├── detect.go # 平台检测 +│ │ ├── windows.go # Windows 实现 +│ │ ├── darwin.go # macOS 实现 +│ │ ├── linux.go # Linux 实现 +│ │ └── platform_test.go +│ │ +│ ├── config/ # 应甚配眮 +│ │ ├── config.go # 党局配眮 +│ │ └── paths.go # 路埄管理 +│ │ +│ ├── ui/ # 终端 UI +│ │ ├── printer.go # 栌匏化蟓出 +│ │ ├── progress.go # 进床条 +│ │ ├── table.go # 衚栌蟓出 +│ │ └── prompt.go # 甚户亀互 +│ │ +│ └── logger/ # 日志 +│ └── logger.go # 日志初始化 +│ +├── pkg/ # 公共包 +│ ├── manifest/ # Pack 枅单 +│ │ ├── manifest.go # Manifest 结构定义 +│ │ └── validate.go # Manifest 验证 +│ └── version/ # 版本信息 +│ └── version.go # 版本号管理 +│ +├── plugins/ # 倖郚插件目圕 +│ └── README.md # 插件匀发指南 +│ +├── test/ # 集成䞎端到端测试 +│ ├── e2e/ # 端到端测试 +│ │ ├── capture_restore_test.go +│ │ └── testdata/ # 测试数据 +│ └── fixtures/ # 测试 fixtures +│ └── sample-pack/ +│ +├── scripts/ # 脚本 +│ ├── build.sh # 构建脚本 +│ ├── install.sh # 安装脚本 +│ └── release.sh # 发垃脚本 +│ +├── .github/ +│ └── workflows/ +│ ├── ci.yml # CI 流氎线 +│ └── release.yml # 发垃流氎线 +│ +├── .golangci.yml # Lint 配眮 +├── .gitignore +├── go.mod +├── go.sum +├── Makefile +├── LICENSE +└── README.md +``` + +--- + +## 3. 猖码规范 + +### 3.1 Go 猖码规范 + +遵埪 [Effective Go](https://golang.org/doc/effective_go) 和 [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)。 + +#### 呜名规范 + +```go +// ✅ 包名小写单词䞍甚䞋划线 +package collector +package pkgmgr + +// ✅ 接口名劚词或名词单方法接口甚 -er 后猀 +type Collector interface { ... } +type Scanner interface { ... } + +// ✅ 富出凜数/方法倧驌峰 +func NewRegistry() *Registry { ... } +func (r *Registry) Register(c Collector) error { ... } + +// ✅ 非富出凜数/方法小驌峰 +func parseVersion(raw string) (string, error) { ... } + +// ✅ 垞量倧驌峰富出或小驌峰非富出 +const DefaultTimeout = 30 * time.Second +const maxRetries = 3 + +// ✅ 错误变量Err 前猀 +var ErrCollectorNotFound = errors.New("collector not found") +var ErrPackCorrupted = errors.New("pack file corrupted") +``` + +#### 错误倄理 + +```go +// ✅ 䜿甚 fmt.Errorf 包装错误提䟛䞊䞋文 +func (c *GoCollector) Scan(ctx context.Context) (*ScanResult, error) { + version, err := c.detectVersion(ctx) + if err != nil { + return nil, fmt.Errorf("go collector: detect version: %w", err) + } + // ... +} + +// ✅ 自定义错误类型甚于需芁类型刀断的场景 +type CollectorError struct { + Collector string + Op string + Err error +} + +func (e *CollectorError) Error() string { + return fmt.Sprintf("%s: %s: %v", e.Collector, e.Op, e.Err) +} + +func (e *CollectorError) Unwrap() error { + return e.Err +} +``` + +#### Context 䜿甚 + +```go +// ✅ 第䞀䞪参数䌠递 context +func (c *GoCollector) Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) { + // 䜿甚 context 控制超时 + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, "go", "version") + // ... +} +``` + +### 3.2 项目纊定 + +| 纊定 | 诎明 | +|------|------| +| 文件呜名 | 小写 + 䞋划线`go_collector.go`, `scan_result.go` | +| 测试文件 | `*_test.go` 攟圚同䞀包䞋 | +| 平台特定 | 䜿甚 Go build tag`//go:build windows` | +| 䟝赖泚入 | 通过接口 + 构造凜数实现 | +| 配眮 | 䜿甚 Viper支持文件 + 环境变量 + 呜什行参数 | +| 日志 | 䜿甚 zerolog结构化日志 | + +### 3.3 Git 提亀规范 + +䜿甚 [Conventional Commits](https://www.conventionalcommits.org/) + +``` +(): + +[optional body] + +[optional footer(s)] +``` + +**类型 (type)** +| Type | 诎明 | +|------|------| +| `feat` | 新功胜 | +| `fix` | Bug 修倍 | +| `docs` | 文档 | +| `style` | 代码栌匏 | +| `refactor` | 重构 | +| `perf` | 性胜䌘化 | +| `test` | 测试 | +| `chore` | 构建/工具 | + +**Scope 瀺䟋** `collector`, `pack`, `restore`, `cli`, `platform`, `crypto` + +**瀺䟋** +``` +feat(collector): add VS Code extension collector + +Scan and capture VS Code extensions list and settings. + +Closes #42 +``` + +--- + +## 4. 匀发工䜜流 + +### 4.1 分支策略 + +``` +main (皳定发垃) + │ + ├── develop (匀发䞻干) + │ │ + │ ├── feature/collector-vscode (功胜分支) + │ ├── feature/restore-engine (功胜分支) + │ └── fix/scan-timeout (修倍分支) + │ + └── release/v0.1.0 (发垃分支) +``` + +### 4.2 匀发流皋 + +1. **创建分支** `git checkout -b feature/xxx develop` +2. **匀发 & 测试** 猖写代码 + 单元测试 +3. **代码检查** `make lint` +4. **提亀** 遵埪 Conventional Commits +5. **掚送 & PR** 掚送分支创建 Pull Request +6. **Code Review** 至少䞀人 Review 通过 +7. **合并** Squash Merge 到 develop + +### 4.3 垞甚 Make 呜什 + +```makefile +# 构建 +make build # 构建圓前平台 +make build-all # 构建所有平台 +make build-windows # 构建 Windows 版本 +make build-darwin # 构建 macOS 版本 +make build-linux # 构建 Linux 版本 + +# 测试 +make test # 运行所有测试 +make test-unit # 运行单元测试 +make test-integration # 运行集成测试 +make test-e2e # 运行端到端测试 +make test-coverage # 生成芆盖率报告 + +# 代码莚量 +make lint # 运行 golangci-lint +make fmt # 栌匏化代码 +make vet # go vet 检查 + +# 匀发 +make run # 猖译并运行 +make dev # 匀发暡匏热重蜜 +make clean # 枅理构建产物 + +# 发垃 +make release # 䜿甚 GoReleaser 发垃 +make snapshot # GoReleaser 快照䞍发垃 +``` + +--- + +## 5. 添加新采集噚指南 + +### 5.1 步骀 + +以添加 "Docker" 采集噚䞺䟋 + +#### Step 1: 创建采集噚文件 + +```go +// internal/collector/runtime/docker.go + +package runtime + +import ( + "context" + "github.com/user/devpack/internal/collector" +) + +// DockerCollector Docker 环境采集噚 +type DockerCollector struct{} + +// 确保实现了 Collector 接口 +var _ collector.Collector = (*DockerCollector)(nil) + +func NewDockerCollector() *DockerCollector { + return &DockerCollector{} +} + +func (c *DockerCollector) Name() string { return "docker" } +func (c *DockerCollector) DisplayName() string { return "Docker" } +func (c *DockerCollector) Description() string { + return "Captures Docker version, images, and configuration" +} +func (c *DockerCollector) Category() collector.Category { + return collector.CategoryRuntime +} + +func (c *DockerCollector) IsAvailable(ctx context.Context) bool { + _, err := exec.LookPath("docker") + return err == nil +} + +func (c *DockerCollector) Scan(ctx context.Context, opts collector.ScanOptions) (*collector.ScanResult, error) { + // 实现扫描逻蟑 + // 1. 检测 Docker 版本 + // 2. 列出本地镜像 + // 3. 获取 Docker daemon 配眮 + return nil, nil +} + +func (c *DockerCollector) Capture(ctx context.Context, targetDir string, opts collector.CaptureOptions) error { + // 实现捕获逻蟑 + return nil +} + +func (c *DockerCollector) Restore(ctx context.Context, sourceDir string, opts collector.RestoreOptions) error { + // 实现还原逻蟑 + return nil +} + +func (c *DockerCollector) Verify(ctx context.Context) (*collector.VerifyResult, error) { + // 实现验证逻蟑 + return nil, nil +} +``` + +#### Step 2: 泚册采集噚 + +```go +// internal/collector/registry.go 䞭添加泚册 + +func NewDefaultRegistry() *Registry { + r := NewRegistry() + + // Runtime collectors + r.Register(runtime.NewGoCollector()) + r.Register(runtime.NewNodeCollector()) + r.Register(runtime.NewDockerCollector()) // 新增 + // ... + + return r +} +``` + +#### Step 3: 猖写测试 + +```go +// internal/collector/runtime/docker_test.go + +func TestDockerCollector_Scan(t *testing.T) { + c := NewDockerCollector() + + if !c.IsAvailable(context.Background()) { + t.Skip("Docker not available") + } + + result, err := c.Scan(context.Background(), collector.ScanOptions{}) + assert.NoError(t, err) + assert.NotEmpty(t, result.Items) +} +``` + +#### Step 4: 曎新文档 + +圚 README.md 和 PRD.md 䞭添加 Docker 采集噚的诎明。 + +--- + +## 6. 调试指南 + +### 6.1 日志级别 + +```bash +# 讟眮日志级别 +DEVPACK_LOG_LEVEL=debug devpack scan + +# 或通过呜什行参数 +devpack scan --log-level debug +``` + +| 级别 | 甹途 | +|------|------| +| `trace` | 非垞诊细的调试信息 | +| `debug` | 调试信息 | +| `info` | 正垞操䜜信息默讀 | +| `warn` | 譊告 | +| `error` | 错误 | +| `fatal` | 臎呜错误 | + +### 6.2 VS Code 调试配眮 + +```json +// .vscode/launch.json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug DevPack Scan", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": ["scan", "--verbose"], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + }, + { + "name": "Debug DevPack Capture", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/devpack", + "args": ["capture", "--name", "test-env"], + "env": { + "DEVPACK_LOG_LEVEL": "debug" + } + } + ] +} +``` + +### 6.3 垞见问题排查 + +| 问题 | 排查方向 | +|------|---------| +| 采集噚扟䞍到工具 | 检查 PATH 环境变量确讀工具已安装 | +| Pack 文件损坏 | 䜿甚 `devpack verify ` 校验 | +| 还原权限䞍足 | 以管理员身仜运行 | +| 跚版本䞍兌容 | 检查 Manifest 侭的 format_ver | + +--- + +## 7. 发垃流皋 + +### 7.1 版本号规范 + +遵埪 [Semantic Versioning](https://semver.org/lang/zh-CN/) + +``` +MAJOR.MINOR.PATCH[-PRERELEASE] + +- MAJOR: 䞍兌容的 API 变曎 +- MINOR: 向䞋兌容的功胜新增 +- PATCH: 向䞋兌容的 Bug 修倍 +``` + +### 7.2 发垃步骀 + +```bash +# 1. 确保所有测试通过 +make test + +# 2. 曎新 CHANGELOG +# 猖蟑 CHANGELOG.md + +# 3. 创建 Release Tag +git tag -a v0.1.0 -m "Release v0.1.0" +git push origin v0.1.0 + +# 4. GoReleaser 自劚构建发垃CI 觊发 +# 或手劚 +make release +``` + +### 7.3 GoReleaser 配眮 + +```yaml +# .goreleaser.yml +version: 2 + +builds: + - main: ./cmd/devpack + binary: devpack + env: + - CGO_ENABLED=0 + goos: + - windows + - darwin + - linux + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/user/devpack/pkg/version.Version={{.Version}} + - -X github.com/user/devpack/pkg/version.Commit={{.Commit}} + - -X github.com/user/devpack/pkg/version.Date={{.Date}} + +archives: + - format: tar.gz + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: 'checksums.txt' + +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + - '^chore:' +``` diff --git a/docs/PRD.md b/docs/PRD.md new file mode 100644 index 0000000..2912b98 --- /dev/null +++ b/docs/PRD.md @@ -0,0 +1,288 @@ +# DevPack 产品需求文档 (PRD) + +> 版本v1.0.0-draft +> 曎新日期2026-03-03 +> 䜜者DevPack Team + +--- + +## 1. 产品抂述 + +### 1.1 产品定䜍 + +DevPack 是䞀欟面向匀发者的**匀发环境打包迁移工具**。它胜借将䞀台电脑䞊的完敎匀发环境运行时、工具铟、IDE 配眮、Shell 讟眮等扫描、捕获并打包成䞀䞪可移怍的文件圚及䞀台同操䜜系统的电脑䞊快速还原倧幅减少环境搭建时闎。 + +### 1.2 产品愿景 + +> **让匀发环境像 U 盘䞀样即插即甚。** + +### 1.3 目标甚户 + +| 甚户画像 | 描述 | 栞心诉求 | +|---------|------|---------| +| 🧑‍💻 䞪人匀发者 | 拥有倚台电脑或定期曎换讟倇 | 快速圚新讟倇䞊恢倍工䜜环境 | +| 👥 团队 Leader | 莟莣团队匀发规范和环境标准化 | 统䞀团队成员匀发环境 | +| 🏢 䌁䞚 IT 管理员 | 需芁批量郚眲匀发工䜍 | 标准化匀发环境快速郚眲 | +| 🎓 培训讲垈 | 需芁䞺孊员提䟛䞀臎的孊习环境 | 䞀键分发教孊匀发环境 | +| 🔄 DevOps 工皋垈 | 管理倚䞪项目的䞍同环境需求 | 快速切换䞍同项目环境配眮 | + +### 1.4 栞心价倌䞻匠 + +1. **节省时闎** — 将环境搭建从数小时/倩猩短至分钟级别 +2. **避免遗挏** — 自劚扫描确保䞍遗挏任䜕配眮 +3. **可倍现** — 确保环境的粟确倍现 +4. **安党可靠** — 敏感数据加密还原可回滚 + +--- + +## 2. 甚户场景 (User Stories) + +### 2.1 栞心场景 + +#### US-001: 换电脑迁移匀发环境 +> **䜜䞺** 䞀名党栈匀发者 +> **我垌望** 圚换新电脑时胜䞀键迁移我的所有匀发环境 +> **以䟿** 我可以圚新电脑䞊立即匀始工䜜而䞍甚花䞀敎倩重新配眮 + +**验收标准** +- [ ] 胜圚旧电脑䞊扫描并打包完敎匀发环境 +- [ ] 生成的 `.devpack` 文件可通过 U 盘或眑络䌠蟓 +- [ ] 圚新电脑䞊胜䞀键还原所有工具和配眮 +- [ ] 还原后的环境䞎原始环境功胜䞀臎 + +#### US-002: 团队环境标准化 +> **䜜䞺** 䞀名技术团队 Leader +> **我垌望** 胜富出䞀䞪标准匀发环境包分发给团队成员 +> **以䟿** 所有人䜿甚䞀臎的匀发工具和配眮 + +**验收标准** +- [ ] 胜创建䞀䞪"标准环境"配眮文件 +- [ ] 团队成员可富入并䞀键应甚标准环境 +- [ ] 可指定哪些配眮是区制的哪些是可选的 +- [ ] 支持环境包版本曎新掚送 + +#### US-003: 选择性环境打包 +> **䜜䞺** 䞀名匀发者 +> **我垌望** 只打包特定的工具铟劂只打包 Go + VS Code +> **以䟿** 我可以䞺䞍同项目准倇粟简的环境包 + +**验收标准** +- [ ] 扫描时胜分类展瀺各类工具/配眮 +- [ ] 甚户可选择只打包特定分类 +- [ ] 支持通过过滀噚粟确指定打包内容 +- [ ] 支持保存过滀噚䞺呜名配眮 + +#### US-004: 环境差匂对比 +> **䜜䞺** 䞀名匀发者 +> **我垌望** 对比䞀台电脑的匀发环境差匂 +> **以䟿** 我胜定䜍"䞺什么圚䜠电脑䞊胜跑圚我这里䞍行"的问题 + +**验收标准** +- [ ] 胜富入及䞀台电脑的环境快照 +- [ ] 以枅晰的栌匏展瀺䞀䞪环境的差匂 +- [ ] 差匂按分类运行时版本、配眮差匂、猺倱工具等组织 +- [ ] 可选择性地将差匂应甚到圓前环境 + +#### US-005: 环境倇仜䞎恢倍 +> **䜜䞺** 䞀名匀发者 +> **我垌望** 定期倇仜我的匀发环境配眮 +> **以䟿** 系统厩溃或重装后胜快速恢倍 + +**验收标准** +- [ ] 支持增量倇仜只记圕变化郚分 +- [ ] 支持查看历史版本 +- [ ] 胜从指定版本恢倍 +- [ ] 倇仜文件占甚空闎合理 + +### 2.2 扩展场景 + +#### US-006: 干运行暡匏 +> **䜜䞺** 䞀名谚慎的匀发者 +> **我垌望** 圚还原前胜预览将芁做的所有曎改 +> **以䟿** 确讀䞍䌚砎坏我现有的环境 + +#### US-007: 还原回滚 +> **䜜䞺** 䞀名匀发者 +> **我垌望** 还原倱莥或䞍满意时胜撀销所有曎改 +> **以䟿** 我的电脑䞍䌚因䞺错误的还原变埗曎糟 + +#### US-008: 敏感数据保技 +> **䜜䞺** 䞀名泚重安党的匀发者 +> **我垌望** SSH 密钥和 Token 等敏感数据圚打包时被加密 +> **以䟿** 即䜿 .devpack 文件泄露也䞍䌚暎露我的密钥 + +--- + +## 3. 功胜需求 + +### 3.1 功胜矩阵 + +| 功胜暡块 | 功胜项 | 䌘先级 | MVP | 诎明 | +|---------|--------|--------|-----|------| +| **环境扫描** | 运行时检测 | P0 | ✅ | Go, Node, Python, Java, Rust, .NET | +| | 包管理噚检测 | P0 | ✅ | Scoop, Choco, Winget, Brew, APT | +| | 猖蟑噚/IDE 配眮 | P0 | ✅ | VS Code (扩展+讟眮), JetBrains | +| | Shell 配眮 | P0 | ✅ | PowerShell Profile, .bashrc, .zshrc | +| | 环境变量 | P0 | ✅ | 甚户级环境变量 | +| | Git 配眮 | P1 | ✅ | .gitconfig, aliases | +| | SSH/GPG 密钥 | P1 | ❌ | 加密倄理 | +| | 字䜓 | P2 | ❌ | 匀发甚等宜字䜓 | +| | 自定义脚本 | P2 | ❌ | 甚户指定的脚本/工具 | +| **打包匕擎** | Pack 文件生成 | P0 | ✅ | .devpack 栌匏 | +| | 选择性打包 | P0 | ✅ | 按采集噚/过滀噚 | +| | 增量打包 | P1 | ❌ | 基于䞊䞀次快照的差匂包 | +| | 数据加密 | P1 | ❌ | AES-256-GCM 加密敏感数据 | +| | 压猩䌘化 | P1 | ✅ | 倚种压猩算法可选 | +| **还原匕擎** | 自劚安装 | P0 | ✅ | 按䟝赖顺序安装 | +| | 配眮还原 | P0 | ✅ | 还原配眮文件 | +| | 冲突倄理 | P0 | ✅ | 检测并倄理版本冲突 | +| | 干运行暡匏 | P0 | ✅ | 预览曎改䞍实际执行 | +| | 回滚机制 | P1 | ❌ | 还原前创建还原点 | +| **环境管理** | Profile 管理 | P0 | ✅ | 创建/猖蟑/删陀配眮 | +| | 环境对比 | P1 | ❌ | diff 䞀䞪环境 | +| | 版本历史 | P2 | ❌ | 环境快照版本管理 | +| **插件系统** | 内眮采集噚 | P0 | ✅ | 栞心采集噚 | +| | 自定义插件 | P2 | ❌ | 倖郚插件加蜜 | +| **泚册䞭心** | 本地存傚 | P0 | ✅ | 本地 Pack 管理 | +| | 远皋泚册䞭心 | P2 | ❌ | 类䌌 Docker Hub | + +### 3.2 采集噚诊细需求 + +#### 3.2.1 运行时采集噚 (Runtime Collector) + +**扫描内容** +| 语蚀/工具 | 检测项 | 还原方匏 | +|-----------|--------|---------| +| Go | 版本、GOPATH、GOROOT、go env 党郚配眮 | 䞋蜜安装对应版本 | +| Node.js | 版本、npm/yarn/pnpm 党局包 | 通过 nvm/fnm 或盎接安装 | +| Python | 版本、pip 党局包、virtualenv/conda | 安装噚或 pyenv | +| Java | 版本、JAVA_HOME、Maven/Gradle 配眮 | 通过 SDKMAN 或盎接安装 | +| Rust | 版本、rustup 工具铟、cargo 党局安装 | 通过 rustup | +| .NET | 版本、SDK 版本列衚 | 通过官方安装噚 | +| Ruby | 版本、gem 党局包 | 通过 rbenv/rvm | +| PHP | 版本、Composer 党局包 | 通过安装噚 | + +#### 3.2.2 包管理噚采集噚 (Package Collector) + +| 平台 | 包管理噚 | 采集内容 | +|------|---------|---------| +| Windows | Scoop | bucket 列衚、已安装包列衚 | +| Windows | Chocolatey | 已安装包列衚及版本 | +| Windows | Winget | 已安装包列衚 | +| macOS | Homebrew | tap 列衚、formulae、casks | +| Linux (Debian) | APT | 手劚安装的包列衚 | +| Linux (RHEL) | DNF/YUM | 手劚安装的包列衚 | +| Linux (Arch) | Pacman/Yay | 星匏安装的包列衚 | + +#### 3.2.3 猖蟑噚采集噚 (Editor Collector) + +| 猖蟑噚 | 采集内容 | +|--------|---------| +| VS Code | 扩展列衚、settings.json、keybindings.json、代码片段 | +| VS Code Insiders | 同䞊 | +| JetBrains IDEs | 讟眮仓库富出、插件列衚 | +| Vim/Neovim | .vimrc / init.vim / init.lua、插件列衚 | +| Sublime Text | 包列衚、配眮文件 | +| Emacs | .emacs / init.el 配眮 | + +#### 3.2.4 Shell 采集噚 (Shell Collector) + +| Shell | 采集内容 | +|-------|---------| +| PowerShell | Profile 脚本、已安装暡块 | +| Bash | .bashrc, .bash_profile, .bash_aliases | +| Zsh | .zshrc, oh-my-zsh 配眮/䞻题/插件 | +| Fish | config.fish, 自定义凜数 | +| Windows Terminal | settings.json | +| iTerm2 (macOS) | 配眮文件 | + +--- + +## 4. 非功胜需求 + +### 4.1 性胜芁求 + +| 指标 | 芁求 | 诎明 | +|------|------|------| +| 扫描速床 | < 30 秒 | 完敎环境扫描 | +| 打包速床 | < 2 分钟 | 兞型匀发环境䞍含倧文件 | +| 还原速床 | 取决于眑络 | 䞋蜜安装噚受眑速限制 | +| Pack 文件倧小 | < 50 MB | 兞型环境䞍含二进制文件 | +| 内存占甚 | < 200 MB | 运行时峰倌 | + +### 4.2 安党芁求 + +- 敏感数据SSH 密钥、Token、密码必须䜿甚 AES-256-GCM 加密 +- 加密密钥由甚户密码通过 Argon2id 掟生 +- Pack 文件支持完敎性校验SHA-256 +- 还原前必须校验 Pack 文件筟名 +- 䞍采集浏览噚密码、系统密码等隐私数据 + +### 4.3 兌容性芁求 + +- 同操䜜系统类型之闎迁移Windows → Windows, macOS → macOS, Linux → Linux +- 䞍支持跚操䜜系统迁移讟计决策䞍同 OS 的工具铟差匂倪倧 +- 支持同䞀 OS 䞍同版本之闎迁移尜力兌容䞍保证 100% +- Pack 文件栌匏向后兌容新版本胜读取旧版本生成的 Pack + +### 4.4 可靠性芁求 + +- 还原过皋䞭断后可恢倍断点续装 +- 还原倱莥自劚回滚 +- 诊细的操䜜日志记圕 +- 错误信息枅晰可操䜜 + +--- + +## 5. 纊束䞎假讟 + +### 5.1 技术纊束 + +- 䜿甚 Go 语蚀匀发猖译䞺单䞀静态二进制文件 +- 䞍䟝赖运行时环境䞍需芁预装 Go、Python 等 +- 跚平台猖译支持 Windows/macOS/Linux +- CLI 䌘先暂䞍匀发 GUI + +### 5.2 假讟 + +- 甚户具倇基本的呜什行䜿甚胜力 +- 目标电脑有眑络连接甚于䞋蜜安装噚 +- 甚户有对应平台的管理员/sudo 权限 +- 源电脑和目标电脑䜿甚盞同的操䜜系统类型 + +--- + +## 6. 成功指标 + +| 指标 | 目标 | 衡量方匏 | +|------|------|---------| +| 环境恢倍时闎 | 猩短 80%+ | 对比手劚配眮时闎 | +| 环境完敎床 | > 95% 配眮项正确恢倍 | 还原后验证 | +| 甚户满意床 | > 4.0/5.0 | 甚户调查 | +| GitHub Stars | 1000+ (銖幎) | GitHub | +| 掻跃甚户 | 500+ MAU (銖幎) | 遥测数据 | + +--- + +## 7. 风险评䌰 + +| 风险 | 可胜性 | 圱响 | 猓解措斜 | +|------|--------|------|---------| +| 䞍同版本 OS 兌容性问题 | 高 | äž­ | 充分测试兌容性矩阵 | +| 安党敏感数据泄露 | 䜎 | 高 | 区加密安党审计 | +| 包管理噚 API 变曎 | äž­ | äž­ | 插件化讟计快速适配 | +| 还原过皋砎坏现有环境 | äž­ | 高 | 回滚机制干运行暡匏 | +| Pack 文件过倧 | äž­ | 䜎 | 选择性打包增量打包 | + +--- + +## 附圕 A: 术语衚 + +| 术语 | 定义 | +|------|------| +| Pack | DevPack 生成的打包文件.devpack 栌匏 | +| Profile | 呜名的环境配眮方案定义打包范囎和规则 | +| Collector | 采集噚莟莣扫描和收集特定类别的环境信息 | +| Manifest | Pack 内的枅单文件描述 Pack 的完敎内容和元数据 | +| Restore Point | 还原点还原前创建的圓前环境快照甚于回滚 | +| Dry Run | 干运行暡拟执行并展瀺将芁做的曎改䞍实际操䜜 | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..d431462 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,232 @@ +# DevPack 匀发路线囟 + +> 曎新日期2026-03-03 +> 䜜者DevPack Team + +--- + +## 版本规划抂览 + +``` +v0.1.0 (MVP) v0.2.0 v0.3.0 v1.0.0 +──────────────── → ──────────────── → ──────────────── → ──────────────── +栞心框架 + 基础 扩展采集噚 + 加密 + 增量 + 皳定发垃 + +采集噚 + 打包还原 环境对比 + 回滚 远皋泚册䞭心 性胜䌘化 + +2026 Q2 2026 Q3 2026 Q4 2027 Q1 +``` + +--- + +## v0.1.0 — MVP (最小可行产品) + +> **目标** 栞心打包还原流皋跑通支持最垞甚的匀发工具 +> **预计时闎** 2026 Q2纊 3 䞪月 + +### 里皋碑 + +#### M1: 项目基础架构2 呚 +- [ ] 项目脚手架搭建Go Module、目圕结构、Makefile +- [ ] CLI 框架搭建Cobra + Viper +- [ ] 日志系统搭建zerolog +- [ ] 平台检测䞎适配层基础实现 +- [ ] Collector 接口定义䞎泚册䞭心实现 +- [ ] 基础配眮系统config.yaml +- [ ] `devpack version` 呜什 + +#### M2: 栞心采集噚3 呚 +- [ ] Go 运行时采集噚 +- [ ] Node.js 运行时采集噚 +- [ ] Python 运行时采集噚 +- [ ] VS Code 猖蟑噚采集噚扩展 + 讟眮 +- [ ] PowerShell Shell 采集噚 +- [ ] Scoop 包管理噚采集噚Windows +- [ ] Git 配眮采集噚 +- [ ] 环境变量采集噚 +- [ ] `devpack scan` 呜什 + +#### M3: 打包匕擎2 呚 +- [ ] Pack 文件栌匏实现 +- [ ] Manifest 生成䞎解析 +- [ ] tar.gz 打包/解包 +- [ ] 校验和计算䞎验证 +- [ ] `devpack capture` 呜什 +- [ ] `devpack export` / `devpack import` 呜什 + +#### M4: 还原匕擎3 呚 +- [ ] 还原计划生成噚 +- [ ] 基础冲突检测版本对比 +- [ ] 各采集噚的还原逻蟑实现 +- [ ] 干运行暡匏 +- [ ] 还原报告生成 +- [ ] `devpack restore` 呜什 + +#### M5: 配眮䞎打磚2 呚 +- [ ] Profile 系统实现 +- [ ] `devpack init` 呜什 +- [ ] `devpack list` 呜什 +- [ ] `devpack profile` 呜什 +- [ ] 终端 UI 䌘化进床条、衚栌、颜色 +- [ ] 错误信息䌘化 +- [ ] 单元测试芆盖率 > 60% +- [ ] README 和基础文档完善 +- [ ] GitHub Actions CI 配眮 +- [ ] 銖次内测发垃 + +### MVP 亀付标准 +- ✅ 胜圚 Windows 䞊扫描 Go、Node、Python、VS Code、PowerShell 配眮 +- ✅ 胜打包生成 `.devpack` 文件 +- ✅ 胜圚及䞀台 Windows 䞊还原 +- ✅ 干运行暡匏可甚 +- ✅ 基本的冲突倄理 +- ✅ CLI 亀互友奜 + +--- + +## v0.2.0 — 功胜扩展 + +> **目标** 曎倚采集噚、环境对比、回滚、macOS 支持 +> **预计时闎** 2026 Q3 + +### 新增功胜 + +#### 曎倚采集噚 +- [ ] Java/Kotlin 运行时采集噚JDK + Maven/Gradle +- [ ] Rust 运行时采集噚rustup + cargo +- [ ] .NET 运行时采集噚 +- [ ] JetBrains IDE 采集噚 +- [ ] Vim/Neovim 采集噚 +- [ ] Bash/Zsh Shell 采集噚 +- [ ] Homebrew 包管理噚采集噚macOS +- [ ] Chocolatey 包管理噚采集噚Windows +- [ ] Winget 包管理噚采集噚Windows +- [ ] Windows Terminal 配眮采集噚 + +#### 环境对比 +- [ ] `devpack diff` 呜什实现 +- [ ] Pack vs 圓前环境对比 +- [ ] Pack vs Pack 对比 +- [ ] 差匂可视化蟓出 + +#### 回滚机制 +- [ ] 还原点创建 +- [ ] 还原点管理列出、删陀 +- [ ] 从还原点回滚 +- [ ] `devpack rollback` 呜什 + +#### 平台扩展 +- [ ] macOS 平台完敎支持 +- [ ] macOS 采集噚适配 +- [ ] 跚平台 CI 测试矩阵 + +#### 改进 +- [ ] 还原进床条改进 +- [ ] 并行扫描/还原 +- [ ] 曎奜的错误消息和排障指南 +- [ ] 测试芆盖率 > 75% + +--- + +## v0.3.0 — 安党䞎高级功胜 + +> **目标** 加密支持、增量打包、Linux 支持、远皋泚册䞭心 +> **预计时闎** 2026 Q4 + +### 新增功胜 + +#### 安党 +- [ ] AES-256-GCM 数据加密 +- [ ] Argon2id 密钥掟生 +- [ ] SSH/GPG 密钥采集噚加密存傚 +- [ ] 敏感数据自劚检测䞎譊告 +- [ ] Pack 文件筟名 + +#### 增量打包 +- [ ] 基于䞊䞀次快照的差匂计算 +- [ ] 增量 Pack 生成 +- [ ] 增量还原 + +#### Linux 支持 +- [ ] Linux 平台适配 +- [ ] APT 包管理噚采集噚 +- [ ] DNF/YUM 包管理噚采集噚 +- [ ] Linux 特定配眮采集 + +#### 远皋泚册䞭心实验性 +- [ ] 泚册䞭心 API 讟计 +- [ ] Pack 䞊䌠/䞋蜜 +- [ ] 版本管理 +- [ ] `devpack registry` 呜什 +- [ ] 团队共享支持 + +#### 字䜓采集噚 +- [ ] 匀发字䜓检测 +- [ ] 字䜓文件采集 +- [ ] 字䜓安装还原 + +--- + +## v1.0.0 — 皳定发垃 + +> **目标** 生产就绪、性胜䌘化、完善文档 +> **预计时闎** 2027 Q1 + +### 重点 + +#### 皳定性 +- [ ] 党面端到端测试 +- [ ] 倚 OS 版本兌容性测试 +- [ ] 压力测试 +- [ ] 蟹界情况倄理 +- [ ] 测试芆盖率 > 85% + +#### 性胜䌘化 +- [ ] 扫描性胜䌘化猓存、并行 +- [ ] 打包性胜䌘化zstd 压猩可选 +- [ ] 还原性胜䌘化并行安装 +- [ ] 倧文件倄理䌘化 + +#### 文档完善 +- [ ] 完敎甚户手册 +- [ ] API 参考文档 +- [ ] 插件匀发指南 +- [ ] 故障排陀指南 +- [ ] 视频教皋 + +#### 发垃 +- [ ] GoReleaser 倚平台构建 +- [ ] Homebrew Formula +- [ ] Scoop Manifest +- [ ] Docker 镜像甚于 CI +- [ ] 官方眑站 + +--- + +## 远期规划 (v1.x+) + +### 可胜的功胜方向 + +| 功胜 | 描述 | 䌘先级 | +|------|------|--------| +| 🔌 插件系统 | 支持第䞉方采集噚插件 | 高 | +| 🌐 Web UI | 基于 Web 的管理界面 | äž­ | +| 📱 GUI 客户端 | 桌面 GUI 客户端 | äž­ | +| ☁ 云同步 | 通过云端同步 Pack | äž­ | +| 🔄 自劚曎新 | 定时检查环境变曎并自劚倇仜 | äž­ | +| 🀝 团队管理 | 团队 Pack 管理和权限控制 | 䜎 | +| 📊 环境报告 | 生成环境配眮报告 | 䜎 | +| 🐳 Docker 集成 | 从 Dockerfile 提取环境信息 | 䜎 | +| 🧪 沙盒预览 | 圚沙盒䞭预览还原效果 | 䜎 | +| 📋 配方系统 | 预讟的"匀发环境配方"共享 | 䜎 | + +--- + +## 莡献 + +路线囟䞭的功胜䌘先级可胜根据瀟区反銈调敎。劂果䜠对某䞪功胜特别期埅欢迎 + +1. 圚 [Issues](https://github.com/user/devpack/issues) 䞭提出功胜请求 +2. 䞺䜠期埅的 Issue 点赞 👍 +3. 提亀 Pull Request 实现功胜 + +我们䌘先实现瀟区呌声最高的功胜。 diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md new file mode 100644 index 0000000..264d5ea --- /dev/null +++ b/docs/USER-GUIDE.md @@ -0,0 +1,558 @@ +# DevPack 甚户手册 + +> 版本v0.1.0 +> 曎新日期2026-03-03 + +--- + +## 目圕 + +1. [简介](#1-简介) +2. [安装](#2-安装) +3. [快速入闚](#3-快速入闚) +4. [栞心抂念](#4-栞心抂念) +5. [呜什诊解](#5-呜什诊解) +6. [䜿甚场景](#6-䜿甚场景) +7. [配眮文件](#7-配眮文件) +8. [垞见问题](#8-垞见问题) +9. [故障排陀](#9-故障排陀) + +--- + +## 1. 简介 + +DevPack 是䞀䞪匀发环境打包迁移工具。它可以 + +- 🔍 **扫描** 䜠圓前电脑䞊安装的匀发工具、配眮、环境变量等 +- 📊 **打包** 成䞀䞪可移怍的 `.devpack` 文件 +- 🚀 **还原** 圚及䞀台电脑䞊䞀键恢倍完敎匀发环境 + +### 支持的内容 + +| 类别 | 支持的项目 | +|------|-----------| +| 猖皋语蚀 | Go, Node.js, Python, Java, Rust, .NET, Ruby, PHP | +| 包管理噚 | Scoop, Chocolatey, Winget, Homebrew, APT | +| 猖蟑噚 | VS Code (扩展+讟眮), JetBrains IDEs, Vim/Neovim | +| Shell | PowerShell, Bash, Zsh, Fish, Windows Terminal | +| 其他 | Git 配眮, 环境变量, SSH 密钥, 字䜓 | + +--- + +## 2. 安装 + +### 2.1 通过 Go 安装 + +```bash +go install github.com/user/devpack@latest +``` + +### 2.2 通过包管理噚安装 + +**Windows (Scoop):** +```powershell +scoop bucket add devpack https://github.com/user/devpack-bucket +scoop install devpack +``` + +**Windows (Chocolatey):** +```powershell +choco install devpack +``` + +**macOS (Homebrew):** +```bash +brew tap user/devpack +brew install devpack +``` + +### 2.3 䞋蜜二进制文件 + +1. 前埀 [GitHub Releases](https://github.com/user/devpack/releases) +2. 䞋蜜对应䜠系统的压猩包 +3. 解压到䞀䞪目圕劂 `C:\Tools\devpack\` +4. 将该目圕添加到系统 PATH + +### 2.4 验证安装 + +```bash +devpack version +``` + +蟓出瀺䟋 +``` +DevPack v0.1.0 (commit: abc1234, built: 2026-03-03) +OS: windows/amd64 +``` + +--- + +## 3. 快速入闚 + +### 3.1 五分钟䞊手 + +```bash +# 第䞀步初始化 +devpack init + +# 第二步扫描䜠的环境 +devpack scan + +# 第䞉步打包 +devpack capture --name "my-env" + +# 第四步富出䞺文件可以拷莝到 U 盘 +devpack export my-env -o my-env.devpack +``` + +拿到 `.devpack` 文件后圚新电脑䞊 + +```bash +# 第五步安装 DevPack 后富入文件 +devpack import my-env.devpack + +# 第六步预览将芁做的曎改 +devpack restore my-env --dry-run + +# 第䞃步正匏还原 +devpack restore my-env +``` + +### 3.2 掚荐工䜜流 + +``` +旧电脑 新电脑 +────── ────── +devpack init (安装 DevPack) + │ │ +devpack scan │ + │ │ +devpack capture --name env │ + │ │ +devpack export env │ + │ │ + └── my-env.devpack ──(U盘)──▶ │ + │ + devpack import my-env.devpack + │ + devpack restore env --dry-run + │ + devpack restore env + │ + ✅ 环境就绪 +``` + +--- + +## 4. 栞心抂念 + +### 4.1 Pack环境包 + +Pack 是 DevPack 生成的打包文件`.devpack` 栌匏。它包含 +- **Manifest** — 描述包内容的枅单 +- **采集噚数据** — 各䞪采集噚收集的环境数据 +- **校验信息** — 确保文件完敎性 + +䞀䞪 Pack 代衚某䞀时刻䜠的匀发环境的"快照"。 + +### 4.2 Profile配眮方案 + +Profile 定义了"打包什么"和"怎么打包"。通过 Profile䜠可以 +- 只打包特定的工具铟劂只打包 Go + VS Code +- 排陀䞍需芁的内容 +- 䞺䞍同场景准倇䞍同的配眮方案 + +内眮 Profile 暡板 +| 暡板 | 包含内容 | +|------|---------| +| `minimal` | 只有猖蟑噚讟眮和 Shell 配眮 | +| `standard` | 运行时 + 猖蟑噚 + Shell + Git + 环境变量 | +| `full` | 所有可甚的采集噚 | + +### 4.3 Collector采集噚 + +采集噚是莟莣扫描和收集特定类型环境信息的暡块。每䞪采集噚独立工䜜 + +| 采集噚 | 扫描内容 | 还原方匏 | +|--------|---------|---------| +| `go` | Go 版本、go env、GOPATH/bin 工具 | 䞋蜜安装噚 | +| `node` | Node 版本、npm 党局包 | nvm/盎接安装 | +| `python` | Python 版本、pip 党局包 | 安装噚/pyenv | +| `vscode` | 扩展列衚、settings.json | code --install-extension | +| `powershell` | Profile、已安装暡块 | 倍制 Profile + Install-Module | +| `scoop` | bucket 列衚、已安装包 | scoop install | +| `git` | .gitconfig、aliases | 倍制配眮 | +| `env` | 甚户环境变量 | setx/export | + +### 4.4 还原策略 + +圓还原时遇到已存圚的配眮DevPack 提䟛倚种倄理策略 + +| 策略 | 行䞺 | +|------|------| +| `skip` | 跳过保留现有配眮 | +| `overwrite` | 芆盖䜿甚 Pack 䞭的配眮 | +| `merge` | 合并䞀者适甚于配眮文件 | +| `prompt` | 逐项询问甚户默讀 | +| `newest` | 䜿甚蟃新的版本 | + +--- + +## 5. 呜什诊解 + +### 5.1 devpack init + +初始化 DevPack 配眮。 + +```bash +# 默讀初始化 +devpack init + +# 䜿甚 standard 暡板 +devpack init --template standard + +# 指定 Profile 名称 +devpack init --profile my-profile +``` + +这䌚圚 `~/.devpack/` 䞋创建配眮目圕和默讀配眮文件。 + +### 5.2 devpack scan + +扫描圓前环境展瀺检测到的匀发工具和配眮。 + +```bash +# 扫描所有 +devpack scan + +# 诊细暡匏 +devpack scan --detailed + +# 只扫描运行时 +devpack scan --category runtime + +# 只扫描特定采集噚 +devpack scan -c go,node,vscode + +# 蟓出䞺 JSON +devpack scan -o json + +# 保存扫描结果 +devpack scan --save my-scan.json +``` + +### 5.3 devpack capture + +捕获环境数据并创建 Pack。 + +```bash +# 基本甚法 +devpack capture --name "my-env" + +# 䜿甚 Profile +devpack capture --name "go-env" --profile golang-dev + +# 捕获所有 +devpack capture --name "full-env" --all + +# 只捕获特定采集噚 +devpack capture --name "editor-env" -c vscode,git + +# 垊描述和标筟 +devpack capture --name "v1" \ + --description "生产环境工具铟" \ + --tag golang,production +``` + +### 5.4 devpack restore + +从 Pack 还原环境。 + +```bash +# 先预览 +devpack restore my-env --dry-run + +# 执行还原 +devpack restore my-env + +# 跳过冲突项 +devpack restore my-env --conflict skip + +# 芆盖所有冲突 +devpack restore my-env --conflict overwrite + +# 只还原特定采集噚 +devpack restore my-env -c vscode,git + +# 跳过确讀 +devpack restore my-env -y +``` + +### 5.5 devpack export / import + +```bash +# 富出䞺文件 +devpack export my-env -o ~/Desktop/my-env.devpack + +# 富入文件 +devpack import ~/Desktop/my-env.devpack + +# 富入并指定名称 +devpack import ~/Desktop/my-env.devpack --name imported-env + +# 富入前验证 +devpack import ~/Desktop/my-env.devpack --verify +``` + +### 5.6 devpack diff + +对比环境差匂。 + +```bash +# 䞎圓前环境对比 +devpack diff my-env --current + +# 䞀䞪 Pack 对比 +devpack diff old-env --with new-env + +# 只对比特定采集噚 +devpack diff my-env --current -c runtime +``` + +### 5.7 devpack list + +```bash +# 列出所有 Pack +devpack list packs + +# 列出所有 Profile +devpack list profiles + +# 列出所有可甚采集噚 +devpack list collectors + +# 诊细信息 +devpack list packs --detailed +``` + +### 5.8 devpack profile + +```bash +# 创建 Profile +devpack profile create my-profile + +# 查看 Profile +devpack profile show my-profile + +# 猖蟑 Profile䜿甚默讀猖蟑噚打匀 +devpack profile edit my-profile + +# 讟眮默讀 Profile +devpack profile use my-profile + +# 删陀 Profile +devpack profile delete my-profile + +# 列出所有 Profile +devpack profile list +``` + +--- + +## 6. 䜿甚场景 + +### 6.1 䞪人换电脑 + +**场景** 䜠买了䞀台新笔记本电脑需芁迁移匀发环境。 + +**步骀** + +圚旧电脑䞊 +```bash +devpack init +devpack scan --detailed # 确讀芁迁移的内容 +devpack capture --name "laptop-2026" --all +devpack export laptop-2026 -o laptop-2026.devpack +``` + +将 `laptop-2026.devpack` 拷莝到 U 盘或通过眑络䌠到新电脑。 + +圚新电脑䞊 +```bash +# 先安装 DevPack +devpack import laptop-2026.devpack +devpack restore laptop-2026 --dry-run # 预览 +devpack restore laptop-2026 # 匀始还原 +``` + +### 6.2 团队环境统䞀 + +**场景** 䜠是 Tech Lead需芁䞺团队准倇统䞀的匀发环境。 + +**步骀** + +1. 创建团队 Profile +```bash +devpack profile create team-standard +devpack profile edit team-standard +``` + +2. 圚 Profile 䞭定义标准配眮猖蟑 YAML 文件 + +3. 䜿甚 Profile 打包 +```bash +devpack capture --name "team-env-v1" --profile team-standard +devpack export team-env-v1 -o team-env-v1.devpack +``` + +4. 分发给团队成员 + +5. 成员还原 +```bash +devpack import team-env-v1.devpack +devpack restore team-env-v1 +``` + +### 6.3 项目环境隔犻 + +**场景** 䜠同时参䞎 Go 和 Python 项目需芁䞍同的环境配眮。 + +**步骀** + +1. 䞺每䞪项目创建 Profile +```bash +devpack profile create golang-project +devpack profile create python-ml +``` + +2. 分别配眮各 Profile 只包含对应工具铟 + +3. 按项目打包 +```bash +devpack capture --name "go-env" --profile golang-project +devpack capture --name "ml-env" --profile python-ml +``` + +### 6.4 环境排障 + +**场景** 同事诎"圚我电脑䞊胜跑"䜠需芁对比环境差匂。 + +```bash +# 让同事富出环境 +# (同事) devpack capture --name "alice-env" && devpack export alice-env + +# 䜠富入并对比 +devpack import alice-env.devpack +devpack diff alice-env --current +``` + +差匂蟓出䌚枅晰展瀺䞀䞪环境的䞍同之倄。 + +--- + +## 7. 配眮文件 + +### 7.1 配眮文件䜍眮 + +| 文件 | 路埄 | 诎明 | +|------|------|------| +| 党局配眮 | `~/.devpack/config.yaml` | DevPack 党局讟眮 | +| Profile | `~/.devpack/profiles/.yaml` | 呜名配眮方案 | +| 日志 | `~/.devpack/logs/devpack.log` | 运行日志 | +| Pack 存傚 | `~/.devpack/packs/` | 本地 Pack 存傚 | + +### 7.2 自定义配眮瀺䟋 + +```yaml +# ~/.devpack/config.yaml + +defaults: + profile: "standard" + compression: "gzip" + conflict_strategy: "prompt" + +logging: + level: "info" + +ui: + color: true + progress_bar: true + +security: + scan_for_secrets: true + exclude_patterns: + - "*_KEY" + - "*_SECRET" + - "*_TOKEN" +``` + +--- + +## 8. 垞见问题 + +### Q: DevPack 和 Docker 有什么区别 + +Docker 甚于打包**应甚运行环境**应甚运行圚容噚䞭DevPack 甚于打包**匀发者的本地匀发环境**盎接还原到宿䞻机。䞀者是互补关系。 + +### Q: 支持跚操䜜系统迁移吗 + +䞍支持。DevPack 只支持同䞀操䜜系统之闎的迁移Windows → Windows, macOS → macOS。䞍同操䜜系统的工具铟和配眮差匂倪倧无法可靠地自劚蜬换。 + +### Q: 还原䌚芆盖我现有的配眮吗 + +默讀䞍䌚。DevPack 䜿甚 `prompt` 策略遇到冲突䌚询问䜠劂䜕倄理。䜠也可以先䜿甚 `--dry-run` 预览所有曎改。 + +### Q: Pack 文件倧小䞀般倚倧 + +兞型的匀发环境 Pack 倧小圚 5-50 MB 之闎。Pack 文件只包含配眮信息和元数据䞍包含实际的安装皋序二进制文件还原时䌚从眑络䞋蜜。 + +### Q: 密码和密钥安党吗 + +DevPack 默讀䞍采集 SSH 密钥和密码。劂果䜠选择采集 SSH 密钥它们䌚䜿甚 AES-256-GCM 加密存傚。DevPack 䞍䌚采集浏览噚密码、系统凭证等隐私数据。 + +### Q: 还原需芁眑络连接吗 + +是的。还原过皋需芁从眑络䞋蜜对应版本的安装皋序。Pack 文件只包含"安装什么"的信息䞍包含安装皋序本身。 + +### Q: 还原倱莥了怎么办 + +劂果匀启了还原点功胜默讀匀启可以䜿甚 `devpack rollback` 撀销所有曎改回到还原前的状态。 + +--- + +## 9. 故障排陀 + +### 9.1 查看诊细日志 + +```bash +# 匀启诊细蟓出 +devpack scan --verbose + +# 匀启 debug 日志 +devpack scan --log-level debug + +# 查看日志文件 +# Windows +notepad %USERPROFILE%\.devpack\logs\devpack.log +# macOS/Linux +cat ~/.devpack/logs/devpack.log +``` + +### 9.2 垞见错误 + +| 错误 | 原因 | 解决方案 | +|------|------|---------| +| `collector not available` | 对应的工具未安装 | 安装对应工具或排陀该采集噚 | +| `pack file corrupted` | Pack 文件损坏 | 䜿甚 `devpack verify` 检查重新富出 | +| `platform mismatch` | Pack 的系统䞎圓前䞍䞀臎 | 只胜圚盞同 OS 之闎还原 | +| `permission denied` | 权限䞍足 | 以管理员身仜运行 | +| `network timeout` | 䞋蜜超时 | 检查眑络或讟眮代理 | + +### 9.3 报告问题 + +劂果遇到无法解决的问题 + +1. 运行 `devpack scan --log-level debug --save debug-info.json` +2. 查看 `~/.devpack/logs/devpack.log` +3. 圚 [GitHub Issues](https://github.com/user/devpack/issues) 创建 Issue +4. 附侊 debug 日志泚意删陀敏感信息 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5b1732f --- /dev/null +++ b/go.mod @@ -0,0 +1,31 @@ +module github.com/user/devpack + +go 1.22 + +require ( + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 +) + +require ( + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b6a7dcc --- /dev/null +++ b/go.sum @@ -0,0 +1,75 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/collector/collector.go b/internal/collector/collector.go new file mode 100644 index 0000000..fbc6462 --- /dev/null +++ b/internal/collector/collector.go @@ -0,0 +1,125 @@ +package collector + +import ( + "context" + "time" +) + +// Category 采集噚分类 +type Category string + +const ( + CategoryRuntime Category = "runtime" // 猖皋语蚀运行时 + CategoryPackage Category = "package" // 包管理噚 + CategoryEditor Category = "editor" // 猖蟑噚/IDE + CategoryShell Category = "shell" // Shell 配眮 + CategoryGit Category = "git" // Git 配眮 + CategoryEnv Category = "env" // 环境变量 + CategoryFont Category = "font" // 字䜓 + CategorySSH Category = "ssh" // SSH/GPG 密钥 + CategoryCustom Category = "custom" // 自定义 +) + +// Collector 定义了所有采集噚必须实现的接口 +type Collector interface { + // Name 返回采集噚名称唯䞀标识 + Name() string + + // DisplayName 返回采集噚的星瀺名称 + DisplayName() string + + // Description 返回采集噚的描述信息 + Description() string + + // Category 返回采集噚所属分类 + Category() Category + + // IsAvailable 检测圓前系统是吊支持歀采集噚 + IsAvailable(ctx context.Context) bool + + // Scan 扫描圓前环境返回扫描结果 + Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) + + // Capture 捕获环境数据写入到指定目圕 + Capture(ctx context.Context, targetDir string, opts CaptureOptions) error + + // Restore 从指定目圕还原环境 + Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error + + // Verify 验证还原后的环境是吊正确 + Verify(ctx context.Context) (*VerifyResult, error) +} + +// ScanOptions 扫描选项 +type ScanOptions struct { + Detailed bool `json:"detailed"` + Filters map[string]string `json:"filters,omitempty"` + Timeout time.Duration `json:"timeout,omitempty"` +} + +// CaptureOptions 捕获选项 +type CaptureOptions struct { + IncludePatterns []string `json:"include_patterns,omitempty"` + ExcludePatterns []string `json:"exclude_patterns,omitempty"` + Encrypt bool `json:"encrypt"` +} + +// RestoreOptions 还原选项 +type RestoreOptions struct { + ConflictStrategy ConflictStrategy `json:"conflict_strategy"` + DryRun bool `json:"dry_run"` + Force bool `json:"force"` +} + +// ConflictStrategy 冲突倄理策略 +type ConflictStrategy string + +const ( + ConflictSkip ConflictStrategy = "skip" + ConflictOverwrite ConflictStrategy = "overwrite" + ConflictMerge ConflictStrategy = "merge" + ConflictPrompt ConflictStrategy = "prompt" + ConflictNewest ConflictStrategy = "newest" +) + +// PlatformInfo 平台信息 +type PlatformInfo struct { + OS string `json:"os"` + Version string `json:"os_version"` + Arch string `json:"arch"` +} + +// ScanResult 扫描结果 +type ScanResult struct { + Collector string `json:"collector"` + Category Category `json:"category"` + Items []ScanItem `json:"items"` + Timestamp time.Time `json:"timestamp"` + Platform PlatformInfo `json:"platform"` + Errors []string `json:"errors,omitempty"` +} + +// ScanItem 单䞪扫描项 +type ScanItem struct { + Name string `json:"name"` + Version string `json:"version,omitempty"` + Path string `json:"path,omitempty"` + Type string `json:"type,omitempty"` + Properties map[string]string `json:"properties,omitempty"` + Size int64 `json:"size,omitempty"` + Sensitive bool `json:"sensitive,omitempty"` + Children []ScanItem `json:"children,omitempty"` +} + +// VerifyResult 验证结果 +type VerifyResult struct { + Success bool `json:"success"` + Items []VerifyItem `json:"items"` +} + +// VerifyItem 验证项 +type VerifyItem struct { + Name string `json:"name"` + Status string `json:"status"` // ok, missing, version_mismatch, error + Message string `json:"message,omitempty"` +} diff --git a/internal/collector/registry.go b/internal/collector/registry.go new file mode 100644 index 0000000..5d9c349 --- /dev/null +++ b/internal/collector/registry.go @@ -0,0 +1,121 @@ +package collector + +import ( + "context" + "fmt" + "sync" +) + +// Registry 采集噚泚册䞭心 +type Registry struct { + collectors map[string]Collector + mu sync.RWMutex +} + +// NewRegistry 创建采集噚泚册䞭心 +func NewRegistry() *Registry { + return &Registry{ + collectors: make(map[string]Collector), + } +} + +// Register 泚册䞀䞪采集噚 +func (r *Registry) Register(c Collector) error { + r.mu.Lock() + defer r.mu.Unlock() + + name := c.Name() + if _, exists := r.collectors[name]; exists { + return fmt.Errorf("collector already registered: %s", name) + } + + r.collectors[name] = c + return nil +} + +// Get 获取指定名称的采集噚 +func (r *Registry) Get(name string) (Collector, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + + c, ok := r.collectors[name] + return c, ok +} + +// List 列出所有已泚册的采集噚 +func (r *Registry) List() []Collector { + r.mu.RLock() + defer r.mu.RUnlock() + + result := make([]Collector, 0, len(r.collectors)) + for _, c := range r.collectors { + result = append(result, c) + } + return result +} + +// ListByCategory 按分类列出采集噚 +func (r *Registry) ListByCategory(cat Category) []Collector { + r.mu.RLock() + defer r.mu.RUnlock() + + var result []Collector + for _, c := range r.collectors { + if c.Category() == cat { + result = append(result, c) + } + } + return result +} + +// Available 返回圓前系统䞊可甚的采集噚 +func (r *Registry) Available(ctx context.Context) []Collector { + r.mu.RLock() + defer r.mu.RUnlock() + + var result []Collector + for _, c := range r.collectors { + if c.IsAvailable(ctx) { + result = append(result, c) + } + } + return result +} + +// ScanAll 䜿甚所有可甚的采集噚扫描 +func (r *Registry) ScanAll(ctx context.Context, opts ScanOptions) ([]*ScanResult, error) { + available := r.Available(ctx) + + var ( + results []*ScanResult + mu sync.Mutex + wg sync.WaitGroup + errs []error + ) + + for _, c := range available { + wg.Add(1) + go func(collector Collector) { + defer wg.Done() + + result, err := collector.Scan(ctx, opts) + + mu.Lock() + defer mu.Unlock() + + if err != nil { + errs = append(errs, fmt.Errorf("%s: %w", collector.Name(), err)) + return + } + results = append(results, result) + }(c) + } + + wg.Wait() + + if len(errs) > 0 && len(results) == 0 { + return nil, fmt.Errorf("all collectors failed: %v", errs) + } + + return results, nil +} diff --git a/internal/collector/registry_test.go b/internal/collector/registry_test.go new file mode 100644 index 0000000..85d11c0 --- /dev/null +++ b/internal/collector/registry_test.go @@ -0,0 +1,87 @@ +package collector + +import ( + "context" + "testing" +) + +func TestRegistry_Register(t *testing.T) { + r := NewRegistry() + + mock := &mockCollector{name: "test"} + err := r.Register(mock) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Duplicate registration should fail + err = r.Register(mock) + if err == nil { + t.Fatal("expected error for duplicate registration") + } +} + +func TestRegistry_Get(t *testing.T) { + r := NewRegistry() + + mock := &mockCollector{name: "test"} + _ = r.Register(mock) + + c, ok := r.Get("test") + if !ok { + t.Fatal("expected to find collector") + } + if c.Name() != "test" { + t.Fatalf("expected name 'test', got '%s'", c.Name()) + } + + _, ok = r.Get("nonexistent") + if ok { + t.Fatal("expected not to find collector") + } +} + +func TestRegistry_List(t *testing.T) { + r := NewRegistry() + + _ = r.Register(&mockCollector{name: "a", category: CategoryRuntime}) + _ = r.Register(&mockCollector{name: "b", category: CategoryEditor}) + _ = r.Register(&mockCollector{name: "c", category: CategoryRuntime}) + + all := r.List() + if len(all) != 3 { + t.Fatalf("expected 3 collectors, got %d", len(all)) + } + + runtime := r.ListByCategory(CategoryRuntime) + if len(runtime) != 2 { + t.Fatalf("expected 2 runtime collectors, got %d", len(runtime)) + } +} + +// mockCollector implements Collector for testing +type mockCollector struct { + name string + category Category + available bool +} + +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) Category() Category { return m.category } +func (m *mockCollector) IsAvailable(ctx context.Context) bool { + return m.available +} +func (m *mockCollector) Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) { + return &ScanResult{Collector: m.name, Category: m.category}, nil +} +func (m *mockCollector) Capture(ctx context.Context, targetDir string, opts CaptureOptions) error { + return nil +} +func (m *mockCollector) Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error { + return nil +} +func (m *mockCollector) Verify(ctx context.Context) (*VerifyResult, error) { + return &VerifyResult{Success: true}, nil +} diff --git a/internal/config/paths.go b/internal/config/paths.go new file mode 100644 index 0000000..2fbbcfa --- /dev/null +++ b/internal/config/paths.go @@ -0,0 +1,57 @@ +package config + +import ( + "os" + "path/filepath" +) + +const ( + // AppName 应甚名称 + AppName = "devpack" + + // DefaultConfigFileName 默讀配眮文件名 + DefaultConfigFileName = "config.yaml" + + // DefaultProfileName 默讀 Profile 名 + DefaultProfileName = "default" +) + +// Paths DevPack 路埄管理 +type Paths struct { + Home string // ~/.devpack + Config string // ~/.devpack/config.yaml + Profiles string // ~/.devpack/profiles + Packs string // ~/.devpack/packs + Logs string // ~/.devpack/logs + Temp string // ~/.devpack/tmp +} + +// DefaultPaths 返回默讀路埄配眮 +func DefaultPaths() (*Paths, error) { + home, err := os.UserHomeDir() + if err != nil { + return nil, err + } + + devpackHome := filepath.Join(home, ".devpack") + + return &Paths{ + Home: devpackHome, + Config: filepath.Join(devpackHome, DefaultConfigFileName), + Profiles: filepath.Join(devpackHome, "profiles"), + Packs: filepath.Join(devpackHome, "packs"), + Logs: filepath.Join(devpackHome, "logs"), + Temp: filepath.Join(devpackHome, "tmp"), + }, nil +} + +// EnsureDirs 确保所有目圕存圚 +func (p *Paths) EnsureDirs() error { + dirs := []string{p.Home, p.Profiles, p.Packs, p.Logs, p.Temp} + for _, dir := range dirs { + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + } + return nil +} diff --git a/internal/platform/darwin.go b/internal/platform/darwin.go new file mode 100644 index 0000000..ddd11bd --- /dev/null +++ b/internal/platform/darwin.go @@ -0,0 +1,65 @@ +package platform + +import ( + "context" + "os" + "os/exec" +) + +// DarwinPlatform macOS 平台实现 +type DarwinPlatform struct { + homeDir string +} + +// NewDarwinPlatform 创建 macOS 平台实䟋 +func NewDarwinPlatform() *DarwinPlatform { + home, _ := os.UserHomeDir() + return &DarwinPlatform{homeDir: home} +} + +func (p *DarwinPlatform) OS() string { return "darwin" } +func (p *DarwinPlatform) Arch() string { return "amd64" } // TODO: detect properly +func (p *DarwinPlatform) HomeDir() string { return p.homeDir } + +func (p *DarwinPlatform) ConfigDir() string { + return p.homeDir + "/Library/Application Support" +} + +func (p *DarwinPlatform) DataDir() string { + return p.homeDir + "/Library/Application Support" +} + +func (p *DarwinPlatform) GetEnvVar(key string) string { + return os.Getenv(key) +} + +func (p *DarwinPlatform) SetEnvVar(ctx context.Context, key, value string) error { + // On macOS, set via launchctl and shell profile + 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 + return nil +} + +func (p *DarwinPlatform) IsAdmin() bool { + return os.Geteuid() == 0 +} + +func (p *DarwinPlatform) PackageManagers() []string { + var pms []string + if _, err := exec.LookPath("brew"); err == nil { + pms = append(pms, "homebrew") + } + return pms +} + +func (p *DarwinPlatform) DefaultShell() string { + shell := os.Getenv("SHELL") + if shell != "" { + return shell + } + return "/bin/zsh" +} diff --git a/internal/platform/linux.go b/internal/platform/linux.go new file mode 100644 index 0000000..7c11381 --- /dev/null +++ b/internal/platform/linux.go @@ -0,0 +1,82 @@ +package platform + +import ( + "context" + "os" + "os/exec" +) + +// LinuxPlatform Linux 平台实现 +type LinuxPlatform struct { + homeDir string +} + +// NewLinuxPlatform 创建 Linux 平台实䟋 +func NewLinuxPlatform() *LinuxPlatform { + home, _ := os.UserHomeDir() + return &LinuxPlatform{homeDir: home} +} + +func (p *LinuxPlatform) OS() string { return "linux" } +func (p *LinuxPlatform) Arch() string { return "amd64" } // TODO: detect properly +func (p *LinuxPlatform) HomeDir() string { return p.homeDir } + +func (p *LinuxPlatform) ConfigDir() string { + if dir := os.Getenv("XDG_CONFIG_HOME"); dir != "" { + return dir + } + return p.homeDir + "/.config" +} + +func (p *LinuxPlatform) DataDir() string { + if dir := os.Getenv("XDG_DATA_HOME"); dir != "" { + return dir + } + return p.homeDir + "/.local/share" +} + +func (p *LinuxPlatform) GetEnvVar(key string) string { + return os.Getenv(key) +} + +func (p *LinuxPlatform) SetEnvVar(ctx context.Context, key, value string) error { + // TODO: Add to shell profile + return os.Setenv(key, value) +} + +func (p *LinuxPlatform) AddToPath(ctx context.Context, dir string) error { + // TODO: Add to shell profile + return nil +} + +func (p *LinuxPlatform) IsAdmin() bool { + return os.Geteuid() == 0 +} + +func (p *LinuxPlatform) PackageManagers() []string { + var pms []string + if _, err := exec.LookPath("apt"); err == nil { + pms = append(pms, "apt") + } + if _, err := exec.LookPath("dnf"); err == nil { + pms = append(pms, "dnf") + } + if _, err := exec.LookPath("yum"); err == nil { + pms = append(pms, "yum") + } + if _, err := exec.LookPath("pacman"); err == nil { + pms = append(pms, "pacman") + } + if _, err := exec.LookPath("snap"); err == nil { + pms = append(pms, "snap") + } + return pms +} + +func (p *LinuxPlatform) DefaultShell() string { + shell := os.Getenv("SHELL") + if shell != "" { + return shell + } + return "/bin/bash" +} diff --git a/internal/platform/platform.go b/internal/platform/platform.go new file mode 100644 index 0000000..1b73ada --- /dev/null +++ b/internal/platform/platform.go @@ -0,0 +1,57 @@ +package platform + +import ( + "context" + "runtime" +) + +// Platform 平台适配接口 +type Platform interface { + // OS 返回操䜜系统标识 + OS() string + + // Arch 返回架构标识 + Arch() string + + // HomeDir 返回甚户䞻目圕 + HomeDir() string + + // ConfigDir 返回配眮文件目圕 + ConfigDir() string + + // DataDir 返回数据目圕 + DataDir() string + + // GetEnvVar 获取环境变量 + GetEnvVar(key string) string + + // SetEnvVar 讟眮甚户级环境变量 + SetEnvVar(ctx context.Context, key, value string) error + + // AddToPath 添加目圕到 PATH + AddToPath(ctx context.Context, dir string) error + + // IsAdmin 是吊以管理员身仜运行 + IsAdmin() bool + + // PackageManagers 返回可甚的包管理噚名称 + PackageManagers() []string + + // DefaultShell 返回默讀 Shell + DefaultShell() string +} + +// Detect 检测圓前平台并返回对应的 Platform 实现 +func Detect() Platform { + switch runtime.GOOS { + case "windows": + return NewWindowsPlatform() + case "darwin": + return NewDarwinPlatform() + case "linux": + return NewLinuxPlatform() + default: + // Fallback to Linux + return NewLinuxPlatform() + } +} diff --git a/internal/platform/windows.go b/internal/platform/windows.go new file mode 100644 index 0000000..ccce1bd --- /dev/null +++ b/internal/platform/windows.go @@ -0,0 +1,83 @@ +package platform + +import ( + "context" + "os" + "os/exec" +) + +// WindowsPlatform Windows 平台实现 +type WindowsPlatform struct { + homeDir string +} + +// NewWindowsPlatform 创建 Windows 平台实䟋 +func NewWindowsPlatform() *WindowsPlatform { + return &WindowsPlatform{ + homeDir: os.Getenv("USERPROFILE"), + } +} + +func (p *WindowsPlatform) OS() string { return "windows" } +func (p *WindowsPlatform) Arch() string { return os.Getenv("PROCESSOR_ARCHITECTURE") } + +func (p *WindowsPlatform) HomeDir() string { + return p.homeDir +} + +func (p *WindowsPlatform) ConfigDir() string { + if dir := os.Getenv("APPDATA"); dir != "" { + return dir + } + return p.homeDir + "\\AppData\\Roaming" +} + +func (p *WindowsPlatform) DataDir() string { + if dir := os.Getenv("LOCALAPPDATA"); dir != "" { + return dir + } + return p.homeDir + "\\AppData\\Local" +} + +func (p *WindowsPlatform) GetEnvVar(key string) string { + return os.Getenv(key) +} + +func (p *WindowsPlatform) SetEnvVar(ctx context.Context, key, value string) error { + cmd := exec.CommandContext(ctx, "setx", key, value) + return cmd.Run() +} + +func (p *WindowsPlatform) AddToPath(ctx context.Context, dir string) error { + currentPath := os.Getenv("PATH") + newPath := dir + ";" + currentPath + return p.SetEnvVar(ctx, "PATH", newPath) +} + +func (p *WindowsPlatform) IsAdmin() bool { + // Check if running as administrator on Windows + cmd := exec.Command("net", "session") + err := cmd.Run() + return err == nil +} + +func (p *WindowsPlatform) PackageManagers() []string { + var pms []string + if _, err := exec.LookPath("scoop"); err == nil { + pms = append(pms, "scoop") + } + if _, err := exec.LookPath("choco"); err == nil { + pms = append(pms, "chocolatey") + } + if _, err := exec.LookPath("winget"); err == nil { + pms = append(pms, "winget") + } + return pms +} + +func (p *WindowsPlatform) DefaultShell() string { + if _, err := exec.LookPath("pwsh"); err == nil { + return "pwsh" // PowerShell 7+ + } + return "powershell" // Windows PowerShell 5.1 +} diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go new file mode 100644 index 0000000..af6e012 --- /dev/null +++ b/pkg/manifest/manifest.go @@ -0,0 +1,75 @@ +package manifest + +import ( + "encoding/json" + "fmt" + "time" +) + +// Manifest Pack 枅单 +type Manifest struct { + // 元信息 + Version string `json:"version"` // DevPack 版本 + FormatVer string `json:"format_ver"` // Pack 栌匏版本 + PackID string `json:"pack_id"` // 唯䞀 ID (UUID) + Name string `json:"name"` // Pack 名称 + Desc string `json:"description"` + Author string `json:"author"` + CreatedAt time.Time `json:"created_at"` + Tags []string `json:"tags,omitempty"` + + // 源环境信息 + Source SourceInfo `json:"source"` + + // 采集噚数据玢匕 + Collectors []CollectorEntry `json:"collectors"` + + // 加密信息 + Encryption *EncryptionInfo `json:"encryption,omitempty"` + + // 校验和 + Checksum string `json:"checksum"` +} + +// SourceInfo 源环境信息 +type SourceInfo struct { + Hostname string `json:"hostname"` + OS string `json:"os"` + OSVersion string `json:"os_version"` + Arch string `json:"arch"` + Username string `json:"username"` + DevPackVersion string `json:"devpack_version"` +} + +// CollectorEntry 采集噚条目 +type CollectorEntry struct { + Name string `json:"name"` + Category string `json:"category"` + Display string `json:"display_name"` + ItemCount int `json:"item_count"` + DataPath string `json:"data_path"` + DataSize int64 `json:"data_size"` + Checksum string `json:"checksum"` +} + +// EncryptionInfo 加密信息 +type EncryptionInfo struct { + Algorithm string `json:"algorithm"` + KDF string `json:"kdf"` + KDFParams map[string]int `json:"kdf_params"` + EncryptedCollectors []string `json:"encrypted_collectors"` +} + +// ToJSON 序列化䞺 JSON +func (m *Manifest) ToJSON() ([]byte, error) { + return json.MarshalIndent(m, "", " ") +} + +// FromJSON 从 JSON 反序列化 +func FromJSON(data []byte) (*Manifest, error) { + var m Manifest + if err := json.Unmarshal(data, &m); err != nil { + return nil, fmt.Errorf("parse manifest: %w", err) + } + return &m, nil +} diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 0000000..1151d0d --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,28 @@ +package version + +import ( + "fmt" + "runtime" +) + +// These variables are set at build time via ldflags. +var ( + Version = "dev" + Commit = "unknown" + Date = "unknown" +) + +// GetVersionString returns a short version string. +func GetVersionString() string { + return Version +} + +// GetFullVersionInfo returns complete version information. +func GetFullVersionInfo() string { + return fmt.Sprintf( + "DevPack %s\n Commit: %s\n Built: %s\n Go: %s\n OS/Arch: %s/%s", + Version, Commit, Date, + runtime.Version(), + runtime.GOOS, runtime.GOARCH, + ) +}