Skip to content

Commit

Permalink
Isolate environment-related code.
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouture committed Nov 20, 2021
1 parent 8c1a780 commit 87e61dc
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 37 deletions.
51 changes: 14 additions & 37 deletions cmd/nv/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 29,7 @@ import (
"syscall"

"github.com/jcouture/nv/internal/build"
"github.com/jcouture/nv/internal/parser"
"github.com/jcouture/nv/internal/env"
"github.com/mitchellh/go-homedir"
)

Expand All @@ -56,24 56,23 @@ func main() {

filenames := strings.Split(fn, ",")

vars := make(map[string]string)
base := make(map[string]string)

for _, filename := range filenames {
// Parse file
parser := parser.NewParser(filename)
parsedVars, err := parser.Parse()
override, err := env.Load(filename)
if err != nil {
fmt.Printf("[Err] %s\n", err)
os.Exit(-1)
}
// Merge with possibly existing variables
mergeVars(vars, parsedVars)
base = env.Join(base, override)
}

loadAndMergeGlobalVars(vars)
globals := loadGlobals()
base = env.Join(base, globals)

clearEnv()
setEnvVars(vars)
env.Clear()
env.Set(base)

binary, lookErr := exec.LookPath(cmd)
if lookErr != nil {
Expand All @@ -95,33 94,11 @@ func printVersion() {
fmt.Printf("nv version %s\n", build.Version)
}

func setEnvVars(vars map[string]string) {
for k, v := range vars {
os.Setenv(k, v)
}
}

func mergeVars(vars1 map[string]string, vars2 map[string]string) {
for k, v := range vars2 {
vars1[k] = v
}
}

func loadAndMergeGlobalVars(vars map[string]string) {
dir, _ := homedir.Dir()
fn := filepath.Join(dir, ".nv")
parser := parser.NewParser(fn)
parsedVars, err := parser.Parse()
if err != nil {
// Return without breaking a sweat
return
}
mergeVars(vars, parsedVars)
}
func loadGlobals() map[string]string {
hdir, _ := homedir.Dir()
fn := filepath.Join(hdir, ".nv")
// Purposefuly ignoring any errors
globals, _ := env.Load(fn)

func clearEnv() {
// Clearing everything out the environment... but $PATH (we’re savages)!
path := os.Getenv("PATH")
os.Clearenv()
os.Setenv("PATH", path)
return globals
}
56 changes: 56 additions & 0 deletions internal/env/env.go
Original file line number Diff line number Diff line change
@@ -0,0 1,56 @@
// Copyright 2015-2021 Jean-Philippe Couture
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package env

import (
"os"

"github.com/jcouture/nv/internal/parser"
)

func Set(vars map[string]string) {
for k, v := range vars {
os.Setenv(k, v)
}
}

func Join(base map[string]string, override map[string]string) map[string]string {
if len(base) == 0 {
return override
}
for k, v := range override {
base[k] = v
}

return base
}

func Load(fn string) (map[string]string, error) {
parser := parser.NewParser(fn)
return parser.Parse()
}

func Clear() {
// Clearing everything out the environment... except $PATH (we’re savages)!
path := os.Getenv("PATH")
os.Clearenv()
os.Setenv("PATH", path)
}
58 changes: 58 additions & 0 deletions internal/env/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 1,58 @@
// Copyright 2015-2021 Jean-Philippe Couture
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package env

import (
"os"
"testing"
)

func TestSet(t *testing.T) {
name := "FOO"
expected := "BAR"

vars := make(map[string]string)
vars[name] = "BAR"
Set(vars)

result := os.Getenv(name)
if result != expected {
t.Errorf("Expected: %s, got: %s\n", expected, result)
}
}

func TestJoin(t *testing.T) {
base := make(map[string]string)
base["FOO"] = "BAR"

override := make(map[string]string)
override["COLOR"] = "RED"

result := Join(base, override)

if len(result) != 2 {
t.Errorf("Expected length: 2, got: %d\n", len(result))
}

if result["FOO"] != "BAR" {
t.Errorf("Expected FOO == BAR, got FOO == %s\n", result["FOO"])
}
}

0 comments on commit 87e61dc

Please sign in to comment.