diff options
| author | Nippy <nippy@rp1.hu> | 2026-05-09 13:33:09 +0200 |
|---|---|---|
| committer | Nippy <nippy@rp1.hu> | 2026-05-09 13:33:09 +0200 |
| commit | a2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5 (patch) | |
| tree | 1a8769217f84bfe9d6216fafaadaf8cdd876d457 /raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/distros/gentoo.go | |
| parent | 34b9c34f982b2596cfa9e368a2d7f74e9a17477c (diff) | |
| download | RaveOS-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.go | 700 |
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) -} |