MCPcopy Index your code
hub / github.com/jetify-com/devbox / syncNixProfileFromFlake

Method syncNixProfileFromFlake

internal/devbox/nixprofile.go:22–98  ·  view source on GitHub ↗

syncNixProfileFromFlake ensures the nix profile has the packages from the buildInputs from the devshell of the generated flake. It also removes any packages from the nix profile that are no longer in the buildInputs.

(ctx context.Context)

Source from the content-addressed store, hash-verified

20//
21// It also removes any packages from the nix profile that are no longer in the buildInputs.
22func (d *Devbox) syncNixProfileFromFlake(ctx context.Context) error {
23 defer debug.FunctionTimer().End()
24 // Get the buildInputs from the generated flake
25 env, err := d.execPrintDevEnv(ctx, false /*usePrintDevEnvCache*/)
26 if err != nil {
27 return err
28 }
29 buildInputs := env["buildInputs"]
30
31 // Get the store-paths of the packages we want installed in the nix profile
32 wantStorePaths := []string{}
33 if buildInputs != "" {
34 // env["buildInputs"] can be empty string if there are no packages in the project
35 // if buildInputs is empty, then we don't want wantStorePaths to be an array with a single "" entry
36 wantStorePaths = strings.Split(buildInputs, " ")
37 }
38
39 profilePath, err := d.profilePath()
40 if err != nil {
41 return err
42 }
43
44 // Get the store-paths of the packages currently installed in the nix profile
45 items, err := nixprofile.ProfileListItems(d.stderr, profilePath)
46 if err != nil {
47 return fmt.Errorf("nix profile list: %v", err)
48 }
49 gotStorePaths := make([]string, 0, len(items))
50 for _, item := range items {
51 gotStorePaths = append(gotStorePaths, item.StorePaths()...)
52 }
53
54 // Diff the store paths and install/remove packages as needed
55 remove, add := lo.Difference(gotStorePaths, wantStorePaths)
56 if len(remove) > 0 {
57 packagesToRemove := make([]string, 0, len(remove))
58 for _, p := range remove {
59 storePath := nix.NewStorePathParts(p)
60 packagesToRemove = append(packagesToRemove, fmt.Sprintf("%s@%s", storePath.Name, storePath.Version))
61 }
62 slog.Debug("removing packages from nix profile", "pkgs", strings.Join(packagesToRemove, ", "))
63
64 if err := nix.ProfileRemove(profilePath, remove...); err != nil {
65 return err
66 }
67 }
68 if len(add) > 0 {
69 if err = nix.ProfileInstall(ctx, &nix.ProfileInstallArgs{
70 Installables: add,
71 ProfilePath: profilePath,
72 Writer: d.stderr,
73 }); errors.Is(err, nix.ErrPriorityConflict) {
74 // We need to install the packages one by one because there was possibly a priority conflict
75 // This is slower, but uncommon.
76 for _, addPath := range add {
77 if err = nix.ProfileInstall(ctx, &nix.ProfileInstallArgs{
78 Installables: []string{addPath},
79 ProfilePath: profilePath,

Callers 1

recomputeStateMethod · 0.95

Calls 11

execPrintDevEnvMethod · 0.95
profilePathMethod · 0.95
FunctionTimerFunction · 0.92
ProfileListItemsFunction · 0.92
NewStorePathPartsFunction · 0.92
ProfileRemoveFunction · 0.92
ProfileInstallFunction · 0.92
wipeProfileHistoryFunction · 0.85
EndMethod · 0.80
StorePathsMethod · 0.80
IsMethod · 0.80

Tested by

no test coverage detected