Installer/spm/download.go

92 lines
1.9 KiB
Go
Raw Normal View History

2024-12-25 08:46:25 +01:00
package spm
import (
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"runtime"
)
type Package struct {
Name string
Arch string
OS string
DownloadURL string
}
func DownloadPackage(pkg Package, destDir string) error {
UpdateProgress(0, fmt.Sprintf("Downloading %s", pkg.Name))
resp, err := http.Get(pkg.DownloadURL)
if err != nil {
return err
}
defer resp.Body.Close()
filePath := filepath.Join(destDir, filepath.Base(pkg.DownloadURL))
out, err := os.Create(filePath)
if err != nil {
return err
}
defer out.Close()
totalSize := resp.ContentLength
var downloaded int64
// Track progress as bytes are downloaded
buf := make([]byte, 1024)
for {
n, err := resp.Body.Read(buf)
if n > 0 {
downloaded += int64(n)
percentage := int(float64(downloaded) / float64(totalSize) * 100)
UpdateProgress(percentage, fmt.Sprintf("Downloading %s", pkg.Name))
if _, err := out.Write(buf[:n]); err != nil {
return err
}
}
if err == io.EOF {
break
}
if err != nil {
return err
}
}
UpdateProgress(100, fmt.Sprintf("%s downloaded", pkg.Name))
return nil
}
func FindPackage(entries []AppIndexEntry, name, release, arch, os string) (*AppIndexEntry, error) {
for _, entry := range entries {
if entry.Name == name && entry.Release == release && entry.Arch == arch && entry.OS == os {
return &entry, nil
}
}
return nil, errors.New("package not found")
}
func DownloadPackageFromAppIndex(appIndexPath, packageName, release, destDir string) error {
arch := runtime.GOARCH
osName := runtime.GOOS
entries, err := ParseAppIndex(appIndexPath)
if err != nil {
return err
}
entry, err := FindPackage(entries, packageName, release, arch, osName)
if err != nil {
return err
}
return DownloadPackage(Package{
Name: entry.Name,
Arch: entry.Arch,
OS: entry.OS,
DownloadURL: entry.DownloadURL,
}, destDir)
}