Skip to content

Commit d659043

Browse files
committed
Issue crc-org#5037 Address review feedback for bundle download command
1 parent 33a05af commit d659043

File tree

2 files changed

+86
-28
lines changed

2 files changed

+86
-28
lines changed

cmd/crc/cmd/bundle/download.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ func getDownloadCmd(config *crcConfig.Config) *cobra.Command {
5050
}
5151

5252
func runDownload(args []string, preset crcPreset.Preset, force bool) error {
53-
// Disk space check (simple check for ~10GB free)
54-
// This is a basic check, more robust checking would require syscall/windows specific implementations
55-
// We skip this for now to avoid adding heavy OS-specific deps, assuming user manages disk space or download fails naturally.
53+
if len(args) > 2 {
54+
return fmt.Errorf("too many arguments: expected at most 2 (version, architecture), got %d", len(args))
55+
}
5656

5757
// If no args, use default bundle path
5858
if len(args) == 0 {
@@ -77,7 +77,7 @@ func runDownload(args []string, preset crcPreset.Preset, force bool) error {
7777
// Check if version is partial (Major.Minor) and resolve it if necessary
7878
resolvedVersion, err := resolveOpenShiftVersion(preset, version)
7979
if err != nil {
80-
logging.Warnf("Could not resolve version %s: %v. Trying with original version string.", version, err)
80+
return fmt.Errorf("failed to resolve version %s: %w", version, err)
8181
} else if resolvedVersion != version {
8282
logging.Debugf("Resolved version %s to %s", version, resolvedVersion)
8383
version = resolvedVersion
@@ -147,8 +147,10 @@ func getVerifiedHashForCustomVersion(sigURL string, bundleName string) (string,
147147

148148
lines := strings.Split(verifiedHashes, "\n")
149149
for _, line := range lines {
150+
line = strings.TrimSpace(line)
150151
if strings.HasSuffix(line, bundleName) {
151152
sha256sum := strings.TrimSuffix(line, " "+bundleName)
153+
sha256sum = strings.TrimSpace(sha256sum)
152154
return sha256sum, nil
153155
}
154156
}

cmd/crc/cmd/bundle/prune.go

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package bundle
22

33
import (
4+
"fmt"
45
"os"
56
"path/filepath"
7+
"regexp"
68
"sort"
9+
"strconv"
710
"strings"
811

912
"github.com/crc-org/crc/v2/pkg/crc/constants"
@@ -23,6 +26,45 @@ func getPruneCmd() *cobra.Command {
2326
}
2427
}
2528

29+
type bundleVersionInfo struct {
30+
name string
31+
major int
32+
minor int
33+
patch int
34+
arch string
35+
}
36+
37+
// parseBundleVersion parses a bundle filename like "crc_vfkit_4.19.13_arm64.crcbundle"
38+
// and extracts the version parts and architecture.
39+
func parseBundleVersion(filename string) (bundleVersionInfo, error) {
40+
re := regexp.MustCompile(`^crc(?:_okd|_microshift)?_(?:vfkit|libvirt|hyperv)_(\d+)\.(\d+)\.(\d+)_([a-z0-9]+)\.crcbundle$`)
41+
matches := re.FindStringSubmatch(filename)
42+
if matches == nil {
43+
return bundleVersionInfo{}, fmt.Errorf("filename %q does not match expected bundle pattern", filename)
44+
}
45+
46+
major, err := strconv.Atoi(matches[1])
47+
if err != nil {
48+
return bundleVersionInfo{}, fmt.Errorf("invalid major version in %q: %w", filename, err)
49+
}
50+
minor, err := strconv.Atoi(matches[2])
51+
if err != nil {
52+
return bundleVersionInfo{}, fmt.Errorf("invalid minor version in %q: %w", filename, err)
53+
}
54+
patch, err := strconv.Atoi(matches[3])
55+
if err != nil {
56+
return bundleVersionInfo{}, fmt.Errorf("invalid patch version in %q: %w", filename, err)
57+
}
58+
59+
return bundleVersionInfo{
60+
name: filename,
61+
major: major,
62+
minor: minor,
63+
patch: patch,
64+
arch: matches[4],
65+
}, nil
66+
}
67+
2668
func runPrune(keep int) error {
2769
cacheDir := constants.MachineCacheDir
2870
if _, err := os.Stat(cacheDir); os.IsNotExist(err) {
@@ -35,37 +77,51 @@ func runPrune(keep int) error {
3577
return err
3678
}
3779

38-
var bundleFiles []os.DirEntry
39-
for _, file := range files {
40-
if strings.HasSuffix(file.Name(), ".crcbundle") {
41-
bundleFiles = append(bundleFiles, file)
42-
}
80+
// Group bundles by major.minor + arch
81+
type groupKey struct {
82+
major int
83+
minor int
84+
arch string
4385
}
86+
groups := make(map[groupKey][]bundleVersionInfo)
4487

45-
if len(bundleFiles) <= keep {
46-
logging.Infof("Nothing to prune (found %d bundles, keeping %d)", len(bundleFiles), keep)
47-
return nil
88+
for _, file := range files {
89+
if !strings.HasSuffix(file.Name(), ".crcbundle") {
90+
continue
91+
}
92+
info, err := parseBundleVersion(file.Name())
93+
if err != nil {
94+
logging.Debugf("Skipping unrecognized bundle file: %s", file.Name())
95+
continue
96+
}
97+
key := groupKey{major: info.major, minor: info.minor, arch: info.arch}
98+
groups[key] = append(groups[key], info)
4899
}
49100

50-
// Sort by modification time, newest first
51-
sort.Slice(bundleFiles, func(i, j int) bool {
52-
infoI, errI := bundleFiles[i].Info()
53-
infoJ, errJ := bundleFiles[j].Info()
54-
if errI != nil || errJ != nil {
55-
// If we can't get info, treat as oldest (sort to end for pruning)
56-
return errJ != nil && errI == nil
101+
pruned := false
102+
for _, bundles := range groups {
103+
if len(bundles) <= keep {
104+
continue
57105
}
58-
return infoI.ModTime().After(infoJ.ModTime())
59-
})
60-
61-
for i := keep; i < len(bundleFiles); i++ {
62-
file := bundleFiles[i]
63-
filePath := filepath.Join(cacheDir, file.Name())
64-
logging.Infof("Pruning old bundle: %s", file.Name())
65-
if err := os.RemoveAll(filePath); err != nil {
66-
logging.Errorf("Failed to remove %s: %v", filePath, err)
106+
107+
// Sort by patch version descending (newest first)
108+
sort.Slice(bundles, func(i, j int) bool {
109+
return bundles[i].patch > bundles[j].patch
110+
})
111+
112+
for i := keep; i < len(bundles); i++ {
113+
filePath := filepath.Join(cacheDir, bundles[i].name)
114+
logging.Infof("Pruning old bundle: %s", bundles[i].name)
115+
if err := os.RemoveAll(filePath); err != nil {
116+
logging.Errorf("Failed to remove %s: %v", filePath, err)
117+
}
118+
pruned = true
67119
}
68120
}
69121

122+
if !pruned {
123+
logging.Infof("Nothing to prune")
124+
}
125+
70126
return nil
71127
}

0 commit comments

Comments
 (0)