tvl-depot/users/Profpatsch/nix-tools.nix
Profpatsch 8ca42dc0cd feat(users/Profpatsch): add nix-run, nix-run-bin, nix-eval
Change-Id: I76f6fa4866c5792c4b9babe2c3a16401162ad833
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11170
Autosubmit: Profpatsch <mail@profpatsch.de>
Reviewed-by: Profpatsch <mail@profpatsch.de>
Tested-by: BuildkiteCI
2024-03-17 01:21:14 +00:00

159 lines
4.1 KiB
Nix
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ depot, pkgs, ... }:
let
bins = depot.nix.getBins pkgs.nix [ "nix-build" "nix-instantiate" ];
# TODO: both of these dont prevent `result` from being created. good? bad?
# Usage (execline syntax):
# nix-run { -A foo <more_nix_options> } args...
#
# Takes an execline block of `nix-build` arguments, which should produce an executable store path.
# Then runs the store path with `prog...`.
nix-run = depot.nix.writeExecline "nix-run" { argMode = "env"; } [
"backtick"
"-iE"
"storepath"
[
runblock
"1"
bins.nix-build
]
runblock
"-r"
"2"
"$storepath"
];
# Usage (execline syntax):
# nix-run-bin { -A foo <more_nix_options> } <foo_bin_name> args...
#
# Takes an execline block of `nix-build` arguments, which should produce a store path with a bin/ directory in it.
# Then runs the given command line with the given arguments. All executables in the built storepaths bin directory are prepended to `PATH`.
nix-run-bin = depot.nix.writeExecline "nix-run-bin" { argMode = "env"; } [
"backtick"
"-iE"
"storepath"
[
runblock
"1"
bins.nix-build
]
"importas"
"-ui"
"PATH"
"PATH"
"export"
"PATH"
"\${storepath}/bin:\${PATH}"
runblock
"-r"
"2"
];
nix-eval = depot.nix.writeExecline "nix-eval" { } [
bins.nix-instantiate
"--read-write-mode"
"--eval"
"--strict"
"$@"
];
# This is a rewrite of execlines runblock.
# It adds the feature that instead of just
# executing the block it reads, it can also
# pass it as argv to given commands.
#
# This is going to be added to a future version
# of execline by skarnet, but for now its easier
# to just dirtily reimplement it in Python.
#
# TODO: this was added to recent execline versions,
# but it doesnt seem to be a drop-in replacement,
# if I use execlines runblock in nix-run-bin above,
# I get errors like
# > export: fatal: unable to exec runblock: Success
runblock = pkgs.writers.writePython3 "runblock"
{
flakeIgnore = [ "E501" "E226" ];
} ''
import sys
import os
from pathlib import Path
skip = False
one = sys.argv[1]
if one == "-r":
skip = True
block_number = int(sys.argv[2])
block_start = 3
elif one.startswith("-"):
print("runblock-python: only -r supported", file=sys.stderr)
sys.exit(100)
else:
block_number = int(one)
block_start = 2
execline_argv_no = int(os.getenvb(b"#"))
runblock_argv = [os.getenv(str(no)) for no in range(1, execline_argv_no + 1)]
def parse_block(args):
new_args = []
if args == []:
print(
"runblock-python: empty block",
file=sys.stderr
)
sys.exit(100)
for arg in args:
if arg == "":
break
elif arg.startswith(" "):
new_args.append(arg[1:])
else:
print(
"runblock-python: unterminated block: {}".format(args),
file=sys.stderr
)
sys.exit(100)
args_rest = args[len(new_args)+1:]
return (new_args, args_rest)
if skip:
rest = runblock_argv
for _ in range(0, block_number-1):
(_, rest) = parse_block(rest)
new_argv = rest
else:
new_argv = []
rest = runblock_argv
for _ in range(0, block_number):
(new_argv, rest) = parse_block(rest)
given_argv = sys.argv[block_start:]
run = given_argv + new_argv
if os.path.isabs(run[0]):
# TODO: ideally Id check if its an executable here, but it was too hard to figure out and I couldnt be bothered tbh
if not Path(run[0]).is_file():
print(
"runblock-python: Executable {} does not exist or is not a file.".format(run[0]),
file=sys.stderr
)
sys.exit(100)
os.execvp(
file=run[0],
args=run
)
'';
in
{
inherit
nix-run
nix-run-bin
nix-eval
;
}