plsfail added
This commit is contained in:
parent
687b99ae04
commit
57abab969e
5 changed files with 129 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
.direnv/
|
.direnv/
|
||||||
|
result/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
{ self, inputs, config, ... }:
|
{
|
||||||
|
self,
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
flake.nixosModules.development =
|
flake.nixosModules.development =
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
@ -17,6 +22,7 @@
|
||||||
zellij
|
zellij
|
||||||
self.packages.${pkgs.stdenv.hostPlatform.system}.ralph
|
self.packages.${pkgs.stdenv.hostPlatform.system}.ralph
|
||||||
self.packages.${pkgs.stdenv.hostPlatform.system}.t3code
|
self.packages.${pkgs.stdenv.hostPlatform.system}.t3code
|
||||||
|
self.packages.${pkgs.stdenv.hostPlatform.system}.plsfail
|
||||||
];
|
];
|
||||||
programs.zoxide = {
|
programs.zoxide = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
||||||
32
modules/packages/plsfail/default.nix
Normal file
32
modules/packages/plsfail/default.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
perSystem =
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
{
|
||||||
|
packages.plsfail = pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
pname = "plsfail";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
substituteInPlace plsfail.py \
|
||||||
|
--replace-fail '#!/usr/bin/env python3' '#!${pkgs.python3}/bin/python3'
|
||||||
|
install -Dm755 plsfail.py "$out/bin/plsfail"
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Run a command until it fails";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
mainProgram = "plsfail";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
88
modules/packages/plsfail/plsfail.py
Normal file
88
modules/packages/plsfail/plsfail.py
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser(description="Run a command until it fails")
|
||||||
|
parser.add_argument(
|
||||||
|
"-n",
|
||||||
|
"--tries",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="Maximum number of attempts; 0 means keep going until failure",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
action="count",
|
||||||
|
default=0,
|
||||||
|
help="Increase progress output",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-q",
|
||||||
|
"--quiet",
|
||||||
|
action="count",
|
||||||
|
default=0,
|
||||||
|
help="Reduce extra progress output",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"command",
|
||||||
|
nargs=argparse.REMAINDER,
|
||||||
|
help="Command to run, prefixed by -- if it has its own flags",
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def progress_level(verbose: int, quiet: int) -> int:
|
||||||
|
return max(verbose - quiet, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def print_progress(level: int, message: str, *, minimum_level: int = 0) -> None:
|
||||||
|
if level >= minimum_level:
|
||||||
|
print(message, file=sys.stderr, flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
args = parse_args()
|
||||||
|
|
||||||
|
command = list(args.command)
|
||||||
|
if command[:1] == ["--"]:
|
||||||
|
command = command[1:]
|
||||||
|
if not command:
|
||||||
|
print("usage: plsfail [options] -- command [args...]", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
level = progress_level(args.verbose, args.quiet)
|
||||||
|
tries = args.tries
|
||||||
|
attempt = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
attempt += 1
|
||||||
|
print_progress(level, f"try {attempt}: running {shlex.join(command)}")
|
||||||
|
result = subprocess.run(command, capture_output=True, text=True)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print_progress(level, f"try {attempt}: failed with exit code {result.returncode}")
|
||||||
|
if result.stdout:
|
||||||
|
sys.stdout.write(result.stdout)
|
||||||
|
sys.stdout.flush()
|
||||||
|
if result.stderr:
|
||||||
|
sys.stderr.write(result.stderr)
|
||||||
|
sys.stderr.flush()
|
||||||
|
return result.returncode
|
||||||
|
|
||||||
|
print_progress(level, f"try {attempt}: ok")
|
||||||
|
|
||||||
|
if tries > 0 and attempt >= tries:
|
||||||
|
print_progress(level, f"completed {attempt} tries without failure")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
1
result
Symbolic link
1
result
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/k0lnr9lz6rcxi2qj1qfssk0786amkmd6-plsfail-0.1.0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue