context: expose more internals
This makes overriding the Nix method easier.
This commit is contained in:
parent
a3427ce7dd
commit
8d502f1574
@ -25,10 +25,14 @@ type Cmd interface {
|
|||||||
type Context interface {
|
type Context interface {
|
||||||
// Streams returns the stdout and stderr writers held by this [Context].
|
// Streams returns the stdout and stderr writers held by this [Context].
|
||||||
Streams() (stdout, stderr io.Writer)
|
Streams() (stdout, stderr io.Writer)
|
||||||
|
// Extra returns a copy of extra arguments held by this [Context].
|
||||||
|
Extra() []string
|
||||||
|
// StoreEnv returns extra [Store] environment variables.
|
||||||
|
StoreEnv() []string
|
||||||
|
|
||||||
// Nix returns an implementation of [Cmd] for running a nix command.
|
// Nix returns an implementation of [Cmd] for running a nix command.
|
||||||
Nix(ctx context.Context, arg ...string) Cmd
|
Nix(ctx context.Context, arg ...string) Cmd
|
||||||
// WriteStdin calls [WriteStdin] for [exec.Cmd]. The function f points to is called if [WriteStdin] succeeds.
|
// WriteStdin calls [WriteStdin] for [Cmd]. The function f points to is called if [WriteStdin] succeeds.
|
||||||
WriteStdin(cmd Cmd, installables iter.Seq[string], f func() error) (int, error)
|
WriteStdin(cmd Cmd, installables iter.Seq[string], f func() error) (int, error)
|
||||||
|
|
||||||
// Unwrap returns the stored [context.Context]
|
// Unwrap returns the stored [context.Context]
|
||||||
|
13
exec.go
13
exec.go
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultWaitDelay = 30 * time.Second
|
DefaultWaitDelay = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// Nix is the name of the nix program.
|
// Nix is the name of the nix program.
|
||||||
@ -28,6 +28,13 @@ type nix struct {
|
|||||||
|
|
||||||
func (n *nix) Unwrap() context.Context { return n.ctx }
|
func (n *nix) Unwrap() context.Context { return n.ctx }
|
||||||
func (n *nix) Streams() (stdout, stderr io.Writer) { return n.stdout, n.stderr }
|
func (n *nix) Streams() (stdout, stderr io.Writer) { return n.stdout, n.stderr }
|
||||||
|
func (n *nix) Extra() (v []string) { v = make([]string, len(n.extra)); copy(v, n.extra); return }
|
||||||
|
func (n *nix) StoreEnv() (v []string) {
|
||||||
|
if n.store == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return n.store.Environ()
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ExtraExperimentalFeatures = "--extra-experimental-features"
|
ExtraExperimentalFeatures = "--extra-experimental-features"
|
||||||
@ -42,6 +49,7 @@ A non-nil stderr implies verbose.
|
|||||||
Streams will not be connected for commands outputting JSON.
|
Streams will not be connected for commands outputting JSON.
|
||||||
*/
|
*/
|
||||||
func New(ctx context.Context, store Store, extraArgs []string, stdout, stderr io.Writer) Context {
|
func New(ctx context.Context, store Store, extraArgs []string, stdout, stderr io.Writer) Context {
|
||||||
|
// since flakes are supposedly experimental
|
||||||
extra := []string{ExtraExperimentalFeatures, ExperimentalFeaturesFlakes}
|
extra := []string{ExtraExperimentalFeatures, ExperimentalFeaturesFlakes}
|
||||||
if store != nil {
|
if store != nil {
|
||||||
extra = append(extraArgs, FlagStore, store.String())
|
extra = append(extraArgs, FlagStore, store.String())
|
||||||
@ -50,7 +58,6 @@ func New(ctx context.Context, store Store, extraArgs []string, stdout, stderr io
|
|||||||
name: Nix,
|
name: Nix,
|
||||||
store: store,
|
store: store,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
// since flakes are supposedly experimental
|
|
||||||
extra: append(extraArgs, extra...),
|
extra: append(extraArgs, extra...),
|
||||||
|
|
||||||
stdout: stdout,
|
stdout: stdout,
|
||||||
@ -70,7 +77,7 @@ func (cmd ExecCmd) ReplaceEnv(env []string) { cmd.Cmd.Env = env }
|
|||||||
func (n *nix) Nix(ctx context.Context, arg ...string) Cmd {
|
func (n *nix) Nix(ctx context.Context, arg ...string) Cmd {
|
||||||
cmd := exec.CommandContext(ctx, n.name, append(n.extra, arg...)...)
|
cmd := exec.CommandContext(ctx, n.name, append(n.extra, arg...)...)
|
||||||
cmd.Cancel = func() error { return cmd.Process.Signal(os.Interrupt) }
|
cmd.Cancel = func() error { return cmd.Process.Signal(os.Interrupt) }
|
||||||
cmd.WaitDelay = defaultWaitDelay
|
cmd.WaitDelay = DefaultWaitDelay
|
||||||
if n.store != nil {
|
if n.store != nil {
|
||||||
cmd.Env = append(cmd.Env, n.store.Environ()...)
|
cmd.Env = append(cmd.Env, n.store.Environ()...)
|
||||||
}
|
}
|
||||||
|
49
exec_test.go
49
exec_test.go
@ -5,13 +5,62 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"gensokyo.uk/nix"
|
"gensokyo.uk/nix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestContext(t *testing.T) {
|
||||||
|
ctx := nix.New(t.Context(), &nix.BinaryCache{
|
||||||
|
Compression: "none",
|
||||||
|
ParallelCompression: false,
|
||||||
|
Bucket: "example",
|
||||||
|
Endpoint: "s3.example.org",
|
||||||
|
Region: "us-east-1",
|
||||||
|
Scheme: "http",
|
||||||
|
CredentialsPath: "/dev/null",
|
||||||
|
KeyPath: nonexistent,
|
||||||
|
}, []string{
|
||||||
|
nix.FlagOption, nix.OptionBuildUseSubstitutes, nix.ValueFalse,
|
||||||
|
nix.FlagOption, nix.OptionSubstituters, "",
|
||||||
|
nix.FlagOption, nix.OptionTrustedSubstituters, "",
|
||||||
|
nix.FlagOption, nix.OptionTrustedPublicKeys, "",
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
extraVal := reflect.ValueOf(ctx).Elem().FieldByName("extra")
|
||||||
|
wantExtra := reflect.NewAt(extraVal.Type(), unsafe.Pointer(extraVal.UnsafeAddr())).Elem().Interface().([]string)
|
||||||
|
|
||||||
|
t.Run("extra", func(t *testing.T) {
|
||||||
|
got := ctx.Extra()
|
||||||
|
if !slices.Equal(got, wantExtra) {
|
||||||
|
t.Errorf("Extra: %#v, want %#v", got, wantExtra)
|
||||||
|
}
|
||||||
|
got[0] = "\x00"
|
||||||
|
if slices.Equal(got, wantExtra) {
|
||||||
|
t.Errorf("Extra did not return a copy")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("store env", func(t *testing.T) {
|
||||||
|
t.Run("nil", func(t *testing.T) {
|
||||||
|
want := nix.New(t.Context(), nil, nil, nil, nil).StoreEnv()
|
||||||
|
if want != nil {
|
||||||
|
t.Errorf("StoreEnv: %#v", want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
want := []string{"AWS_SHARED_CREDENTIALS_FILE=/dev/null"}
|
||||||
|
got := ctx.StoreEnv()
|
||||||
|
if !slices.Equal(got, want) {
|
||||||
|
t.Errorf("StoreEnv: %#v, want %#v", got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestNixWriteStdin(t *testing.T) {
|
func TestNixWriteStdin(t *testing.T) {
|
||||||
t.Run("store", func(t *testing.T) {
|
t.Run("store", func(t *testing.T) {
|
||||||
ctx := nix.New(t.Context(), &nix.BinaryCache{
|
ctx := nix.New(t.Context(), &nix.BinaryCache{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user