From b168c1f7d2009df977e16ea6b0d100b9b2399c6d Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 22 May 2024 13:31:22 -0700 Subject: [PATCH] latest --- main.go | 14 ++++-- mirror.go | 7 ++- sources.go | 100 +++++++++++++-------------------------- sources_list_legacy.tmpl | 5 -- sources_list_modern.tmpl | 14 ------ ubuntu.go | 32 ------------- 6 files changed, 46 insertions(+), 126 deletions(-) delete mode 100644 sources_list_legacy.tmpl delete mode 100644 sources_list_modern.tmpl diff --git a/main.go b/main.go index 3ad5d1a..02f2462 100644 --- a/main.go +++ b/main.go @@ -33,9 +33,11 @@ func CLIEntry() { log.Fatal(err) } - // Create sources.list.d directory if it doesn't exist - if err := createSourcesListD(); err != nil { - log.Fatal(err) + oldMirrorURL, err := findMirrorURLInFile(sourcesFilePath) + + if err != nil { + // redundant + log.Fatalf("Failed to find mirror URL in file %s: %v", sourcesFilePath, err) } // Fetch and find the fastest mirror @@ -48,8 +50,12 @@ func CLIEntry() { // Display latency statistics displayLatencyStatistics(latencies, fastestMirrorURL, fastestTime) + if err != nil { + log.Fatalf("Failed to find mirror URL in file %s: %v", sourcesFilePath, err) + } + // Update sources file with the fastest mirror - if err := updateSourcesFile(sourcesFilePath, fastestMirrorURL, suites); err != nil { + if err := updateSourcesFile(sourcesFilePath, oldMirrorURL, fastestMirrorURL); err != nil { log.Fatal(err) } log.Println("Fastmirror CLI finished successfully") diff --git a/mirror.go b/mirror.go index dce1a52..6ca4e3e 100644 --- a/mirror.go +++ b/mirror.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/schollz/progressbar/v3" + progressbar "github.com/schollz/progressbar/v3" ) func findFastestMirror(suites []string) (string, time.Duration, []time.Duration, error) { @@ -33,7 +33,6 @@ func findFastestMirror(suites []string) (string, time.Duration, []time.Duration, downCount := 0 noIndexCount := 0 - codename, err := getUbuntuCodename() if err != nil { return "", 0, nil, err } @@ -52,7 +51,7 @@ func findFastestMirror(suites []string) (string, time.Duration, []time.Duration, if strings.HasPrefix(mirror, "https://") { mirror = strings.TrimSuffix(mirror, "/") startTime := time.Now() - isValid := isValidMirror(httpClient, mirror, codename, suites) + isValid := isValidMirror(httpClient, mirror, suites) elapsedTime := time.Since(startTime) if isValid { @@ -80,7 +79,7 @@ func findFastestMirror(suites []string) (string, time.Duration, []time.Duration, return fastestMirrorURL, fastestTime, latencies, nil } -func isValidMirror(httpClient http.Client, mirrorURL, codename string, suites []string) bool { +func isValidMirror(httpClient http.Client, mirrorURL string, suites []string) bool { for _, suite := range suites { uri := fmt.Sprintf("%s/dists/%s/Release", mirrorURL, suite) resp, err := httpClient.Get(uri) diff --git a/sources.go b/sources.go index deae704..a26f967 100644 --- a/sources.go +++ b/sources.go @@ -4,19 +4,13 @@ import ( "bufio" _ "embed" "fmt" - "html/template" "log" "os" "path/filepath" + "regexp" "strings" ) -//go:embed sources_list_legacy.tmpl -var legacyTemplate string - -//go:embed sources_list_modern.tmpl -var modernTemplate string - func findSourcesFilePath() (string, error) { const sourcesListPath = "/etc/apt/sources.list" const sourcesListDPath = "/etc/apt/sources.list.d/" @@ -24,6 +18,7 @@ func findSourcesFilePath() (string, error) { log.Printf("Found Ubuntu sources file: %s", sourcesListPath) return sourcesListPath, nil } + files, err := os.ReadDir(sourcesListDPath) if err != nil { return "", fmt.Errorf("failed to read directory %s: %v", sourcesListDPath, err) @@ -43,14 +38,28 @@ func findSourcesFilePath() (string, error) { return "", fmt.Errorf("no Ubuntu sources file found") } -func isUbuntuSourcesFile(filePath string) bool { - content, err := os.ReadFile(filePath) +var ubuntuMirrorURLRegex = regexp.MustCompile(`http://((?P[a-z]{2})\.)?(archive|ports)\.ubuntu\.com/(?P.*)`) + +func findMirrorURLInFile(filePath string) (string, error) { + fileContent, err := os.ReadFile(filePath) if err != nil { - log.Printf("Failed to read file %s: %v", filePath, err) + return "", fmt.Errorf("failed to read file %s: %v", filePath, err) + } + match := ubuntuMirrorURLRegex.FindString(string(fileContent)) + if match != "" { + return match, nil + } + return "", fmt.Errorf("no URL found in file %s", filePath) +} + +func isUbuntuSourcesFile(filePath string) bool { + match, err := findMirrorURLInFile(filePath) + if err != nil { + log.Printf("Failed to find OEM mirror URL in file %s: %v", filePath, err) return false } - - return strings.Contains(strings.ToLower(string(content)), "ubuntu.com") + log.Printf("Found OEM mirror URL in file %s: %s", filePath, match) + return true } func createBackup(filePath string) error { @@ -65,17 +74,6 @@ func createBackup(filePath string) error { return nil } -func createSourcesListD() error { - const sourcesListDPath = "/etc/apt/sources.list.d/" - if _, err := os.Stat(sourcesListDPath); os.IsNotExist(err) { - if err := os.Mkdir(sourcesListDPath, 0755); err != nil { - return fmt.Errorf("failed to create directory %s: %v", sourcesListDPath, err) - } - log.Printf("Created directory: %s", sourcesListDPath) - } - return nil -} - func extractSuites(filePath string) ([]string, error) { content, err := os.ReadFile(filePath) if err != nil { @@ -121,56 +119,24 @@ func extractSuites(filePath string) ([]string, error) { return suites, nil } -func updateSourcesFile(filePath, mirrorURL string, suites []string) error { - codename, err := getUbuntuCodename() +func updateSourcesFile(filePath, oldMirrorURL, newMirrorURL string) error { + file, err := os.Open(filePath) if err != nil { - return err + return fmt.Errorf("failed to open sources file %s: %v", filePath, err) } - majorVersion, minorVersion, err := getUbuntuVersion() + file.Close() + contentBytes, err := os.ReadFile(filePath) if err != nil { - return err + return fmt.Errorf("failed to read sources file %s: %v", filePath, err) } - suitesString := strings.Join(suites, " ") + log.Printf("update: replacing %s with %s in %s", oldMirrorURL, newMirrorURL, filePath) + // replace old mirror URL with new mirror URL + content := string(contentBytes) + content = strings.ReplaceAll(content, oldMirrorURL, newMirrorURL) - var content string - data := struct { - MirrorURL string - Codename string - Suites string - }{ - MirrorURL: mirrorURL, - Codename: codename, - Suites: suitesString, - } - - if majorVersion > 24 || (majorVersion == 24 && minorVersion >= 4) { - tmpl, err := template.New("modern").Parse(modernTemplate) - if err != nil { - return fmt.Errorf("failed to parse modern template: %v", err) - } - var buf strings.Builder - err = tmpl.Execute(&buf, data) - if err != nil { - return fmt.Errorf("failed to execute modern template: %v", err) - } - content = buf.String() - } else { - tmpl, err := template.New("legacy").Parse(legacyTemplate) - if err != nil { - return fmt.Errorf("failed to parse legacy template: %v", err) - } - var buf strings.Builder - err = tmpl.Execute(&buf, data) - if err != nil { - return fmt.Errorf("failed to execute legacy template: %v", err) - } - content = buf.String() - } - - err = os.WriteFile(filePath, []byte(content), 0644) - if err != nil { - return fmt.Errorf("failed to update sources file %s: %v", filePath, err) + if err := os.WriteFile(filePath, []byte(content), 0644); err != nil { + return fmt.Errorf("failed to write sources file %s: %v", filePath, err) } log.Printf("Updated sources file: %s", filePath) return nil diff --git a/sources_list_legacy.tmpl b/sources_list_legacy.tmpl deleted file mode 100644 index 26ae018..0000000 --- a/sources_list_legacy.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -deb {{.MirrorURL}} {{.Codename}} {{.Suites}} -deb {{.MirrorURL}} {{.Codename}}-updates {{.Suites}} -deb {{.MirrorURL}} {{.Codename}}-backports {{.Suites}} -deb {{.MirrorURL}} {{.Codename}}-security {{.Suites}} - diff --git a/sources_list_modern.tmpl b/sources_list_modern.tmpl deleted file mode 100644 index 4826bcf..0000000 --- a/sources_list_modern.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -Types: deb -URIs: {{.MirrorURL}} -Suites: {{.Codename}} {{.Codename}}-updates {{.Codename}}-backports -Components: {{.Suites}} -Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg - -## Ubuntu security updates. Aside from URIs and Suites, -## this should mirror your choices in the previous section. -Types: deb -URIs: {{.MirrorURL}} -Suites: {{.Codename}}-security -Components: {{.Suites}} -Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg - diff --git a/ubuntu.go b/ubuntu.go index f4eb9ee..bc90348 100644 --- a/ubuntu.go +++ b/ubuntu.go @@ -3,41 +3,9 @@ package fastmirror import ( "fmt" "os/exec" - "strconv" "strings" ) -func getUbuntuCodename() (string, error) { - cmd := exec.Command("lsb_release", "-cs") - output, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("failed to run lsb_release: %v", err) - } - return strings.TrimSpace(string(output)), nil -} - -func getUbuntuVersion() (int, int, error) { - cmd := exec.Command("lsb_release", "-rs") - output, err := cmd.Output() - if err != nil { - return 0, 0, fmt.Errorf("failed to run lsb_release: %v", err) - } - version := strings.TrimSpace(string(output)) - parts := strings.Split(version, ".") - if len(parts) != 2 { - return 0, 0, fmt.Errorf("unexpected version format: %s", version) - } - majorVersion, err := strconv.Atoi(parts[0]) - if err != nil { - return 0, 0, fmt.Errorf("failed to parse major version: %v", err) - } - minorVersion, err := strconv.Atoi(parts[1]) - if err != nil { - return 0, 0, fmt.Errorf("failed to parse minor version: %v", err) - } - return majorVersion, minorVersion, nil -} - func isUbuntu() error { cmd := exec.Command("lsb_release", "-is") output, err := cmd.Output()