mirror of https://git.jolheiser.com/nixfig.git
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package nixfig
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
var (
|
|
// Nix is the command to call for nix
|
|
Nix string
|
|
ErrNixNotFound = errors.New("nix was not found or set. You can set it either with `nixfig.Nix` or the `NIXFIG_NIX` environment variable")
|
|
)
|
|
|
|
func init() {
|
|
nixPath, _ := exec.LookPath("nix")
|
|
Nix = nixPath
|
|
if envPath, ok := os.LookupEnv("NIXFIG_NIX"); ok {
|
|
Nix = envPath
|
|
}
|
|
}
|
|
|
|
// Unmarshal unmarshals a nix expression as JSON into a struct
|
|
func Unmarshal(data []byte, v any) error {
|
|
if Nix == "" {
|
|
return ErrNixNotFound
|
|
}
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
cmd := exec.Command(Nix, "eval", "--json", "--expr", string(data))
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("could not run %q: %w", Nix, err)
|
|
}
|
|
if stderr.Len() > 0 {
|
|
return errors.New(stderr.String())
|
|
}
|
|
|
|
if err := json.Unmarshal(stdout.Bytes(), v); err != nil {
|
|
return fmt.Errorf("could not unmarshal nix config as JSON: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Marshal marshals a struct into a nix expression
|
|
func Marshal(v any) ([]byte, error) {
|
|
if Nix == "" {
|
|
return nil, ErrNixNotFound
|
|
}
|
|
|
|
data, err := json.Marshal(v)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not marshal JSON: %w", err)
|
|
}
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
cmd := exec.Command(Nix, "eval", "--expr", fmt.Sprintf(`(builtins.fromJSON %q)`, string(data)))
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return nil, fmt.Errorf("could not run %q: %w", Nix, err)
|
|
}
|
|
if stderr.Len() > 0 {
|
|
return nil, errors.New(stderr.String())
|
|
}
|
|
|
|
return stdout.Bytes(), nil
|
|
}
|