gentleman-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWhen to Use
适用场景
Use this skill when:
- Adding support for new operating systems
- Modifying OS detection logic
- Working with command execution (sudo, brew, pkg)
- Adding new system checks
- Implementing backup/restore functionality
在以下场景中使用本技能:
- 添加新操作系统支持
- 修改操作系统检测逻辑
- 处理命令执行(sudo、brew、pkg)
- 添加新的系统检查项
- 实现备份/恢复功能
Critical Patterns
核心模式
Pattern 1: OSType Enum
模式1:OSType枚举类型
All OS types are defined in :
detect.gogo
type OSType int
const (
OSMac OSType = iota
OSLinux
OSArch
OSDebian // Debian-based (Debian, Ubuntu)
OSTermux // Termux on Android
OSUnknown
)所有操作系统类型均在中定义:
detect.gogo
type OSType int
const (
OSMac OSType = iota
OSLinux
OSArch
OSDebian // Debian-based (Debian, Ubuntu)
OSTermux // Termux on Android
OSUnknown
)Pattern 2: SystemInfo Structure
模式2:SystemInfo结构体
Detection results in struct:
SystemInfogo
type SystemInfo struct {
OS OSType
OSName string
IsWSL bool
IsARM bool
IsTermux bool
HomeDir string
HasBrew bool
HasPkg bool // Termux package manager
HasXcode bool
UserShell string
Prefix string // Termux $PREFIX or empty
}检测结果存储在结构体中:
SystemInfogo
type SystemInfo struct {
OS OSType
OSName string
IsWSL bool
IsARM bool
IsTermux bool
HomeDir string
HasBrew bool
HasPkg bool // Termux package manager
HasXcode bool
UserShell string
Prefix string // Termux $PREFIX or empty
}Pattern 3: OS Detection Priority
模式3:操作系统检测优先级
Termux is checked FIRST (runs on Linux but is special):
go
func Detect() *SystemInfo {
info := &SystemInfo{...}
// Check Termux FIRST
if isTermux() {
info.OS = OSTermux
info.IsTermux = true
info.HasPkg = checkPkg()
return info
}
// Then check standard OS
switch runtime.GOOS {
case "darwin":
info.OS = OSMac
case "linux":
if isArchLinux() {
info.OS = OSArch
} else if isDebian() {
info.OS = OSDebian
}
}
return info
}会优先检测Termux(它基于Linux但属于特殊场景):
go
func Detect() *SystemInfo {
info := &SystemInfo{...}
// Check Termux FIRST
if isTermux() {
info.OS = OSTermux
info.IsTermux = true
info.HasPkg = checkPkg()
return info
}
// Then check standard OS
switch runtime.GOOS {
case "darwin":
info.OS = OSMac
case "linux":
if isArchLinux() {
info.OS = OSArch
} else if isDebian() {
info.OS = OSDebian
}
}
return info
}Pattern 4: Command Execution Functions
模式4:命令执行函数
Use the right function for each context:
go
// Basic command (no sudo, no logs)
system.Run("git clone ...", nil)
// With real-time logs
system.RunWithLogs("git clone ...", nil, func(line string) {
SendLog(stepID, line)
})
// Homebrew commands
system.RunBrewWithLogs("install fish", nil, logFunc)
// Sudo commands (password prompt)
system.RunSudo("apt-get install -y git", nil)
system.RunSudoWithLogs("pacman -S git", nil, logFunc)
// Termux pkg commands (no sudo needed)
system.RunPkgInstall("fish git", nil, logFunc)
system.RunPkgWithLogs("update", nil, logFunc)根据上下文选择合适的函数:
go
// Basic command (no sudo, no logs)
system.Run("git clone ...", nil)
// With real-time logs
system.RunWithLogs("git clone ...", nil, func(line string) {
SendLog(stepID, line)
})
// Homebrew commands
system.RunBrewWithLogs("install fish", nil, logFunc)
// Sudo commands (password prompt)
system.RunSudo("apt-get install -y git", nil)
system.RunSudoWithLogs("pacman -S git", nil, logFunc)
// Termux pkg commands (no sudo needed)
system.RunPkgInstall("fish git", nil, logFunc)
system.RunPkgWithLogs("update", nil, logFunc)Decision Tree
决策树
Adding new OS support?
├── Add OSType constant in detect.go
├── Add detection function (isNewOS())
├── Update Detect() with priority order
├── Update SystemInfo if new fields needed
└── Add OS case in installer.go steps
Running a command?
├── Needs sudo? → RunSudo() or RunSudoWithLogs()
├── Needs brew? → RunBrewWithLogs()
├── On Termux? → RunPkgInstall() or RunPkgWithLogs()
├── Needs logs? → RunWithLogs()
└── Simple exec? → Run()
Checking if tool exists?
├── Use CommandExists("toolname")
└── Returns bool添加新操作系统支持?
├── 在detect.go中添加OSType常量
├── 添加检测函数(isNewOS())
├── 按优先级顺序更新Detect()函数
├── 若需新增字段则更新SystemInfo结构体
└── 在installer.go步骤中添加对应操作系统分支
执行命令?
├── 需要sudo?→ 使用RunSudo()或RunSudoWithLogs()
├── 需要brew?→ 使用RunBrewWithLogs()
├── 运行在Termux?→ 使用RunPkgInstall()或RunPkgWithLogs()
├── 需要日志?→ 使用RunWithLogs()
└── 简单执行?→ 使用Run()
检查工具是否存在?
├── 调用CommandExists("toolname")
└── 返回布尔值Code Examples
代码示例
Example 1: Termux Detection
示例1:Termux检测
go
func isTermux() bool {
// Check TERMUX_VERSION environment variable
if os.Getenv("TERMUX_VERSION") != "" {
return true
}
// Check PREFIX contains termux path
prefix := os.Getenv("PREFIX")
if strings.Contains(prefix, "com.termux") {
return true
}
// Check for Termux-specific paths
if _, err := os.Stat("/data/data/com.termux"); err == nil {
return true
}
return false
}go
func isTermux() bool {
// Check TERMUX_VERSION environment variable
if os.Getenv("TERMUX_VERSION") != "" {
return true
}
// Check PREFIX contains termux path
prefix := os.Getenv("PREFIX")
if strings.Contains(prefix, "com.termux") {
return true
}
// Check for Termux-specific paths
if _, err := os.Stat("/data/data/com.termux"); err == nil {
return true
}
return false
}Example 2: Platform-Specific Execution
示例2:平台特定执行逻辑
go
func installTool(m *Model) error {
var result *system.ExecResult
switch {
case m.SystemInfo.IsTermux:
// Termux: use pkg (no sudo)
result = system.RunPkgInstall("tool", nil, logFunc)
case m.SystemInfo.OS == system.OSArch:
// Arch: use pacman with sudo
result = system.RunSudoWithLogs("pacman -S --noconfirm tool", nil, logFunc)
case m.SystemInfo.OS == system.OSMac:
// macOS: use Homebrew
result = system.RunBrewWithLogs("install tool", nil, logFunc)
case m.SystemInfo.OS == system.OSDebian:
// Debian/Ubuntu: use Homebrew (installed by us)
result = system.RunBrewWithLogs("install tool", nil, logFunc)
default:
return fmt.Errorf("unsupported OS: %v", m.SystemInfo.OS)
}
return result.Error
}go
func installTool(m *Model) error {
var result *system.ExecResult
switch {
case m.SystemInfo.IsTermux:
// Termux: use pkg (no sudo)
result = system.RunPkgInstall("tool", nil, logFunc)
case m.SystemInfo.OS == system.OSArch:
// Arch: use pacman with sudo
result = system.RunSudoWithLogs("pacman -S --noconfirm tool", nil, logFunc)
case m.SystemInfo.OS == system.OSMac:
// macOS: use Homebrew
result = system.RunBrewWithLogs("install tool", nil, logFunc)
case m.SystemInfo.OS == system.OSDebian:
// Debian/Ubuntu: use Homebrew (installed by us)
result = system.RunBrewWithLogs("install tool", nil, logFunc)
default:
return fmt.Errorf("unsupported OS: %v", m.SystemInfo.OS)
}
return result.Error
}Example 3: Homebrew Prefix Detection
示例3:Homebrew路径检测
go
func GetBrewPrefix() string {
if runtime.GOOS == "darwin" {
// Apple Silicon uses /opt/homebrew
// Intel uses /usr/local
if runtime.GOARCH == "arm64" {
return "/opt/homebrew"
}
return "/usr/local"
}
return "/home/linuxbrew/.linuxbrew"
}go
func GetBrewPrefix() string {
if runtime.GOOS == "darwin" {
// Apple Silicon uses /opt/homebrew
// Intel uses /usr/local
if runtime.GOARCH == "arm64" {
return "/opt/homebrew"
}
return "/usr/local"
}
return "/home/linuxbrew/.linuxbrew"
}Example 4: File Operations
示例4:文件操作
go
// Ensure directory exists
if err := system.EnsureDir(filepath.Join(homeDir, ".config/tool")); err != nil {
return err
}
// Copy single file
if err := system.CopyFile(src, dst); err != nil {
return err
}
// Copy directory contents
if err := system.CopyDir("Gentleman.Dots/Config/*", destDir+"/"); err != nil {
return err
}go
// Ensure directory exists
if err := system.EnsureDir(filepath.Join(homeDir, ".config/tool")); err != nil {
return err
}
// Copy single file
if err := system.CopyFile(src, dst); err != nil {
return err
}
// Copy directory contents
if err := system.CopyDir("Gentleman.Dots/Config/*", destDir+"/"); err != nil {
return err
}ExecResult Structure
ExecResult结构体
go
type ExecResult struct {
Output string // stdout
Stderr string // stderr
ExitCode int // exit code
Error error // error if any
}
// Usage
result := system.Run("command", nil)
if result.Error != nil {
// Handle error
}
if result.ExitCode != 0 {
// Non-zero exit
}go
type ExecResult struct {
Output string // stdout
Stderr string // stderr
ExitCode int // exit code
Error error // error if any
}
// Usage
result := system.Run("command", nil)
if result.Error != nil {
// Handle error
}
if result.ExitCode != 0 {
// Non-zero exit
}Commands
命令
bash
cd installer && go test ./internal/system/... # Run system tests
cd installer && go test -run TestDetect # Test OS detection
cd installer && go test -run TestExec # Test command executionbash
cd installer && go test ./internal/system/... # 运行系统测试
cd installer && go test -run TestDetect # 测试操作系统检测
cd installer && go test -run TestExec # 测试命令执行Resources
资源参考
- Detection: See for OS detection
installer/internal/system/detect.go - Execution: See for command running
installer/internal/system/exec.go - Backup: See for backup/restore
installer/internal/system/backup.go - Tests: See for patterns
installer/internal/system/*_test.go
- 检测模块: 查看了解操作系统检测逻辑
installer/internal/system/detect.go - 执行模块: 查看了解命令运行逻辑
installer/internal/system/exec.go - 备份模块: 查看了解备份/恢复逻辑
installer/internal/system/backup.go - 测试用例: 查看了解实现模式
installer/internal/system/*_test.go