package pkg_manager import ( "fmt" "os" "os/exec" "strings" ) // PackageManager interface defines common operations type PackageManager interface { Install(packages ...string) error Remove(packages ...string) error Search(term string) error Update() error Upgrade() error ListInstalled() error ShowInfo(pkg string) error AddRepository(repo string) error RemoveRepository(repo string) error ListRepositories() error CleanCache() error AutoRemove() error CheckDependencies(pkg string) error ShowDependencies(pkg string) error } // Manager represents a concrete package manager type Manager struct { command string installCmd []string removeCmd []string searchCmd []string updateCmd []string upgradeCmd []string listCmd []string infoCmd []string addRepoCmd []string removeRepoCmd []string listRepoCmd []string cleanCacheCmd []string autoRemoveCmd []string checkDependsCmd []string showDependsCmd []string needsSudo bool versionSep string cacheDir string } // UniversalManager represents universal package managers like snap/flatpak type UniversalManager struct { Manager isAvailable bool } // PackageVersion represents a package with optional version type PackageVersion struct { Name string Version string } var universalManagers = map[string]*UniversalManager{ "snap": { Manager: Manager{ command: "snap", installCmd: []string{"install"}, removeCmd: []string{"remove"}, searchCmd: []string{"find"}, updateCmd: []string{"refresh"}, upgradeCmd: []string{"refresh"}, needsSudo: true, }, }, "flatpak": { Manager: Manager{ command: "flatpak", installCmd: []string{"install", "-y"}, removeCmd: []string{"uninstall", "-y"}, searchCmd: []string{"search"}, updateCmd: []string{"update", "-y"}, upgradeCmd: []string{"update", "-y"}, needsSudo: false, }, }, } var managers = map[string]Manager{ "apt": { command: "apt", installCmd: []string{"install", "-y"}, removeCmd: []string{"remove", "-y"}, searchCmd: []string{"search"}, updateCmd: []string{"update"}, upgradeCmd: []string{"upgrade", "-y"}, listCmd: []string{"list", "--installed"}, infoCmd: []string{"show"}, addRepoCmd: []string{"add-apt-repository", "-y"}, removeRepoCmd: []string{"add-apt-repository", "-r", "-y"}, listRepoCmd: []string{"sources"}, cleanCacheCmd: []string{"clean"}, autoRemoveCmd: []string{"autoremove", "-y"}, checkDependsCmd: []string{"check"}, showDependsCmd: []string{"depends"}, needsSudo: true, versionSep: "=", cacheDir: "/var/cache/apt", }, "dnf": { command: "dnf", installCmd: []string{"install", "-y"}, removeCmd: []string{"remove", "-y"}, searchCmd: []string{"search"}, updateCmd: []string{"check-update"}, upgradeCmd: []string{"upgrade", "-y"}, listCmd: []string{"list", "installed"}, infoCmd: []string{"info"}, addRepoCmd: []string{"config-manager", "--add-repo"}, removeRepoCmd: []string{"config-manager", "--disable"}, listRepoCmd: []string{"repolist"}, cleanCacheCmd: []string{"clean", "all"}, autoRemoveCmd: []string{"autoremove", "-y"}, checkDependsCmd: []string{"check-dependencies"}, showDependsCmd: []string{"repoquery", "--requires"}, needsSudo: true, versionSep: "-", cacheDir: "/var/cache/dnf", }, "yum": { command: "yum", installCmd: []string{"install", "-y"}, removeCmd: []string{"remove", "-y"}, searchCmd: []string{"search"}, updateCmd: []string{"check-update"}, upgradeCmd: []string{"upgrade", "-y"}, needsSudo: true, versionSep: "-", cacheDir: "/var/cache/yum", }, "pacman": { command: "pacman", installCmd: []string{"-S", "--noconfirm"}, removeCmd: []string{"-R", "--noconfirm"}, searchCmd: []string{"-Ss"}, updateCmd: []string{"-Sy"}, upgradeCmd: []string{"-Syu", "--noconfirm"}, needsSudo: true, versionSep: "=", cacheDir: "/var/cache/pacman", }, "zypper": { command: "zypper", installCmd: []string{"install", "-y"}, removeCmd: []string{"remove", "-y"}, searchCmd: []string{"search"}, updateCmd: []string{"refresh"}, upgradeCmd: []string{"update", "-y"}, needsSudo: true, versionSep: "=", cacheDir: "/var/cache/zypp", }, "apk": { command: "apk", installCmd: []string{"add"}, removeCmd: []string{"del"}, searchCmd: []string{"search"}, updateCmd: []string{"update"}, upgradeCmd: []string{"upgrade"}, needsSudo: true, versionSep: "=", cacheDir: "/var/cache/apk", }, "xbps": { command: "xbps-install", installCmd: []string{"-y"}, removeCmd: []string{"-R"}, searchCmd: []string{"-Rs"}, updateCmd: []string{"-S"}, upgradeCmd: []string{"-Su"}, listCmd: []string{"-l"}, infoCmd: []string{"-S"}, addRepoCmd: []string{"-R", "add"}, removeRepoCmd: []string{"-R", "remove"}, listRepoCmd: []string{"-R", "list"}, cleanCacheCmd: []string{"-Op"}, autoRemoveCmd: []string{"-Oo"}, checkDependsCmd: []string{"-C"}, showDependsCmd: []string{"-x"}, needsSudo: true, versionSep: "-", cacheDir: "/var/cache/xbps", }, "emerge": { command: "emerge", installCmd: []string{"--ask", "n"}, removeCmd: []string{"--unmerge", "--ask", "n"}, searchCmd: []string{"--search"}, updateCmd: []string{"--sync"}, upgradeCmd: []string{"--update", "--deep", "--ask", "n", "@world"}, listCmd: []string{"--list-sets"}, infoCmd: []string{"--info"}, addRepoCmd: []string{"--repos-conf", "add"}, removeRepoCmd: []string{"--repos-conf", "remove"}, listRepoCmd: []string{"--repos-conf", "list"}, cleanCacheCmd: []string{"--depclean"}, autoRemoveCmd: []string{"--depclean"}, checkDependsCmd: []string{"--depclean", "-p"}, showDependsCmd: []string{"--deps"}, needsSudo: true, versionSep: "-", cacheDir: "/var/cache/portage", }, } // ParsePackageVersion parses package name and version func ParsePackageVersion(pkg string) PackageVersion { parts := strings.Split(pkg, "@") if len(parts) == 2 { return PackageVersion{ Name: parts[0], Version: parts[1], } } return PackageVersion{Name: pkg} } // formatPackageWithVersion formats package with version using manager's separator func (m *Manager) formatPackageWithVersion(pv PackageVersion) string { if pv.Version == "" { return pv.Name } return fmt.Sprintf("%s%s%s", pv.Name, m.versionSep, pv.Version) } // Install packages with version support func (m *Manager) Install(packages ...string) error { if len(packages) == 0 { return fmt.Errorf("no packages specified") } formattedPkgs := make([]string, len(packages)) for i, pkg := range packages { pv := ParsePackageVersion(pkg) formattedPkgs[i] = m.formatPackageWithVersion(pv) } return m.execCommand(m.installCmd, formattedPkgs...) } // InitializeUniversalManagers checks which universal package managers are available func InitializeUniversalManagers() { for _, mgr := range universalManagers { _, err := exec.LookPath(mgr.command) mgr.isAvailable = err == nil } } // GetUniversalManager returns a universal package manager if available func GetUniversalManager(name string) (*UniversalManager, bool) { if mgr, exists := universalManagers[name]; exists && mgr.isAvailable { return mgr, true } return nil, false } type OutputMode int const ( OutputQuiet OutputMode = iota OutputVerbose ) var outputMode = OutputQuiet // SetOutputMode sets the output verbosity func SetOutputMode(mode OutputMode) { outputMode = mode } func (m *Manager) execCommand(baseCmd []string, args ...string) error { cmdArgs := append(baseCmd, args...) var cmd *exec.Cmd if m.needsSudo && os.Geteuid() != 0 { // Clear the line to prevent spinner interference with sudo prompt fmt.Print("\r\033[K") cmdArgs = append([]string{m.command}, cmdArgs...) cmd = exec.Command("sudo", cmdArgs...) } else { cmd = exec.Command(m.command, cmdArgs...) } // Always capture output if outputMode == OutputVerbose { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr } else { // Capture but don't display output in quiet mode cmd.Stdout = nil cmd.Stderr = nil } cmd.Stdin = os.Stdin return cmd.Run() } // Remove packages func (m *Manager) Remove(packages ...string) error { if len(packages) == 0 { return fmt.Errorf("no packages specified") } return m.execCommand(m.removeCmd, packages...) } // Search for packages func (m *Manager) Search(term string) error { if term == "" { return fmt.Errorf("no search term specified") } return m.execCommand(m.searchCmd, term) } // Update package lists func (m *Manager) Update() error { return m.execCommand(m.updateCmd) } // Upgrade installed packages func (m *Manager) Upgrade() error { return m.execCommand(m.upgradeCmd) } // ListInstalled lists all installed packages func (m *Manager) ListInstalled() error { return m.execCommand(m.listCmd) } // ShowInfo shows detailed information about a package func (m *Manager) ShowInfo(pkg string) error { return m.execCommand(m.infoCmd, pkg) } // AddRepository adds a new repository func (m *Manager) AddRepository(repo string) error { return m.execCommand(m.addRepoCmd, repo) } // RemoveRepository removes a repository func (m *Manager) RemoveRepository(repo string) error { return m.execCommand(m.removeRepoCmd, repo) } // ListRepositories lists all configured repositories func (m *Manager) ListRepositories() error { return m.execCommand(m.listRepoCmd) } // CleanCache cleans the package manager cache func (m *Manager) CleanCache() error { return m.execCommand(m.cleanCacheCmd) } // AutoRemove removes unused dependencies func (m *Manager) AutoRemove() error { return m.execCommand(m.autoRemoveCmd) } // CheckDependencies checks for dependency issues func (m *Manager) CheckDependencies(pkg string) error { if pkg == "" { return m.execCommand(m.checkDependsCmd) } return m.execCommand(m.checkDependsCmd, pkg) } // ShowDependencies shows dependencies for a package func (m *Manager) ShowDependencies(pkg string) error { return m.execCommand(m.showDependsCmd, pkg) } // DetectPackageManager identifies the system's package manager func DetectPackageManager() (*Manager, error) { for _, mgr := range managers { if _, err := exec.LookPath(mgr.command); err == nil { return &mgr, nil } } return nil, fmt.Errorf("no supported package manager found") }