system_setup_tool/osinfo.go

234 lines
5.3 KiB
Go

package main
import (
"fmt"
"log"
"os"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
type OSManager struct {
OS *OS
SudoPassword string
Packages []string
Model model
}
func NewOSManager(os *OS, sudoPassword string, packages []string) *OSManager {
return &OSManager{
OS: os,
SudoPassword: sudoPassword,
Packages: packages,
Model: newModel(packages, sudoPassword, os),
}
}
func (o *OSManager) Name() string {
return "OS Package Manager"
}
func (o *OSManager) InstallManager() error { return nil }
func (o *OSManager) Install(packages []string) error {
o.Packages = packages
o.Model = newModel(packages, o.SudoPassword, o.OS)
p := tea.NewProgram(o.Model)
_, err := p.Run()
return err
}
func (o *OSManager) InstallPackage(pkg string) error {
return installPackage(o.OS.InstallCommand, pkg, o.SudoPassword)
}
func (o *OSManager) InstallBuildEssentials() error {
return installBuildEssentials(o.OS, o.SudoPassword)
}
func (o *OSManager) InstallSpecialSoftware() error {
return o.Model.installSpecialSoftware()
}
func (o *OSManager) RemovePackage(pkg string) error {
fullCmd := fmt.Sprintf("%s %s", o.OS.RemoveCommand, pkg)
command := execCommand("sudo", "-S", "sh", "-c", fullCmd)
command.Stdin = strings.NewReader(o.SudoPassword + "\n")
return command.Run()
}
func (o *OSManager) SearchPackage(pkg string) []string {
cmdParts := strings.Fields(o.OS.SearchCommand)
if len(cmdParts) == 0 {
log.Printf("Invalid search command for OS package manager")
return []string{}
}
cmd := execCommand(cmdParts[0], append(cmdParts[1:], pkg)...)
packages, err := cmd.Output()
if err != nil {
log.Printf("Error fetching %s packages: %v", o.OS.PackageManager, err)
return []string{}
}
packageList := strings.Split(strings.TrimSpace(string(packages)), "\n")
return packageList
}
type OS struct {
ID string
Name string
Version string
PackageManager string
InstallCommand string
SearchCommand string
RemoveCommand string
}
func parseOsRelease(osRelease string) *OS {
var result OS
result.ID = "Unknown"
result.Name = "Unknown"
result.Version = "Unknown"
result.PackageManager = "Unkown"
result.InstallCommand = "Unkown"
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)
}
err = result.getInstallCommand()
if err != nil {
log.Fatal(err)
}
err = result.getSearchCommand()
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 (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 := execLookPath(pmname)
if err == nil {
os.PackageManager = pmname
return nil
}
}
return fmt.Errorf("no packagemanager found for os: %s", os)
}
}
func (os *OS) getInstallCommand() error {
switch os.PackageManager {
case "apt":
os.InstallCommand = "apt install -y"
return nil
case "pacman":
os.InstallCommand = "pacman -S --noconfirm --needed"
return nil
case "dnf":
os.InstallCommand = "dnf install -y --best"
return nil
default:
return fmt.Errorf("no install command found for package manager: %s", os.ID)
}
}
func (os *OS) getSearchCommand() error {
switch os.PackageManager {
case "apt":
os.SearchCommand = "apt search"
return nil
case "pacman":
os.SearchCommand = "pacman -Ss"
return nil
case "dnf":
os.SearchCommand = "dnf search"
return nil
default:
return fmt.Errorf("no install command found for package manager: %s", os.ID)
}
}
func (os *OS) getDeleteCommand() error {
switch os.PackageManager {
case "apt":
os.RemoveCommand = "apt remove"
return nil
case "pacman":
os.RemoveCommand = "pacman -R"
return nil
case "dnf":
os.RemoveCommand = "dnf remove"
return nil
default:
return fmt.Errorf("no install command found for package manager: %s", os.ID)
}
}
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("fehler bei der Installation der Build Essentials: %v", err)
}
return nil
}