diff --git a/format.go b/format.go index 860b09d..58cd0ef 100644 --- a/format.go +++ b/format.go @@ -1,5 +1,23 @@ package nixbuild +import ( + "context" + "os/exec" +) + +const ( + nixExtraExperimentalFeatures = "--extra-experimental-features" + nixExperimentalFeaturesFlakes = "nix-command flakes" +) + +// since flakes are supposedly experimental +var nixEnableFlakes = []string{nixExtraExperimentalFeatures, nixExperimentalFeaturesFlakes} + +// Nix returns the [exec.Cmd] struct to execute a nix command. +func Nix(ctx context.Context, arg ...string) *exec.Cmd { + return exec.CommandContext(ctx, "nix", append(nixEnableFlakes, arg...)...) +} + const ( nixosSuffix0 = "#nixosConfigurations." nixosSuffix1 = ".config.system.build.toplevel" diff --git a/format_test.go b/format_test.go index f8bf8ca..7d82ba2 100644 --- a/format_test.go +++ b/format_test.go @@ -1,11 +1,34 @@ package nixbuild_test import ( + "slices" "testing" "git.gensokyo.uk/yonah/nixbuild" ) +func TestNix(t *testing.T) { + testCases := []struct { + name string + arg []string + want []string + }{ + {"build", []string{"build"}, + []string{"nix", "--extra-experimental-features", "nix-command flakes", "build"}}, + {"build workflow", []string{"build", `--out-link "result"`, "--print-out-paths", "--print-build-logs"}, + []string{"nix", "--extra-experimental-features", "nix-command flakes", "build", `--out-link "result"`, "--print-out-paths", "--print-build-logs"}}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := nixbuild.Nix(t.Context(), tc.arg...) + if !slices.Equal(got.Args, tc.want) { + t.Errorf("Nix: %#v, want %#v", + got.Args, tc.want) + } + }) + } +} + func TestInstallable(t *testing.T) { testCases := []struct { name, flake, host, want string diff --git a/instantiated.go b/instantiated.go index 2a7a77a..8c17e3e 100644 --- a/instantiated.go +++ b/instantiated.go @@ -5,7 +5,6 @@ import ( "context" "errors" "io" - "os/exec" "path" "slices" "strings" @@ -105,11 +104,8 @@ func EvalInstantiated(ctx context.Context, installable string) ([]string, error) c, cancel := context.WithCancel(ctx) defer cancel() - cmd := exec.CommandContext(c, - "nix", "build", installable, - // since flakes are supposedly experimental - "--extra-experimental-features", "nix-command flakes", - // 'instantiated' messages are only emitted when actually evaluating something + cmd := Nix(c, "build", installable, + // 'instantiated' messages are only emitted when actually evaluating something "--option", "eval-cache", "false", // do not actually build anything "--dry-run", diff --git a/instantiated_test.go b/instantiated_test.go index d399105..25c7955 100644 --- a/instantiated_test.go +++ b/instantiated_test.go @@ -2,6 +2,7 @@ package nixbuild_test import ( "errors" + "os" "runtime" "slices" "strings" @@ -42,6 +43,12 @@ func TestDecodeInstantiated(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + if tc.wantErr != nil { + w := nixbuild.Stderr + nixbuild.Stderr = os.Stderr + t.Cleanup(func() { nixbuild.Stderr = w }) + } + stderr := strings.NewReader(tc.out) got, err := nixbuild.DecodeInstantiated(stderr) if !errors.Is(err, tc.wantErr) { @@ -70,6 +77,16 @@ func TestDecodeInstantiated(t *testing.T) { t.Error("unexpected MalformedInstantiatedError equivalence") } }) + + t.Run("unreachable", func(t *testing.T) { + defer func() { + wantPanic := "unreachable" + if r := recover(); r != wantPanic { + t.Errorf("Error: panic = %q, want %q", r, wantPanic) + } + }() + _ = (&nixbuild.MalformedInstantiatedError{Type: -1}).Error() + }) }) }