Skip to content

Commit bd4a98a

Browse files
committed
requested changes by Greg and Mike
1 parent 4b36838 commit bd4a98a

File tree

6 files changed

+64
-59
lines changed

6 files changed

+64
-59
lines changed

internal/envir/util.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ package envir
66
import (
77
"os"
88
"strconv"
9+
"strings"
10+
11+
"slices"
912
)
1013

1114
func IsDevboxCloud() bool {
@@ -43,3 +46,31 @@ func GetValueOrDefault(key, def string) string {
4346

4447
return val
4548
}
49+
50+
// MapToPairs creates a slice of environment variable "key=value" pairs from a
51+
// map.
52+
func MapToPairs(m map[string]string) []string {
53+
pairs := make([]string, len(m))
54+
i := 0
55+
for k, v := range m {
56+
pairs[i] = k + "=" + v
57+
i++
58+
}
59+
slices.Sort(pairs) // for reproducibility
60+
return pairs
61+
}
62+
63+
// PairsToMap creates a map from a slice of "key=value" environment variable
64+
// pairs. Note that maps are not ordered, which can affect the final variable
65+
// values when pairs contains duplicate keys.
66+
func PairsToMap(pairs []string) map[string]string {
67+
vars := make(map[string]string, len(pairs))
68+
for _, p := range pairs {
69+
k, v, ok := strings.Cut(p, "=")
70+
if !ok {
71+
continue
72+
}
73+
vars[k] = v
74+
}
75+
return vars
76+
}

internal/impl/devbox.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ import (
1313
"os/exec"
1414
"path/filepath"
1515
"runtime/trace"
16-
"slices"
1716
"strconv"
1817
"strings"
1918
"text/tabwriter"
2019

20+
"slices"
21+
2122
"github.com/pkg/errors"
2223
"github.com/samber/lo"
2324
"go.jetpack.io/devbox/internal/devpkg"
@@ -26,6 +27,7 @@ import (
2627
"go.jetpack.io/devbox/internal/searcher"
2728
"go.jetpack.io/devbox/internal/shellgen"
2829
"go.jetpack.io/devbox/internal/telemetry"
30+
"golang.org/x/exp/maps"
2931

3032
"go.jetpack.io/devbox/internal/boxcli/usererr"
3133
"go.jetpack.io/devbox/internal/cmdutil"
@@ -320,7 +322,7 @@ func (d *Devbox) EnvVars(ctx context.Context) ([]string, error) {
320322
if err != nil {
321323
return nil, err
322324
}
323-
return mapToPairs(envs), nil
325+
return envir.MapToPairs(envs), nil
324326
}
325327

326328
func (d *Devbox) ShellEnvHash(ctx context.Context) (string, error) {
@@ -787,8 +789,8 @@ func (d *Devbox) computeNixEnv(ctx context.Context, usePrintDevEnvCache bool) (m
787789

788790
debug.Log("current environment PATH is: %s", env["PATH"])
789791

790-
pathStack := envpath.Stack(env)
791-
debug.Log("Original path stack is: %s", pathStack)
792+
originalEnv := make(map[string]string, len(env))
793+
maps.Copy(originalEnv, env)
792794

793795
vaf, err := d.nix.PrintDevEnv(ctx, &nix.PrintDevEnvArgs{
794796
FlakesFilePath: d.nixFlakesFilePath(),
@@ -894,7 +896,10 @@ func (d *Devbox) computeNixEnv(ctx context.Context, usePrintDevEnvCache bool) (m
894896
})
895897
debug.Log("PATH after filtering with buildInputs (%v) is: %s", buildInputs, nixEnvPath)
896898

897-
env = pathStack.PushAndUpdateEnv(env, d.projectDirHash(), nixEnvPath, d.preservePathStack)
899+
pathStack := envpath.Stack(originalEnv)
900+
pathStack.Push(env, d.projectDirHash(), nixEnvPath, d.preservePathStack)
901+
env["PATH"] = pathStack.Path(env)
902+
898903
debug.Log("New path stack is: %s", pathStack)
899904

900905
debug.Log("computed environment PATH is: %s", env["PATH"])

internal/impl/envpath/stack.go

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type stack struct {
3232

3333
func Stack(env map[string]string) *stack {
3434
stackEnv, ok := env[PathStackEnv]
35-
if !ok {
35+
if !ok || strings.TrimSpace(stackEnv) == "" {
3636
// if path stack is empty, then push the current PATH, which is the
3737
// external environment prior to any devbox-shellenv being applied to it.
3838
stackEnv = InitPathEnv
@@ -48,29 +48,33 @@ func (s *stack) String() string {
4848
return strings.Join(s.keys, ":")
4949
}
5050

51+
func (s *stack) Path(env map[string]string) string {
52+
// Look up the paths-list for each stack element, and join them together to get the final PATH.
53+
pathLists := lo.Map(s.keys, func(part string, idx int) string { return env[part] })
54+
return JoinPathLists(pathLists...)
55+
}
56+
5157
// Key is the element stored in the stack for a devbox-project. It represents
5258
// a pointer to the nixEnvPath value stored in its own env-var, also using this same
5359
// Key.
5460
func Key(projectHash string) string {
5561
return "DEVBOX_NIX_ENV_PATH_" + projectHash
5662
}
5763

58-
// PushAndUpdateEnv adds the new nixEnvPath for the devbox-project identified by projectHash.
59-
// The nixEnvPath is pushed to the top of the stack (given highest priority), unless preservePathStack
60-
// is enabled.
64+
// Push adds the new nixEnvPath for the devbox-project identified by projectHash.
65+
// The nixEnvPath is pushed to the top of the stack (given highest priority),
66+
// unless preservePathStack is enabled.
6167
//
62-
// It also updated the env by modifying the following env-vars:
68+
// It also updates the env by modifying the following env-vars:
6369
// 1. nixEnvPath key
6470
// 2. PathStack
6571
// 3. PATH
66-
//
67-
// Returns the modified env map
68-
func (s *stack) PushAndUpdateEnv(
72+
func (s *stack) Push(
6973
env map[string]string,
7074
projectHash string,
7175
nixEnvPath string,
7276
preservePathStack bool,
73-
) map[string]string {
77+
) {
7478
key := Key(projectHash)
7579

7680
// Add this nixEnvPath to env
@@ -85,15 +89,10 @@ func (s *stack) PushAndUpdateEnv(
8589
s.keys = lo.Uniq(slices.Insert(s.keys, 0, key))
8690
}
8791
env[PathStackEnv] = s.String()
88-
89-
// Look up the paths-list for each stack element, and join them together to get the final PATH.
90-
pathLists := lo.Map(s.keys, func(part string, idx int) string { return env[part] })
91-
env["PATH"] = JoinPathLists(pathLists...)
92-
return env
9392
}
9493

9594
// Has tests if the stack has the specified key. Refer to the Key function for constructing
9695
// the appropriate key for any devbox-project.
97-
func (s *stack) Has(key string) bool {
98-
return lo.Contains(s.keys, key)
96+
func (s *stack) Has(projectHash string) bool {
97+
return lo.Contains(s.keys, Key(projectHash))
9998
}

internal/impl/envvars.go

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,16 @@ package impl
55

66
import (
77
"os"
8-
"slices"
98
"strings"
109

10+
"slices"
11+
12+
"go.jetpack.io/devbox/internal/envir"
1113
"go.jetpack.io/devbox/internal/impl/envpath"
1214
)
1315

1416
const devboxSetPrefix = "__DEVBOX_SET_"
1517

16-
// mapToPairs creates a slice of environment variable "key=value" pairs from a
17-
// map.
18-
func mapToPairs(m map[string]string) []string {
19-
pairs := make([]string, len(m))
20-
i := 0
21-
for k, v := range m {
22-
pairs[i] = k + "=" + v
23-
i++
24-
}
25-
slices.Sort(pairs) // for reproducibility
26-
return pairs
27-
}
28-
29-
// pairsToMap creates a map from a slice of "key=value" environment variable
30-
// pairs. Note that maps are not ordered, which can affect the final variable
31-
// values when pairs contains duplicate keys.
32-
func pairsToMap(pairs []string) map[string]string {
33-
vars := make(map[string]string, len(pairs))
34-
for _, p := range pairs {
35-
k, v, ok := strings.Cut(p, "=")
36-
if !ok {
37-
continue
38-
}
39-
vars[k] = v
40-
}
41-
return vars
42-
}
43-
4418
// exportify formats vars as a line-separated string of shell export statements.
4519
// Each line is of the form `export key="value";` with any special characters in
4620
// value escaped. This means that the shell will always interpret values as
@@ -100,11 +74,6 @@ func markEnvsAsSetByDevbox(envs ...map[string]string) {
10074
// as a proxy for this. This allows us to differentiate between global and
10175
// individual project shells.
10276
func (d *Devbox) IsEnvEnabled() bool {
103-
env := map[string]string{}
104-
for _, keyVal := range os.Environ() {
105-
parts := strings.Split(keyVal, "=")
106-
env[parts[0]] = parts[1]
107-
}
108-
pathStack := envpath.Stack(env)
109-
return pathStack.Has(envpath.Key(d.projectDirHash()))
77+
pathStack := envpath.Stack(envir.PairsToMap(os.Environ()))
78+
return pathStack.Has(d.projectDirHash())
11079
}

internal/impl/shell.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ func (s *DevboxShell) Run() error {
247247
env["SHELL"] = s.binPath
248248

249249
cmd = exec.Command(s.binPath)
250-
cmd.Env = mapToPairs(env)
250+
cmd.Env = envir.MapToPairs(env)
251251
cmd.Args = append(cmd.Args, extraArgs...)
252252
cmd.Stdin = os.Stdin
253253
cmd.Stdout = os.Stdout

internal/impl/shell_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"testing"
1414

1515
"github.com/google/go-cmp/cmp"
16+
"go.jetpack.io/devbox/internal/envir"
1617
"go.jetpack.io/devbox/internal/shellgen"
1718
)
1819

@@ -45,7 +46,7 @@ func testWriteDevboxShellrc(t *testing.T, testdirs []string) {
4546
test := &tests[i]
4647
test.name = filepath.Base(path)
4748
if b, err := os.ReadFile(filepath.Join(path, "env")); err == nil {
48-
test.env = pairsToMap(strings.Split(string(b), "\n"))
49+
test.env = envir.PairsToMap(strings.Split(string(b), "\n"))
4950
}
5051

5152
test.hooksFilePath = shellgen.ScriptPath(projectDir, shellgen.HooksFilename)

0 commit comments

Comments
 (0)