treewide: use internal pipe for nix command
This essentially does the same thing underneath the hood but the API is less painful to use, and it makes more sense in this use case.
This commit is contained in:
parent
be2b069edf
commit
68ae0efe19
13
build.go
13
build.go
@ -2,6 +2,7 @@ package nixbuild
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"iter"
|
||||
"strings"
|
||||
)
|
||||
@ -24,12 +25,10 @@ func Build(ctx context.Context, installables iter.Seq[string]) error {
|
||||
cmd.Args = append(cmd.Args, FlagVerbose)
|
||||
}
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ir, iw := io.Pipe()
|
||||
cmd.Stdin = ir
|
||||
|
||||
if err = cmd.Start(); err != nil {
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -38,12 +37,12 @@ func Build(ctx context.Context, installables iter.Seq[string]) error {
|
||||
// this is just what nix requires now :c
|
||||
drv += "^*"
|
||||
}
|
||||
if _, err = stdin.Write([]byte(drv + "\n")); err != nil {
|
||||
if _, err := iw.Write([]byte(drv + "\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = stdin.Close(); err != nil {
|
||||
if err := iw.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,9 @@ import (
|
||||
"iter"
|
||||
"os/exec"
|
||||
"path"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"syscall"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -132,16 +131,18 @@ func (d *InstantiatedDecoder) Decode() ([]string, error) {
|
||||
type InstantiatedEvaluator struct {
|
||||
// underlying nix program
|
||||
cmd *exec.Cmd
|
||||
// kills the nix command
|
||||
cancel context.CancelFunc
|
||||
// populated by Close
|
||||
waitErr error
|
||||
// synchronises access to waitErr
|
||||
waitMu sync.RWMutex
|
||||
|
||||
*InstantiatedDecoder
|
||||
}
|
||||
|
||||
// Err returns the first error encountered by the [InstantiatedEvaluator].
|
||||
// Err blocks until process exit and returns the first error encountered by the [InstantiatedEvaluator].
|
||||
func (e *InstantiatedEvaluator) Err() error {
|
||||
e.waitMu.RLock()
|
||||
defer e.waitMu.RUnlock()
|
||||
return errors.Join(e.waitErr, e.InstantiatedDecoder.Err())
|
||||
}
|
||||
|
||||
@ -157,41 +158,26 @@ func NewInstantiatedEvaluator(ctx context.Context, installable string) (*Instant
|
||||
// increase verbosity so nix outputs 'instantiated' messages
|
||||
FlagPrintBuildLogs, FlagDebug,
|
||||
),
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
e.cmd.Stdout = Stdout
|
||||
|
||||
// verbose output ends up on stderr in the current nix implementation
|
||||
if stderr, err := e.cmd.StderrPipe(); err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
} else {
|
||||
e.InstantiatedDecoder = NewInstantiatedDecoder(stderr)
|
||||
}
|
||||
er, ew := io.Pipe()
|
||||
e.cmd.Stderr = ew
|
||||
e.InstantiatedDecoder = NewInstantiatedDecoder(er)
|
||||
|
||||
if err := e.cmd.Start(); err != nil {
|
||||
cancel()
|
||||
// have finalizer take care of the pipe
|
||||
return nil, err
|
||||
}
|
||||
e.waitMu.Lock()
|
||||
go func() { e.waitErr = e.cmd.Wait(); cancel(); _ = ew.Close(); e.waitMu.Unlock() }()
|
||||
|
||||
runtime.SetFinalizer(e, (*InstantiatedEvaluator).Close)
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// Close releases system resources held by [InstantiatedEvaluator].
|
||||
func (e *InstantiatedEvaluator) Close() error {
|
||||
if e.cmd.ProcessState != nil {
|
||||
return syscall.EBADE
|
||||
}
|
||||
|
||||
e.cancel()
|
||||
e.waitErr = e.cmd.Wait()
|
||||
runtime.SetFinalizer(e, nil)
|
||||
return e.Err()
|
||||
}
|
||||
|
||||
// EvalInstantiated calls the underlying [InstantiatedDecoder.Decode] of a new [InstantiatedEvaluator].
|
||||
func EvalInstantiated(ctx context.Context, installable string) ([]string, error) {
|
||||
evaluator, err := NewInstantiatedEvaluator(ctx, installable)
|
||||
@ -199,5 +185,5 @@ func EvalInstantiated(ctx context.Context, installable string) ([]string, error)
|
||||
return nil, err
|
||||
}
|
||||
instantiated, _ := evaluator.Decode() // error joined by Close
|
||||
return instantiated, evaluator.Close()
|
||||
return instantiated, evaluator.Err()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user