instantiated: attach decode function to decoder

This commit is contained in:
Yonah 2025-07-14 19:05:16 +09:00
parent e959aaaf94
commit 240b8baace
Signed by: yonah
SSH Key Fingerprint: SHA256:vnQvK8+XXH9Tbni2AV1a/8qdVK/zPcXw52GM0ruQvwA
2 changed files with 9 additions and 12 deletions

View File

@ -108,12 +108,10 @@ func (d *InstantiatedDecoder) Drv() iter.Seq[string] {
} }
} }
// DecodeInstantiated interprets the verbose output of `nix build` and returns a slice of all instantiated derivations. // Decode collects and deduplicates derivations emitted by [InstantiatedDecoder].
func DecodeInstantiated(r io.Reader) ([]string, error) { func (d *InstantiatedDecoder) Decode() ([]string, error) {
decoder := NewInstantiatedDecoder(r)
instantiated := make([]string, 0, instantiatedInitialCap) instantiated := make([]string, 0, instantiatedInitialCap)
for drv := range decoder.Drv() { for drv := range d.Drv() {
if len(instantiated) == cap(instantiated) { if len(instantiated) == cap(instantiated) {
// grow the buffer exponentially to minimise copies // grow the buffer exponentially to minimise copies
instantiated = slices.Grow(instantiated, cap(instantiated)<<1) instantiated = slices.Grow(instantiated, cap(instantiated)<<1)
@ -122,12 +120,11 @@ func DecodeInstantiated(r io.Reader) ([]string, error) {
} }
slices.Sort(instantiated) slices.Sort(instantiated)
return slices.Compact(instantiated), decoder.Err() return slices.Compact(instantiated), d.Err()
} }
// EvalInstantiated evaluates the installable and returns all derivations instantiated during the evaluation. // EvalInstantiated evaluates the installable and returns all derivations instantiated during the evaluation.
// This relies on verbose output of `nix build` and is certainly not the correct way to do it, but so far it works // This interprets verbose output of `nix build` and is certainly not the correct way to do it, but so far it works
// significantly better than `nix-store -qR` and there does not appear to be a better way. // significantly better than `nix-store -qR` and there does not appear to be a better way.
func EvalInstantiated(ctx context.Context, installable string) ([]string, error) { func EvalInstantiated(ctx context.Context, installable string) ([]string, error) {
c, cancel := context.WithCancel(ctx) c, cancel := context.WithCancel(ctx)
@ -153,7 +150,7 @@ func EvalInstantiated(ctx context.Context, installable string) ([]string, error)
return nil, err return nil, err
} }
instantiated, decodeErr := DecodeInstantiated(stderr) instantiated, decodeErr := NewInstantiatedDecoder(stderr).Decode()
waitErr := cmd.Wait() waitErr := cmd.Wait()
return instantiated, errors.Join(decodeErr, waitErr) return instantiated, errors.Join(decodeErr, waitErr)
} }

View File

@ -50,7 +50,7 @@ func TestDecodeInstantiated(t *testing.T) {
} }
stderr := strings.NewReader(tc.out) stderr := strings.NewReader(tc.out)
got, err := nixbuild.DecodeInstantiated(stderr) got, err := nixbuild.NewInstantiatedDecoder(stderr).Decode()
if !errors.Is(err, tc.wantErr) { if !errors.Is(err, tc.wantErr) {
t.Fatalf("DecodeInstantiated: error = %v, want %v", err, tc.wantErr) t.Fatalf("DecodeInstantiated: error = %v, want %v", err, tc.wantErr)
} }
@ -146,7 +146,7 @@ func BenchmarkDecodeInstantiated(b *testing.B) {
stderr := strings.NewReader(pluiedevPappardelleOut) stderr := strings.NewReader(pluiedevPappardelleOut)
var v []string var v []string
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
v, _ = nixbuild.DecodeInstantiated(stderr) v, _ = nixbuild.NewInstantiatedDecoder(stderr).Decode()
runtime.KeepAlive(v) runtime.KeepAlive(v)
} }
} }
@ -155,7 +155,7 @@ func BenchmarkDecodeInstantiatedCopy(b *testing.B) {
stderr := strings.NewReader(getchooAtlasOut) stderr := strings.NewReader(getchooAtlasOut)
var v []string var v []string
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
v, _ = nixbuild.DecodeInstantiated(stderr) v, _ = nixbuild.NewInstantiatedDecoder(stderr).Decode()
runtime.KeepAlive(v) runtime.KeepAlive(v)
} }
} }