Skip to content

Commit 4d73d2c

Browse files
committed
[package outputs] add --outputs flag to devbox add, and save in config
1 parent bc6493f commit 4d73d2c

File tree

8 files changed

+159
-25
lines changed

8 files changed

+159
-25
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# Editors
1111
.idea
1212
.vscode
13+
.zed
1314

1415
# NodeJS
1516
node_modules

internal/boxcli/add.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type addCmdFlags struct {
2424
platforms []string
2525
excludePlatforms []string
2626
patchGlibc bool
27+
outputs []string
2728
}
2829

2930
func addCmd() *cobra.Command {
@@ -67,6 +68,9 @@ func addCmd() *cobra.Command {
6768
command.Flags().BoolVar(
6869
&flags.patchGlibc, "patch-glibc", false,
6970
"patch any ELF binaries to use the latest glibc version in nixpkgs")
71+
command.Flags().StringSliceVarP(
72+
&flags.outputs, "outputs", "o", []string{},
73+
"specify the outputs to select for the nix package")
7074

7175
return command
7276
}
@@ -87,5 +91,6 @@ func addCmdFunc(cmd *cobra.Command, args []string, flags addCmdFlags) error {
8791
Platforms: flags.platforms,
8892
ExcludePlatforms: flags.excludePlatforms,
8993
PatchGlibc: flags.patchGlibc,
94+
Outputs: flags.outputs,
9095
})
9196
}

internal/devbox/devopt/devboxopts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type AddOpts struct {
4848
ExcludePlatforms []string
4949
DisablePlugin bool
5050
PatchGlibc bool
51+
Outputs []string
5152
}
5253

5354
type UpdateOpts struct {

internal/devbox/packages.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,14 @@ func (d *Devbox) setPackageOptions(pkgs []string, opts devopt.AddOpts) error {
128128
pkg, opts.DisablePlugin); err != nil {
129129
return err
130130
}
131-
132131
if err := d.cfg.Packages.SetPatchGLibc(
133132
pkg, opts.PatchGlibc); err != nil {
134133
return err
135134
}
135+
if err := d.cfg.Packages.SetOutputs(
136+
d.stderr, pkg, opts.Outputs); err != nil {
137+
return err
138+
}
136139
}
137140

138141
// Resolving here ensures we allow insecure before running ensureStateIsUpToDate
@@ -175,7 +178,7 @@ func (d *Devbox) printPostAddMessage(
175178
}
176179
}
177180

