package installer import ( "fmt" "strings" "gitgud.io/mike/mpv-manager/pkg/constants" ) // PackageManager handles package manager operations type PackageManager struct { family string cmd string } // NewPackageManager creates a new package manager instance func NewPackageManager(family string) *PackageManager { var cmd string switch family { case constants.PMFamilyDebian: cmd = constants.CommandApt case constants.PMFamilyRHEL: cmd = constants.CommandDnf case constants.PMFamilyArch: cmd = constants.CommandPacman } return &PackageManager{family: family, cmd: cmd} } // BuildInstallCommand builds an install command with privilege prefix func (pm *PackageManager) BuildInstallCommand(packageName string, withPrivilege bool) []string { cmds, ok := constants.PackageManagerConfigs[pm.cmd] if !ok { return nil } var result []string if withPrivilege { result = append(result, GetPrivilegePrefix()...) } result = append(result, cmds.Install...) result = append(result, packageName) return result } // BuildUpdateCommand builds a package update command with privilege prefix func (pm *PackageManager) BuildUpdateCommand(withPrivilege bool) []string { cmds, ok := constants.PackageManagerConfigs[pm.cmd] if !ok { return nil } var result []string if withPrivilege { result = append(result, GetPrivilegePrefix()...) } result = append(result, cmds.Update...) return result } // BuildUpgradeCommand builds an upgrade command with privilege prefix func (pm *PackageManager) BuildUpgradeCommand(packageName string, withPrivilege bool) []string { cmds, ok := constants.PackageManagerConfigs[pm.cmd] if !ok { return nil } var result []string if withPrivilege { result = append(result, GetPrivilegePrefix()...) } result = append(result, cmds.Upgrade...) if packageName != "" { result = append(result, packageName) } return result } // BuildRemoveCommand builds a remove command with privilege prefix func (pm *PackageManager) BuildRemoveCommand(packageName string, withPrivilege bool) []string { cmds, ok := constants.PackageManagerConfigs[pm.cmd] if !ok { return nil } var result []string if withPrivilege { result = append(result, GetPrivilegePrefix()...) } result = append(result, cmds.Remove...) result = append(result, packageName) return result } // GetCommandName returns the base command name func (pm *PackageManager) GetCommandName() string { return pm.cmd } // GetFamily returns the package manager family func (pm *PackageManager) GetFamily() string { return pm.family } // FlatpakManager handles Flatpak operations type FlatpakManager struct{} // NewFlatpakManager creates a new Flatpak manager instance func NewFlatpakManager() *FlatpakManager { return &FlatpakManager{} } // BuildInstallCommands builds Flatpak install commands (may return multiple commands) func (fm *FlatpakManager) BuildInstallCommands(appID string, enableFlathub bool) [][]string { var commands [][]string if enableFlathub { commands = append(commands, constants.FlatpakCommands["add-remote"]) } installCmd := append([]string{}, constants.FlatpakCommands["install"]...) installCmd = append(installCmd, appID) commands = append(commands, installCmd) return commands } // BuildUpdateCommand builds a Flatpak update command func (fm *FlatpakManager) BuildUpdateCommand(appID string) []string { updateCmd := append([]string{}, constants.FlatpakCommands["update"]...) if appID != "" { updateCmd = append(updateCmd, appID) } return updateCmd } // BuildRemoveCommand builds a Flatpak remove command func (fm *FlatpakManager) BuildRemoveCommand(appID string) []string { removeCmd := append([]string{}, constants.FlatpakCommands["remove"]...) removeCmd = append(removeCmd, appID) return removeCmd } // BuildOverrideCommand builds a Flatpak override command func (fm *FlatpakManager) BuildOverrideCommand(override string, appID string) []string { cmd := append([]string{}, constants.FlatpakCommands["override"]...) cmd = append(cmd, override, appID) return cmd } // BuildGsettingsCommand builds a command to run gsettings in Flatpak func (fm *FlatpakManager) BuildGsettingsCommand(appID, schema, key, value string) []string { return []string{ "flatpak", "run", "--command=gsettings", appID, "set", schema, key, value, } } // ExecuteCommands executes multiple commands and returns combined error func ExecuteCommands(cr *CommandRunner, commandSets [][]string) error { for i, cmdSet := range commandSets { if len(cmdSet) == 0 { continue } cmdStr := strings.Join(cmdSet, " ") if cr != nil { if len(commandSets) > 1 { cr.outputChan <- fmt.Sprintf("Step %d/%d: %s", i+1, len(commandSets), cmdStr) } else { cr.outputChan <- fmt.Sprintf("Running: %s", cmdStr) } } if err := cr.RunCommand(cmdSet[0], cmdSet[1:]...); err != nil { return err } } return nil } // ExecuteCommandsWithPrivilege executes commands with package manager support func ExecuteCommandsWithPrivilege(cr *CommandRunner, family string, commandType, packageName string, enableFlathub bool) error { switch family { case constants.PMFamilyDebian, constants.PMFamilyRHEL, constants.PMFamilyArch: pm := NewPackageManager(family) var cmdSet []string withPrivilege := true switch commandType { case "install": cmdSet = pm.BuildInstallCommand(packageName, withPrivilege) case "update": cmdSet = pm.BuildUpdateCommand(withPrivilege) case "upgrade": cmdSet = pm.BuildUpgradeCommand(packageName, withPrivilege) case "remove": cmdSet = pm.BuildRemoveCommand(packageName, withPrivilege) } if cr != nil { cr.outputChan <- fmt.Sprintf("Running: %s", strings.Join(cmdSet, " ")) } return cr.RunCommand(cmdSet[0], cmdSet[1:]...) case "flatpak": fm := NewFlatpakManager() switch commandType { case "install": cmds := fm.BuildInstallCommands(packageName, enableFlathub) if cr != nil { for i, cmd := range cmds { if len(cmds) > 1 { cr.outputChan <- fmt.Sprintf("Step %d/%d: %s", i+1, len(cmds), strings.Join(cmd, " ")) } else { cr.outputChan <- fmt.Sprintf("Running: %s", strings.Join(cmd, " ")) } } } // Execute each command (might be multiple for install with flathub) for _, cmd := range cmds { if err := cr.RunCommand(cmd[0], cmd[1:]...); err != nil { return err } } return nil case "update": cmd := fm.BuildUpdateCommand(packageName) if cr != nil { cr.outputChan <- fmt.Sprintf("Running: %s", strings.Join(cmd, " ")) } return cr.RunCommand(cmd[0], cmd[1:]...) case "remove": cmd := fm.BuildRemoveCommand(packageName) if cr != nil { cr.outputChan <- fmt.Sprintf("Running: %s", strings.Join(cmd, " ")) } return cr.RunCommand(cmd[0], cmd[1:]...) } } return fmt.Errorf("unsupported package manager: %s", family) }