This is an automated email from the ASF dual-hosted git repository.

msciabarra pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/openserverless-cli.git

commit 4824e2c81a282af6919ca679403610ca1d568982
Author: Michele Sciabarra <[email protected]>
AuthorDate: Sun Jul 28 20:09:07 2024 +0200

    refactoring and cleanup
---
 README.md         |  24 ++---
 TODO.txt          |   6 +-
 Taskfile.yml      |   6 +-
 common.go         |  11 ++
 main.go           | 314 ++++++++++++++++++++++++++++++------------------------
 main_test.go      |  13 +++
 nuv.go            |  31 +++---
 prereq.go         |  30 +++---
 prereq_test.go    |  14 +--
 tests/prereq.bats |   4 +-
 version.txt       |   2 +-
 11 files changed, 258 insertions(+), 197 deletions(-)

diff --git a/README.md b/README.md
index ff70bd0..556b12c 100644
--- a/README.md
+++ b/README.md
@@ -18,21 +18,17 @@
   ~
 -->
 
-![example 
workflow](https://github.com/nuvolaris/nuv/actions/workflows/check.yml/badge.svg)
 ![Nuv Latest Release](https://badgen.net/github/release/nuvolaris/nuv/stable) 
![License](https://badgen.net/github/license/nuvolaris/nuv) 
 
 **WARNING: this is still work in progress**
 
-The code may not build, there can be errors that will destroy your hard disk 
and so on.
+The code may not build, there can be errors, and it can even destroy your hard 
disk or send you in another dimension.
 
-Also documentation and code may not be aligned, as we first write 
documentation and then write code, so you may read documentation of code that 
does not yet exist!
+Documentation is also work in progress....
 
-You have been warned!
+# `ops`, the next generation
 
-# `nuv`, the next generation
+`ops` is the OpenServerless all-mighty CLI tool.
 
-Nuv is the nuvolaris all-mighty build tool.
-
-This is a rewrite of the current build tools to make it super powerful.
 
 It is basically the [task](https://taskfile.dev) tool enhanced to support:
 
@@ -42,7 +38,7 @@ It is basically the [task](https://taskfile.dev) tool 
enhanced to support:
 - a way to create a hierarchy of taskfiles 
 - documentation for tasks powered by [docopt](http://docopt.org/)
 
-Note that to avoid an egg and chicken problem, `nuv` itself is built with his 
ancestor, `task`.
+Note that to avoid an egg and chicken problem, `ops` itself is built with his 
ancestor, `task`.
 
 - Build it with just `task build`.
 - Run tests with `task test`.
@@ -55,13 +51,11 @@ The following environment variables allows to ovverride 
certain defaults.
 
 - `DEBUG` and `TRACE` when set gives debugging and tracing informations, 
`EXTRA` appends extra arguments to the task invocation - useful when you need 
to set extra variables with a nuvopts active.
 - `NUV_ROOT` is the folder where `nuv` looks for its tasks. If not defined, it 
follows the algorithm below to find it.
-- `NUV_BIN` is the folder where `nuv` looks for binaries (external command 
line tools). If not defined, it defaults to the same directory where  `nuv` is 
located.
+- `OPS_BIN` is the folder where `nuv` looks for binaries (external command 
line tools). If not defined, it defaults to `~/.nuv/bin`
+- `OPS_CMD` is the actual command executed - defaults to the absolute path of 
the target of the symbolic link but it can be overriden.
 - `NUV_REPO` is the github repo where `nuv` downloads its tasks. If not 
defined, it defaults to `https://github.com/nuvolaris/olaris`.
 - `NUV_BRANCH` is the branch where `nuv` looks for its tasks. The branch to 
use is defined at build time and it is the base version (without the patch 
level). For example, if `nuv` is `0.3.0-morpheus` the branch to use will be 
`0.3-morpheus`.
-- `NUV_CMD` is the actual command executed - defaults to the absolute path of 
the target of the symbolic link but it can be overriden.
 - `NUV_VERSION` can be defined to set nuv's version value. It is useful to 
override version validations when updating tasks (and you know what you are 
doing). 
-- `NUV_NO_NUVOPTS` can be defined to disable nuvopts parsing. Useful to test 
hidden tasks. When this is enabled it also shows all the tasks instead of just 
those with a description.
-- `NUV_PORT` is the port where `nuv` will run the web server. If not defined, 
it defaults to `9678`.
 - `NUV_TMP` is a temporary folder where you can store temp files - defaults to 
`~/.nuv/tmp`
 - `NUV_APIHOST` is the host for `nuv -login`. It is used in place of the first 
argument of `nuv -login`. If empty, the command will expect the first argument 
to be the apihost.
 - `NUV_USER`: set the username for `nuv -login`. The default is `nuvolaris`. 
It can be overriden by passing the username as an argument to `nuv -login` or 
by setting the environment variable.
@@ -69,6 +63,10 @@ The following environment variables allows to ovverride 
certain defaults.
 - `NUV_PWD` is the folder where `nuv` is executed (the current working 
directory). It is used to preserve the original working directory when `nuv` is 
used again in tasks (e.g. nuv -realpath to retrieve the correct path). Change 
it only if you know what you are doing!
 - `NUV_ROOT_PLUGIN` is the folder where `nuv` looks for plugins. If not 
defined, it defaults to the same directory where  `nuv` is located.
 - `NUV_OLARIS` holds the head commit hash of the used olaris repo. You can see 
the hash with `nuv -info`.
+- `NUV_PORT` is the port where `nuv` will run embedde web server for the 
configurator. If not defined, it defaults to `9678`.
+- `NUV_NO_NUVOPTS` can be defined to disable nuvopts parsing. Useful to test 
hidden tasks. When this is enabled it also shows all the tasks instead of just 
those with a description.
+- `OPS_NO_PREREQ` disable downloading of prerequisites - you have to ensure at 
least coreutils is in the path...
+
 
 ## Where `nuv` looks for binaries 
 - `NUV_USE_COREUTILS` enables the use of 
[coreutils](https://github.com/uutils/coreutils) instead of the current unix 
tools implementation. They will eventually replace the current tools.
diff --git a/TODO.txt b/TODO.txt
index 069b826..a6b58c8 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,8 +1,8 @@
 * recompile
 * upgrade task and sh
-- udpdate wsk and task
+* udpdate wsk and task
 
-- remove old stuff
+* remove old stuff
 js (goja&c)
 mkdir
 realpath
@@ -10,12 +10,12 @@ zipf
 deploy
 someutils
 
-
 - apply diff one by one to sh and task
 
 - run tests and subtests
 
 - move everything in the ops package and add cmd/ops/main.go
+
 - rename all nuv in ops
 
 - move the documentation in place
diff --git a/Taskfile.yml b/Taskfile.yml
index 233cbd1..109e5c7 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -83,9 +83,9 @@ tasks:
     desc: unit test nuv
     cmds:
       - rm -Rf ~/.nuv/olaris
-      - go test github.com/apache/openserverless-cli
-      - go test github.com/apache/openserverless-cli/config
-      - go test github.com/apache/openserverless-cli/tools  
+      - go test -v github.com/apache/openserverless-cli
+      - go test -v github.com/apache/openserverless-cli/config
+      - go test -v github.com/apache/openserverless-cli/tools  
       - echo TODO go test github.com/apache/openserverless-cli/auth
       
 
diff --git a/common.go b/common.go
index f1cb9fe..62852f2 100644
--- a/common.go
+++ b/common.go
@@ -184,3 +184,14 @@ func debugf(format string, args ...any) {
                log.Printf("DEBUG: "+format+"\n", args...)
        }
 }
+
+func touch(dir string, name string) error {
+       tgt := filepath.Join(dir, name)
+       trace("touch", tgt)
+       f, err := os.Create(tgt)
+       if err != nil {
+               return err
+       }
+       f.Close()
+       return nil
+}
diff --git a/main.go b/main.go
index 5aa4f59..6932455 100644
--- a/main.go
+++ b/main.go
@@ -37,8 +37,8 @@ import (
 )
 
 func setupCmd(me string) (string, error) {
-       if os.Getenv("NUV_CMD") != "" {
-               return os.Getenv("NUV_CMD"), nil
+       if os.Getenv("OPS_CMD") != "" {
+               return os.Getenv("OPS_CMD"), nil
        }
 
        // look in path
@@ -66,30 +66,29 @@ func setupCmd(me string) (string, error) {
        if err != nil {
                return "", err
        }
-       trace("ME:", me)
        //nolint:errcheck
-       os.Setenv("NUV_CMD", me)
+       os.Setenv("OPS_CMD", me)
+       trace("OPS_CMD:", me)
        return me, nil
 }
 
-func setupBinPath(cmd string) {
+func setupBinPath() error {
        // initialize tools (used by the shell to find myself)
-       if os.Getenv("NUV_BIN") == "" {
-               os.Setenv("NUV_BIN", filepath.Dir(cmd))
-       }
-       os.Setenv("PATH", fmt.Sprintf("%s%c%s", os.Getenv("NUV_BIN"), 
os.PathListSeparator, os.Getenv("PATH")))
-       debugf("PATH=%s", os.Getenv("PATH"))
 
-       //subpath := fmt.Sprintf("\"%s\"%c\"%s\"", os.Getenv("NUV_BIN"), 
os.PathListSeparator, joinpath(os.Getenv("NUV_BIN"), 
runtime.GOOS+"-"+runtime.GOARCH))
-       //os.Setenv("PATH", fmt.Sprintf("%s%c%s", subpath, 
os.PathListSeparator, os.Getenv("PATH")))
+       bindir, err := EnsureBindir()
+       if err != nil {
+               os.Setenv("PATH", fmt.Sprintf("%s%c%s", bindir, 
os.PathListSeparator, os.Getenv("PATH")))
+               debugf("PATH=%s", os.Getenv("PATH"))
+       }
+       return err
 }
 
 func info() {
        fmt.Println("NUV_VERSION:", NuvVersion)
        fmt.Println("NUV_BRANCH:", getNuvBranch())
-       fmt.Println("NUV_CMD:", tools.GetNuvCmd())
+       fmt.Println("OPS_CMD:", tools.GetNuvCmd())
+       fmt.Println("OPS_BIN:", os.Getenv("OPS_BIN"))
        fmt.Println("NUV_REPO:", getNuvRepo())
-       fmt.Println("NUV_BIN:", os.Getenv("NUV_BIN"))
        fmt.Println("NUV_TMP:", os.Getenv("NUV_TMP"))
        root, _ := getNuvRoot()
        fmt.Println("NUV_ROOT:", root)
@@ -97,58 +96,165 @@ func info() {
        fmt.Println("NUV_OLARIS:", os.Getenv("NUV_OLARIS"))
 }
 
+// execute the embedded tools
+// version
+// info
+// help
+// serve
+// update
+// retry
+// login
+// config
+// plugin
+func executeEmbeddedToolsAndExit(cmd string, args []string, nuvHome string) 
int {
+       if cmd == "" || cmd == "-" || cmd == "task" {
+               exitCode, err := Task(args[2:]...)
+               if err != nil {
+                       log.Println(err)
+               }
+               return exitCode
+       }
+
+       switch cmd {
+       case "version":
+               fmt.Println(NuvVersion)
+       case "v":
+               fmt.Println(NuvVersion)
+
+       case "info":
+               info()
+
+       case "help":
+               tools.Help()
+
+       case "serve":
+               nuvRootDir := getRootDirOrExit()
+               if err := Serve(nuvRootDir, args[1:]); err != nil {
+                       log.Fatalf("error: %v", err)
+               }
+
+       case "update":
+               // ok no up, nor down, let's download it
+               dir, err := pullTasks(true, true)
+               if err != nil {
+                       log.Fatalf("error: %v", err)
+               }
+               if err := setNuvOlarisHash(dir); err != nil {
+                       log.Fatal("unable to set NUV_OLARIS...", err.Error())
+               }
+
+       case "retry":
+               if err := tools.ExpBackoffRetry(args[1:]); err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+
+       case "login":
+               os.Args = args[1:]
+               loginResult, err := auth.LoginCmd()
+               if err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+
+               if loginResult == nil {
+                       os.Exit(1)
+               }
+
+               fmt.Println("Successfully logged in as " + loginResult.Login + 
".")
+               if err := wskPropertySet(loginResult.ApiHost, 
loginResult.Auth); err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+               fmt.Println("Nuvolaris host and auth set successfully. You are 
now ready to use nuv -wsk!")
+
+       case "config":
+               os.Args = args[1:]
+               nuvRootPath := joinpath(getRootDirOrExit(), NUVROOT)
+               configPath := joinpath(nuvHome, CONFIGFILE)
+               configMap, err := buildConfigMap(nuvRootPath, configPath)
+               if err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+
+               if err := config.ConfigTool(*configMap); err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+
+       case "plugin":
+               os.Args = args[1:]
+               if err := pluginTool(); err != nil {
+                       log.Fatalf("error: %s", err.Error())
+               }
+
+       default:
+               // check if it is an embedded to and invoke it
+               if tools.IsTool(cmd) {
+                       code, err := tools.RunTool(cmd, args[2:])
+                       if err != nil {
+                               log.Print(err.Error())
+                       }
+                       return code
+               }
+               // no embeded tool found
+               warn("unknown tool", "-"+cmd)
+       }
+       return 0
+}
+
 func Main() {
-       // set runtime version as environment variable
+       var err error
+
+       // disable log prefix
+       log.SetFlags(0)
+
+       // set default runtime.json
        if os.Getenv("WSK_RUNTIMES_JSON") == "" {
                os.Setenv("WSK_RUNTIMES_JSON", WSK_RUNTIMES_JSON)
-               trace(WSK_RUNTIMES_JSON)
+               trace("WSK_RUNTIMES_JSON len=", len(WSK_RUNTIMES_JSON))
        }
 
-       // set version
+       // set runtime version as environment variable
        if os.Getenv("NUV_VERSION") != "" {
                NuvVersion = os.Getenv("NUV_VERSION")
        } else {
                NuvVersion = strings.TrimSpace(NuvVersion)
        }
 
-       // disable log prefix
-       log.SetFlags(0)
-
-       var err error
+       // setup NUV_CMD
        me := os.Args[0]
-       if filepath.Base(me) == "ops" || filepath.Base(me) == "ops.exe" {
+       if strings.Contains("ops ops.exe nuv nuv.exe", filepath.Base(me)) {
                tools.NuvCmd, err = setupCmd(me)
                if err != nil {
                        log.Fatalf("cannot setup cmd: %s", err.Error())
                }
-               setupBinPath(tools.NuvCmd)
        }
 
+       // setup home
        nuvHome, err := homedir.Expand("~/.nuv")
        if err != nil {
-               log.Fatalf("error: %s", err.Error())
+               log.Fatalf("cannot setup home: %s", err.Error())
        }
 
-       // Check if olaris exists. If not, run `-update` to auto setup
-       olarisDir := joinpath(joinpath(nuvHome, getNuvBranch()), "olaris")
-       if !isDir(olarisDir) {
-               log.Println("Welcome to nuv! Setting up...")
-               dir, err := pullTasks(true, true)
-               if err != nil {
-                       log.Fatalf("error: %v", err)
-               }
-               if err := setNuvOlarisHash(dir); err != nil {
-                       warn("unable to set NUV_OLARIS...", err.Error())
-               }
+       // add ~/.nuv/bin to the path at the beginng
+       err = setupBinPath()
+       if err != nil {
+               log.Fatalf("cannot setup PATH: %s", err.Error())
        }
 
-       setupTmp()
-       setNuvPwdEnv()
-       setNuvRootPluginEnv()
-       if err := setNuvOlarisHash(olarisDir); err != nil {
-               warn("unable to set NUV_OLARIS...", err.Error())
+       // ensure there is ~/.nuv/tmp
+       err = setupTmp()
+       if err != nil {
+               log.Fatalf("cannot setup NUV_TMP: %s", err.Error())
        }
 
+       //  setup the NUV_PWD variable
+       err = setNuvPwdEnv()
+       if err != nil {
+               log.Fatalf("cannot setup NUV_PWD: %s", err.Error())
+       }
+
+       // set the rootdir for plugins
+       setNuvRootPluginEnv()
+
+       // set the environemnt variables from the config
        nuvRootDir := getRootDirOrExit()
        debug("nuvRootDir", nuvRootDir)
        err = setAllConfigEnvVars(nuvRootDir, nuvHome)
@@ -156,108 +262,17 @@ func Main() {
                log.Fatalf("cannot apply env vars from configs: %s", 
err.Error())
        }
 
-       // first argument with prefix "-" is an embedded tool
-       // using "-" or "--" or "-task" invokes embedded task
-       trace("OS args:", os.Args)
+       // first argument with prefix "-" is considered an embedded tool
+       // using "-" or "--" or "-task" invokes the embedded task
        args := os.Args
-
        if len(args) > 1 && len(args[1]) > 0 && args[1][0] == '-' {
                cmd := args[1][1:]
-               if cmd == "" || cmd == "-" || cmd == "task" {
-                       exitCode, err := Task(args[2:]...)
-                       if err != nil {
-                               log.Println(err)
-                       }
-                       os.Exit(exitCode)
-               }
-
-               switch cmd {
-               case "version":
-                       fmt.Println(NuvVersion)
-               case "v":
-                       fmt.Println(NuvVersion)
-
-               case "info":
-                       info()
-
-               case "help":
-                       tools.Help()
-
-               case "serve":
-                       nuvRootDir := getRootDirOrExit()
-                       if err := Serve(nuvRootDir, args[1:]); err != nil {
-                               log.Fatalf("error: %v", err)
-                       }
-
-               case "update":
-                       // ok no up, nor down, let's download it
-                       dir, err := pullTasks(true, true)
-                       if err != nil {
-                               log.Fatalf("error: %v", err)
-                       }
-                       if err := setNuvOlarisHash(dir); err != nil {
-                               log.Fatal("unable to set NUV_OLARIS...", 
err.Error())
-                       }
-
-               case "retry":
-                       if err := tools.ExpBackoffRetry(args[1:]); err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-
-               case "login":
-                       os.Args = args[1:]
-                       loginResult, err := auth.LoginCmd()
-                       if err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-
-                       if loginResult == nil {
-                               os.Exit(1)
-                       }
-
-                       fmt.Println("Successfully logged in as " + 
loginResult.Login + ".")
-                       if err := wskPropertySet(loginResult.ApiHost, 
loginResult.Auth); err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-                       fmt.Println("Nuvolaris host and auth set successfully. 
You are now ready to use nuv -wsk!")
-
-               case "config":
-                       os.Args = args[1:]
-                       nuvRootPath := joinpath(getRootDirOrExit(), NUVROOT)
-                       configPath := joinpath(nuvHome, CONFIGFILE)
-                       configMap, err := buildConfigMap(nuvRootPath, 
configPath)
-                       if err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-
-                       if err := config.ConfigTool(*configMap); err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-
-               case "plugin":
-                       os.Args = args[1:]
-                       if err := pluginTool(); err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-
-               default:
-                       // check if it is an embedded to and invoke it
-                       if tools.IsTool(cmd) {
-                               code, err := tools.RunTool(cmd, args[2:])
-                               if err != nil {
-                                       log.Print(err.Error())
-                               }
-                               os.Exit(code)
-                       }
-                       // no embeded tool found
-                       warn("unknown tool", "-"+cmd)
-               }
-               os.Exit(0)
+               trace("executing embedded tool", cmd, args)
+               // execute the embeded tool and exit
+               exitCode := executeEmbeddedToolsAndExit(cmd, args, nuvHome)
+               os.Exit(exitCode)
        }
 
-       // check if olaris was recently updated
-       checkUpdated(nuvHome, 24*time.Hour)
-
        // in case args[1] is a wsk wrapper command
        // invoke it and exit
        if len(args) > 1 {
@@ -283,8 +298,25 @@ func Main() {
        if err := preflightChecks(); err != nil {
                log.Fatalf("[PREFLIGHT CHECK] error: %s", err.Error())
        }
+
        // ***************
 
+       // Check if olaris exists. If not,  pull tasks to auto setup
+       olarisDir := joinpath(joinpath(nuvHome, getNuvBranch()), "olaris")
+       if !isDir(olarisDir) {
+               log.Println("Welcome to nuv! Setting up...")
+               _, err = pullTasks(true, true)
+               if err != nil {
+                       log.Fatalf("error: %v", err)
+               }
+               if err := setNuvOlarisHash(olarisDir); err != nil {
+                       warn("unable to set NUV_OLARIS...", err.Error())
+               }
+       }
+
+       // check if olaris was recently updated
+       checkUpdated(nuvHome, 24*time.Hour)
+
        if err := runNuv(nuvRootDir, args); err != nil {
                log.Fatalf("error: %s", err.Error())
        }
@@ -380,13 +412,17 @@ func setNuvRootPluginEnv() {
        trace("set NUV_ROOT_PLUGIN", os.Getenv("NUV_ROOT_PLUGIN"))
 }
 
-func setNuvPwdEnv() {
+func setNuvPwdEnv() error {
        if os.Getenv("NUV_PWD") == "" {
-               dir, _ := os.Getwd()
+               dir, err := os.Getwd()
+               if err != nil {
+                       return err
+               }
                //nolint:errcheck
                os.Setenv("NUV_PWD", dir)
        }
        trace("set NUV_PWD", os.Getenv("NUV_PWD"))
+       return nil
 }
 
 func buildConfigMap(nuvRootPath string, configPath string) (*config.ConfigMap, 
error) {
diff --git a/main_test.go b/main_test.go
index 6b5e4d5..c1b6cdd 100644
--- a/main_test.go
+++ b/main_test.go
@@ -34,6 +34,19 @@ func pr(args ...any) {
        fmt.Println(args...)
 }
 
+func after(where, all string) string {
+       // Find the index of the first occurrence of `where` in `all`
+       index := strings.Index(all, where)
+
+       // If `where` is not found, return an empty string
+       if index == -1 {
+               return all
+       }
+
+       // Return the substring after `where`
+       return all[index+len(where):]
+}
+
 // as creates a string array
 // func as(s ...string) []string {
 //     return s
diff --git a/nuv.go b/nuv.go
index 0efc60b..8433880 100644
--- a/nuv.go
+++ b/nuv.go
@@ -101,25 +101,18 @@ func parseArgs(usage string, args []string) []string {
        return res
 }
 
-// setupTmp sets up a tmp folder
-func setupTmp() {
-       // setup NUV_TMP
+// sets up a tmp folder and NUV_TMP envvar
+func setupTmp() error {
        var err error
        tmp := os.Getenv("NUV_TMP")
        if tmp == "" {
                tmp, err = homedir.Expand("~/.nuv/tmp")
-               if err == nil {
-                       //nolint:errcheck
-                       os.Setenv("NUV_TMP", tmp)
+               if err != nil {
+                       return err
                }
+               os.Setenv("NUV_TMP", tmp)
        }
-       if err == nil {
-               err = os.MkdirAll(tmp, 0755)
-       }
-       if err != nil {
-               warn("cannot create tmp dir", err)
-               os.Exit(1)
-       }
+       return os.MkdirAll(tmp, 0755)
 }
 
 // load saved args in files names _*_ in current directory
@@ -174,7 +167,11 @@ func Nuv(base string, args []string) error {
 
        isSubCmd := false
 
-       ensurePrereq()
+       err = ensurePrereq()
+       if err != nil {
+               fmt.Println("ERROR: cannot ensure prerequisites: " + 
err.Error())
+               os.Exit(1)
+       }
        for _, task := range args {
                trace("task name", task)
 
@@ -194,7 +191,11 @@ func Nuv(base string, args []string) error {
                        if err := os.Chdir(taskName); err != nil {
                                return err
                        }
-                       ensurePrereq()
+                       err = ensurePrereq()
+                       if err != nil {
+                               fmt.Println("ERROR: cannot ensure 
prerequisites" + err.Error())
+                               os.Exit(1)
+                       }
                        //remove it from the args
                        rest = rest[1:]
                        isSubCmd = true
diff --git a/prereq.go b/prereq.go
index bb87a4d..65b5b19 100644
--- a/prereq.go
+++ b/prereq.go
@@ -5,6 +5,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "runtime"
        "strings"
 
        "github.com/mitchellh/go-homedir"
@@ -75,8 +76,16 @@ func loadPrereq() (Prereq, error) {
 }
 
 // ensure there is a bindir for downloading prerequisites
-func ensureBindir() (string, error) {
-       bindir, err := homedir.Expand("~/.nuv/bin")
+// read it from OPS_BIN and create it
+// otherwise setup one in ~/nuv/<os>-<arch>/bin
+// and sets OPS_BIN
+func EnsureBindir() (string, error) {
+       var err error = nil
+       bindir := os.Getenv("OPS_BIN")
+       if bindir == "" {
+               bindir, err = homedir.Expand(fmt.Sprintf("~/.nuv/%s-%s/bin", 
runtime.GOOS, runtime.GOARCH))
+               os.Setenv("OP_BIN", bindir)
+       }
        if err != nil {
                return "", err
        }
@@ -88,17 +97,6 @@ func ensureBindir() (string, error) {
        return bindir, nil
 }
 
-func touch(dir string, name string) error {
-       tgt := filepath.Join(dir, name)
-       trace("touch", tgt)
-       f, err := os.Create(tgt)
-       if err != nil {
-               return err
-       }
-       f.Close()
-       return nil
-}
-
 // create a mark of current version touching <name>-<version> and remove all 
the other files starting with <name>-
 func touchAndClean(dir string, name string, version string) error {
 
@@ -137,7 +135,7 @@ func downloadPrereq(name string, task PrereqTask) error {
                return nil
        }
 
-       bindir, err := ensureBindir()
+       bindir, err := EnsureBindir()
        if err != nil {
                return err
        }
@@ -179,6 +177,10 @@ func downloadPrereq(name string, task PrereqTask) error {
 
 // ensure prereq are satified looking at the prereq.yml
 func ensurePrereq() error {
+       // skip prereq - useful for tests
+       if os.Getenv("OPS_NO_PREREQ") != "" {
+               return nil
+       }
        trace("ensurePrereq")
        prereq, err := loadPrereq()
        for task := range prereq.Tasks {
diff --git a/prereq_test.go b/prereq_test.go
index 22c9fb9..7e34ab5 100644
--- a/prereq_test.go
+++ b/prereq_test.go
@@ -30,22 +30,22 @@ func Example_loadPrereq() {
 }
 
 func Example_ensureBindir() {
-       bindir, _ := homedir.Expand("~/.nuv/bin")
+       bindir, _ := EnsureBindir()
        os.RemoveAll(bindir)
        _, err1 := os.Stat(bindir)
-       bindir1, _ := ensureBindir()
+       bindir1, _ := EnsureBindir()
        _, err2 := os.Stat(bindir)
-       fmt.Printf("no dir: %s\ncreated: %t\nyes dir: %v\n", 
nhpath(err1.Error()), bindir1 == bindir, err2)
+       fmt.Printf("no dir:%s\ncreated: %t\nyes dir: %v\n", after(":", 
err1.Error()), bindir1 == bindir, err2)
        // Output:
-       // no dir: stat /home/.nuv/bin: no such file or directory
+       // no dir: no such file or directory
        // created: true
        // yes dir: <nil>
 }
 
 func Example_touchAndClean() {
-       bindir, _ := ensureBindir()
+       bindir, _ := EnsureBindir()
        os.RemoveAll(bindir)
-       bindir, _ = ensureBindir()
+       bindir, _ = EnsureBindir()
        touch(bindir, "hello")
        err := touchAndClean(bindir, "hello", "1.2.3")
        fmt.Println(err, exists(bindir, "hello"), exists(bindir, 
"hello-1.2.3"), exists(bindir, "hello-1.2.4"))
@@ -81,7 +81,7 @@ func Example_downloadPrereq() {
 }
 
 func Example_ensurePrereq() {
-       bindir, _ := homedir.Expand("~/.nuv/bin")
+       bindir, _ := EnsureBindir()
        os.RemoveAll(bindir)
        os.Chdir(workDir)
        os.Chdir("tests")
diff --git a/tests/prereq.bats b/tests/prereq.bats
index b6d9df8..36d8cd1 100644
--- a/tests/prereq.bats
+++ b/tests/prereq.bats
@@ -19,8 +19,8 @@ setup() {
     load 'test_helper/bats-support/load'
     load 'test_helper/bats-assert/load'
     export NO_COLOR=1
-    export NUV_BRANCH="0.3.0"
-  
+    export NUV_BRANCH="0.1.0-testing"
+    rm -Rvf ~/.nuv
 }
 
 #@test "ops prereq" {
diff --git a/version.txt b/version.txt
index 9bcce31..f2c21b4 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.1.0-testing.2407271736
+0.1.0-testing.2407281938

Reply via email to