From ff2d140e5adbea2c6013cfe8f7fbff0f55c837f2 Mon Sep 17 00:00:00 2001 From: Meili C Date: Tue, 12 Nov 2024 13:32:00 -0900 Subject: [PATCH] feat: add "run" command to invoke a compiler this commit adds a "run" command to zvm that allows you to invoke a zig compiler via its version name. for example: `zvm run 0.14.0 build run --help` which is useful if you switch around projects a lot and just want to run a single command without symlinking the version first. --- README.md | 2 ++ cli/meta/exec.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ cli/run.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 40 +++++++++++++++++++++++++----------- 4 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 cli/meta/exec.go create mode 100644 cli/run.go diff --git a/README.md b/README.md index e9af269..dc0f91c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ like), then ZVM will update the exact executable you've called `upgrade` from. ```sh curl https://raw.githubusercontent.com/tristanisham/zvm/master/install.sh | bash +# Or +go install -ldflags "-s -w" github.com/tristanisham/zvm@latest ``` diff --git a/cli/meta/exec.go b/cli/meta/exec.go new file mode 100644 index 0000000..e96f460 --- /dev/null +++ b/cli/meta/exec.go @@ -0,0 +1,53 @@ +// Copyright 2022 Tristan Isham. All rights reserved. +// Use of this source code is governed by the MIT +// license that can be found in the LICENSE file. +package meta + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +// Execute the given Zig command with a specified compiler +func Exec(bin string, cmd []string) error { + // zvm run 0.14.0 build run --help + if bin == "" { + return fmt.Errorf("compiler binary cannot be empty") + } + + zig := exec.Command(bin, cmd...) + zig.Stdin, zig.Stdout, zig.Stderr = os.Stdin, os.Stdout, os.Stderr + + err := zig.Run() + if err != nil { + if err, ok := err.(*exec.ExitError); ok { + os.Exit(err.ExitCode()) + } else { + return fmt.Errorf("Error executing command '%s': %s\n", cmd, err) + } + } + + return nil +} + +// Execute the given Zig command with a specified compiler +// This is a convenience function that will automatically split a +// command and execute it +func ExecString(cmd string) error { + command := strings.Split(cmd, " ") + if len(command) < 1 { + return fmt.Errorf("No command given") + } + + zig := exec.Command(command[0], command[1:]...) + zig.Stdin, zig.Stdout, zig.Stderr = os.Stdin, os.Stdout, os.Stderr + + err := zig.Run() + if err != nil { + return fmt.Errorf("Error executing command '%s': %s\n", cmd, err) + } + + return nil +} diff --git a/cli/run.go b/cli/run.go new file mode 100644 index 0000000..7b8b426 --- /dev/null +++ b/cli/run.go @@ -0,0 +1,53 @@ +// Copyright 2022 Tristan Isham. All rights reserved. +// Use of this source code is governed by the MIT +// license that can be found in the LICENSE file. +package cli + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/tristanisham/zvm/cli/meta" +) + +// Run the given Zig compiler with the provided arguments +func (z *ZVM) Run(ver string, cmd []string) error { + if err := z.getVersion(ver); err != nil { + if errors.Is(err, os.ErrNotExist) { + + fmt.Printf("It looks like %s isn't installed. Would you like to install it first? [y/n]\n", ver) + + if getConfirmation() { + if err = z.Install(ver, false); err != nil { + return err + } + } else { + return fmt.Errorf("version %s is not installed", ver) + } + } + } + + return z.runBin(ver, cmd) +} + +func (z *ZVM) runBin(ver string, cmd []string) error { + // $ZVM_PATH/$VERSION/zig cmd + bin := filepath.Join(z.baseDir, ver, "zig") + + // Skip symlink checks, does this Zig binary exist? + stat, err := os.Stat(bin) + if err != nil { + return fmt.Errorf("%w: %s", err, stat.Name()) + } + + // the logging here really muddies up the output of the Zig compiler + // and adds a lot of noise. For that reason this function exits with + // the zig compilers exit code + if err := meta.Exec(bin, cmd); err != nil { + return err + } + + return nil +} diff --git a/main.go b/main.go index 7c1e9a6..af9287e 100644 --- a/main.go +++ b/main.go @@ -136,6 +136,22 @@ var zvmApp = &opts.App{ } }, }, + { + Name: "run", + Usage: "run a command with the given Zig version", + Args: true, + Flags: []opts.Flag{ + &opts.BoolFlag{ + Name: "sync", + Usage: "sync your current version of Zig with the repository", + }, + }, + Action: func(ctx *opts.Context) error { + versionArg := strings.TrimPrefix(ctx.Args().First(), "v") + cmd := ctx.Args().Tail() + return zvm.Run(versionArg, cmd) + }, + }, { Name: "list", Usage: "list installed Zig versions. Flag `--all` to see remote options", @@ -291,18 +307,18 @@ func main() { // run and report errors if err := zvmApp.Run(os.Args); err != nil { -// if meta.VERSION == "v0.7.9" && errors.Is(err, cli.ErrInvalidVersionMap) { -// meta.CtaGeneric("Help", `Encountered an issue while trying to install ZLS for Zig 'master'. - -// Problem: ZVM v0.7.7 and v0.7.8 may have saved an invalid 'zlsVersionMapUrl' to your settings, -// which causes this error. The latest version, v0.7.9, can fix this issue by using the correct URL. - -// To resolve this: -// 1. Open your ZVM settings file: '~/.zvm/settings.json' -// 2. Remove the 'zlsVersionMapUrl' key & value from the file (if present). -// What happens next: ZVM will automatically use the correct version map the next time you run it -// If the issue persists, please double-check your settings and try again, or create a GitHub Issue.`) -// } + // if meta.VERSION == "v0.7.9" && errors.Is(err, cli.ErrInvalidVersionMap) { + // meta.CtaGeneric("Help", `Encountered an issue while trying to install ZLS for Zig 'master'. + + // Problem: ZVM v0.7.7 and v0.7.8 may have saved an invalid 'zlsVersionMapUrl' to your settings, + // which causes this error. The latest version, v0.7.9, can fix this issue by using the correct URL. + + // To resolve this: + // 1. Open your ZVM settings file: '~/.zvm/settings.json' + // 2. Remove the 'zlsVersionMapUrl' key & value from the file (if present). + // What happens next: ZVM will automatically use the correct version map the next time you run it + // If the issue persists, please double-check your settings and try again, or create a GitHub Issue.`) + // } meta.CtaFatal(err) }