@@ -248,10 +248,23 @@ const (
248
248
// The `mode` is used for:
249
249
// 1. Skipping certain operations that may not apply.
250
250
// 2. User messaging to explain what operations are happening, because this function may take time to execute.
251
- func (d * Devbox ) ensureStateIsUpToDate (ctx context.Context , mode installMode ) error {
251
+ //
252
+ // nolint:revive to turn off linter complaining about function complexity
253
+ func (d * Devbox ) ensureStateIsUpToDate (ctx context.Context , mode installMode ) error { //nolint:revive
252
254
defer trace .StartRegion (ctx , "devboxEnsureStateIsUpToDate" ).End ()
253
255
defer debug .FunctionTimer ().End ()
254
256
257
+ if mode != ensure && ! d .IsEnvEnabled () {
258
+ // if mode is install/uninstall/update and we are not in a devbox environment,
259
+ // then we skip some operations below for speed.
260
+ // Remove the local.lock file so that we re-compute the project state when
261
+ // we are in the devbox environment again.
262
+ fmt .Printf ("mode is not ensure and env is not enabled, so will remove local.lock on exit\n " )
263
+
264
+ defer func () { _ = d .lockfile .RemoveLocal () }()
265
+ // return nil
266
+ }
267
+
255
268
// if mode is install or uninstall, then we need to update the nix-profile
256
269
// and lockfile, so we must continue below.
257
270
upToDate , err := d .lockfile .IsUpToDateAndInstalled ()
@@ -262,10 +275,12 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
262
275
if mode == ensure {
263
276
// if mode is ensure and we are up to date, then we can skip the rest
264
277
if upToDate {
278
+ fmt .Printf ("state is up to date. Returning early\n " )
265
279
return nil
266
280
}
267
281
fmt .Fprintln (d .stderr , "Ensuring packages are installed." )
268
282
}
283
+ fmt .Printf ("state is not up to date. Continuing...\n " )
269
284
270
285
// Validate packages. Must be run up-front and definitely prior to computeEnv
271
286
// and syncNixProfile below that will evaluate the flake and may give
@@ -285,6 +300,9 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
285
300
return err
286
301
}
287
302
303
+ fmt .Printf ("mode is %s\n " , mode )
304
+ fmt .Printf ("env is enabled: %v\n " , d .IsEnvEnabled ())
305
+
288
306
if err := shellgen .GenerateForPrintEnv (ctx , d ); err != nil {
289
307
return err
290
308
}
@@ -293,24 +311,37 @@ func (d *Devbox) ensureStateIsUpToDate(ctx context.Context, mode installMode) er
293
311
return err
294
312
}
295
313
296
- // Always re-compute print-dev-env to ensure all packages are installed, and
297
- // the correct set of packages are reflected in the nix-profile below.
298
- env , err := d .computeEnv (ctx , false /*usePrintDevEnvCache*/ )
299
- if err != nil {
300
- return err
301
- }
314
+ // The steps contained in this if-block of computeEnv and syncNixProfile are a tad
315
+ // slow. So, we only do it if we are in a devbox environment, or if mode is ensure.
316
+ if mode == ensure || d .IsEnvEnabled () {
317
+ // Re-compute print-dev-env to ensure all packages are installed, and
318
+ // the correct set of packages are reflected in the nix-profile below.
319
+ env , err := d .computeEnv (ctx , false /*usePrintDevEnvCache*/ )
320
+ if err != nil {
321
+ return err
322
+ }
302
323
303
- // Ensure the nix profile has the packages from the flake.
304
- buildInputs := []string {}
305
- if env ["buildInputs" ] != "" {
306
- // env["buildInputs"] can be empty string if there are no packages in the project
307
- // if buildInputs is empty, then we don't want wantStorePaths to be an array with a single "" entry
308
- buildInputs = strings .Split (env ["buildInputs" ], " " )
309
- }
310
- if err := d .syncNixProfile (ctx , buildInputs ); err != nil {
311
- return err
324
+ // Ensure the nix profile has the packages from the flake.
325
+ buildInputs := []string {}
326
+ if env ["buildInputs" ] != "" {
327
+ // env["buildInputs"] can be empty string if there are no packages in the project
328
+ // if buildInputs is empty, then we don't want wantStorePaths to be an array with a single "" entry
329
+ buildInputs = strings .Split (env ["buildInputs" ], " " )
330
+ }
331
+ if err := d .syncNixProfile (ctx , buildInputs ); err != nil {
332
+ return err
333
+ }
334
+
335
+ } else if mode == install || mode == update {
336
+ // Else: if we are not in a devbox environment, and we are installing or updating
337
+ // then we must ensure the new nix packages are in the nix store. This way, the
338
+ // next time we enter a devbox environment, we will have the packages available locally.
339
+ if err := d .installNixPackagesToStore (ctx ); err != nil {
340
+ return err
341
+ }
312
342
}
313
343
344
+ fmt .Printf ("calling lockfile.tidy\n " )
314
345
// Ensure we clean out packages that are no longer needed.
315
346
d .lockfile .Tidy ()
316
347
@@ -395,6 +426,33 @@ func (d *Devbox) InstallRunXPackages(ctx context.Context) error {
395
426
return nil
396
427
}
397
428
429
+ // installNixPackagesToStore will install all the packages in the nix store, if
430
+ // mode is install or update, and we're not in a devbox environment.
431
+ // This is done by running `nix build` on the flake
432
+ func (d * Devbox ) installNixPackagesToStore (ctx context.Context ) error {
433
+ packages , err := d .AllInstallablePackages ()
434
+ if err != nil {
435
+ return err
436
+ }
437
+ packages = lo .Filter (packages , devpkg .IsNix ) // Remove non-nix packages from the list
438
+
439
+ installables := []string {}
440
+ for _ , pkg := range packages {
441
+ i , err := pkg .Installable ()
442
+ if err != nil {
443
+ return err
444
+ }
445
+ installables = append (installables , i )
446
+ }
447
+
448
+ if len (installables ) == 0 {
449
+ return nil
450
+ }
451
+
452
+ // --no-link to avoid generating the result objects
453
+ return nix .Build (ctx , []string {"--no-link" }, installables ... )
454
+ }
455
+
398
456
// validatePackagesToBeInstalled will ensure that packages are available to be installed
399
457
// in the user's current system.
400
458
func (d * Devbox ) validatePackagesToBeInstalled (ctx context.Context ) error {
0 commit comments