Skip to content

Commit 02812f4

Browse files
authored
[devbox] Check packages exist in nix before adding (jetify-com#2447)
## Summary Check whether a package exists in nix or not before adding via `devbox add` Remove-duplicates so packages are not added twice to the list. ## How was it tested? Compiled, ran `devbox add`, checked for errors, inspected `devbox.json` ## Is this change backwards-compatible? Yes
1 parent ee7056a commit 02812f4

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

devbox.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ func Open(dir string) (*Devbox, error) {
3838
}
3939

4040
func (d *Devbox) Add(pkgs ...string) error {
41-
// TODO: validate packages and detect duplicates.
41+
for _, pkg := range pkgs {
42+
ok := nix.PkgExists(pkg)
43+
if !ok {
44+
return errors.Errorf("Package %s not found.", pkg)
45+
}
46+
}
47+
// TODO: detect duplicates
4248
d.cfg.Packages = append(d.cfg.Packages, pkgs...)
4349
return d.saveCfg()
4450
}

nix/nix.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package nix
22

33
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
47
"os"
58
"os/exec"
69
"strings"
@@ -24,3 +27,54 @@ func Exec(path string, command []string) error {
2427
cmd.Dir = path
2528
return cmd.Run()
2629
}
30+
31+
func PkgExists(pkg string) bool {
32+
_, found := PkgInfo(pkg)
33+
return found
34+
}
35+
36+
type Info struct {
37+
NixName string
38+
Name string
39+
Version string
40+
System string
41+
}
42+
43+
func PkgInfo(pkg string) (*Info, bool) {
44+
buf := new(bytes.Buffer)
45+
attr := fmt.Sprintf("nixpkgs.%s", pkg)
46+
cmd := exec.Command("nix-env", "--json", "-qa", "-A", attr)
47+
cmd.Stdout = buf
48+
err := cmd.Run()
49+
if err != nil {
50+
// nix-env returns an error if the package name is invalid, for now assume
51+
// all errors are invalid packages.
52+
return nil, false /* not found */
53+
}
54+
pkgInfo := parseInfo(pkg, buf.Bytes())
55+
if pkgInfo == nil {
56+
return nil, false /* not found */
57+
}
58+
return pkgInfo, true /* found */
59+
}
60+
61+
func parseInfo(pkg string, data []byte) *Info {
62+
var results map[string]map[string]any
63+
err := json.Unmarshal(data, &results)
64+
if err != nil {
65+
panic(err)
66+
}
67+
if len(results) != 1 {
68+
panic(fmt.Sprintf("unexpected number of results: %d", len(results)))
69+
}
70+
for _, result := range results {
71+
pkgInfo := &Info{
72+
NixName: pkg,
73+
Name: result["pname"].(string),
74+
Version: result["version"].(string),
75+
System: result["system"].(string),
76+
}
77+
return pkgInfo
78+
}
79+
return nil
80+
}

planner/go_planner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (g *GoPlanner) Plan(srcDir string) *BuildPlan {
2626
},
2727
InstallCommand: "go get",
2828
BuildCommand: "CGO_ENABLED=0 go build -o out",
29-
StartCommand: "GIN_MODE=release ./out", // TODO: Move gin specific stuff elsewhere.
29+
StartCommand: "./out", // TODO: Move gin specific stuff elsewhere.
3030
}
3131
}
3232

0 commit comments

Comments
 (0)