Skip to content

Commit 0cb96c1

Browse files
authored
[filegen] move plansdk.FlakePlan and plansdk.FlakeInput (#1191)
## Summary 1. move `plansdk.FlakePlan` and `plansdk.FlakeInput` into `filegen` and make both internal to the package. 2. move `impl.FlakePlan()` to `filegen.newFlakePlan()` (note, it is internal) 3. move `impl.FlakeInputs()` to `filegen.flakeInputs()` (again, internal now) ## How was it tested?
1 parent acf1072 commit 0cb96c1

File tree

9 files changed

+180
-170
lines changed

9 files changed

+180
-170
lines changed

internal/filegen/flake_input.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package filegen
2+
3+
import (
4+
"context"
5+
"runtime/trace"
6+
"strings"
7+
8+
"github.com/samber/lo"
9+
"go.jetpack.io/devbox/internal/goutil"
10+
"go.jetpack.io/devbox/internal/nix"
11+
"go.jetpack.io/devbox/internal/planner/plansdk"
12+
)
13+
14+
type flakeInput struct {
15+
Name string
16+
Packages []string
17+
URL string
18+
}
19+
20+
// IsNixpkgs returns true if the input is a nixpkgs flake of the form:
21+
// github:NixOS/nixpkgs/...
22+
//
23+
// While there are many ways to specify this input, devbox always uses
24+
// github:NixOS/nixpkgs/<hash> as the URL. If the user wishes to reference nixpkgs
25+
// themselves, this function may not return true.
26+
func (f *flakeInput) IsNixpkgs() bool {
27+
return nix.IsGithubNixpkgsURL(f.URL)
28+
}
29+
30+
func (f *flakeInput) HashFromNixPkgsURL() string {
31+
if !f.IsNixpkgs() {
32+
return ""
33+
}
34+
return nix.HashFromNixPkgsURL(f.URL)
35+
}
36+
37+
func (f *flakeInput) URLWithCaching() string {
38+
if !f.IsNixpkgs() {
39+
return f.URL
40+
}
41+
hash := nix.HashFromNixPkgsURL(f.URL)
42+
return plansdk.GetNixpkgsInfo(hash).URL
43+
}
44+
45+
func (f *flakeInput) PkgImportName() string {
46+
return f.Name + "-pkgs"
47+
}
48+
49+
func (f *flakeInput) BuildInputs() []string {
50+
if !f.IsNixpkgs() {
51+
return lo.Map(f.Packages, func(pkg string, _ int) string {
52+
return f.Name + "." + pkg
53+
})
54+
}
55+
return lo.Map(f.Packages, func(pkg string, _ int) string {
56+
parts := strings.Split(pkg, ".")
57+
// Ugh, not sure if this is reliable?
58+
return f.PkgImportName() + "." + strings.Join(parts[2:], ".")
59+
})
60+
}
61+
62+
// flakeInputs returns a list of flake inputs for the top level flake.nix
63+
// created by devbox. We map packages to the correct flake and attribute path
64+
// and group flakes by URL to avoid duplication. All inputs should be locked
65+
// i.e. have a commit hash and always resolve to the same package/version.
66+
// Note: inputs returned by this function include plugin packages. (php only for now)
67+
// It's not entirely clear we always want to add plugin packages to the top level
68+
func flakeInputs(ctx context.Context, devbox devboxer) ([]*flakeInput, error) {
69+
defer trace.StartRegion(ctx, "flakeInputs").End()
70+
71+
inputs := map[string]*flakeInput{}
72+
73+
userPackages := devbox.PackagesAsInputs()
74+
pluginPackages, err := devbox.PluginManager().PluginPackages(userPackages)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
order := []string{}
80+
// We prioritize plugin packages so that the php plugin works. Not sure
81+
// if this is behavior we want for user plugins. We may need to add an optional
82+
// priority field to the config.
83+
for _, pkg := range append(pluginPackages, userPackages...) {
84+
AttributePath, err := pkg.FullPackageAttributePath()
85+
if err != nil {
86+
return nil, err
87+
}
88+
if input, ok := inputs[pkg.URLForInput()]; !ok {
89+
order = append(order, pkg.URLForInput())
90+
inputs[pkg.URLForInput()] = &flakeInput{
91+
Name: pkg.InputName(),
92+
URL: pkg.URLForInput(),
93+
Packages: []string{AttributePath},
94+
}
95+
} else {
96+
input.Packages = lo.Uniq(
97+
append(inputs[pkg.URLForInput()].Packages, AttributePath),
98+
)
99+
}
100+
}
101+
102+
return goutil.PickByKeysSorted(inputs, order), nil
103+
}

internal/filegen/flake_plan.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package filegen
2+
3+
import (
4+
"context"
5+
"runtime/trace"
6+
7+
"go.jetpack.io/devbox/internal/planner/plansdk"
8+
)
9+
10+
// FlakePlan contains the data to populate the top level flake.nix file
11+
// that builds the devbox environment
12+
type FlakePlan struct {
13+
NixpkgsInfo *plansdk.NixpkgsInfo
14+
FlakeInputs []*flakeInput
15+
}
16+
17+
func newFlakePlan(ctx context.Context, devbox devboxer) (*FlakePlan, error) {
18+
ctx, task := trace.NewTask(ctx, "devboxFlakePlan")
19+
defer task.End()
20+
21+
// Create plugin directories first because inputs might depend on them
22+
for _, pkg := range devbox.PackagesAsInputs() {
23+
if err := devbox.PluginManager().Create(pkg); err != nil {
24+
return nil, err
25+
}
26+
}
27+
28+
for _, included := range devbox.Config().Include {
29+
// This is a slightly weird place to put this, but since includes can't be
30+
// added via command and we need them to be added before we call
31+
// plugin manager.Include
32+
if err := devbox.Lockfile().Add(included); err != nil {
33+
return nil, err
34+
}
35+
if err := devbox.PluginManager().Include(included); err != nil {
36+
return nil, err
37+
}
38+
}
39+
40+
shellPlan := &FlakePlan{}
41+
var err error
42+
shellPlan.FlakeInputs, err = flakeInputs(ctx, devbox)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
nixpkgsInfo := plansdk.GetNixpkgsInfo(devbox.Config().NixPkgsCommitHash())
48+
49+
// This is an optimization. Try to reuse the nixpkgs info from the flake
50+
// inputs to avoid introducing a new one.
51+
for _, input := range shellPlan.FlakeInputs {
52+
if input.IsNixpkgs() {
53+
nixpkgsInfo = plansdk.GetNixpkgsInfo(input.HashFromNixPkgsURL())
54+
break
55+
}
56+
}
57+
58+
shellPlan.NixpkgsInfo = nixpkgsInfo
59+
60+
return shellPlan, nil
61+
}

internal/filegen/generate.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/pkg/errors"
2020
"go.jetpack.io/devbox/internal/cuecfg"
2121
"go.jetpack.io/devbox/internal/debug"
22-
"go.jetpack.io/devbox/internal/planner/plansdk"
2322
)
2423

