Skip to content

Commit ef831bb

Browse files
authored
internal/nix: add DaemonVersion function (#1959)
`nix.DaemonVersion` attempts to connect to the Nix daemon and returns its version string. Devbox will use the error from this function when configuring cache authentication: - If the nix daemon is running, we need to update ~root/.aws/config so that it can authenticate with the private devbox cache. This requires a sudo prompt. - If it's not running, then it's probably a single-user install without a daemon. We won't need sudo.
1 parent cd883bf commit ef831bb

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

internal/nix/store.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,55 @@ func parseStorePathFromInstallableOutput(installable string, output []byte) ([]s
9090

9191
return nil, fmt.Errorf("failed to parse store path from installable (%s) output: %s", installable, output)
9292
}
93+
94+
// DaemonError reports an unsuccessful attempt to connect to the Nix daemon.
95+
type DaemonError struct {
96+
cmd string
97+
stderr []byte
98+
err error
99+
}
100+
101+
func (e *DaemonError) Error() string {
102+
if len(e.stderr) != 0 {
103+
return e.Redact() + ": " + string(e.stderr)
104+
}
105+
return e.Redact()
106+
}
107+
108+
func (e *DaemonError) Unwrap() error {
109+
return e.err
110+
}
111+
112+
func (e *DaemonError) Redact() string {
113+
// Don't include e.stderr in redacted messages because it can contain
114+
// things like paths and usernames.
115+
return fmt.Sprintf("command %s: %s", e.cmd, e.err)
116+
}
117+
118+
// DaemonVersion returns the version of the currently running Nix daemon.
119+
func DaemonVersion(ctx context.Context) (string, error) {
120+
cmd := commandContext(ctx, "store", "info", "--json", "--store", "daemon")
121+
out, err := cmd.Output()
122+
123+
// ExitError means the command ran, but couldn't connect.
124+
var exitErr *exec.ExitError
125+
if errors.As(err, &exitErr) {
126+
return "", &DaemonError{
127+
cmd: cmd.String(),
128+
stderr: exitErr.Stderr,
129+
err: err,
130+
}
131+
}
132+
133+
// All other errors mean we couldn't launch the Nix CLI (either it is
134+
// missing or not executable).
135+
if err != nil {
136+
return "", redact.Errorf("command %s: %s", redact.Safe(cmd), err)
137+
}
138+
139+
info := struct{ Version string }{}
140+
if err := json.Unmarshal(out, &info); err != nil {
141+
return "", redact.Errorf("%s: unmarshal JSON output: %s", redact.Safe(cmd.String()), err)
142+
}
143+
return info.Version, nil
144+
}

0 commit comments

Comments
 (0)