Skip to content

Commit 2ecb5ed

Browse files
savilsavil
authored andcommitted
recompute env in shell and run
1 parent 399b7f3 commit 2ecb5ed

File tree

7 files changed

+66
-47
lines changed

7 files changed

+66
-47
lines changed

internal/boxcli/run.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ import (
2121

2222
type runCmdFlags struct {
2323
envFlag
24-
config configFlags
25-
omitNixEnv bool
26-
pure bool
27-
listScripts bool
24+
config configFlags
25+
omitNixEnv bool
26+
pure bool
27+
listScripts bool
28+
recomputeEnv bool
2829
}
2930

3031
// runFlagDefaults are the flag default values that differ
@@ -62,6 +63,7 @@ func runCmd(defaults runFlagDefaults) *cobra.Command {
6263
"shell environment will omit the env-vars from print-dev-env",
6364
)
6465
_ = command.Flags().MarkHidden("omit-nix-env")
66+
command.Flags().BoolVar(&flags.recomputeEnv, "recompute", true, "recompute environment if needed")
6567

6668
command.ValidArgs = listScripts(command, flags)
6769

@@ -84,6 +86,7 @@ func listScripts(cmd *cobra.Command, flags runCmdFlags) []string {
8486
}
8587

8688
func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error {
89+
ctx := cmd.Context()
8790
if len(args) == 0 || flags.listScripts {
8891
scripts := listScripts(cmd, flags)
8992
if len(scripts) == 0 {
@@ -111,9 +114,9 @@ func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error {
111114
// Check the directory exists.
112115
box, err := devbox.Open(&devopt.Opts{
113116
Dir: path,
117+
Env: env,
114118
Environment: flags.config.environment,
115119
Stderr: cmd.ErrOrStderr(),
116-
Env: env,
117120
})
118121
if err != nil {
119122
return redact.Errorf("error reading devbox.json: %w", err)
@@ -122,8 +125,12 @@ func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error {
122125
envOpts := devopt.EnvOptions{
123126
OmitNixEnv: flags.omitNixEnv,
124127
Pure: flags.pure,
128+
RecomputeEnv: &devopt.RecomputeEnvOpts{
129+
Disabled: !flags.recomputeEnv,
130+
StateOutOfDateMessage: fmt.Sprintf(devbox.StateOutOfDateMessage, "with --recompute=true"),
131+
},
125132
}
126-
if err := box.RunScript(cmd.Context(), envOpts, script, scriptArgs); err != nil {
133+
if err := box.RunScript(ctx, envOpts, script, scriptArgs); err != nil {
127134
return redact.Errorf("error running script %q in Devbox: %w", script, err)
128135
}
129136
return nil

internal/boxcli/shell.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ import (
1717

1818
type shellCmdFlags struct {
1919
envFlag
20-
config configFlags
21-
omitNixEnv bool
22-
printEnv bool
23-
pure bool
20+
config configFlags
21+
omitNixEnv bool
22+
printEnv bool
23+
pure bool
24+
recomputeEnv bool
2425
}
2526

2627
// shellFlagDefaults are the flag default values that differ
@@ -53,17 +54,20 @@ func shellCmd(defaults shellFlagDefaults) *cobra.Command {
5354
"shell environment will omit the env-vars from print-dev-env",
5455
)
5556
_ = command.Flags().MarkHidden("omit-nix-env")
57+
command.Flags().BoolVar(&flags.recomputeEnv, "recompute", true, "recompute environment if needed")
5658

5759
flags.config.register(command)
5860
flags.envFlag.register(command)
5961
return command
6062
}
6163

6264
func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error {
65+
ctx := cmd.Context()
6366
env, err := flags.Env(flags.config.path)
6467
if err != nil {
6568
return err
6669
}
70+
6771
// Check the directory exists.
6872
box, err := devbox.Open(&devopt.Opts{
6973
Dir: flags.config.path,
@@ -91,9 +95,13 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error {
9195
return shellInceptionErrorMsg("devbox shell")
9296
}
9397

94-
return box.Shell(cmd.Context(), devopt.EnvOptions{
98+
return box.Shell(ctx, devopt.EnvOptions{
9599
OmitNixEnv: flags.omitNixEnv,
96100
Pure: flags.pure,
101+
RecomputeEnv: &devopt.RecomputeEnvOpts{
102+
Disabled: !flags.recomputeEnv,
103+
StateOutOfDateMessage: fmt.Sprintf(devbox.StateOutOfDateMessage, "with --recompute=true"),
104+
},
97105
})
98106
}
99107

internal/boxcli/shellenv.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,14 @@ func shellEnvFunc(
116116
}
117117

118118
envStr, err := box.EnvExports(ctx, devopt.EnvExportsOpts{
119-
DontRecomputeEnvironment: !flags.recomputeEnv,
120119
EnvOptions: devopt.EnvOptions{
121120
OmitNixEnv: flags.omitNixEnv,
122121
PreservePathStack: flags.preservePathStack,
123122
Pure: flags.pure,
123+
RecomputeEnv: &devopt.RecomputeEnvOpts{
124+
Disabled: !flags.recomputeEnv,
125+
StateOutOfDateMessage: fmt.Sprintf(devbox.StateOutOfDateMessage, box.RefreshAliasOrCommand()),
126+
},
124127
},
125128
NoRefreshAlias: flags.noRefreshAlias,
126129
RunHooks: flags.runInitHook,

internal/devbox/devbox.go

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -351,22 +351,7 @@ func (d *Devbox) EnvExports(ctx context.Context, opts devopt.EnvExportsOpts) (st
351351
var envs map[string]string
352352
var err error
353353

354-
if opts.DontRecomputeEnvironment {
355-
upToDate, _ := d.lockfile.IsUpToDateAndInstalled(isFishShell())
356-
if !upToDate {
357-
ux.FHidableWarning(
358-
ctx,
359-
d.stderr,
360-
StateOutOfDateMessage,
361-
d.refreshAliasOrCommand(),
362-
)
363-
}
364-
365-
envs, err = d.computeEnv(ctx, true /*usePrintDevEnvCache*/, opts.EnvOptions)
366-
} else {
367-
envs, err = d.ensureStateIsUpToDateAndComputeEnv(ctx, opts.EnvOptions)
368-
}
369-
354+
envs, err = d.ensureStateIsUpToDateAndComputeEnv(ctx, opts.EnvOptions)
370355
if err != nil {
371356
return "", err
372357
}
@@ -819,23 +804,34 @@ func (d *Devbox) ensureStateIsUpToDateAndComputeEnv(
819804
) (map[string]string, error) {
820805
defer debug.FunctionTimer().End()
821806

822-
// When ensureStateIsUpToDate is called with ensure=true, it always
823-
// returns early if the lockfile is up to date. So we don't need to check here
824-
if err := d.ensureStateIsUpToDate(ctx, ensure); isConnectionError(err) {
825-
if !fileutil.Exists(d.nixPrintDevEnvCachePath()) {
826-
ux.Ferrorf(
807+
if envOpts.RecomputeEnv.Disabled {
808+
upToDate, _ := d.lockfile.IsUpToDateAndInstalled(isFishShell())
809+
if !upToDate {
810+
ux.FHidableWarning(
811+
ctx,
827812
d.stderr,
828-
"Error connecting to the internet and no cached environment found. Aborting.\n",
813+
envOpts.RecomputeEnv.StateOutOfDateMessage,
829814
)
815+
}
816+
} else {
817+
// When ensureStateIsUpToDate is called with ensure=true, it always
818+
// returns early if the lockfile is up to date. So we don't need to check here
819+
if err := d.ensureStateIsUpToDate(ctx, ensure); isConnectionError(err) {
820+
if !fileutil.Exists(d.nixPrintDevEnvCachePath()) {
821+
ux.Ferrorf(
822+
d.stderr,
823+
"Error connecting to the internet and no cached environment found. Aborting.\n",
824+
)
825+
return nil, err
826+
}
827+
ux.Fwarningf(
828+
d.stderr,
829+
"Error connecting to the internet. Will attempt to use cached environment.\n",
830+
)
831+
} else if err != nil {
832+
// Some other non connection error, just return it.
830833
return nil, err
831834
}
832-
ux.Fwarningf(
833-
d.stderr,
834-
"Error connecting to the internet. Will attempt to use cached environment.\n",
835-
)
836-
} else if err != nil {
837-
// Some other non connection error, just return it.
838-
return nil, err
839835
}
840836

841837
// Since ensureStateIsUpToDate calls computeEnv when not up do date,

internal/devbox/devopt/devboxopts.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ type UpdateOpts struct {
6262
}
6363

6464
type EnvExportsOpts struct {
65-
DontRecomputeEnvironment bool
66-
EnvOptions EnvOptions
67-
NoRefreshAlias bool
68-
RunHooks bool
65+
EnvOptions EnvOptions
66+
NoRefreshAlias bool
67+
RunHooks bool
6968
}
7069

7170
// EnvOptions configure the Devbox Environment in the `computeEnv` function.
@@ -76,4 +75,10 @@ type EnvOptions struct {
7675
OmitNixEnv bool
7776
PreservePathStack bool
7877
Pure bool
78+
RecomputeEnv *RecomputeEnvOpts
79+
}
80+
81+
type RecomputeEnvOpts struct {
82+
Disabled bool // Disabled instead of Enabled, because zero-value is false
83+
StateOutOfDateMessage string
7984
}

internal/devbox/packages.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
303303
ctx,
304304
d.stderr,
305305
StateOutOfDateMessage,
306-
d.refreshAliasOrCommand(),
306+
d.RefreshAliasOrCommand(),
307307
)
308308
}
309309

internal/devbox/refresh.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (d *Devbox) isGlobal() bool {
2626
// In some cases (e.g. 2 non-global projects somehow active at the same time),
2727
// refresh might not match. This is a tiny edge case, so no need to make UX
2828
// great, we just print out the entire command.
29-
func (d *Devbox) refreshAliasOrCommand() string {
29+
func (d *Devbox) RefreshAliasOrCommand() string {
3030
if !d.isRefreshAliasSet() {
3131
// even if alias is not set, it might still be set by the end of this process
3232
return fmt.Sprintf("`%s` or `%s`", d.refreshAliasName(), d.refreshCmd())

0 commit comments

Comments
 (0)