Skip to content

Commit 2fed34f

Browse files
committed
[Devbox] introduce devopt.EnvOptions
1 parent 7e34f00 commit 2fed34f

File tree

7 files changed

+80
-59
lines changed

7 files changed

+80
-59
lines changed

internal/boxcli/run.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ func listScripts(cmd *cobra.Command, flags runCmdFlags) []string {
7373
Dir: flags.config.path,
7474
Environment: flags.config.environment,
7575
Stderr: cmd.ErrOrStderr(),
76-
Pure: flags.pure,
7776
IgnoreWarnings: true,
7877
})
7978
if err != nil {
@@ -114,15 +113,17 @@ func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error {
114113
Dir: path,
115114
Environment: flags.config.environment,
116115
Stderr: cmd.ErrOrStderr(),
117-
OmitNixEnv: flags.omitNixEnv,
118-
Pure: flags.pure,
119116
Env: env,
120117
})
121118
if err != nil {
122119
return redact.Errorf("error reading devbox.json: %w", err)
123120
}
124121

125-
if err := box.RunScript(cmd.Context(), script, scriptArgs); err != nil {
122+
envOpts := devopt.EnvOptions{
123+
OmitNixEnv: flags.omitNixEnv,
124+
Pure: flags.pure,
125+
}
126+
if err := box.RunScript(cmd.Context(), envOpts, script, scriptArgs); err != nil {
126127
return redact.Errorf("error running script %q in Devbox: %w", script, err)
127128
}
128129
return nil

internal/boxcli/shell.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error {
6969
Dir: flags.config.path,
7070
Env: env,
7171
Environment: flags.config.environment,
72-
OmitNixEnv: flags.omitNixEnv,
73-
Pure: flags.pure,
7472
Stderr: cmd.ErrOrStderr(),
7573
})
7674
if err != nil {
@@ -93,7 +91,10 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error {
9391
return shellInceptionErrorMsg("devbox shell")
9492
}
9593

96-
return box.Shell(cmd.Context())
94+
return box.Shell(cmd.Context(), devopt.EnvOptions{
95+
OmitNixEnv: flags.omitNixEnv,
96+
Pure: flags.pure,
97+
})
9798
}
9899

