package fileutils
import (
"context"
"errors"
"fmt"
"path"
"github.com/sirupsen/logrus"
"github.com/lima-vm/lima/v2/pkg/downloader"
"github.com/lima-vm/lima/v2/pkg/limatype"
)
var ErrSkipped = errors.New("skipped to download")
func DownloadFile(ctx context.Context, dest string, f limatype.File, decompress bool, description string, expectedArch limatype.Arch) (string, error) {
if f.Arch != expectedArch {
return "", fmt.Errorf("%w: %q: unsupported arch: %q", ErrSkipped, f.Location, f.Arch)
}
fields := logrus.Fields{"location": f.Location, "arch": f.Arch, "digest": f.Digest}
logrus.WithFields(fields).Infof("Attempting to download %s", description)
res, err := downloader.Download(ctx, dest, f.Location,
downloader.WithCache(),
downloader.WithDecompress(decompress),
downloader.WithDescription(fmt.Sprintf("%s (%s)", description, path.Base(f.Location))),
downloader.WithExpectedDigest(f.Digest),
)
if err != nil {
return "", fmt.Errorf("failed to download %q: %w", f.Location, err)
}
logrus.Debugf("res.ValidatedDigest=%v", res.ValidatedDigest)
switch res.Status {
case downloader.StatusDownloaded:
logrus.Infof("Downloaded %s from %q", description, f.Location)
case downloader.StatusUsedCache:
logrus.Infof("Using cache %q", res.CachePath)
default:
logrus.Warnf("Unexpected result from downloader.Download(): %+v", res)
}
return res.CachePath, nil
}
func CachedFile(f limatype.File) (string, error) {
res, err := downloader.Cached(f.Location,
downloader.WithCache(),
downloader.WithExpectedDigest(f.Digest))
if err != nil {
return "", fmt.Errorf("cache did not contain %q: %w", f.Location, err)
}
return res.CachePath, nil
}
func Errors(errs []error) error {
var finalErr error
for _, err := range errs {
if errors.Is(err, ErrSkipped) {
logrus.Debug(err)
} else {
finalErr = errors.Join(finalErr, err)
}
}
if len(errs) > 0 && finalErr == nil {
finalErr = fmt.Errorf("%v", errs)
}
return finalErr
}