Skip to content

📦 安装器 Installer

当系统里没有 Composer(甚至没有 PHP)时,自动把它们装好——这就是 pkg/installer 的职责。

包路径:github.com/scagogogo/composer-skills/pkg/installer

installer 包提供三层抽象:

层次入口适合场景
🧱 基础安装器Installer / NewInstaller / DefaultInstaller只想装/卸/查版本,不关心进度
⚙️ 配置驱动Config / DefaultConfig / SmartConfig自定义路径、sudo、PHP 自动装、目标版本
🚀 智能安装器SmartInstaller / EnsureComposerInstalled需要进度回调、重试、取消、自动诊断

底层还有平台分发(PlatformInstaller、Linux/macOS/Windows/Unix 各自的安装策略)、Linux 发行版检测与 PHP 安装(distro.go)、以及一组工具函数(utils.go)。

🏗️ 三层抽象与平台分发

核心能力清单

📦

自动安装 Composer

调用 getcomposer.org 安装脚本或系统包管理器把 Composer 装到目标目录。

🐘

自动装 PHP

AutoInstallPHP=true 时,缺 PHP 会先用 apt/dnf/pacman/apk 等装好 PHP 再装 Composer。

💻

跨平台分发

GetPlatformInstaller 按 GOOS 路由到 Linux/MacOS/Windows/Unix 安装器。

🚀

智能安装

SmartInstaller 提供进度回调、自动重试、上下文取消、安装后验证。

🐧

发行版感知

DetectLinuxDistro 识别 ubuntu/centos/arch/alpine 等,匹配正确的包管理器。

🔧

工具函数

GetPlatformName/GetArchName/CanUseSudo/ValidateInstallPath 辅助诊断与校验。

Installer 类型

基础安装器,持有一份 Config

go
type Installer struct {
    config Config
}

构造与配置

go
func NewInstaller(config Config) *Installer   // 用指定配置创建
func DefaultInstaller() *Installer            // 用 DefaultConfig() 创建

func (i *Installer) GetConfig() Config        // 读取当前配置
func (i *Installer) SetConfig(config Config)  // 运行时替换配置

安装与卸载

go
func (i *Installer) Install() error                              // 按配置安装(含 PHP 检查、包管理器优先、平台分发)
func (i *Installer) InstallVersion(version string) error         // 安装指定版本,如 "1"/"2"/"2.5.1"/"latest"/"preview"
func (i *Installer) Uninstall() error                            // 定位并卸载 Composer
func (i *Installer) IsInstalled() bool                           // 是否已安装(PATH + 常见路径)
func (i *Installer) GetInstalledVersion() (string, error)        // 已安装版本的 --version 输出

Install() 的内部流程:

  1. 检查 PHPHasPHP() 为否时,若 AutoInstallPHP=true 则尝试 InstallPHP,否则直接返回 ErrPHPNotFound
  2. Linux 包管理器优先:在 Linux 上若 PreferPackageManager=true,先尝试 InstallComposerViaPackageManager,成功并通过 composer --version 验证即返回。
  3. 平台分发:调用 GetPlatformInstaller(i.config) 拿到对应平台的 PlatformInstaller,执行其 Install()

常见错误

错误变量含义
ErrInstallationFailed安装过程失败(脚本执行错误等)
ErrInsufficientRights权限不足,需 sudo / 管理员
ErrUnsupportedPlatform不支持的操作系统平台
ErrDownloadFailed下载失败
ErrPHPNotFound未找到 PHP 且未能自动安装
ErrComposerAlreadyInstalledComposer 已安装
ErrComposerNotFound卸载/查版本时找不到 composer 二进制

快速示例

最省心:智能确保已安装

go
package main

import (
    "fmt"
    "log"

    "github.com/scagogogo/composer-skills/pkg/installer"
)

func main() {
    // 已装则直接返回;未装则按 SmartConfig 自动安装
    result, err := installer.EnsureComposerInstalled(nil)
    if err != nil {
        log.Fatalf("安装失败: %v", err)
    }
    fmt.Printf("Composer 已就绪: %s (版本 %s)\n", result.ComposerPath, result.Version)
}

指定配置安装

go
package main

import (
    "log"

    "github.com/scagogogo/composer-skills/pkg/installer"
)

func main() {
    cfg := installer.DefaultConfig()
    cfg.InstallPath = "/usr/local/bin"
    cfg.UseSudo = true
    cfg.AutoInstallPHP = true

    inst := installer.NewInstaller(cfg)
    if err := inst.Install(); err != nil {
        log.Fatalf("安装失败: %v", err)
    }
}

安装指定版本并查版本

go
package main

import (
    "fmt"
    "log"

    "github.com/scagogogo/composer-skills/pkg/installer"
)

func main() {
    inst := installer.DefaultInstaller()

    if err := inst.InstallVersion("2.5.1"); err != nil {
        log.Fatalf("安装失败: %v", err)
    }

    ver, err := inst.GetInstalledVersion()
    if err != nil {
        log.Fatalf("查询版本失败: %v", err)
    }
    fmt.Println("已安装版本:", ver)
}

子文档

文档内容
⚙️ 配置 ConfigConfig 字段、DefaultConfig vs SmartConfig 对比、安装路径/sudo/PHP 自动装
💻 平台安装器PlatformInstaller 接口、GetPlatformInstaller、各平台 Install 策略
🚀 智能安装器SmartInstaller、进度回调、重试、取消、EnsureComposerInstalled
🐧 发行版与 PHPDetectLinuxDistroDistroInfo、PHP 检测/安装、Composer 版本管理
🔧 工具函数GetPlatformName / GetArchName / CanUseSudo / ValidateInstallPath

进阶

  • 与 Detector 配合:安装前可用 pkg/detector 探测,已装则跳过;安装后再探测验证。
  • 与 Composer 配合:安装成功后用拿到的路径初始化 composer.New(composer.Options{ExecutablePath: ...})
  • 进度可视化:CLI / TUI 场景把 ProgressCallback 接到进度条上,见 智能安装器
  • CI 环境:CI 容器通常已是 root,UseSudo=false 即可;SmartConfig 在 Linux 默认 UseSudo=true,容器里可按需覆盖。

基于 MIT 许可证发布