package packagemanager import ( "fmt" "log" "os" "strings" "system_setup_tool/internal/shell" ) type OSManager struct { OS *OS SudoPassword string } func NewOSManager(sudoPassword string) *OSManager { os, err := GetLinuxDistribution() if err != nil { log.Fatalf("error geting os information: %v", err) } return &OSManager{ OS: os, SudoPassword: sudoPassword, } } 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, packages) if err != nil { return err } return nil } 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) RemovePackage(pkg string) error { fullCmd := fmt.Sprintf("%s %s", o.OS.RemoveCommand, pkg) command := shell.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 := shell.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 } func (o *OSManager) UpdatePackage(pkg string) error { fullCmd := fmt.Sprintf("%s %s", o.OS.UpdateCommand, pkg) command := shell.ExecCommand("sudo", "-S", "sh", "-c", fullCmd) command.Stdin = strings.NewReader(o.SudoPassword + "\n") return command.Run() } func (o *OSManager) UpdateAllPackages() error { fullCmd := fmt.Sprintf("%s", o.OS.UpdateCommand) command := shell.ExecCommand("sudo", "-S", "sh", "-c", fullCmd) command.Stdin = strings.NewReader(o.SudoPassword + "\n") return command.Run() } type OS struct { ID string Name string Version string PackageManager string InstallCommand string SearchCommand string RemoveCommand string UpdateCommand string } func parseOsRelease(osRelease string) *OS { var result OS result.ID = "Unknown" result.Name = "Unknown" result.Version = "Unknown" result.PackageManager = "Unkown" result.InstallCommand = "Unkown" result.SearchCommand = "Unkown" result.RemoveCommand = "Unkown" result.UpdateCommand = "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) } err = result.getUpdateCommand() 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 := shell.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 (os *OS) getUpdateCommand() error { switch os.PackageManager { case "apt": os.UpdateCommand = "apt update" return nil case "pacman": os.UpdateCommand = "pacman -S" return nil case "dnf": os.UpdateCommand = "dnf update" 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("error installing Build Essentials: %v", err) } return nil }