From 5a43aea13bce887f9e40bb47abd0e9806c0ddcbb Mon Sep 17 00:00:00 2001 From: partisan Date: Fri, 14 Feb 2025 18:44:45 +0000 Subject: [PATCH] oopsie --- spm/download.go | 256 ++++++++++++++++++++++++------------------------ 1 file changed, 128 insertions(+), 128 deletions(-) diff --git a/spm/download.go b/spm/download.go index 30d239c..e4ad88d 100644 --- a/spm/download.go +++ b/spm/download.go @@ -1,128 +1,128 @@ -package spm - -import ( - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "runtime" - "time" -) - -// DownloadPackageFromAppIndex selects and downloads the correct package from the APPINDEX. -func DownloadPackageFromAppIndex(appIndexPath string, packageName string, release string, pkgType string, destDir string) error { - // Parse the APPINDEX - entries, err := ParseAppIndex(appIndexPath) - if err != nil { - return fmt.Errorf("failed to parse APPINDEX: %w", err) - } - - // Find the right entry - var selected *AppIndexEntry - for _, e := range entries { - if e.Name == packageName && - e.Release == release && - e.Type == pkgType && - e.OS == runtime.GOOS && - e.Arch == runtime.GOARCH { - selected = &e - break - } - } - - // Handle no matching entry - if selected == nil { - return fmt.Errorf("package not found in APPINDEX: %s (release: %s, type: %s, os: %s, arch: %s)", packageName, release, pkgType, runtime.GOOS, runtime.GOARCH) - } - - // Check if the package is already installed and up-to-date - installDir, err := GetInstallDir() - if err != nil { - return fmt.Errorf("failed to get install directory: %w", err) - } - needsUpdate, err := IsUpdateNeeded(installDir, packageName, release, selected.Version, selected.Arch, selected.OS) - if err != nil { - return fmt.Errorf("failed to check update status: %w", err) - } - if !needsUpdate { - UpdateProgress(0, "Already up-to-date, skipping download.") - return nil // Skip download - } - - // Download the package - UpdateProgress(0, fmt.Sprintf("Downloading %s %s (%s)...", packageName, selected.Version, selected.Type)) - resp, err := http.Get(selected.DownloadURL) - if err != nil { - return fmt.Errorf("failed to download package: %w", err) - } - defer resp.Body.Close() - - // Save the downloaded file - downloadedFileName := filepath.Base(selected.DownloadURL) - downloadedFilePath := filepath.Join(destDir, downloadedFileName) - - out, err := os.OpenFile(downloadedFilePath, os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return fmt.Errorf("failed to create output file: %w", err) - } - defer out.Close() - - totalSize := resp.ContentLength - var downloaded int64 - buf := make([]byte, 32*1024) // Use a larger buffer for efficiency - - for { - n, errRead := resp.Body.Read(buf) - if n > 0 { - downloaded += int64(n) - percentage := int(float64(downloaded) / float64(totalSize) * 100) - UpdateProgress(percentage, fmt.Sprintf("Downloading %s %s (%s)...", packageName, selected.Version, selected.Type)) - if _, errWrite := out.Write(buf[:n]); errWrite != nil { - return fmt.Errorf("failed to write to output file: %w", errWrite) - } - } - if errRead == io.EOF { - break - } - if errRead != nil { - return fmt.Errorf("error while reading response: %w", errRead) - } - } - - // Ensure the file handle is closed before renaming - out.Close() - - // Construct the expected filename - expectedFileName := fmt.Sprintf("%s@%s@%s@%s@%s@%s.tar.gz", - packageName, selected.Arch, selected.OS, selected.Type, selected.Release, selected.Version) - - expectedFilePath := filepath.Join(destDir, expectedFileName) - - // I dont know why is this happening, I dont want to know but sometimes some process is helding up the donwloaded files so thats why it retries here - maxRetries := 5 - for i := 0; i < maxRetries; i++ { - err = os.Rename(downloadedFilePath, expectedFilePath) - if err == nil { - break - } - - // Check if file is in use - f, checkErr := os.Open(downloadedFilePath) - if checkErr != nil { - return fmt.Errorf("file is locked by another process: %w", checkErr) - } - f.Close() - - if i < maxRetries-1 { - time.Sleep(500 * time.Millisecond) // Wait before retrying - } - } - - if err != nil { - return fmt.Errorf("failed to rename downloaded file after retries: %w", err) - } - - UpdateProgress(100, fmt.Sprintf("Downloaded %s %s (%s).", packageName, selected.Version, selected.Type)) - return nil -} +package spm + +import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "runtime" + "time" +) + +// DownloadPackageFromAppIndex selects and downloads the correct package from the APPINDEX. +func DownloadPackageFromAppIndex(appIndexPath string, packageName string, release string, pkgType string, destDir string) error { + // Parse the APPINDEX + entries, err := ParseAppIndex(appIndexPath) + if err != nil { + return fmt.Errorf("failed to parse APPINDEX: %w", err) + } + + // Find the right entry + var selected *AppIndexEntry + for _, e := range entries { + if e.Name == packageName && + e.Release == release && + e.Type == pkgType && + e.OS == runtime.GOOS && + e.Arch == runtime.GOARCH { + selected = &e + break + } + } + + // Handle no matching entry + if selected == nil { + return fmt.Errorf("package not found in APPINDEX: %s (release: %s, type: %s, os: %s, arch: %s)", packageName, release, pkgType, runtime.GOOS, runtime.GOARCH) + } + + // Check if the package is already installed and up-to-date + installDir, err := GetInstallDir() + if err != nil { + return fmt.Errorf("failed to get install directory: %w", err) + } + needsUpdate, err := IsUpdateNeeded(installDir, packageName, release, selected.Version, selected.Arch, selected.OS) + if err != nil { + return fmt.Errorf("failed to check update status: %w", err) + } + if !needsUpdate { + UpdateProgress(0, "Already up-to-date, skipping download.") + return fmt.Errorf("Already up-to-date") + } + + // Download the package + UpdateProgress(0, fmt.Sprintf("Downloading %s %s (%s)...", packageName, selected.Version, selected.Type)) + resp, err := http.Get(selected.DownloadURL) + if err != nil { + return fmt.Errorf("failed to download package: %w", err) + } + defer resp.Body.Close() + + // Save the downloaded file + downloadedFileName := filepath.Base(selected.DownloadURL) + downloadedFilePath := filepath.Join(destDir, downloadedFileName) + + out, err := os.OpenFile(downloadedFilePath, os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("failed to create output file: %w", err) + } + defer out.Close() + + totalSize := resp.ContentLength + var downloaded int64 + buf := make([]byte, 32*1024) // Use a larger buffer for efficiency + + for { + n, errRead := resp.Body.Read(buf) + if n > 0 { + downloaded += int64(n) + percentage := int(float64(downloaded) / float64(totalSize) * 100) + UpdateProgress(percentage, fmt.Sprintf("Downloading %s %s (%s)...", packageName, selected.Version, selected.Type)) + if _, errWrite := out.Write(buf[:n]); errWrite != nil { + return fmt.Errorf("failed to write to output file: %w", errWrite) + } + } + if errRead == io.EOF { + break + } + if errRead != nil { + return fmt.Errorf("error while reading response: %w", errRead) + } + } + + // Ensure the file handle is closed before renaming + out.Close() + + // Construct the expected filename + expectedFileName := fmt.Sprintf("%s@%s@%s@%s@%s@%s.tar.gz", + packageName, selected.Arch, selected.OS, selected.Type, selected.Release, selected.Version) + + expectedFilePath := filepath.Join(destDir, expectedFileName) + + // I dont know why is this happening, I dont want to know but sometimes some process is helding up the donwloaded files so thats why it retries here + maxRetries := 5 + for i := 0; i < maxRetries; i++ { + err = os.Rename(downloadedFilePath, expectedFilePath) + if err == nil { + break + } + + // Check if file is in use + f, checkErr := os.Open(downloadedFilePath) + if checkErr != nil { + return fmt.Errorf("file is locked by another process: %w", checkErr) + } + f.Close() + + if i < maxRetries-1 { + time.Sleep(500 * time.Millisecond) // Wait before retrying + } + } + + if err != nil { + return fmt.Errorf("failed to rename downloaded file after retries: %w", err) + } + + UpdateProgress(100, fmt.Sprintf("Downloaded %s %s (%s).", packageName, selected.Version, selected.Type)) + return nil +}