178-
if len(opts.Platforms) == 0 && len(opts.ExcludePlatforms) == 0 && !opts.AllowInsecure {
181+
if len(opts.Platforms) == 0 && len(opts.ExcludePlatforms) == 0 && len(opts.Outputs) == 0 && !opts.AllowInsecure {
179182
if len(unchangedPackageNames) == 1 {
180183
ux.Finfo(d.stderr, "Package %q was already in devbox.json and was not modified\n", unchangedPackageNames[0])
181184
} else if len(unchangedPackageNames) > 1 {

internal/devconfig/ast.go

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -196,32 +196,15 @@ func (c *configAST) appendPlatforms(name, fieldName string, platforms []string)
196196
return
197197
}
198198

199-
pkgObject := c.FindPkgObject(name)
200-
if pkgObject == nil {
201-
return
202-
}
199+
c.appendStringSliceField(name, fieldName, platforms)
200+
}
203201

204-
var arr *hujson.Array
205-
if i := c.memberIndex(pkgObject, fieldName); i == -1 {
206-
arr = &hujson.Array{
207-
Elements: make([]hujson.Value, 0, len(platforms)),
208-
}
209-
pkgObject.Members = append(pkgObject.Members, hujson.ObjectMember{
210-
Name: hujson.Value{
211-
Value: hujson.String(fieldName),
212-
BeforeExtra: []byte{'\n'},
213-
},
214-
Value: hujson.Value{Value: arr},
215-
})
216-
} else {
217-
arr = pkgObject.Members[i].Value.Value.(*hujson.Array)
218-
arr.Elements = slices.Grow(arr.Elements, len(platforms))
202+
func (c *configAST) appendOutputs(name, fieldName string, outputs []string) {
203+
if len(outputs) == 0 {
204+
return
219205
}
220206

221-
for _, p := range platforms {
222-
arr.Elements = append(arr.Elements, hujson.Value{Value: hujson.String(p)})
223-
}
224-
c.root.Format()
207+
c.appendStringSliceField(name, fieldName, outputs)
225208
}
226209

227210
func (c *configAST) FindPkgObject(name string) *hujson.Object {
@@ -307,3 +290,32 @@ func joinNameVersion(name, version string) string {
307290
}
308291
return name + "@" + version
309292
}
293+
294+
func (c *configAST) appendStringSliceField(name, fieldName string, fieldValues []string) {
295+
pkgObject := c.FindPkgObject(name)
296+
if pkgObject == nil {
297+
return
298+
}
299+
300+
var arr *hujson.Array
301+
if i := c.memberIndex(pkgObject, fieldName); i == -1 {
302+
arr = &hujson.Array{
303+
Elements: make([]hujson.Value, 0, len(fieldValues)),
304+
}
305+
pkgObject.Members = append(pkgObject.Members, hujson.ObjectMember{
306+
Name: hujson.Value{
307+
Value: hujson.String(fieldName),
308+
BeforeExtra: []byte{'\n'},
309+
},
310+
Value: hujson.Value{Value: arr},
311+
})
312+
} else {
313+
arr = pkgObject.Members[i].Value.Value.(*hujson.Array)
314+
arr.Elements = slices.Grow(arr.Elements, len(fieldValues))
315+
}
316+
317+
for _, p := range fieldValues {
318+
arr.Elements = append(arr.Elements, hujson.Value{Value: hujson.String(p)})
319+
}
320+
c.root.Format()
321+
}

internal/devconfig/config_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,68 @@ func TestExcludePlatforms(t *testing.T) {
591591
}
592592
}
593593

594+
func TestSetOutputs(t *testing.T) {
595+
in, want := parseConfigTxtarTest(t, `
596+
-- in --
597+
{
598+
"packages": {
599+
"prometheus": {
600+
"version": "latest"
601+
}
602+
}
603+
}
604+
-- want --
605+
{
606+
"packages": {
607+
"prometheus": {
608+
"version": "latest",
609+
"outputs": ["cli"]
610+
}
611+
}
612+
}`)
613+
614+
err := in.Packages.SetOutputs(io.Discard, "prometheus@latest", []string{"cli"})
615+
if err != nil {
616+
t.Error(err)
617+
}
618+
if diff := cmp.Diff(want, in.Bytes(), optParseHujson()); diff != "" {
619+
t.Errorf("wrong parsed config json (-want +got):\n%s", diff)
620+
}
621+
if diff := cmp.Diff(want, in.Bytes()); diff != "" {
622+
t.Errorf("wrong raw config hujson (-want +got):\n%s", diff)
623+
}
624+
}
625+
626+
func TestSetOutputsMigrateArray(t *testing.T) {
627+
in, want := parseConfigTxtarTest(t, `
628+
-- in --
629+
{
630+
"packages": ["go", "[email protected]", "prometheus@latest"]
631+
}
632+
-- want --
633+
{
634+
"packages": {
635+
"go": "",
636+
"python": "3.10",
637+
"prometheus": {
638+
"version": "latest",
639+
"outputs": ["cli"]
640+
}
641+
}
642+
}`)
643+
644+
err := in.Packages.SetOutputs(io.Discard, "prometheus@latest", []string{"cli"})
645+
if err != nil {
646+
t.Error(err)
647+
}
648+
if diff := cmp.Diff(want, in.Bytes(), optParseHujson()); diff != "" {
649+
t.Errorf("wrong parsed config json (-want +got):\n%s", diff)
650+
}
651+
if diff := cmp.Diff(want, in.Bytes()); diff != "" {
652+
t.Errorf("wrong raw config hujson (-want +got):\n%s", diff)
653+
}
654+
}
655+
594656
func TestDefault(t *testing.T) {
595657
path := filepath.Join(t.TempDir())
596658
in := DefaultConfig()

internal/devconfig/packages.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,28 @@ func (pkgs *Packages) SetDisablePlugin(versionedName string, v bool) error {
203203
return nil
204204
}
205205

206+
func (pkgs *Packages) SetOutputs(writer io.Writer, versionedName string, outputs []string) error {
207+
name, version := parseVersionedName(versionedName)
208+
i := pkgs.index(name, version)
209+
if i == -1 {
210+
return errors.Errorf("package %s not found", versionedName)
211+
}
212+
213+
toAdd := []string{}
214+
for _, o := range outputs {
215+
if !slices.Contains(pkgs.Collection[i].Outputs, o) {
216+
toAdd = append(toAdd, o)
217+
}
218+
}
219+
220+
if len(toAdd) > 0 {
221+
pkg := &pkgs.Collection[i]
222+
pkgs.ast.appendOutputs(pkg.name, "outputs", toAdd)
223+
ux.Finfo(writer, "Added outputs %s to package %s\n", strings.Join(toAdd, ", "), versionedName)
224+
}
225+
return nil
226+
}
227+
206228
func (pkgs *Packages) index(name, version string) int {
207229
return slices.IndexFunc(pkgs.Collection, func(p Package) bool {
208230
return p.name == name && p.Version == version
@@ -220,6 +242,10 @@ type Package struct {
220242
// PatchGlibc applies a function to the package's derivation that
221243
// patches any ELF binaries to use the latest version of nixpkgs#glibc.
222244
PatchGlibc bool `json:"patch_glibc,omitempty"`
245+
246+
// Outputs is the list of outputs to use for this package, assuming
247+
// it is a nix package. If empty, the default output is used.
248+
Outputs []string `json:"outputs,omitempty"`
223249
}
224250

225251
func NewVersionOnlyPackage(name, version string) Package {
@@ -246,12 +272,17 @@ func NewPackage(name string, values map[string]any) Package {
246272
if e, ok := values["excluded_platforms"]; ok {
247273
excludedPlatforms = e.([]string)
248274
}
275+
var outputs []string
276+
if o, ok := values["outputs"]; ok {
277+
outputs = o.([]string)
278+
}
249279

250280
return Package{
251281
name: name,
252282
Version: version.(string),
253283
Platforms: platforms,
254284
ExcludedPlatforms: excludedPlatforms,
285+
Outputs: outputs,
255286
}
256287
}
257288

internal/devconfig/packages_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,25 @@ func TestJsonifyConfigPackages(t *testing.T) {
155155
},
156156
},
157157
},
158+
{
159+
name: "map-with-platforms-and-excluded-platforms-and-outputs-nixpkgs-reference",
160+
jsonConfig: `{"packages":{"github:nixos/nixpkgs/5233fd2ba76a3accb5aaa999c00509a11fd0793c#hello":` +
161+
`{"version":"latest",` +
162+
`"platforms":["x86_64-darwin","aarch64-linux"],` +
163+
`"excluded_platforms":["x86_64-linux"],` +
164+
`"outputs":["cli"]` +
165+
`}}}`,
166+
expected: Packages{
167+
Collection: []Package{
168+
NewPackage("github:nixos/nixpkgs/5233fd2ba76a3accb5aaa999c00509a11fd0793c#hello", map[string]any{
169+
"version": "latest",
170+
"platforms": []string{"x86_64-darwin", "aarch64-linux"},
171+
"excluded_platforms": []string{"x86_64-linux"},
172+
"outputs": []string{"cli"},
173+
}),
174+
},
175+
},
176+
},
158177
}
159178

160179
for _, testCase := range testCases {

0 commit comments

Comments
 (0)