2524
//go:embed tmpl/*
@@ -33,7 +32,7 @@ var shellFiles = []string{"shell.nix"}
3332
func GenerateForPrintEnv(ctx context.Context, devbox devboxer) error {
3433
defer trace.StartRegion(ctx, "generateShellFiles").End()
3534

36-
plan, err := devbox.FlakePlan(ctx)
35+
plan, err := newFlakePlan(ctx, devbox)
3736
if err != nil {
3837
return err
3938
}
@@ -149,7 +148,7 @@ var templateFuncs = template.FuncMap{
149148
"debug": debug.IsEnabled,
150149
}
151150

152-
func makeFlakeFile(outPath string, plan *plansdk.FlakePlan) error {
151+
func makeFlakeFile(outPath string, plan *FlakePlan) error {
153152
flakeDir := filepath.Join(outPath, "flake")
154153
err := writeFromTemplate(flakeDir, plan, "flake.nix")
155154
if err != nil {

internal/filegen/generate_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"testing"
1212

1313
"github.com/google/go-cmp/cmp"
14-
"go.jetpack.io/devbox/internal/planner/plansdk"
1514
)
1615

1716
// update overwrites golden files with the new test results.
@@ -38,7 +37,7 @@ func TestWriteFromTemplate(t *testing.T) {
3837
NixpkgsInfo struct {
3938
URL string
4039
}
41-
FlakeInputs []plansdk.FlakeInput
40+
FlakeInputs []flakeInput
4241
}{}
4342
err = writeFromTemplate(dir, emptyPlan, "flake.nix")
4443
if err != nil {
@@ -82,14 +81,14 @@ var testFlakeTmplPlan = &struct {
8281
NixpkgsInfo struct {
8382
URL string
8483
}
85-
FlakeInputs []plansdk.FlakeInput
84+
FlakeInputs []flakeInput
8685
}{
8786
NixpkgsInfo: struct {
8887
URL string
8988
}{
9089
URL: "https://github.com/nixos/nixpkgs/archive/b9c00c1d41ccd6385da243415299b39aa73357be.tar.gz",
9190
},
92-
FlakeInputs: []plansdk.FlakeInput{
91+
FlakeInputs: []flakeInput{
9392
{
9493
Name: "nixpkgs",
9594
URL: "github:NixOS/nixpkgs/b9c00c1d41ccd6385da243415299b39aa73357be",

internal/filegen/write_scripts.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package filegen
22

33
import (
4-
"context"
54
"fmt"
65
"os"
76
"path/filepath"
@@ -11,8 +10,8 @@ import (
1110
"go.jetpack.io/devbox/internal/boxcli/featureflag"
1211
"go.jetpack.io/devbox/internal/debug"
1312
"go.jetpack.io/devbox/internal/devconfig"
13+
"go.jetpack.io/devbox/internal/lock"
1414
"go.jetpack.io/devbox/internal/nix"
15-
"go.jetpack.io/devbox/internal/planner/plansdk"
1615
"go.jetpack.io/devbox/internal/plugin"
1716
)
1817

@@ -23,8 +22,9 @@ const HooksFilename = ".hooks"
2322

2423
type devboxer interface {
2524
Config() *devconfig.Config
26-
FlakePlan(context.Context) (*plansdk.FlakePlan, error)
25+
Lockfile() *lock.File
2726
PackagesAsInputs() []*nix.Input
27+
PluginManager() *plugin.Manager
2828
ProjectDir() string
2929
}
3030

internal/impl/devbox.go

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
"go.jetpack.io/devbox/internal/impl/devopt"
3434
"go.jetpack.io/devbox/internal/lock"
3535
"go.jetpack.io/devbox/internal/nix"
36-
"go.jetpack.io/devbox/internal/planner/plansdk"
3736
"go.jetpack.io/devbox/internal/plugin"
3837
"go.jetpack.io/devbox/internal/redact"
3938
"go.jetpack.io/devbox/internal/searcher"
@@ -138,52 +137,6 @@ func (d *Devbox) NixPkgsCommitHash() string {
138137
return d.cfg.NixPkgsCommitHash()
139138
}
140139

141-
func (d *Devbox) FlakePlan(ctx context.Context) (*plansdk.FlakePlan, error) {
142-
ctx, task := trace.NewTask(ctx, "devboxFlakePlan")
143-
defer task.End()
144-
145-
// Create plugin directories first because inputs might depend on them
146-
for _, pkg := range d.PackagesAsInputs() {
147-
if err := d.pluginManager.Create(pkg); err != nil {
148-
return nil, err
149-
}
150-
}
151-
152-
for _, included := range d.cfg.Include {
153-
// This is a slightly weird place to put this, but since includes can't be
154-
// added via command and we need them to be added before we call
155-
// plugin manager.Include
156-
if err := d.lockfile.Add(included); err != nil {
157-
return nil, err
158-
}
159-
if err := d.pluginManager.Include(included); err != nil {
160-
return nil, err
161-
}
162-
}
163-
164-
shellPlan := &plansdk.FlakePlan{}
165-
var err error
166-
shellPlan.FlakeInputs, err = d.flakeInputs(ctx)
167-
if err != nil {
168-
return nil, err
169-
}
170-
171-
nixpkgsInfo := plansdk.GetNixpkgsInfo(d.cfg.NixPkgsCommitHash())
172-
173-
// This is an optimization. Try to reuse the nixpkgs info from the flake
174-
// inputs to avoid introducing a new one.
175-
for _, input := range shellPlan.FlakeInputs {
176-
if input.IsNixpkgs() {
177-
nixpkgsInfo = plansdk.GetNixpkgsInfo(input.HashFromNixPkgsURL())
178-
break
179-
}
180-
}
181-
182-
shellPlan.NixpkgsInfo = nixpkgsInfo
183-
184-
return shellPlan, nil
185-
}
186-
187140
func (d *Devbox) Generate(ctx context.Context) error {
188141
ctx, task := trace.NewTask(ctx, "devboxGenerate")
189142
defer task.End()
@@ -1175,3 +1128,11 @@ func ExportifySystemPathWithoutWrappers() string {
11751128

11761129
return exportify(envs)
11771130
}
1131+
1132+
func (d *Devbox) PluginManager() *plugin.Manager {
1133+
return d.pluginManager
1134+
}
1135+
1136+
func (d *Devbox) Lockfile() *lock.File {
1137+
return d.lockfile
1138+
}

internal/impl/flakes.go

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,9 @@
44
package impl
55

66
import (
7-
"context"
8-
"runtime/trace"
97
"strings"
10-
11-
"github.com/samber/lo"
12-
13-
"go.jetpack.io/devbox/internal/goutil"
14-
"go.jetpack.io/devbox/internal/planner/plansdk"
158
)
169

17-
// flakeInputs returns a list of flake inputs for the top level flake.nix
18-
// created by devbox. We map packages to the correct flake and attribute path
19-
// and group flakes by URL to avoid duplication. All inputs should be locked
20-
// i.e. have a commit hash and always resolve to the same package/version.
21-
// Note: inputs returned by this function include plugin packages. (php only for now)
22-
// It's not entirely clear we always want to add plugin packages to the top level
23-
func (d *Devbox) flakeInputs(ctx context.Context) ([]*plansdk.FlakeInput, error) {
24-
defer trace.StartRegion(ctx, "flakeInputs").End()
25-
26-
inputs := map[string]*plansdk.FlakeInput{}
27-
28-
userPackages := d.PackagesAsInputs()
29-
pluginPackages, err := d.pluginManager.PluginPackages(userPackages)
30-
if err != nil {
31-
return nil, err
32-
}
33-
34-
order := []string{}
35-
// We prioritize plugin packages so that the php plugin works. Not sure
36-
// if this is behavior we want for user plugins. We may need to add an optional
37-
// priority field to the config.
38-
for _, pkg := range append(pluginPackages, userPackages...) {
39-
AttributePath, err := pkg.FullPackageAttributePath()
40-
if err != nil {
41-
return nil, err
42-
}
43-
if input, ok := inputs[pkg.URLForInput()]; !ok {
44-
order = append(order, pkg.URLForInput())
45-
inputs[pkg.URLForInput()] = &plansdk.FlakeInput{
46-
Name: pkg.InputName(),
47-
URL: pkg.URLForInput(),
48-
Packages: []string{AttributePath},
49-
}
50-
} else {
51-
input.Packages = lo.Uniq(
52-
append(inputs[pkg.URLForInput()].Packages, AttributePath),
53-
)
54-
}
55-
}
56-
57-
return goutil.PickByKeysSorted(inputs, order), nil
58-
}
59-
6010
// getLocalFlakesDirs searches packages and returns list of directories
6111
// of local flakes that are mentioned in config.
6212
// e.g., path:./my-flake#packageName -> ./my-flakes

0 commit comments

Comments
 (0)