diff --git a/Makefile b/Makefile index 77dbe8c..9bd49df 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ all: test build ## Run tests and build binary build: ## Build the binary for current platform @echo "๐Ÿ”จ Building $(BINARY_NAME) v$(VERSION)..." go build $(LDFLAGS) -o $(BINARY_NAME) . - @echo "โœ… Build complete: ./$(BINARY_NAME)" + @echo "Build complete: ./$(BINARY_NAME)" build-all: ## Build binaries for all platforms @echo "๐Ÿ—๏ธ Building for all platforms..." @@ -26,53 +26,53 @@ build-all: ## Build binaries for all platforms GOOS=linux GOARCH=386 go build $(LDFLAGS) -o dist/$(BINARY_NAME)-linux-386 . GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o dist/$(BINARY_NAME)-darwin-amd64 . GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o dist/$(BINARY_NAME)-darwin-arm64 . - @echo "โœ… Multi-platform build complete in ./dist/" + @echo "Multi-platform build complete in ./dist/" test: ## Run tests @echo "๐Ÿงช Running tests..." go test -v ./... - @echo "โœ… Tests complete" + @echo "Tests complete" test-coverage: ## Run tests with coverage @echo "๐Ÿงช Running tests with coverage..." go test -coverprofile=coverage.out ./... go tool cover -html=coverage.out -o coverage.html - @echo "โœ… Coverage report generated: coverage.html" + @echo "Coverage report generated: coverage.html" fmt: ## Format code - @echo "๐ŸŽจ Formatting code..." + @echo "Formatting code..." go fmt ./... - @echo "โœ… Code formatted" + @echo "Code formatted" lint: ## Run linters - @echo "๐Ÿ” Running linters..." + @echo "Running linters..." @if command -v golangci-lint >/dev/null 2>&1; then \ golangci-lint run; \ else \ - echo "โš ๏ธ golangci-lint not installed. Install with: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \ + echo "golangci-lint not installed. Install with: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \ go vet ./...; \ fi - @echo "โœ… Linting complete" + @echo "Linting complete" clean: ## Clean build artifacts - @echo "๐Ÿงน Cleaning up..." + @echo "Cleaning up..." rm -f $(BINARY_NAME) rm -rf dist/ rm -f coverage.out coverage.html - @echo "โœ… Clean complete" + @echo "Clean complete" install: build ## Install binary to /usr/local/bin - @echo "๐Ÿ“ฆ Installing $(BINARY_NAME) to /usr/local/bin..." + @echo "Installing $(BINARY_NAME) to /usr/local/bin..." sudo cp $(BINARY_NAME) /usr/local/bin/ - @echo "โœ… Installation complete" + @echo "Installation complete" uninstall: ## Remove binary from /usr/local/bin - @echo "๐Ÿ—‘๏ธ Uninstalling $(BINARY_NAME)..." + @echo "Uninstalling $(BINARY_NAME)..." sudo rm -f /usr/local/bin/$(BINARY_NAME) - @echo "โœ… Uninstallation complete" + @echo "Uninstallation complete" package: build-all ## Create distribution packages - @echo "๐Ÿ“ฆ Creating packages..." + @echo "Creating packages..." @mkdir -p dist/packages # Create tar.gz archives @@ -84,7 +84,7 @@ package: build-all ## Create distribution packages fi \ done - @echo "โœ… Packages created in dist/packages/" + @echo "Packages created in dist/packages/" release: clean test package ## Prepare a release @echo "๐Ÿš€ Release $(VERSION) ready!" @@ -95,7 +95,7 @@ deps: ## Download dependencies @echo "๐Ÿ“ฅ Downloading dependencies..." go mod download go mod tidy - @echo "โœ… Dependencies updated" + @echo "Dependencies updated" dev-deps: ## Install development dependencies @echo "๐Ÿ› ๏ธ Installing development dependencies..." @@ -103,7 +103,7 @@ dev-deps: ## Install development dependencies echo "Installing golangci-lint..."; \ go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; \ fi - @echo "โœ… Development dependencies installed" + @echo "Development dependencies installed" run: build ## Build and run the application @echo "๐Ÿƒ Running $(BINARY_NAME)..." @@ -114,7 +114,7 @@ demo: build ## Run a demo of the find command ./$(BINARY_NAME) find --top 3 check: fmt lint test ## Run all checks (format, lint, test) - @echo "โœ… All checks passed!" + @echo "All checks passed!" help: ## Show this help message @echo "FastestMirror Build System" diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md deleted file mode 100644 index 9948b64..0000000 --- a/PROJECT_SUMMARY.md +++ /dev/null @@ -1,99 +0,0 @@ -# FastestMirror Project Summary - -## Project Overview -FastestMirror is a professional Go application that automatically detects Linux distributions and finds the fastest package repository mirrors. It's designed to be both technically impressive and subtly entertaining - perfect for a resume project. - -## Key Technical Features - -### ๐Ÿ—๏ธ Architecture -- **Clean Architecture**: Organized with `cmd/`, `internal/`, and `pkg/` structure following Go best practices -- **Modular Design**: Separate packages for distribution detection, mirror testing, and configuration management -- **Concurrent Processing**: Uses Go goroutines for parallel mirror testing -- **Error Handling**: Robust error handling throughout with meaningful error messages - -### ๐Ÿ” Distribution Detection -- Parses `/etc/os-release`, `/etc/lsb-release`, and fallback detection methods -- Supports major Linux families: Debian, Arch, Fedora, openSUSE, Gentoo, Alpine, etc. -- Graceful fallback mechanisms for edge cases - -### โšก Mirror Testing Infrastructure -- Concurrent HTTP speed testing with configurable timeouts -- Latency measurement and download speed calculation -- Smart scoring algorithm combining multiple metrics -- Proper connection handling and resource cleanup - -### ๐ŸŽจ User Experience -- Beautiful CLI interface with colors and progress bars -- Professional help text with subtle humor -- Comprehensive command structure with subcommands -- Safe operations with backup and dry-run modes - -### ๐Ÿ”ง Configuration Management -- Safe backup creation with timestamps -- Support for major package manager configurations -- Atomic operations with rollback capability -- Proper permission handling and root privilege checks - -## Commands Implemented - -### `fastestmirror find` -- Auto-detects distribution -- Tests mirrors concurrently -- Shows ranked results with performance metrics -- Configurable timeout and result count - -### `fastestmirror apply` -- Requires appropriate privileges -- Creates automatic backups -- Applies fastest mirror safely -- Provides post-application instructions - -### `fastestmirror version` -- Shows build information -- Displays Go version and architecture -- Links to repository - -## Technical Highlights - -### Dependencies -- **Cobra**: Professional CLI framework -- **Color Libraries**: Beautiful terminal output -- **Progress Bars**: Visual feedback during operations -- **Standard Library**: Extensive use of Go's robust standard library - -### Code Quality -- Comprehensive error handling -- Clean separation of concerns -- Concurrent operations with proper synchronization -- Resource management and cleanup - -### Safety Features -- Automatic configuration backups -- Dry-run mode for testing -- Root privilege validation -- Rollback capabilities on failure - -## Subtle Humor Elements -The project includes professional yet entertaining elements: -- Witty error messages ("your connection might be fucked") -- Humorous descriptions in help text -- Satirical comments in code and documentation -- Professional tone with personality - -## Resume Value -This project demonstrates: -- **Go Proficiency**: Modern Go idioms and best practices -- **Systems Programming**: Linux distribution detection and configuration management -- **Concurrent Programming**: Goroutines and proper synchronization -- **CLI Development**: Professional command-line interface design -- **Error Handling**: Robust error management and user feedback -- **Testing Infrastructure**: Network operations and performance measurement -- **Software Architecture**: Clean, modular design patterns - -## Repository -- **Location**: `https://git.gostacks.org/iwasforcedtobehere/fastestmirror` -- **Author**: `@iwasforcedtobehere` -- **License**: MIT -- **Build System**: Comprehensive Makefile with cross-platform builds - -This project showcases technical competence while maintaining personality - exactly what makes a great resume project stand out! \ No newline at end of file diff --git a/README.md b/README.md index 8686b3f..a4b4bf4 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ FastestMirror is a blazingly fast, auto-magical tool that finds and configures the fastest package repository mirrors for your Linux distribution. No more suffering through downloads that move slower than continental drift! -## Features That'll Make You Smile ๐Ÿ˜Š +## Features -- **๐Ÿ” Auto-Detection**: Automatically detects your Linux distribution (because we're not psychic, but we're pretty close) -- **โšก Concurrent Testing**: Tests multiple mirrors simultaneously using Go's goroutines (multithreading that actually works) -- **๐ŸŽจ Beautiful Output**: Colorful terminal interface that doesn't make your eyes bleed -- **๐Ÿ“Š Smart Scoring**: Combines speed and latency metrics to find the objectively best mirror -- **๐Ÿ”’ Safe Operations**: Always backs up your config before making changes (we're not monsters) -- **๐ŸŒ Wide Support**: Works with major Linux distributions and their families +- **Auto-Detection**: Automatically detects your Linux distribution (because we're not psychic, but we're pretty close) +- **Concurrent Testing**: Tests multiple mirrors simultaneously using Go's goroutines (multithreading that actually works) +- **Beautiful Output**: Colorful terminal interface that doesn't make your eyes bleed +- **Smart Scoring**: Combines speed and latency metrics to find the objectively best mirror +- **Safe Operations**: Always backs up your config before making changes (we're not monsters) +- **Wide Support**: Works with major Linux distributions and their families ## Supported Distributions @@ -120,13 +120,13 @@ fastestmirror find --help ## Example Output ``` -๐Ÿ” Detecting your Linux distribution... -๐Ÿ“ฆ Found: Ubuntu 22.04.3 LTS (debian family) -๐Ÿ”ง Loading mirrors for debian family... -โšก Testing 8 mirrors (timeout: 10s)... +Detecting your Linux distribution... +Found: Ubuntu 22.04.3 LTS (debian family) +Loading mirrors for debian family... +Testing 8 mirrors (timeout: 10s)... Testing mirrors โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 8/8 -๐ŸŽ‰ Testing complete! Here are your results: +Testing complete! Here are your results: Rank Mirror URL Latency Speed Score โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -136,10 +136,10 @@ Rank Mirror URL Latency Speed Sco #4 http://archive.ubuntu.com/ubuntu/ 234ms 6.2 MB/s 66.3 #5 http://us.archive.ubuntu.com/ubuntu/ 312ms 4.1 MB/s 44.2 -๐Ÿ† Winner: http://mirror.kakao.com/ubuntu/ -โšก This bad boy clocks in at 15.2 MB/s with 45ms latency +Winner: http://mirror.kakao.com/ubuntu/ +This bad boy clocks in at 15.2 MB/s with 45ms latency -๐Ÿ’ก To apply the fastest mirror, run: fastestmirror apply +To apply the fastest mirror, run: fastestmirror apply ``` ## Configuration diff --git a/cmd/apply.go b/cmd/apply.go index 7138216..3de6326 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -47,7 +47,7 @@ func runApply(cmd *cobra.Command, args []string) error { } // Detect distribution - fmt.Println("๐Ÿ” Detecting distribution...") + fmt.Println("Detecting distribution...") distroInfo, err := distro.DetectDistribution() if err != nil { return fmt.Errorf("could not detect distribution: %w", err) @@ -73,7 +73,7 @@ func runApply(cmd *cobra.Command, args []string) error { configManager := config.NewConfigManager(distroInfo) // First, find the fastest mirror - fmt.Printf("๐Ÿ” Finding fastest mirror for %s...\n", color.YellowString(distroInfo.Family)) + fmt.Printf("Finding fastest mirror for %s...\n", color.YellowString(distroInfo.Family)) mirrorList := mirror.NewMirrorList(distroInfo.Family) @@ -95,12 +95,12 @@ func runApply(cmd *cobra.Command, args []string) error { 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()) + 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.Printf("\nThis will modify %s\n", color.YellowString(configFile)) fmt.Print("Do you want to continue? [y/N]: ") var response string @@ -113,33 +113,33 @@ func runApply(cmd *cobra.Command, args []string) error { } // Create backup - fmt.Println("๐Ÿ’พ Creating 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)) + fmt.Printf("Backup created: %s\n", color.GreenString(backupPath)) // Apply the fastest mirror - fmt.Println("๐Ÿ”ง Applying fastest mirror configuration...") + 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.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") + 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.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") + fmt.Printf("Don't forget to run your package manager's update command:\n") switch distroInfo.Family { case "debian": diff --git a/cmd/find.go b/cmd/find.go index 1114b98..816d88e 100644 --- a/cmd/find.go +++ b/cmd/find.go @@ -33,21 +33,21 @@ This command will: func runFind(cmd *cobra.Command, args []string) error { // Detect distribution - fmt.Println(color.CyanString("๐Ÿ” Detecting your Linux distribution...")) + fmt.Println(color.CyanString("Detecting your Linux distribution...")) distroInfo, err := distro.DetectDistribution() if err != nil { return fmt.Errorf("fuck me, couldn't detect your distro: %w", err) } - fmt.Printf("๐Ÿ“ฆ Found: %s\n", color.GreenString(distroInfo.String())) + fmt.Printf("Found: %s\n", color.GreenString(distroInfo.String())) if !distroInfo.IsSupported() { return fmt.Errorf("sorry, %s isn't supported yet - but hey, you're using something exotic! ๐Ÿฆ„", distroInfo.ID) } // Get mirrors for this distribution family - fmt.Printf("๐Ÿ”ง Loading mirrors for %s family...\n", color.YellowString(distroInfo.Family)) + fmt.Printf("Loading mirrors for %s family...\n", color.YellowString(distroInfo.Family)) mirrorList := mirror.NewMirrorList(distroInfo.Family) @@ -60,8 +60,7 @@ func runFind(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to load mirrors: %w", err) } - fmt.Printf("โšก Testing %d mirrors (timeout: %ds each)...\n", - len(mirrorList.Mirrors), timeout) + fmt.Printf("Testing mirrors (timeout: %ds each)...\n", timeout) err = mirrorList.TestMirrors(ctx, time.Duration(timeout)*time.Second) @@ -70,7 +69,7 @@ func runFind(cmd *cobra.Command, args []string) error { } // Display results - fmt.Println("\n" + color.GreenString("๐ŸŽ‰ Testing complete! Here are your results:")) + fmt.Println("\n" + color.GreenString("Testing complete! Here are your results:")) fmt.Println() topMirrors := mirrorList.GetTop(topCount) @@ -85,11 +84,11 @@ func runFind(cmd *cobra.Command, args []string) error { } if verbose { - fmt.Printf("๐Ÿ“Š Test Summary: %d/%d mirrors responded successfully\n", successCount, len(allMirrors)) + fmt.Printf("Test Summary: %d/%d mirrors responded successfully\n", successCount, len(allMirrors)) fmt.Println() } if len(topMirrors) == 0 { - fmt.Println(color.RedString("๐Ÿ˜ฑ No working mirrors found. Your internet might be fucked, or all mirrors are down.")) + fmt.Println(color.RedString("No working mirrors found. Your internet might be fucked, or all mirrors are down.")) return nil } @@ -132,32 +131,29 @@ func runFind(cmd *cobra.Command, args []string) error { fmt.Println() best := mirrorList.GetBest() if best != nil { - fmt.Printf("๐Ÿ† Winner: %s\n", color.GreenString(best.URL)) - fmt.Printf("โšก This bad boy clocks in at %.1f MB/s with %dms latency\n", + fmt.Printf("Winner: %s\n", color.GreenString(best.URL)) + fmt.Printf("This bad boy clocks in at %.1f MB/s with %dms latency\n", best.Speed, best.Latency.Milliseconds()) } - // Show failed mirrors in verbose mode + // Show failed mirror count in verbose mode (no detailed errors) if verbose { - failedMirrors := make([]mirror.Mirror, 0) + failedCount := 0 for _, m := range allMirrors { if m.Error != nil { - failedMirrors = append(failedMirrors, m) + failedCount++ } } - if len(failedMirrors) > 0 { + if failedCount > 0 { fmt.Println() - fmt.Printf("โŒ Failed mirrors (%d):\n", len(failedMirrors)) - for _, m := range failedMirrors { - fmt.Printf(" %s - %s\n", color.RedString(m.URL), m.Error.Error()) - } + fmt.Printf("Failed mirrors: %d (errors hidden for cleaner output)\n", failedCount) } } fmt.Println() - fmt.Printf("๐Ÿ’ก To apply the fastest mirror, run: %s\n", - color.YellowString("fastestmirror apply")) + fmt.Printf("To apply the fastest mirror, run: %s\n", + color.CyanString("fastestmirror apply")) return nil } diff --git a/internal/mirror/tester.go b/internal/mirror/tester.go index 53c3b63..9b4edbd 100644 --- a/internal/mirror/tester.go +++ b/internal/mirror/tester.go @@ -80,11 +80,11 @@ func NewMirrorList(family string) *MirrorList { func (ml *MirrorList) LoadMirrors(ctx context.Context, family string) error { fetcher := NewMirrorFetcher() - fmt.Printf("๐ŸŒ Fetching complete mirror list for %s...\n", family) + fmt.Printf("Fetching complete mirror list for %s...\n", family) mirrors, err := fetcher.FetchMirrors(ctx, family) if err != nil { - fmt.Printf("โš ๏ธ Failed to fetch mirrors online, using fallback list: %v\n", err) + fmt.Printf("Failed to fetch mirrors online, using fallback list: %v\n", err) mirrors = fetcher.getDefaultMirrors(family) } @@ -102,7 +102,7 @@ func (ml *MirrorList) LoadMirrors(ctx context.Context, family string) error { }) } - fmt.Printf("๐Ÿ“ก Loaded %d mirrors for testing\n", len(ml.Mirrors)) + fmt.Printf("Loaded %d mirrors for testing\n", len(ml.Mirrors)) return nil } @@ -118,7 +118,7 @@ func (ml *MirrorList) TestMirrors(ctx context.Context, timeout time.Duration) er results := make(chan TestResult, len(ml.Mirrors)) var wg sync.WaitGroup - fmt.Printf("๐Ÿ”„ Testing %d mirrors concurrently...\n", len(ml.Mirrors)) + fmt.Printf("Testing %d mirrors concurrently...\n", len(ml.Mirrors)) // Test each mirror concurrently for i := range ml.Mirrors { @@ -154,7 +154,7 @@ func (ml *MirrorList) TestMirrors(ctx context.Context, timeout time.Duration) er } } - fmt.Printf("โœ… Testing complete: %d successful, %d failed\n", successCount, failureCount) + fmt.Printf("Testing complete: %d successful, %d failed\n", successCount, failureCount) // Sort by score (higher is better), but put failed mirrors at the end sort.Slice(ml.Mirrors, func(i, j int) bool {