package nixbuild import ( "context" "errors" "io" "iter" "os/exec" ) // Nix is the name of the nix program. var Nix = "nix" type nix struct { name string ctx context.Context extra []string stdout, stderr io.Writer } func (n *nix) Unwrap() context.Context { return n.ctx } func (n *nix) Streams() (stdout, stderr io.Writer) { return n.stdout, n.stderr } const ( ExtraExperimentalFeatures = "--extra-experimental-features" ExperimentalFeaturesFlakes = "nix-command flakes" ) /* New returns a new [Context]. A non-nil stderr implies verbose. Streams will not be connected for commands outputting JSON. */ func New(ctx context.Context, extraArgs []string, stdout, stderr io.Writer) Context { return &nix{ name: Nix, ctx: ctx, // since flakes are supposedly experimental extra: append(extraArgs, ExtraExperimentalFeatures, ExperimentalFeaturesFlakes), stdout: stdout, stderr: stderr, } } func (n *nix) Nix(ctx context.Context, arg ...string) *exec.Cmd { return exec.CommandContext(ctx, n.name, append(n.extra, arg...)...) } func (n *nix) WriteStdin(cmd *exec.Cmd, installables iter.Seq[string], f func() error) (int, error) { w, err := cmd.StdinPipe() if err != nil { return 0, err } if err = cmd.Start(); err != nil { return 0, err } count, writeErr := WriteStdin(w, installables) closeErr := w.Close() var fErr error if f != nil && writeErr == nil && closeErr == nil { fErr = f() } return count, errors.Join(writeErr, closeErr, fErr, cmd.Wait()) }