derivation: parse nix derivation show
This time it's JSON, and actual intended behaviour.
This commit is contained in:
parent
68ae0efe19
commit
6aafccce4c
15
build.go
15
build.go
@ -2,9 +2,9 @@ package nixbuild
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"iter"
|
"iter"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Build builds all entries yielded by installables.
|
// Build builds all entries yielded by installables.
|
||||||
@ -32,18 +32,11 @@ func Build(ctx context.Context, installables iter.Seq[string]) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for drv := range installables {
|
if _, err := WriteStdin(iw, installables); err != nil {
|
||||||
if strings.HasSuffix(drv, ".drv") {
|
return errors.Join(err, cmd.Wait())
|
||||||
// this is just what nix requires now :c
|
|
||||||
drv += "^*"
|
|
||||||
}
|
|
||||||
if _, err := iw.Write([]byte(drv + "\n")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := iw.Close(); err != nil {
|
if err := iw.Close(); err != nil {
|
||||||
return err
|
return errors.Join(err, cmd.Wait())
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.Wait()
|
return cmd.Wait()
|
||||||
|
@ -42,7 +42,20 @@ func main() {
|
|||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Connect nix stderr").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Connect nix stderr").
|
||||||
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
||||||
|
|
||||||
c.Command("build", "Build a list of installables", func(args []string) error {
|
c.Command("show", command.UsageInternal, func(args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return commandHandlerError("usage requires at least 1 argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
if drv, err := nixbuild.DerivationShow(ctx, slices.Values(args)); err != nil {
|
||||||
|
return commandHandlerError(fmt.Sprintf("cannot show: %v", err))
|
||||||
|
} else {
|
||||||
|
log.Printf("got %d derivations:\n%#v", len(drv), drv)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
c.Command("build", command.UsageInternal, func(args []string) error {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return commandHandlerError("build requires at least 1 argument")
|
return commandHandlerError("build requires at least 1 argument")
|
||||||
}
|
}
|
||||||
|
88
derivation.go
Normal file
88
derivation.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package nixbuild
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"iter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// DerivationMap is the output of `nix derivation show`.
|
||||||
|
DerivationMap map[string]Derivation
|
||||||
|
|
||||||
|
// Derivation is a description of a derivation.
|
||||||
|
Derivation struct {
|
||||||
|
// Args are arguments passed to Builder.
|
||||||
|
Args []string `json:"args"`
|
||||||
|
// Builder is the store path of the program that builds the [Derivation].
|
||||||
|
Builder string `json:"builder"`
|
||||||
|
// System is the value of pkgs.system during evaluation.
|
||||||
|
System string `json:"system"`
|
||||||
|
// Name is the user-facing name of a derivation, as seen in the nix store path suffix.
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
Environment json.RawMessage `json:"env"`
|
||||||
|
InputDerivations InputDerivationsMap `json:"inputDrvs"`
|
||||||
|
InputSources []string `json:"inputSrcs"`
|
||||||
|
Outputs OutputsMap `json:"outputs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputsMap is an output name to [Output] map.
|
||||||
|
OutputsMap map[string]Output
|
||||||
|
|
||||||
|
// Output is an output of a [Derivation].
|
||||||
|
Output struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputDerivationsMap is a store path to metadata map.
|
||||||
|
InputDerivationsMap map[string]InputDerivation
|
||||||
|
|
||||||
|
// InputDerivation contains input derivation metadata.
|
||||||
|
InputDerivation struct {
|
||||||
|
DynamicOutputs json.RawMessage `json:"dynamicOutputs"`
|
||||||
|
Outputs []string `json:"outputs"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// DerivationShow returns a [DerivationMap] describing all entries yielded by installables.
|
||||||
|
func DerivationShow(ctx context.Context, installables iter.Seq[string]) (DerivationMap, error) {
|
||||||
|
c, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
cmd := Nix(c, CommandDerivation, CommandDerivationShow,
|
||||||
|
FlagStdin)
|
||||||
|
ir, iw := io.Pipe()
|
||||||
|
cmd.Stdin = ir
|
||||||
|
or, ow := io.Pipe()
|
||||||
|
cmd.Stdout = ow
|
||||||
|
if Stderr != nil {
|
||||||
|
cmd.Stderr = Stderr
|
||||||
|
}
|
||||||
|
cmd.Cancel = func() error { _ = ow.Close(); return cmd.Process.Kill() }
|
||||||
|
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan error)
|
||||||
|
var v DerivationMap
|
||||||
|
go func() { done <- json.NewDecoder(or).Decode(&v) }()
|
||||||
|
|
||||||
|
if _, err := WriteStdin(iw, installables); err != nil {
|
||||||
|
return nil, errors.Join(err, cmd.Wait())
|
||||||
|
}
|
||||||
|
if err := iw.Close(); err != nil {
|
||||||
|
return nil, errors.Join(err, cmd.Wait())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
// deferred cancel closes pipe
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err := <-done
|
||||||
|
return v, err
|
||||||
|
}
|
26
format.go
26
format.go
@ -2,12 +2,21 @@ package nixbuild
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
"iter"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// CommandBuild build a derivation or fetch a store path
|
// CommandBuild build a derivation or fetch a store path
|
||||||
CommandBuild = "build"
|
CommandBuild = "build"
|
||||||
|
// CommandDerivation work with derivations, Nix's notion of a build plan.
|
||||||
|
CommandDerivation = "derivation"
|
||||||
|
// CommandDerivationAdd add a store derivation
|
||||||
|
CommandDerivationAdd = "add"
|
||||||
|
// CommandDerivationShow show the contents of a store derivation
|
||||||
|
CommandDerivationShow = "show"
|
||||||
|
|
||||||
// FlagDryRun show what this command would do without doing it.
|
// FlagDryRun show what this command would do without doing it.
|
||||||
FlagDryRun = "--dry-run"
|
FlagDryRun = "--dry-run"
|
||||||
@ -86,3 +95,20 @@ const (
|
|||||||
|
|
||||||
// NixOSInstallable returns the nixos installable for a given flake and host.
|
// NixOSInstallable returns the nixos installable for a given flake and host.
|
||||||
func NixOSInstallable(flake, host string) string { return flake + nixosSuffix0 + host + nixosSuffix1 }
|
func NixOSInstallable(flake, host string) string { return flake + nixosSuffix0 + host + nixosSuffix1 }
|
||||||
|
|
||||||
|
// WriteStdin writes installables for a nix process running with [FlagStdin].
|
||||||
|
func WriteStdin(w io.Writer, installables iter.Seq[string]) (int, error) {
|
||||||
|
var count int
|
||||||
|
for drv := range installables {
|
||||||
|
if strings.HasSuffix(drv, ".drv") {
|
||||||
|
// this is just what nix requires now :c
|
||||||
|
drv += "^*"
|
||||||
|
}
|
||||||
|
n, err := w.Write([]byte(drv + "\n"))
|
||||||
|
count += n
|
||||||
|
if err != nil {
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user