diff --git a/cli/config.go b/cli/config.go index 4cda455..0728370 100644 --- a/cli/config.go +++ b/cli/config.go @@ -61,6 +61,7 @@ type zigVersionMap = map[string]zigVersion // A representation of individual Zig versions type zigVersion = map[string]any + func (z *ZVM) loadVersionCache() error { ver, err := os.ReadFile(filepath.Join(z.zvmBaseDir, "versions.json")) if err != nil { @@ -97,3 +98,4 @@ func (z *ZVM) loadSettings() error { return json.Unmarshal(data, &z.Settings) } + diff --git a/cli/install.go b/cli/install.go index 0ce0d56..969ec7a 100644 --- a/cli/install.go +++ b/cli/install.go @@ -2,6 +2,8 @@ package cli import ( "archive/zip" + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "io" @@ -26,7 +28,7 @@ func (z *ZVM) Install(version string) error { return err } - req.Header.Set("User-Agent", "zvm (Zig Version Manager) v0.0.1-beta.4") + req.Header.Set("User-Agent", "zvm (Zig Version Manager) v0.1.4") client := http.DefaultClient resp, err := client.Do(req) if err != nil { @@ -87,11 +89,23 @@ func (z *ZVM) Install(version string) error { fmt.Sprintf("Downloading %s:", clr_opt_ver_str), ) - _, err = io.Copy(io.MultiWriter(out, pbar), tarReq.Body) + hash := sha256.New() + + _, err = io.Copy(io.MultiWriter(out, hash, pbar), tarReq.Body) + if err != nil { + return err + } + + shasum, err := getVersionShasum(version, &rawVersionStructure) if err != nil { return err } + fmt.Println("Checking shasum...") + if hex.EncodeToString(hash.Sum(nil)) != *shasum { + return fmt.Errorf("shasum for %v does not match expected value", version) + } + fmt.Println("Shasum's match! 🎉") // The base directory where all Zig files for the appropriate version are installed // installedVersionPath := filepath.Join(zvm, version) fmt.Println("Extracting bundle...") @@ -149,6 +163,24 @@ func getTarPath(version string, data *map[string]map[string]any) (*string, error return nil, fmt.Errorf("invalid Zig version: %s", version) } +func getVersionShasum(version string, data *map[string]map[string]any) (*string, error) { + if info, ok := (*data)[version]; ok { + arch, ops := zigStyleSysInfo() + if systemInfo, ok := info[fmt.Sprintf("%s-%s", arch, ops)]; ok { + if base, ok := systemInfo.(map[string]any); ok { + if shasum, ok := base["shasum"].(string); ok { + return &shasum, nil + } + } else { + return nil, fmt.Errorf("unable to find necessary download path") + } + } else { + return nil, fmt.Errorf("invalid/unsupported system: ARCH: %s OS: %s", arch, ops) + } + } + return nil, fmt.Errorf("invalid Zig version: %s", version) +} + func zigStyleSysInfo() (string, string) { arch := runtime.GOARCH goos := runtime.GOOS diff --git a/cli/uninstall.go b/cli/uninstall.go index 9890215..a0fe891 100644 --- a/cli/uninstall.go +++ b/cli/uninstall.go @@ -13,7 +13,7 @@ func (z *ZVM) Uninstall(ver string) error { if err := os.RemoveAll(version); err != nil { return err } - fmt.Printf("Uninstalled %s.\nRun `zvm ls` to view installed versions.\n", ver) + fmt.Printf("✔ Uninstalled %s.\nRun `zvm ls` to view installed versions.\n", ver) return nil } fmt.Printf("Version: %s not found locally.\nHere are your installed versions:\n", ver) diff --git a/main.go b/main.go index c048581..301952c 100644 --- a/main.go +++ b/main.go @@ -56,7 +56,7 @@ func main() { } } case "version", "--version", "-v": - fmt.Println("zvm v0.1.2") + fmt.Println("zvm v0.1.3") return case "help", "--help", "-h": var help string