Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/pkg/fileutils/download.go
2611 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package fileutils
5
6
import (
7
"context"
8
"errors"
9
"fmt"
10
"path"
11
12
"github.com/sirupsen/logrus"
13
14
"github.com/lima-vm/lima/v2/pkg/downloader"
15
"github.com/lima-vm/lima/v2/pkg/limatype"
16
)
17
18
// ErrSkipped is returned when the downloader did not attempt to download the specified file.
19
var ErrSkipped = errors.New("skipped to download")
20
21
// DownloadFile downloads a file to the cache, optionally copying it to the destination. Returns path in cache.
22
func DownloadFile(ctx context.Context, dest string, f limatype.File, decompress bool, description string, expectedArch limatype.Arch) (string, error) {
23
if f.Arch != expectedArch {
24
return "", fmt.Errorf("%w: %q: unsupported arch: %q", ErrSkipped, f.Location, f.Arch)
25
}
26
fields := logrus.Fields{"location": f.Location, "arch": f.Arch, "digest": f.Digest}
27
logrus.WithFields(fields).Infof("Attempting to download %s", description)
28
res, err := downloader.Download(ctx, dest, f.Location,
29
downloader.WithCache(),
30
downloader.WithDecompress(decompress),
31
downloader.WithDescription(fmt.Sprintf("%s (%s)", description, path.Base(f.Location))),
32
downloader.WithExpectedDigest(f.Digest),
33
)
34
if err != nil {
35
return "", fmt.Errorf("failed to download %q: %w", f.Location, err)
36
}
37
logrus.Debugf("res.ValidatedDigest=%v", res.ValidatedDigest)
38
switch res.Status {
39
case downloader.StatusDownloaded:
40
logrus.Infof("Downloaded %s from %q", description, f.Location)
41
case downloader.StatusUsedCache:
42
logrus.Infof("Using cache %q", res.CachePath)
43
default:
44
logrus.Warnf("Unexpected result from downloader.Download(): %+v", res)
45
}
46
return res.CachePath, nil
47
}
48
49
// CachedFile checks if a file is in the cache, validating the digest if it is available. Returns path in cache.
50
func CachedFile(f limatype.File) (string, error) {
51
res, err := downloader.Cached(f.Location,
52
downloader.WithCache(),
53
downloader.WithExpectedDigest(f.Digest))
54
if err != nil {
55
return "", fmt.Errorf("cache did not contain %q: %w", f.Location, err)
56
}
57
return res.CachePath, nil
58
}
59
60
// Errors compose multiple into a single error.
61
// Errors filters out ErrSkipped.
62
func Errors(errs []error) error {
63
var finalErr error
64
for _, err := range errs {
65
if errors.Is(err, ErrSkipped) {
66
logrus.Debug(err)
67
} else {
68
finalErr = errors.Join(finalErr, err)
69
}
70
}
71
if len(errs) > 0 && finalErr == nil {
72
// errs only contains ErrSkipped
73
finalErr = fmt.Errorf("%v", errs)
74
}
75
return finalErr
76
}
77
78