@@ -255,13 +255,14 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
255
255
defer trace .StartRegion (ctx , "devboxEnsureStateIsUpToDate" ).End ()
256
256
defer debug .FunctionTimer ().End ()
257
257
258
- // if mode is install or uninstall, then we need to update the nix-profile
259
- // and lockfile, so we must continue below.
260
258
upToDate , err := d .lockfile .IsUpToDateAndInstalled ()
261
259
if err != nil {
262
260
return err
263
261
}
264
262
263
+ // if mode is install or uninstall, then we need to compute some state
264
+ // like updating the flake or installing packages locally, so must continue
265
+ // below
265
266
if mode == ensure {
266
267
// if mode is ensure and we are up to date, then we can skip the rest
267
268
if upToDate {
@@ -270,6 +271,47 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
270
271
fmt .Fprintln (d .stderr , "Ensuring packages are installed." )
271
272
}
272
273
274
+ recomputeState := mode == ensure || d .IsEnvEnabled ()
275
+ if recomputeState {
276
+ if err := d .recomputeState (ctx , mode ); err != nil {
277
+ return err
278
+ }
279
+ } else {
280
+ // TODO: in the next PR, we will only `nix build` the packages that are being
281
+ // added or updated. For now, we continue to call recomputeState here.
282
+ if err := d .recomputeState (ctx , mode ); err != nil {
283
+ return err
284
+ }
285
+ }
286
+
287
+ // If we're in a devbox shell (global or project), then the environment might
288
+ // be out of date after the user installs something. If have direnv active
289
+ // it should reload automatically so we don't need to refresh.
290
+ if d .IsEnvEnabled () && ! upToDate && ! d .IsDirenvActive () {
291
+ ux .Fwarning (
292
+ d .stderr ,
293
+ "Your shell environment may be out of date. Run `%s` to update it.\n " ,
294
+ d .refreshAliasOrCommand (),
295
+ )
296
+ }
297
+
298
+ if recomputeState {
299
+ if err := d .lockfile .Save (); err != nil {
300
+ return err
301
+ }
302
+ return d .lockfile .UpdateAndSaveLocalLock ()
303
+ }
304
+ // if we are not recomputing state, then we are only updating the lockfile
305
+ // and we do not update the local.lock file
306
+ return d .lockfile .Save ()
307
+ }
308
+
309
+ // recomputeState updates the local state comprising of:
310
+ // - plugins directories
311
+ // - devbox.lock file
312
+ // - the generated flake
313
+ // - the nix-profile
314
+ func (d * Devbox ) recomputeState (ctx context.Context , mode installMode ) error {
273
315
// Create plugin directories first because packages might need them
274
316
for _ , pkg := range d .InstallablePackages () {
275
317
if err := d .PluginManager ().Create (pkg ); err != nil {
@@ -310,18 +352,7 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
310
352
}
311
353
}
312
354
313
- // If we're in a devbox shell (global or project), then the environment might
314
- // be out of date after the user installs something. If have direnv active
315
- // it should reload automatically so we don't need to refresh.
316
- if d .IsEnvEnabled () && ! upToDate && ! d .IsDirenvActive () {
317
- ux .Fwarning (
318
- d .stderr ,
319
- "Your shell environment may be out of date. Run `%s` to update it.\n " ,
320
- d .refreshAliasOrCommand (),
321
- )
322
- }
323
-
324
- return d .lockfile .Save ()
355
+ return nil
325
356
}
326
357
327
358
func (d * Devbox ) profilePath () (string , error ) {
0 commit comments