99100
func shellInceptionErrorMsg(cmdPath string) error {

internal/boxcli/shellenv.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,10 @@ func shellEnvFunc(
9595
return "", err
9696
}
9797
box, err := devbox.Open(&devopt.Opts{
98-
Dir: flags.config.path,
99-
Environment: flags.config.environment,
100-
OmitNixEnv: flags.omitNixEnv,
101-
Stderr: cmd.ErrOrStderr(),
102-
PreservePathStack: flags.preservePathStack,
103-
Pure: flags.pure,
104-
Env: env,
98+
Dir: flags.config.path,
99+
Environment: flags.config.environment,
100+
Stderr: cmd.ErrOrStderr(),
101+
Env: env,
105102
})
106103
if err != nil {
107104
return "", err
@@ -115,8 +112,13 @@ func shellEnvFunc(
115112

116113
envStr, err := box.EnvExports(cmd.Context(), devopt.EnvExportsOpts{
117114
DontRecomputeEnvironment: !flags.recomputeEnv,
118-
NoRefreshAlias: flags.noRefreshAlias,
119-
RunHooks: flags.runInitHook,
115+
EnvOptions: devopt.EnvOptions{
116+
OmitNixEnv: flags.omitNixEnv,
117+
PreservePathStack: flags.preservePathStack,
118+
Pure: flags.pure,
119+
},
120+
NoRefreshAlias: flags.noRefreshAlias,
121+
RunHooks: flags.runInitHook,
120122
})
121123
if err != nil {
122124
return "", err

internal/devbox/devbox.go

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ const (
5959
type Devbox struct {
6060
cfg *devconfig.Config
6161
env map[string]string
62-
omitNixEnv bool
6362
environment string
6463
lockfile *lock.File
6564
nix nix.Nixer
6665
projectDir string
6766
pluginManager *plugin.Manager
68-
preservePathStack bool
69-
pure bool
7067
customProcessComposeFile string
7168

7269
// This is needed because of the --quiet flag.
@@ -98,14 +95,11 @@ func Open(opts *devopt.Opts) (*Devbox, error) {
9895
box := &Devbox{
9996
cfg: cfg,
10097
env: opts.Env,
101-
omitNixEnv: opts.OmitNixEnv,
10298
environment: environment,
10399
nix: &nix.Nix{},
104100
projectDir: projectDir,
105101
pluginManager: plugin.NewManager(),
106102
stderr: opts.Stderr,
107-
preservePathStack: opts.PreservePathStack,
108-
pure: opts.Pure,
109103
customProcessComposeFile: opts.CustomProcessComposeFile,
110104
}
111105

@@ -200,11 +194,11 @@ func (d *Devbox) Generate(ctx context.Context) error {
200194
return errors.WithStack(shellgen.GenerateForPrintEnv(ctx, d))
201195
}
202196

203-
func (d *Devbox) Shell(ctx context.Context) error {
197+
func (d *Devbox) Shell(ctx context.Context, envOpts devopt.EnvOptions) error {
204198
ctx, task := trace.NewTask(ctx, "devboxShell")
205199
defer task.End()
206200

207-
envs, err := d.ensureStateIsUpToDateAndComputeEnv(ctx)
201+
envs, err := d.ensureStateIsUpToDateAndComputeEnv(ctx, envOpts)
208202
if err != nil {
209203
return err
210204
}
@@ -228,15 +222,22 @@ func (d *Devbox) Shell(ctx context.Context) error {
228222
WithShellStartTime(telemetry.ShellStart()),
229223
}
230224

231-
shell, err := NewDevboxShell(d, opts...)
225+
shell, err := NewDevboxShell(d, envOpts, opts...)
232226
if err != nil {
233227
return err
234228
}
235229

236230
return shell.Run()
237231
}
238232

239-
func (d *Devbox) RunScript(ctx context.Context, cmdName string, cmdArgs []string) error {
233+
// runDevboxServicesScript invokes RunScript with the envOptions set to the appropriate
234+
// defaults for the `devbox services` scenario.
235+
// TODO: move to services.go
236+
func (d *Devbox) runDevboxServicesScript(ctx context.Context, cmdArgs []string) error {
237+
return d.RunScript(ctx, devopt.EnvOptions{}, "devbox", cmdArgs)
238+
}
239+
240+
func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdName string, cmdArgs []string) error {
240241
ctx, task := trace.NewTask(ctx, "devboxRun")
241242
defer task.End()
242243

@@ -245,7 +246,7 @@ func (d *Devbox) RunScript(ctx context.Context, cmdName string, cmdArgs []string
245246
}
246247

247248
lock.SetIgnoreShellMismatch(true)
248-
env, err := d.ensureStateIsUpToDateAndComputeEnv(ctx)
249+
env, err := d.ensureStateIsUpToDateAndComputeEnv(ctx, envOpts)
249250
if err != nil {
250251
return err
251252
}
@@ -329,9 +330,9 @@ func (d *Devbox) EnvExports(ctx context.Context, opts devopt.EnvExportsOpts) (st
329330
)
330331
}
331332

332-
envs, err = d.computeEnv(ctx, true /*usePrintDevEnvCache*/)
333+
envs, err = d.computeEnv(ctx, true /*usePrintDevEnvCache*/, opts.EnvOptions)
333334
} else {
334-
envs, err = d.ensureStateIsUpToDateAndComputeEnv(ctx)
335+
envs, err = d.ensureStateIsUpToDateAndComputeEnv(ctx, opts.EnvOptions)
335336
}
336337

337338
if err != nil {
@@ -356,7 +357,7 @@ func (d *Devbox) EnvVars(ctx context.Context) ([]string, error) {
356357
ctx, task := trace.NewTask(ctx, "devboxEnvVars")
357358
defer task.End()
358359
// this only returns env variables for the shell environment excluding hooks
359-
envs, err := d.ensureStateIsUpToDateAndComputeEnv(ctx)
360+
envs, err := d.ensureStateIsUpToDateAndComputeEnv(ctx, devopt.EnvOptions{})
360361
if err != nil {
361362
return nil, err
362363
}
@@ -566,11 +567,12 @@ func (d *Devbox) Services() (services.Services, error) {
566567
return result, nil
567568
}
568569

570+
// TODO: move to services.go
569571
func (d *Devbox) StartServices(
570572
ctx context.Context, runInCurrentShell bool, serviceNames ...string,
571573
) error {
572574
if !runInCurrentShell {
573-
return d.RunScript(ctx, "devbox",
575+
return d.runDevboxServicesScript(ctx,
574576
append(
575577
[]string{"services", "start", "--run-in-current-shell"},
576578
serviceNames...,
@@ -610,14 +612,15 @@ func (d *Devbox) StartServices(
610612
return nil
611613
}
612614

615+
// TODO: move to services.go
613616
func (d *Devbox) StopServices(ctx context.Context, runInCurrentShell, allProjects bool, serviceNames ...string) error {
614617
if !runInCurrentShell {
615618
args := []string{"services", "stop", "--run-in-current-shell"}
616619
args = append(args, serviceNames...)
617620
if allProjects {
618621
args = append(args, "--all-projects")
619622
}
620-
return d.RunScript(ctx, "devbox", args)
623+
return d.runDevboxServicesScript(ctx, args)
621624
}
622625

623626
if allProjects {
@@ -649,10 +652,10 @@ func (d *Devbox) StopServices(ctx context.Context, runInCurrentShell, allProject
649652
return nil
650653
}
651654

655+
// TODO: move to services.go
652656
func (d *Devbox) ListServices(ctx context.Context, runInCurrentShell bool) error {
653657
if !runInCurrentShell {
654-
return d.RunScript(ctx,
655-
"devbox", []string{"services", "ls", "--run-in-current-shell"})
658+
return d.runDevboxServicesScript(ctx, []string{"services", "ls", "--run-in-current-shell"})
656659
}
657660

658661
svcSet, err := d.Services()
@@ -688,11 +691,12 @@ func (d *Devbox) ListServices(ctx context.Context, runInCurrentShell bool) error
688691
return nil
689692
}
690693

694+
// TODO: move to services.go
691695
func (d *Devbox) RestartServices(
692696
ctx context.Context, runInCurrentShell bool, serviceNames ...string,
693697
) error {
694698
if !runInCurrentShell {
695-
return d.RunScript(ctx, "devbox",
699+
return d.runDevboxServicesScript(ctx,
696700
append(
697701
[]string{"services", "restart", "--run-in-current-shell"},
698702
serviceNames...,
@@ -727,6 +731,7 @@ func (d *Devbox) RestartServices(
727731
return nil
728732
}
729733

734+
// TODO: move to services.go
730735
func (d *Devbox) StartProcessManager(
731736
ctx context.Context,
732737
runInCurrentShell bool,
@@ -750,7 +755,7 @@ func (d *Devbox) StartProcessManager(
750755
args = append(args, "--pcflags", flag)
751756
}
752757

753-
return d.RunScript(ctx, "devbox", args)
758+
return d.runDevboxServicesScript(ctx, args)
754759
}
755760

756761
svcs, err := d.Services()
@@ -874,13 +879,17 @@ func (d *Devbox) execPrintDevEnv(ctx context.Context, usePrintDevEnvCache bool)
874879
// Note that the shellrc.tmpl template (which sources this environment) does
875880
// some additional processing. The computeEnv environment won't necessarily
876881
// represent the final "devbox run" or "devbox shell" environments.
877-
func (d *Devbox) computeEnv(ctx context.Context, usePrintDevEnvCache bool) (map[string]string, error) {
882+
func (d *Devbox) computeEnv(
883+
ctx context.Context,
884+
usePrintDevEnvCache bool,
885+
envOpts devopt.EnvOptions,
886+
) (map[string]string, error) {
878887
defer debug.FunctionTimer().End()
879888
defer trace.StartRegion(ctx, "devboxComputeEnv").End()
880889

881890
// Append variables from current env if --pure is not passed
882891
currentEnv := os.Environ()
883-
env, err := d.parseEnvAndExcludeSpecialCases(currentEnv)
892+
env, err := d.parseEnvAndExcludeSpecialCases(currentEnv, envOpts.Pure)
884893
if err != nil {
885894
return nil, err
886895
}
@@ -898,7 +907,7 @@ func (d *Devbox) computeEnv(ctx context.Context, usePrintDevEnvCache bool) (map[
898907
originalEnv := make(map[string]string, len(env))
899908
maps.Copy(originalEnv, env)
900909

901-
if !d.omitNixEnv {
910+
if !envOpts.OmitNixEnv {
902911
nixEnv, err := d.execPrintDevEnv(ctx, usePrintDevEnvCache)
903912
if err != nil {
904913
return nil, err
@@ -977,13 +986,13 @@ func (d *Devbox) computeEnv(ctx context.Context, usePrintDevEnvCache bool) (map[
977986
devboxEnvPath = envpath.JoinPathLists(devboxEnvPath, runXPaths)
978987

979988
pathStack := envpath.Stack(env, originalEnv)
980-
pathStack.Push(env, d.ProjectDirHash(), devboxEnvPath, d.preservePathStack)
989+
pathStack.Push(env, d.ProjectDirHash(), devboxEnvPath, envOpts.PreservePathStack)
981990
env["PATH"] = pathStack.Path(env)
982991
slog.Debug("new path stack is", "path_stack", pathStack)
983992

984993
slog.Debug("computed environment PATH", "path", env["PATH"])
985994

986-
if !d.pure {
995+
if !envOpts.Pure {
987996
// preserve the original XDG_DATA_DIRS by prepending to it
988997
env["XDG_DATA_DIRS"] = envpath.JoinPathLists(env["XDG_DATA_DIRS"], os.Getenv("XDG_DATA_DIRS"))
989998
}
@@ -999,6 +1008,7 @@ func (d *Devbox) computeEnv(ctx context.Context, usePrintDevEnvCache bool) (map[
9991008
// while ensuring these reflect the current (up to date) state of the project.
10001009
func (d *Devbox) ensureStateIsUpToDateAndComputeEnv(
10011010
ctx context.Context,
1011+
envOpts devopt.EnvOptions,
10021012
) (map[string]string, error) {
10031013
defer debug.FunctionTimer().End()
10041014

@@ -1025,7 +1035,7 @@ func (d *Devbox) ensureStateIsUpToDateAndComputeEnv(
10251035
// it's ok to use usePrintDevEnvCache=true here always. This does end up
10261036
// doing some non-nix work twice if lockfile is not up to date.
10271037
// TODO: Improve this to avoid extra work.
1028-
return d.computeEnv(ctx, true /*usePrintDevEnvCache*/)
1038+
return d.computeEnv(ctx, true /*usePrintDevEnvCache*/, envOpts)
10291039
}
10301040

10311041
func (d *Devbox) nixPrintDevEnvCachePath() string {
@@ -1244,7 +1254,7 @@ func (d *Devbox) addHashToEnv(env map[string]string) error {
12441254

12451255
// parseEnvAndExcludeSpecialCases converts env as []string to map[string]string
12461256
// In case of pure shell, it leaks HOME and it leaks PATH with some modifications
1247-
func (d *Devbox) parseEnvAndExcludeSpecialCases(currentEnv []string) (map[string]string, error) {
1257+
func (d *Devbox) parseEnvAndExcludeSpecialCases(currentEnv []string, pure bool) (map[string]string, error) {
12481258
env := make(map[string]string, len(currentEnv))
12491259
for _, kv := range currentEnv {
12501260
key, val, found := strings.Cut(kv, "=")
@@ -1258,13 +1268,13 @@ func (d *Devbox) parseEnvAndExcludeSpecialCases(currentEnv []string) (map[string
12581268
// - HOME required for devbox binary to work
12591269
// - PATH to find the nix installation. It is cleaned for pure mode below.
12601270
// - TERM to enable colored text in the pure shell
1261-
if !d.pure || key == "HOME" || key == "PATH" || key == "TERM" {
1271+
if !pure || key == "HOME" || key == "PATH" || key == "TERM" {
12621272
env[key] = val
12631273
}
12641274
}
12651275

12661276
// handling special case for PATH
1267-
if d.pure {
1277+
if pure {
12681278
// Setting a custom env variable to differentiate pure and regular shell
12691279
env["DEVBOX_PURE_SHELL"] = "1"
12701280
// Finding nix executables in path and passing it through

0 commit comments

Comments
 (0)