-
Notifications
You must be signed in to change notification settings - Fork 269
[global] global shellenv should not recompute env #1534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c350e4c
ef04e16
32f7f8b
d5748d7
bef145c
c8d73d0
7a06876
57d3cd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -168,21 +168,22 @@ func (d *Devbox) Shell(ctx context.Context) error { | |
ctx, task := trace.NewTask(ctx, "devboxShell") | ||
defer task.End() | ||
|
||
if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { | ||
return err | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we move |
||
fmt.Fprintln(d.stderr, "Starting a devbox shell...") | ||
|
||
profileDir, err := d.profilePath() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
envs, err := d.nixEnv(ctx) | ||
envs, err := d.ensurePackagesAreInstalledAndComputeEnv(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Fprintln(d.stderr, "Starting a devbox shell...") | ||
|
||
// Used to determine whether we're inside a shell (e.g. to prevent shell inception) | ||
// TODO: This is likely obsolete but we need to decide what happens when | ||
// the user does shell-ception. One option is to leave the current shell and | ||
// join a new one (that way they are not in nested shells.) | ||
envs[envir.DevboxShellEnabled] = "1" | ||
|
||
if err = createDevboxSymlink(d); err != nil { | ||
|
@@ -210,15 +211,11 @@ func (d *Devbox) RunScript(ctx context.Context, cmdName string, cmdArgs []string | |
ctx, task := trace.NewTask(ctx, "devboxRun") | ||
defer task.End() | ||
|
||
if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { | ||
return err | ||
} | ||
|
||
if err := shellgen.WriteScriptsToFiles(d); err != nil { | ||
return err | ||
} | ||
|
||
env, err := d.nixEnv(ctx) | ||
env, err := d.ensurePackagesAreInstalledAndComputeEnv(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -274,22 +271,39 @@ func (d *Devbox) ListScripts() []string { | |
return keys | ||
} | ||
|
||
func (d *Devbox) NixEnv(ctx context.Context, includeHooks bool) (string, error) { | ||
func (d *Devbox) NixEnv(ctx context.Context, opts devopt.NixEnvOpts) (string, error) { | ||
ctx, task := trace.NewTask(ctx, "devboxNixEnv") | ||
defer task.End() | ||
|
||
if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { | ||
return "", err | ||
var envs map[string]string | ||
var err error | ||
|
||
if opts.DontRecomputeEnvironment { | ||
upToDate, _ := d.lockfile.IsUpToDateAndInstalled() | ||
if !upToDate { | ||
cmd := `eval "$(devbox global shellenv --recompute)"` | ||
if strings.HasSuffix(os.Getenv("SHELL"), "fish") { | ||
cmd = `devbox global shellenv --recompute | source` | ||
} | ||
ux.Finfo( | ||
d.stderr, | ||
"Your devbox environment may be out of date. Please run \n\n%s\n\n", | ||
cmd, | ||
) | ||
} | ||
|
||
envs, err = d.computeNixEnv(ctx, true /*usePrintDevEnvCache*/) | ||
} else { | ||
envs, err = d.ensurePackagesAreInstalledAndComputeEnv(ctx) | ||
} | ||
|
||
envs, err := d.nixEnv(ctx) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
envStr := exportify(envs) | ||
|
||
if includeHooks { | ||
if opts.RunHooks { | ||
hooksStr := ". " + shellgen.ScriptPath(d.ProjectDir(), shellgen.HooksFilename) | ||
envStr = fmt.Sprintf("%s\n%s;\n", envStr, hooksStr) | ||
} | ||
|
@@ -301,12 +315,7 @@ func (d *Devbox) EnvVars(ctx context.Context) ([]string, error) { | |
ctx, task := trace.NewTask(ctx, "devboxEnvVars") | ||
defer task.End() | ||
// this only returns env variables for the shell environment excluding hooks | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm I think this comment was actually for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its explaining why Mohsen did |
||
// and excluding "export " prefix in "export key=value" format | ||
if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { | ||
return nil, err | ||
} | ||
|
||
envs, err := d.nixEnv(ctx) | ||
envs, err := d.ensurePackagesAreInstalledAndComputeEnv(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
@@ -903,25 +912,23 @@ func (d *Devbox) computeNixEnv(ctx context.Context, usePrintDevEnvCache bool) (m | |
return env, d.addHashToEnv(env) | ||
} | ||
|
||
// nixEnv is a wrapper around computeNixEnv that returns a cached result if | ||
// it has previously computed and the local lock file is up to date. | ||
// Note that this is in-memory cache of the final environment, and not the same | ||
// as the nix print-dev-env cache which is stored in a file. | ||
func (d *Devbox) nixEnv(ctx context.Context) (map[string]string, error) { | ||
// ensurePackagesAreInstalledAndComputeEnv does what it says :P | ||
func (d *Devbox) ensurePackagesAreInstalledAndComputeEnv( | ||
ctx context.Context, | ||
) (map[string]string, error) { | ||
defer debug.FunctionTimer().End() | ||
|
||
usePrintDevEnvCache := false | ||
|
||
// If lockfile is up-to-date, we can use the print-dev-env cache. | ||
upToDate, err := d.lockfile.IsUpToDateAndInstalled() | ||
if err != nil { | ||
// When ensurePackagesAreInstalled is called with ensure=true, it always | ||
// returns early if the lockfile is up to date. So we don't need to check here | ||
if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { | ||
return nil, err | ||
} | ||
if upToDate { | ||
usePrintDevEnvCache = true | ||
} | ||
|
||
return d.computeNixEnv(ctx, usePrintDevEnvCache) | ||
// Since ensurePackagesAreInstalled calls computeNixEnv when not up do date, | ||
// it's ok to use usePrintDevEnvCache=true here always. This does end up | ||
// doing some non-nix work twice if lockfile is not up to date. | ||
// TODO: Improve this to avoid extra work. | ||
return d.computeNixEnv(ctx, true) | ||
} | ||
|
||
func (d *Devbox) nixPrintDevEnvCachePath() string { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nbd, but I prefer the
recomputeEnvIfNeeded
as a param name. Can we reuse that withinNixEnvOpts
as well?Alternatively, could it be
skipRecomputeEnvironment
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I struggled with this as well. Here's why I went with this:
The issue with
recomputeEnvIfNeeded
is that we would need to default it totrue
. I prefer if the default is true and only pass in a param to make it false.The reason that flag is the other way around is because
devbox global shellenv --no-recompute=false
would be super awkward because of the double negative.