summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go
diff options
context:
space:
mode:
authorNippy <nippy@rp1.hu>2026-05-09 13:33:09 +0200
committerNippy <nippy@rp1.hu>2026-05-09 13:33:09 +0200
commita2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5 (patch)
tree1a8769217f84bfe9d6216fafaadaf8cdd876d457 /raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go
parent34b9c34f982b2596cfa9e368a2d7f74e9a17477c (diff)
downloadRaveOS-PKGBUILD-a2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5.tar.gz
RaveOS-PKGBUILD-a2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5.zip
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go700
1 files changed, 0 insertions, 700 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go
deleted file mode 100644
index e0a2a9c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go
+++ /dev/null
@@ -1,700 +0,0 @@
-package distros
-
-import (
- "context"
- "fmt"
- "os/exec"
- "runtime"
- "strings"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/deps"
-)
-
-var GentooGlobalUseFlags = []string{
- "dbus",
- "udev",
- "alsa",
- "policykit",
- "jpeg",
- "png",
- "webp",
- "gif",
- "tiff",
- "svg",
- "brotli",
- "gdbm",
- "accessibility",
- "gtk",
- "qt6",
- "egl",
- "gbm",
-}
-
-func init() {
- Register("gentoo", "#54487A", FamilyGentoo, func(config DistroConfig, logChan chan<- string) Distribution {
- return NewGentooDistribution(config, logChan)
- })
-}
-
-type GentooDistribution struct {
- *BaseDistribution
- *ManualPackageInstaller
- config DistroConfig
- skipGlobalUseFlags bool
-}
-
-func NewGentooDistribution(config DistroConfig, logChan chan<- string) *GentooDistribution {
- base := NewBaseDistribution(logChan)
- return &GentooDistribution{
- BaseDistribution: base,
- ManualPackageInstaller: &ManualPackageInstaller{BaseDistribution: base},
- config: config,
- }
-}
-
-func (g *GentooDistribution) getArchKeyword() string {
- arch := runtime.GOARCH
- switch arch {
- case "amd64":
- return "~amd64"
- case "arm64":
- return "~arm64"
- default:
- return "~amd64"
- }
-}
-
-func (g *GentooDistribution) GetID() string {
- return g.config.ID
-}
-
-func (g *GentooDistribution) GetColorHex() string {
- return g.config.ColorHex
-}
-
-func (g *GentooDistribution) GetFamily() DistroFamily {
- return g.config.Family
-}
-
-func (g *GentooDistribution) GetPackageManager() PackageManagerType {
- return PackageManagerPortage
-}
-
-func (g *GentooDistribution) DetectDependencies(ctx context.Context, wm deps.WindowManager) ([]deps.Dependency, error) {
- return g.DetectDependenciesWithTerminal(ctx, wm, deps.TerminalGhostty)
-}
-
-func (g *GentooDistribution) DetectDependenciesWithTerminal(ctx context.Context, wm deps.WindowManager, terminal deps.Terminal) ([]deps.Dependency, error) {
- var dependencies []deps.Dependency
-
- dependencies = append(dependencies, g.detectDMS())
-
- dependencies = append(dependencies, g.detectSpecificTerminal(terminal))
-
- dependencies = append(dependencies, g.detectGit())
- dependencies = append(dependencies, g.detectWindowManager(wm))
- dependencies = append(dependencies, g.detectQuickshell())
- dependencies = append(dependencies, g.detectXDGPortal())
- dependencies = append(dependencies, g.detectAccountsService())
-
- if wm == deps.WindowManagerHyprland {
- dependencies = append(dependencies, g.detectHyprlandTools()...)
- }
-
- if wm == deps.WindowManagerNiri {
- dependencies = append(dependencies, g.detectXwaylandSatellite())
- }
-
- dependencies = append(dependencies, g.detectMatugen())
- dependencies = append(dependencies, g.detectDgop())
-
- return dependencies, nil
-}
-
-func (g *GentooDistribution) detectXDGPortal() deps.Dependency {
- return g.detectPackage("xdg-desktop-portal-gtk", "Desktop integration portal for GTK", g.packageInstalled("sys-apps/xdg-desktop-portal-gtk"))
-}
-
-func (g *GentooDistribution) detectXwaylandSatellite() deps.Dependency {
- return g.detectPackage("xwayland-satellite", "Xwayland support", g.packageInstalled("gui-apps/xwayland-satellite"))
-}
-
-func (g *GentooDistribution) detectAccountsService() deps.Dependency {
- return g.detectPackage("accountsservice", "D-Bus interface for user account query and manipulation", g.packageInstalled("sys-apps/accountsservice"))
-}
-
-func (g *GentooDistribution) packageInstalled(pkg string) bool {
- cmd := exec.Command("qlist", "-I", pkg)
- err := cmd.Run()
- return err == nil
-}
-
-func (g *GentooDistribution) GetPackageMapping(wm deps.WindowManager) map[string]PackageMapping {
- return g.GetPackageMappingWithVariants(wm, make(map[string]deps.PackageVariant))
-}
-
-func (g *GentooDistribution) GetPackageMappingWithVariants(wm deps.WindowManager, variants map[string]deps.PackageVariant) map[string]PackageMapping {
- archKeyword := g.getArchKeyword()
- packages := map[string]PackageMapping{
- "git": {Name: "dev-vcs/git", Repository: RepoTypeSystem},
- "kitty": {Name: "x11-terms/kitty", Repository: RepoTypeSystem, UseFlags: "X wayland"},
- "alacritty": {Name: "x11-terms/alacritty", Repository: RepoTypeSystem, UseFlags: "X wayland"},
- "xdg-desktop-portal-gtk": {Name: "sys-apps/xdg-desktop-portal-gtk", Repository: RepoTypeSystem, UseFlags: "wayland X"},
- "accountsservice": {Name: "sys-apps/accountsservice", Repository: RepoTypeSystem},
-
- "qtbase": {Name: "dev-qt/qtbase", Repository: RepoTypeSystem, UseFlags: "wayland opengl vulkan widgets"},
- "qtdeclarative": {Name: "dev-qt/qtdeclarative", Repository: RepoTypeSystem, UseFlags: "opengl vulkan"},
- "qtwayland": {Name: "dev-qt/qtwayland", Repository: RepoTypeSystem},
- "mesa": {Name: "media-libs/mesa", Repository: RepoTypeSystem, UseFlags: "opengl vulkan"},
-
- "quickshell": g.getQuickshellMapping(variants["quickshell"]),
- "matugen": {Name: "x11-misc/matugen", Repository: RepoTypeGURU, AcceptKeywords: archKeyword},
- "dms (DankMaterialShell)": g.getDmsMapping(variants["dms (DankMaterialShell)"]),
- "dgop": {Name: "dgop", Repository: RepoTypeManual, BuildFunc: "installDgop"},
- }
-
- switch wm {
- case deps.WindowManagerHyprland:
- packages["hyprland"] = g.getHyprlandMapping(variants["hyprland"])
- packages["hyprctl"] = g.getHyprlandMapping(variants["hyprland"])
- packages["jq"] = PackageMapping{Name: "app-misc/jq", Repository: RepoTypeSystem}
- case deps.WindowManagerNiri:
- packages["niri"] = g.getNiriMapping(variants["niri"])
- packages["xwayland-satellite"] = PackageMapping{Name: "gui-apps/xwayland-satellite", Repository: RepoTypeGURU, AcceptKeywords: archKeyword}
- }
-
- return packages
-}
-
-func (g *GentooDistribution) getQuickshellMapping(_ deps.PackageVariant) PackageMapping {
- return PackageMapping{Name: "gui-apps/quickshell", Repository: RepoTypeGURU, UseFlags: "breakpad jemalloc sockets wayland layer-shell session-lock toplevel-management screencopy X pipewire tray mpris pam hyprland hyprland-global-shortcuts hyprland-focus-grab i3 i3-ipc bluetooth", AcceptKeywords: "**"}
-}
-
-func (g *GentooDistribution) getDmsMapping(_ deps.PackageVariant) PackageMapping {
- return PackageMapping{Name: "dms", Repository: RepoTypeManual, BuildFunc: "installDankMaterialShell"}
-}
-
-func (g *GentooDistribution) getHyprlandMapping(_ deps.PackageVariant) PackageMapping {
- return PackageMapping{Name: "gui-wm/hyprland", Repository: RepoTypeSystem, UseFlags: "X", AcceptKeywords: g.getArchKeyword()}
-}
-
-func (g *GentooDistribution) getNiriMapping(_ deps.PackageVariant) PackageMapping {
- return PackageMapping{Name: "gui-wm/niri", Repository: RepoTypeGURU, UseFlags: "dbus screencast", AcceptKeywords: g.getArchKeyword()}
-}
-
-func (g *GentooDistribution) getPrerequisites() []string {
- return []string{
- "app-eselect/eselect-repository",
- "dev-vcs/git",
- "dev-build/make",
- "app-arch/unzip",
- "dev-util/pkgconf",
- "dev-qt/qtdeclarative",
- }
-}
-
-func (g *GentooDistribution) setGlobalUseFlags(ctx context.Context, sudoPassword string) error {
- useFlags := strings.Join(GentooGlobalUseFlags, " ")
-
- checkCmd := exec.CommandContext(ctx, "grep", "-q", "^USE=", "/etc/portage/make.conf")
- hasUse := checkCmd.Run() == nil
-
- var cmd *exec.Cmd
- if hasUse {
- cmd = ExecSudoCommand(ctx, sudoPassword, fmt.Sprintf("sed -i 's/^USE=\"\\(.*\\)\"/USE=\"\\1 %s\"/' /etc/portage/make.conf", useFlags))
- } else {
- cmd = ExecSudoCommand(ctx, sudoPassword, fmt.Sprintf("bash -c \"echo 'USE=\\\"%s\\\"' >> /etc/portage/make.conf\"", useFlags))
- }
-
- output, err := cmd.CombinedOutput()
- if err != nil {
- g.log(fmt.Sprintf("Failed to set global USE flags: %s", string(output)))
- return err
- }
-
- g.log(fmt.Sprintf("Set global USE flags: %s", useFlags))
- return nil
-}
-
-func (g *GentooDistribution) InstallPrerequisites(ctx context.Context, sudoPassword string, progressChan chan<- InstallProgressMsg) error {
- prerequisites := g.getPrerequisites()
- var missingPkgs []string
-
- if !g.skipGlobalUseFlags {
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.05,
- Step: "Setting global USE flags...",
- IsComplete: false,
- LogOutput: "Configuring global USE flags in /etc/portage/make.conf",
- }
-
- if err := g.setGlobalUseFlags(ctx, sudoPassword); err != nil {
- g.logError("failed to set global USE flags", err)
- return fmt.Errorf("failed to set global USE flags: %w", err)
- }
- } else {
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.05,
- Step: "Skipping global USE flags...",
- IsComplete: false,
- LogOutput: "Skipping global USE flags configuration (using existing configuration)",
- }
- }
-
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.06,
- Step: "Checking prerequisites...",
- IsComplete: false,
- LogOutput: "Checking prerequisite packages",
- }
-
- for _, pkg := range prerequisites {
- checkCmd := exec.CommandContext(ctx, "qlist", "-I", pkg)
- if err := checkCmd.Run(); err != nil {
- missingPkgs = append(missingPkgs, pkg)
- }
- }
-
- _, err := exec.LookPath("go")
- if err != nil {
- g.log("go not found in PATH, will install dev-lang/go")
- missingPkgs = append(missingPkgs, "dev-lang/go")
- } else {
- g.log("go already available in PATH")
- }
-
- if len(missingPkgs) == 0 {
- g.log("All prerequisites already installed")
- return nil
- }
-
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.07,
- Step: "Syncing Portage tree...",
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: "sudo emerge --sync",
- LogOutput: "Syncing Portage tree with emerge --sync",
- }
-
- syncCmd := ExecSudoCommand(ctx, sudoPassword, "emerge --sync --quiet")
- syncOutput, syncErr := syncCmd.CombinedOutput()
- if syncErr != nil {
- g.log(fmt.Sprintf("emerge --sync output: %s", string(syncOutput)))
- return fmt.Errorf("failed to sync Portage tree: %w\nOutput: %s", syncErr, string(syncOutput))
- }
- g.log("Portage tree synced successfully")
-
- g.log(fmt.Sprintf("Installing prerequisites: %s", strings.Join(missingPkgs, ", ")))
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.08,
- Step: fmt.Sprintf("Installing %d prerequisites...", len(missingPkgs)),
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: fmt.Sprintf("sudo emerge --ask=n %s", strings.Join(missingPkgs, " ")),
- LogOutput: fmt.Sprintf("Installing prerequisites: %s", strings.Join(missingPkgs, ", ")),
- }
-
- args := []string{"emerge", "--ask=n", "--quiet"}
- args = append(args, missingPkgs...)
- cmd := ExecSudoCommand(ctx, sudoPassword, strings.Join(args, " "))
- output, err := cmd.CombinedOutput()
- if err != nil {
- g.logError("failed to install prerequisites", err)
- g.log(fmt.Sprintf("Prerequisites command output: %s", string(output)))
- return fmt.Errorf("failed to install prerequisites: %w\nOutput: %s", err, string(output))
- }
- g.log(fmt.Sprintf("Prerequisites install output: %s", string(output)))
-
- return nil
-}
-
-func (g *GentooDistribution) InstallPackages(ctx context.Context, dependencies []deps.Dependency, wm deps.WindowManager, sudoPassword string, reinstallFlags map[string]bool, disabledFlags map[string]bool, skipGlobalUseFlags bool, progressChan chan<- InstallProgressMsg) error {
- g.skipGlobalUseFlags = skipGlobalUseFlags
-
- progressChan <- InstallProgressMsg{
- Phase: PhasePrerequisites,
- Progress: 0.05,
- Step: "Checking system prerequisites...",
- IsComplete: false,
- LogOutput: "Starting prerequisite check...",
- }
-
- if err := g.InstallPrerequisites(ctx, sudoPassword, progressChan); err != nil {
- return fmt.Errorf("failed to install prerequisites: %w", err)
- }
-
- systemPkgs, guruPkgs, manualPkgs, variantMap := g.categorizePackages(dependencies, wm, reinstallFlags, disabledFlags)
-
- g.log(fmt.Sprintf("CATEGORIZED PACKAGES: system=%d, guru=%d, manual=%d", len(systemPkgs), len(guruPkgs), len(manualPkgs)))
-
- if len(systemPkgs) > 0 {
- systemPkgNames := g.extractPackageNames(systemPkgs)
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.35,
- Step: fmt.Sprintf("Installing %d system packages...", len(systemPkgs)),
- IsComplete: false,
- NeedsSudo: true,
- LogOutput: fmt.Sprintf("Installing system packages: %s", strings.Join(systemPkgNames, ", ")),
- }
- if err := g.installPortagePackages(ctx, systemPkgs, sudoPassword, progressChan); err != nil {
- return fmt.Errorf("failed to install Portage packages: %w", err)
- }
- }
-
- if len(guruPkgs) > 0 {
- g.log(fmt.Sprintf("FOUND %d GURU PACKAGES - WILL SYNC GURU REPO", len(guruPkgs)))
- progressChan <- InstallProgressMsg{
- Phase: PhaseAURPackages,
- Progress: 0.60,
- Step: "Syncing GURU repository...",
- IsComplete: false,
- LogOutput: "Syncing GURU repository to fetch latest ebuilds",
- }
- g.log("ABOUT TO CALL syncGURURepo")
- if err := g.syncGURURepo(ctx, sudoPassword, progressChan); err != nil {
- g.log(fmt.Sprintf("syncGURURepo RETURNED ERROR: %v", err))
- return fmt.Errorf("failed to sync GURU repository: %w", err)
- }
- g.log("syncGURURepo COMPLETED SUCCESSFULLY")
-
- guruPkgNames := g.extractPackageNames(guruPkgs)
- progressChan <- InstallProgressMsg{
- Phase: PhaseAURPackages,
- Progress: 0.65,
- Step: fmt.Sprintf("Installing %d GURU packages...", len(guruPkgs)),
- IsComplete: false,
- LogOutput: fmt.Sprintf("Installing GURU packages: %s", strings.Join(guruPkgNames, ", ")),
- }
- if err := g.installGURUPackages(ctx, guruPkgs, sudoPassword, progressChan); err != nil {
- return fmt.Errorf("failed to install GURU packages: %w", err)
- }
- }
-
- if len(manualPkgs) > 0 {
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.85,
- Step: fmt.Sprintf("Building %d packages from source...", len(manualPkgs)),
- IsComplete: false,
- LogOutput: fmt.Sprintf("Building from source: %s", strings.Join(manualPkgs, ", ")),
- }
- if err := g.InstallManualPackages(ctx, manualPkgs, variantMap, sudoPassword, progressChan); err != nil {
- return fmt.Errorf("failed to install manual packages: %w", err)
- }
- }
-
- progressChan <- InstallProgressMsg{
- Phase: PhaseConfiguration,
- Progress: 0.90,
- Step: "Configuring system...",
- IsComplete: false,
- LogOutput: "Starting post-installation configuration...",
- }
-
- terminal := g.DetectTerminalFromDeps(dependencies)
- if err := g.WriteEnvironmentConfig(terminal); err != nil {
- g.log(fmt.Sprintf("Warning: failed to write environment config: %v", err))
- }
-
- if err := g.WriteWindowManagerConfig(wm); err != nil {
- g.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
- }
-
- if err := g.EnableDMSService(ctx, wm); err != nil {
- g.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
- }
-
- progressChan <- InstallProgressMsg{
- Phase: PhaseComplete,
- Progress: 1.0,
- Step: "Installation complete!",
- IsComplete: true,
- LogOutput: "All packages installed and configured successfully",
- }
-
- return nil
-}
-
-func (g *GentooDistribution) categorizePackages(dependencies []deps.Dependency, wm deps.WindowManager, reinstallFlags map[string]bool, disabledFlags map[string]bool) ([]PackageMapping, []PackageMapping, []string, map[string]deps.PackageVariant) {
- systemPkgs := []PackageMapping{}
- guruPkgs := []PackageMapping{}
- manualPkgs := []string{}
-
- variantMap := make(map[string]deps.PackageVariant)
- for _, dep := range dependencies {
- variantMap[dep.Name] = dep.Variant
- }
-
- packageMap := g.GetPackageMappingWithVariants(wm, variantMap)
-
- for _, dep := range dependencies {
- if disabledFlags[dep.Name] {
- continue
- }
-
- if dep.Status == deps.StatusInstalled && !reinstallFlags[dep.Name] {
- continue
- }
-
- pkgInfo, exists := packageMap[dep.Name]
- if !exists {
- g.log(fmt.Sprintf("Warning: No package mapping for %s", dep.Name))
- continue
- }
-
- switch pkgInfo.Repository {
- case RepoTypeSystem:
- systemPkgs = append(systemPkgs, pkgInfo)
- case RepoTypeGURU:
- guruPkgs = append(guruPkgs, pkgInfo)
- case RepoTypeManual:
- manualPkgs = append(manualPkgs, dep.Name)
- }
- }
-
- return systemPkgs, guruPkgs, manualPkgs, variantMap
-}
-
-func (g *GentooDistribution) extractPackageNames(packages []PackageMapping) []string {
- names := make([]string, len(packages))
- for i, pkg := range packages {
- names[i] = pkg.Name
- }
- return names
-}
-
-func (g *GentooDistribution) installPortagePackages(ctx context.Context, packages []PackageMapping, sudoPassword string, progressChan chan<- InstallProgressMsg) error {
- if len(packages) == 0 {
- return nil
- }
-
- packageNames := g.extractPackageNames(packages)
- g.log(fmt.Sprintf("Installing Portage packages: %s", strings.Join(packageNames, ", ")))
-
- for _, pkg := range packages {
- if pkg.AcceptKeywords != "" {
- if err := g.setPackageAcceptKeywords(ctx, pkg.Name, pkg.AcceptKeywords, sudoPassword); err != nil {
- return fmt.Errorf("failed to set accept keywords for %s: %w", pkg.Name, err)
- }
- }
- if pkg.UseFlags != "" {
- if err := g.setPackageUseFlags(ctx, pkg.Name, pkg.UseFlags, sudoPassword); err != nil {
- return fmt.Errorf("failed to set USE flags for %s: %w", pkg.Name, err)
- }
- }
- }
-
- args := []string{"emerge", "--ask=n", "--quiet"}
- args = append(args, packageNames...)
-
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.40,
- Step: "Installing system packages...",
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: fmt.Sprintf("sudo %s", strings.Join(args, " ")),
- }
-
- cmd := ExecSudoCommand(ctx, sudoPassword, strings.Join(args, " "))
- return g.runWithProgressTimeout(cmd, progressChan, PhaseSystemPackages, 0.40, 0.60, 0)
-}
-
-func (g *GentooDistribution) setPackageUseFlags(ctx context.Context, packageName, useFlags, sudoPassword string) error {
- packageUseDir := "/etc/portage/package.use"
-
- mkdirCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("mkdir -p %s", packageUseDir))
- if output, err := mkdirCmd.CombinedOutput(); err != nil {
- g.log(fmt.Sprintf("mkdir output: %s", string(output)))
- return fmt.Errorf("failed to create package.use directory: %w", err)
- }
-
- useFlagLine := fmt.Sprintf("%s %s", packageName, useFlags)
-
- checkExistingCmd := exec.CommandContext(ctx, "bash", "-c",
- fmt.Sprintf("grep -q '^%s ' %s/danklinux 2>/dev/null", packageName, packageUseDir))
- if checkExistingCmd.Run() == nil {
- g.log(fmt.Sprintf("Updating USE flags for %s from existing entry", packageName))
- escapedPkg := strings.ReplaceAll(packageName, "/", "\\/")
- replaceCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("sed -i '/^%s /d' %s/danklinux; exit_code=$?; exit $exit_code", escapedPkg, packageUseDir))
- if output, err := replaceCmd.CombinedOutput(); err != nil {
- g.log(fmt.Sprintf("sed delete output: %s", string(output)))
- return fmt.Errorf("failed to remove old USE flags: %w", err)
- }
- }
-
- appendCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("bash -c \"echo '%s' >> %s/danklinux\"", useFlagLine, packageUseDir))
-
- output, err := appendCmd.CombinedOutput()
- if err != nil {
- g.log(fmt.Sprintf("append output: %s", string(output)))
- return fmt.Errorf("failed to write USE flags to package.use: %w", err)
- }
-
- g.log(fmt.Sprintf("Set USE flags for %s: %s", packageName, useFlags))
- return nil
-}
-
-func (g *GentooDistribution) syncGURURepo(ctx context.Context, sudoPassword string, progressChan chan<- InstallProgressMsg) error {
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.55,
- Step: "Enabling GURU repository...",
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: "sudo eselect repository enable guru",
- LogOutput: "Enabling GURU repository with eselect",
- }
-
- // Enable GURU repository
- enableCmd := ExecSudoCommand(ctx, sudoPassword,
- "eselect repository enable guru 2>&1; exit_code=$?; exit $exit_code")
- output, err := enableCmd.CombinedOutput()
-
- g.log(fmt.Sprintf("eselect repository enable guru output:\n%s", string(output)))
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.55,
- LogOutput: "GURU repository enabled",
- }
-
- if err != nil {
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.55,
- LogOutput: fmt.Sprintf("ERROR enabling GURU: %v", err),
- Error: err,
- }
- return fmt.Errorf("failed to enable GURU repository: %w\nOutput: %s", err, string(output))
- }
-
- // Sync GURU repository
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.57,
- Step: "Syncing GURU repository...",
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: "sudo emaint sync --repo guru",
- LogOutput: "Syncing GURU repository",
- }
-
- syncCmd := ExecSudoCommand(ctx, sudoPassword,
- "emaint sync --repo guru 2>&1; exit_code=$?; exit $exit_code")
- syncOutput, syncErr := syncCmd.CombinedOutput()
-
- g.log(fmt.Sprintf("emaint sync --repo guru output:\n%s", string(syncOutput)))
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.57,
- LogOutput: "GURU repository synced",
- }
-
- if syncErr != nil {
- progressChan <- InstallProgressMsg{
- Phase: PhaseSystemPackages,
- Progress: 0.57,
- LogOutput: fmt.Sprintf("ERROR syncing GURU: %v", syncErr),
- Error: syncErr,
- }
- return fmt.Errorf("failed to sync GURU repository: %w\nOutput: %s", syncErr, string(syncOutput))
- }
-
- return nil
-}
-
-func (g *GentooDistribution) setPackageAcceptKeywords(ctx context.Context, packageName, keywords, sudoPassword string) error {
- checkCmd := exec.CommandContext(ctx, "portageq", "match", "/", packageName)
- if output, err := checkCmd.CombinedOutput(); err == nil && len(output) > 0 {
- g.log(fmt.Sprintf("Package %s is already available (may already be unmasked)", packageName))
- return nil
- }
-
- acceptKeywordsDir := "/etc/portage/package.accept_keywords"
-
- mkdirCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("mkdir -p %s", acceptKeywordsDir))
- if output, err := mkdirCmd.CombinedOutput(); err != nil {
- g.log(fmt.Sprintf("mkdir output: %s", string(output)))
- return fmt.Errorf("failed to create package.accept_keywords directory: %w", err)
- }
-
- keywordLine := fmt.Sprintf("%s %s", packageName, keywords)
-
- checkExistingCmd := exec.CommandContext(ctx, "bash", "-c",
- fmt.Sprintf("grep -q '^%s ' %s/danklinux 2>/dev/null", packageName, acceptKeywordsDir))
- if checkExistingCmd.Run() == nil {
- g.log(fmt.Sprintf("Updating accept keywords for %s from existing entry", packageName))
- escapedPkg := strings.ReplaceAll(packageName, "/", "\\/")
- replaceCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("sed -i '/^%s /d' %s/danklinux; exit_code=$?; exit $exit_code", escapedPkg, acceptKeywordsDir))
- if output, err := replaceCmd.CombinedOutput(); err != nil {
- g.log(fmt.Sprintf("sed delete output: %s", string(output)))
- return fmt.Errorf("failed to remove old accept keywords: %w", err)
- }
- }
-
- appendCmd := ExecSudoCommand(ctx, sudoPassword,
- fmt.Sprintf("bash -c \"echo '%s' >> %s/danklinux\"", keywordLine, acceptKeywordsDir))
-
- output, err := appendCmd.CombinedOutput()
- if err != nil {
- g.log(fmt.Sprintf("append output: %s", string(output)))
- return fmt.Errorf("failed to write accept keywords: %w", err)
- }
-
- g.log(fmt.Sprintf("Set accept keywords for %s: %s", packageName, keywords))
- return nil
-}
-
-func (g *GentooDistribution) installGURUPackages(ctx context.Context, packages []PackageMapping, sudoPassword string, progressChan chan<- InstallProgressMsg) error {
- if len(packages) == 0 {
- return nil
- }
-
- packageNames := g.extractPackageNames(packages)
- g.log(fmt.Sprintf("Installing GURU packages: %s", strings.Join(packageNames, ", ")))
-
- for _, pkg := range packages {
- if pkg.AcceptKeywords != "" {
- if err := g.setPackageAcceptKeywords(ctx, pkg.Name, pkg.AcceptKeywords, sudoPassword); err != nil {
- return fmt.Errorf("failed to set accept keywords for %s: %w", pkg.Name, err)
- }
- }
- if pkg.UseFlags != "" {
- if err := g.setPackageUseFlags(ctx, pkg.Name, pkg.UseFlags, sudoPassword); err != nil {
- return fmt.Errorf("failed to set USE flags for %s: %w", pkg.Name, err)
- }
- }
- }
-
- guruPackages := make([]string, len(packageNames))
- for i, pkg := range packageNames {
- guruPackages[i] = pkg + "::guru"
- }
-
- args := []string{"emerge", "--ask=n", "--quiet"}
- args = append(args, guruPackages...)
-
- progressChan <- InstallProgressMsg{
- Phase: PhaseAURPackages,
- Progress: 0.70,
- Step: "Installing GURU packages...",
- IsComplete: false,
- NeedsSudo: true,
- CommandInfo: fmt.Sprintf("sudo %s", strings.Join(args, " ")),
- }
-
- cmd := ExecSudoCommand(ctx, sudoPassword, strings.Join(args, " "))
- return g.runWithProgressTimeout(cmd, progressChan, PhaseAURPackages, 0.70, 0.85, 0)
-}