92 lines
1.9 KiB
Go
92 lines
1.9 KiB
Go
|
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)
|
||
|
}
|