package cmd import ( "context" "fmt" "os" "path/filepath" "strings" "time" "git.gostacks.org/iwasforcedtobehere/fastestmirror/internal/config" "git.gostacks.org/iwasforcedtobehere/fastestmirror/internal/distro" "git.gostacks.org/iwasforcedtobehere/fastestmirror/internal/mirror" "github.com/fatih/color" "github.com/spf13/cobra" ) var applyCmd = &cobra.Command{ Use: "apply", Short: "Apply the fastest mirror to your system configuration", Long: `Apply the fastest mirror found to your system's package manager configuration. This will: โ€ข Backup your current configuration (because we're not savages) โ€ข Update your package manager to use the fastest mirror โ€ข Test the new configuration WARNING: This modifies system files and requires root privileges. Don't blame us if you break something - you've been warned! ๐Ÿ”ฅ`, RunE: runApply, } var ( force bool dryRun bool backupPath string ) func runApply(cmd *cobra.Command, args []string) error { // Check if running as root if os.Geteuid() != 0 && !dryRun { binaryName := "fastestmirror" if len(os.Args) > 0 { binaryName = filepath.Base(os.Args[0]) } return fmt.Errorf("this command requires root privileges. Try: sudo %s apply", binaryName) } // Detect distribution fmt.Println("๐Ÿ” Detecting distribution...") distroInfo, err := distro.DetectDistribution() if err != nil { return fmt.Errorf("could not detect distribution: %w", err) } if !distroInfo.IsSupported() { return fmt.Errorf("distribution %s is not supported yet", distroInfo.ID) } configFile := distroInfo.GetConfigFile() if configFile == "" { return fmt.Errorf("no configuration file defined for %s", distroInfo.Family) } if dryRun { fmt.Printf("๐Ÿงช DRY RUN: Would modify %s\n", configFile) fmt.Println("๐Ÿงช DRY RUN: Would backup existing configuration") fmt.Println("๐Ÿงช DRY RUN: Would test fastest mirror and apply changes") return nil } // Create configuration manager configManager := config.NewConfigManager(distroInfo) // First, find the fastest mirror fmt.Printf("๐Ÿ” Finding fastest mirror for %s...\n", color.YellowString(distroInfo.Family)) mirrorList := mirror.NewMirrorList(distroInfo.Family) ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) defer cancel() err = mirrorList.LoadMirrors(ctx, distroInfo.Family) if err != nil { return fmt.Errorf("failed to load mirrors: %w", err) } err = mirrorList.TestMirrors(ctx, 10*time.Second) if err != nil { return fmt.Errorf("failed to test mirrors: %w", err) } bestMirror := mirrorList.GetBest() if bestMirror == nil { return fmt.Errorf("no working mirrors found - your connection might be fucked") } fmt.Printf("๐Ÿ† Best mirror found: %s\n", color.GreenString(bestMirror.URL)) fmt.Printf("โšก Speed: %.1f MB/s, Latency: %dms\n", bestMirror.Speed, bestMirror.Latency.Milliseconds()) // Ask for confirmation unless forced if !force { fmt.Printf("\nโš ๏ธ This will modify %s\n", color.YellowString(configFile)) fmt.Print("Do you want to continue? [y/N]: ") var response string fmt.Scanln(&response) if strings.ToLower(response) != "y" && strings.ToLower(response) != "yes" { fmt.Println("Operation cancelled.") return nil } } // Create backup fmt.Println("๐Ÿ’พ Creating backup...") backupPath, err := configManager.BackupConfig() if err != nil { return fmt.Errorf("failed to create backup: %w", err) } fmt.Printf("โœ… Backup created: %s\n", color.GreenString(backupPath)) // Apply the fastest mirror fmt.Println("๐Ÿ”ง Applying fastest mirror configuration...") err = configManager.ApplyMirror(bestMirror.URL) if err != nil { // Try to restore backup on failure fmt.Printf("โŒ Failed to apply configuration: %v\n", err) fmt.Println("๏ฟฝ Attempting to restore backup...") if restoreErr := configManager.RestoreBackup(backupPath); restoreErr != nil { return fmt.Errorf("configuration failed AND backup restore failed: %v (original error: %v)", restoreErr, err) } fmt.Println("โœ… Backup restored successfully") return fmt.Errorf("configuration application failed, backup restored: %w", err) } fmt.Printf("๐ŸŽ‰ Successfully applied fastest mirror!\n") fmt.Printf("๐Ÿ”— New mirror: %s\n", color.GreenString(bestMirror.URL)) fmt.Println() fmt.Printf("๐Ÿ’ก Don't forget to run your package manager's update command:\n") switch distroInfo.Family { case "debian": fmt.Printf(" %s\n", color.CyanString("sudo apt update")) case "arch": fmt.Printf(" %s\n", color.CyanString("sudo pacman -Sy")) case "fedora": fmt.Printf(" %s\n", color.CyanString("sudo dnf clean all && sudo dnf makecache")) } return nil } func init() { rootCmd.AddCommand(applyCmd) applyCmd.Flags().BoolVarP(&force, "force", "f", false, "Force application without confirmation") applyCmd.Flags().BoolVarP(&dryRun, "dry-run", "d", false, "Show what would be done without making changes") applyCmd.Flags().StringVarP(&backupPath, "backup", "b", "", "Custom backup file path") }