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
This commit is contained in:
parent
11a2098e0b
commit
8ca42dc0cd
1 changed files with 159 additions and 0 deletions
159
users/Profpatsch/nix-tools.nix
Normal file
159
users/Profpatsch/nix-tools.nix
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
bins = depot.nix.getBins pkgs.nix [ "nix-build" "nix-instantiate" ];
|
||||||
|
|
||||||
|
# TODO: both of these don’t 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 storepath’s 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 execline’s 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 it’s easier
|
||||||
|
# to just dirtily reimplement it in Python.
|
||||||
|
#
|
||||||
|
# TODO: this was added to recent execline versions,
|
||||||
|
# but it doesn’t seem to be a drop-in replacement,
|
||||||
|
# if I use execline’s 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 I’d check if it’s an executable here, but it was too hard to figure out and I couldn’t 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
|
||||||
|
;
|
||||||
|
}
|
Loading…
Reference in a new issue