Add instantiate and narinfo
This commit is contained in:
parent
4e3e77171c
commit
5247d1f329
|
@ -2,13 +2,15 @@
|
|||
|
||||
An actor for interacting with the [Nix](https://nixos.org/) daemon via the [Syndicated Actor Model](https://syndicate-lang.org/).
|
||||
|
||||
*This is only a proof-of-concept and is not useful in any meaningful way.*
|
||||
*This is only a proof-of-concept and is not yet useful.*
|
||||
|
||||
## Example configuration
|
||||
```
|
||||
? <nixspace ?nixspace> $nixspace [
|
||||
|
||||
? <realise "/nix/store/sv1yikjpf7q8b9w4xszb2ipg0cgcq1xv-imv-4.4.0.drv" ?outputs> [ ]
|
||||
? <instantiate "let pkgs = import <nixpkgs> {}; in pkgs.hello" { } ?drv> [
|
||||
? <realise $drv ?outputs> [ ]
|
||||
]
|
||||
|
||||
? <eval "3 * 4" {} _> []
|
||||
? <eval "builtins.getEnv \"PATH\"" {impure: ""} _> []
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
version 1 .
|
||||
|
||||
|
||||
Build = <nix-build @input string @output any> .
|
||||
|
||||
Realise = <realise @drv string @outputs [string ...]> .
|
||||
|
||||
Instantiate = <instantiate @expr string @options Dict @result any> .
|
||||
|
||||
Eval = <eval @expr string @options {symbol: any ...:...} @result any> .
|
||||
|
||||
Narinfo = <narinfo @path string @info Dict> .
|
||||
|
||||
Dict = {symbol: any ...:...} .
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import std/[asyncdispatch, json, osproc, strutils, tables]
|
||||
import std/[asyncdispatch, httpclient, json, osproc, parseutils, strutils, tables]
|
||||
import preserves, preserves/jsonhooks
|
||||
import syndicate
|
||||
from syndicate/protocols/dataspace import Observe
|
||||
|
@ -10,9 +10,48 @@ import ./nix_actor/[main, store]
|
|||
|
||||
type
|
||||
Value = Preserve[void]
|
||||
Options = Table[Symbol, Value]
|
||||
Observe = dataspace.Observe[Ref]
|
||||
|
||||
proc parseArgs(args: var seq[string]; opts: Dict) =
|
||||
for sym, val in opts:
|
||||
add(args, "--" & $sym)
|
||||
if not val.isString "":
|
||||
var js: JsonNode
|
||||
if fromPreserve(js, val): add(args, $js)
|
||||
else: stderr.writeLine "invalid option --", sym, " ", val
|
||||
|
||||
proc parseNarinfo(info: var Dict; text: string) =
|
||||
var
|
||||
key, val: string
|
||||
off: int
|
||||
while off < len(text):
|
||||
off = off + parseUntil(text, key, ':', off) + 1
|
||||
off = off + skipWhitespace(text, off)
|
||||
off = off + parseUntil(text, val, '\n', off) + 1
|
||||
if key != "" and val != "":
|
||||
if allCharsInSet(val, Digits):
|
||||
info[Symbol key] = val.parsePreserves
|
||||
else:
|
||||
info[Symbol key] = val.toPreserve
|
||||
|
||||
proc narinfo(turn: var Turn; ds: Ref; path: string) =
|
||||
let
|
||||
client = newAsyncHttpClient()
|
||||
url = "https://cache.nixos.org/" & path & ".narinfo"
|
||||
futGet = get(client, url)
|
||||
stderr.writeLine "fetching ", url
|
||||
addCallback(futGet, turn) do (turn: var Turn):
|
||||
let resp = read(futGet)
|
||||
if code(resp) != Http200:
|
||||
close(client)
|
||||
else:
|
||||
let futBody = body(resp)
|
||||
addCallback(futBody, turn) do (turn: var Turn):
|
||||
close(client)
|
||||
var narinfo = Narinfo(path: path)
|
||||
parseNarinfo(narinfo.info, read(futBody))
|
||||
discard publish(turn, ds, narinfo)
|
||||
|
||||
proc build(spec: string): Build =
|
||||
var execOutput = execProcess("nix", args = ["build", "--json", "--no-link", spec], options = {poUsePath})
|
||||
var js = parseJson(execOutput)
|
||||
|
@ -22,15 +61,18 @@ proc realise(realise: Realise): seq[string] =
|
|||
var execlines = execProcess("nix-store", args = ["--realize", realise.drv], options = {poUsePath})
|
||||
split(strip(execlines), '\n')
|
||||
|
||||
proc instantiate(instantiate: Instantiate): Value =
|
||||
const cmd = "nix-instantiate"
|
||||
var args = @["--expr", instantiate.expr]
|
||||
parseArgs(args, instantiate.options)
|
||||
var execOutput = strip execProcess(cmd, args = args, options = {poUsePath})
|
||||
execOutput.toPreserve
|
||||
|
||||
proc eval(eval: Eval): Value =
|
||||
var args = @["eval", "--json", "--expr", eval.expr]
|
||||
for sym, val in eval.options:
|
||||
add(args, "--" & $sym)
|
||||
if not val.isString "":
|
||||
var js: JsonNode
|
||||
if fromPreserve(js, val): add(args, $js)
|
||||
else: stderr.writeLine "invalid option ", sym, " ", val
|
||||
var execOutput = strip execProcess("nix", args = args, options = {poUsePath})
|
||||
const cmd = "nix"
|
||||
var args = @["eval", "--expr", eval.expr]
|
||||
parseArgs(args, eval.options)
|
||||
var execOutput = strip execProcess(cmd, args = args, options = {poUsePath})
|
||||
if execOutput != "":
|
||||
var js = parseJson(execOutput)
|
||||
result = js.toPreserve
|
||||
|
@ -47,6 +89,14 @@ proc bootNixFacet(ds: Ref; turn: var Turn): Facet =
|
|||
ass.outputs = realise(ass)
|
||||
discard publish(turn, ds, ass)
|
||||
|
||||
during(turn, ds, ?Observe(pattern: !Instantiate) ?? {0: grabLit(), 1: grabDict()}) do (e: string, o: Value):
|
||||
var ass = Instantiate(expr: e)
|
||||
if not fromPreserve(ass.options, unpackLiterals(o)):
|
||||
stderr.writeLine "invalid options ", o
|
||||
else:
|
||||
ass.result = instantiate(ass)
|
||||
discard publish(turn, ds, ass)
|
||||
|
||||
during(turn, ds, ?Observe(pattern: !Eval) ?? {0: grabLit(), 1: grabDict()}) do (e: string, o: Value):
|
||||
var ass = Eval(expr: e)
|
||||
if not fromPreserve(ass.options, unpackLiterals(o)):
|
||||
|
@ -55,6 +105,9 @@ proc bootNixFacet(ds: Ref; turn: var Turn): Facet =
|
|||
ass.result = eval(ass)
|
||||
discard publish(turn, ds, ass)
|
||||
|
||||
during(turn, ds, ?Observe(pattern: !Narinfo) ?? {0: grabLit()}) do (path: string):
|
||||
narinfo(turn, ds, path)
|
||||
|
||||
type Args {.preservesDictionary.} = object
|
||||
dataspace: Ref
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
define:ssl
|
|
@ -12,12 +12,22 @@ type
|
|||
`drv`*: string
|
||||
`outputs`*: seq[string]
|
||||
|
||||
Narinfo* {.preservesRecord: "narinfo".} = object
|
||||
`path`*: string
|
||||
`info`*: Dict
|
||||
|
||||
Dict* = Table[Symbol, Preserve[void]]
|
||||
Build* {.preservesRecord: "nix-build".} = object
|
||||
`input`*: string
|
||||
`output`*: Preserve[void]
|
||||
|
||||
proc `$`*(x: Eval | Realise | Build): string =
|
||||
Instantiate* {.preservesRecord: "instantiate".} = object
|
||||
`expr`*: string
|
||||
`options`*: Dict
|
||||
`result`*: Preserve[void]
|
||||
|
||||
proc `$`*(x: Eval | Realise | Narinfo | Dict | Build | Instantiate): string =
|
||||
`$`(toPreserve(x))
|
||||
|
||||
proc encode*(x: Eval | Realise | Build): seq[byte] =
|
||||
proc encode*(x: Eval | Realise | Narinfo | Dict | Build | Instantiate): seq[byte] =
|
||||
encode(toPreserve(x))
|
||||
|
|
Loading…
Reference in New Issue