264 lines
5.7 KiB
Go
264 lines
5.7 KiB
Go
package packagemanager
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"system_setup_tool/internal/shell"
|
|
)
|
|
|
|
type OSManager struct {
|
|
OS *OS
|
|
SudoPassword string
|
|
pm PackageManager
|
|
}
|
|
|
|
func NewOSManager(sudoPassword string) *OSManager {
|
|
switch runtime.GOOS {
|
|
case "linux":
|
|
os, err := GetLinuxDistribution()
|
|
if err != nil {
|
|
log.Fatalf("error getting os information: %v", err)
|
|
}
|
|
var pm PackageManager
|
|
switch os.ID {
|
|
case "debian", "ubuntu":
|
|
pm = &AptManager{SudoPassword: sudoPassword}
|
|
case "arch":
|
|
pm = &PacmanManager{SudoPassword: sudoPassword}
|
|
case "fedora":
|
|
pm = &DnfManager{SudoPassword: sudoPassword}
|
|
default:
|
|
log.Fatalf("Unsupported Linux distribution: %s", os.ID)
|
|
}
|
|
return &OSManager{
|
|
OS: os,
|
|
SudoPassword: sudoPassword,
|
|
pm: pm,
|
|
}
|
|
case "windows":
|
|
os, err := getPlatformInfo()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
if _, err := shell.ExecLookPath("winget"); err == nil {
|
|
return &OSManager{
|
|
OS: os,
|
|
SudoPassword: "",
|
|
pm: &WingetManager{},
|
|
}
|
|
} else if _, err := shell.ExecLookPath("choco"); err == nil {
|
|
return &OSManager{
|
|
OS: os,
|
|
SudoPassword: "",
|
|
pm: &ChocoManager{},
|
|
}
|
|
} else {
|
|
log.Println("Neither Winget nor Chocolatey found on Windows. Package management functionality will be limited.")
|
|
}
|
|
case "darwin":
|
|
os, err := platformInfoMac()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
_, err = shell.ExecLookPath("brew")
|
|
if err == nil {
|
|
return &OSManager{
|
|
OS: os,
|
|
SudoPassword: sudoPassword,
|
|
pm: &HomebrewManager{},
|
|
}
|
|
} else {
|
|
manager := &HomebrewManager{}
|
|
manager.InstallManager()
|
|
return &OSManager{
|
|
OS: os,
|
|
SudoPassword: sudoPassword,
|
|
pm: manager,
|
|
}
|
|
}
|
|
default:
|
|
log.Fatal("Operating system not supported")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *OSManager) Name() string {
|
|
return "OS Package Manager"
|
|
}
|
|
|
|
func (o *OSManager) InstallManager() error { return nil }
|
|
|
|
func (o *OSManager) Install(packages []string) error {
|
|
if len(packages) == 0 {
|
|
return nil
|
|
}
|
|
err := InstallWithProgress(o.pm, packages)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *OSManager) InstallPackage(pkg string) error {
|
|
return o.pm.InstallPackage(pkg) //(o.OS.InstallCommand, pkg, o.SudoPassword)
|
|
}
|
|
|
|
func (o *OSManager) InstallBuildEssentials() error {
|
|
return InstallBuildEssentials(o.OS, o.SudoPassword)
|
|
}
|
|
|
|
func (o *OSManager) RemovePackage(pkg string) error {
|
|
return o.pm.RemovePackage(pkg)
|
|
}
|
|
|
|
func (o *OSManager) SearchPackage(pkg string) []string {
|
|
return o.pm.SearchPackage(pkg)
|
|
}
|
|
|
|
func (o *OSManager) UpdatePackage(pkg string) error {
|
|
return o.pm.UpdatePackage(pkg)
|
|
}
|
|
|
|
func (o *OSManager) UpdateAllPackages() error {
|
|
return o.pm.UpdateAllPackages()
|
|
}
|
|
|
|
type OS struct {
|
|
ID string
|
|
Name string
|
|
Version string
|
|
PackageManager string
|
|
}
|
|
|
|
func parseOsRelease(osRelease string) *OS {
|
|
var result OS
|
|
result.ID = "Unknown"
|
|
result.Name = "Unknown"
|
|
result.Version = "Unknown"
|
|
|
|
lines := strings.Split(osRelease, "\n")
|
|
|
|
for _, line := range lines {
|
|
splitLine := strings.SplitN(line, "=", 2)
|
|
if len(splitLine) != 2 {
|
|
continue
|
|
}
|
|
switch splitLine[0] {
|
|
case "ID":
|
|
result.ID = strings.ToLower(strings.Trim(splitLine[1], "\""))
|
|
case "NAME":
|
|
result.Name = strings.Trim(splitLine[1], "\"")
|
|
case "VERSION_ID":
|
|
result.Version = strings.Trim(splitLine[1], "\"")
|
|
}
|
|
}
|
|
err := result.getPackageManager()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return &result
|
|
}
|
|
|
|
func GetLinuxDistribution() (*OS, error) {
|
|
_, err := os.Stat("/etc/os-release")
|
|
if os.IsNotExist(err) {
|
|
return nil, fmt.Errorf("unable to read system information")
|
|
}
|
|
|
|
osRelease, _ := os.ReadFile("/etc/os-release")
|
|
return parseOsRelease(string(osRelease)), nil
|
|
}
|
|
|
|
func InstallBuildEssentials(os *OS, sudoPassword string) error {
|
|
var command string
|
|
switch os.PackageManager {
|
|
case "pacman":
|
|
command = "pacman -S --noconfirm --needed base-devel"
|
|
case "apt":
|
|
command = "apt install -y build-essential"
|
|
case "dnf":
|
|
command = "dnf install -y @development-tools"
|
|
default:
|
|
return fmt.Errorf("keine Build Essentials für OS %s definiert", os.ID)
|
|
}
|
|
|
|
fmt.Printf("Installiere Build Essentials für %s...\n", os.Name)
|
|
if err := InstallPackage(command, "", sudoPassword); err != nil {
|
|
return fmt.Errorf("error installing Build Essentials: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getSysctlValue(key string) (string, error) {
|
|
stdout, err := shell.ExecCommand(".", "sysctl", key).Output()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
version := strings.TrimPrefix(string(stdout), key+": ")
|
|
return strings.TrimSpace(version), nil
|
|
}
|
|
|
|
func platformInfoMac() (*OS, error) {
|
|
var result OS
|
|
result.ID = "Unknown"
|
|
result.Name = "MacOS"
|
|
result.Version = "Unknown"
|
|
|
|
version, err := getSysctlValue("kern.osproductversion")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result.Version = version
|
|
ID, err := getSysctlValue("kern.osversion")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result.ID = ID
|
|
|
|
return &result, nil
|
|
}
|
|
|
|
func getPlatformInfo() (*OS, error) {
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
return platformInfoWin()
|
|
case "darwin":
|
|
return platformInfoMac()
|
|
case "linux":
|
|
return GetLinuxDistribution()
|
|
default:
|
|
return nil, fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
|
|
}
|
|
}
|
|
|
|
func (os *OS) getPackageManager() error {
|
|
switch os.ID {
|
|
case "debian", "ubuntu":
|
|
os.PackageManager = "apt"
|
|
return nil
|
|
case "arch":
|
|
os.PackageManager = "pacman"
|
|
return nil
|
|
case "fedora":
|
|
os.PackageManager = "dnf"
|
|
return nil
|
|
default:
|
|
pmcommands := []string{
|
|
"apt",
|
|
"dnf",
|
|
"pacman",
|
|
}
|
|
for _, pmname := range pmcommands {
|
|
_, err := shell.ExecLookPath(pmname)
|
|
if err == nil {
|
|
os.PackageManager = pmname
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("no packagemanager found fos os: %s", os.Name)
|
|
}
|
|
}
|