diff --git a/pkgs/development/misc/resholve/README.md b/pkgs/development/misc/resholve/README.md index ddba7fc1493..6b99aebb597 100644 --- a/pkgs/development/misc/resholve/README.md +++ b/pkgs/development/misc/resholve/README.md @@ -6,9 +6,28 @@ until then I'll outline how to use the `resholvePackage` function. > Fair warning: resholve does *not* aspire to resolving all valid Shell > scripts. It depends on the OSH/Oil parser, which aims to support most (but -> not all) Bash, and aims to be a ~90% sort of solution. +> not all) Bash. resholve aims to be a ~90% sort of solution. -Let's start with a simple example from one of my own projects: +## API Concepts + +The main difference between `resholvePackage` and other builder functions +is the `solutions` attrset, which describes which scripts to resolve and how. +Each "solution" (k=v pair) in this attrset describes one resholve invocation. + +> NOTE: For most shell packages, one invocation will probably be enough: +> - Packages with a single script will only need one solution. +> - Packages with multiple scripts can still use one solution if the scripts +> don't require conflicting directives. +> - Packages with scripts that require conflicting directives can use multiple +> solutions to resolve the scripts separately, but produce a single package. + +## Basic Example + +Here's a simple example from one of my own projects, with annotations: + ```nix { stdenv, lib, resholvePackage, fetchFromGitHub, bashup-events44, bashInteractive_5, doCheck ? true, shellcheck }: @@ -22,10 +41,20 @@ resholvePackage rec { }; solutions = { + # Give each solution a short name. This is what you'd use to + # override its settings, and it shows in (some) error messages. profile = { - # the only *required* arguments + # the only *required* arguments are the 3 below + + # Specify 1 or more $out-relative script paths. Unlike many + # builders, resholvePackage modifies the output files during + # fixup (to correctly resolve in-package sourcing). scripts = [ "bin/shellswain.bash" ]; + + # "none" for no shebang, "${bash}/bin/bash" for bash, etc. interpreter = "none"; + + # packages resholve should resolve executables from inputs = [ bashup-events44 ]; }; }; @@ -39,100 +68,91 @@ resholvePackage rec { } ``` -I'll focus on the `solutions` attribute, since this is the only part -that differs from other derivations. +## Options -Each "solution" (k=v pair) -describes one resholve invocation. For most shell packages, one -invocation will probably be enough. resholve will make you be very -explicit about your script's dependencies, and it may also need your -help sorting out some references or problems that it can't safely -handle on its own. +`resholvePackage` maps Nix types/idioms into the flags and environment variables +that the `resholve` CLI expects. Here's an overview: -If you have more than one script, and your scripts need conflicting -directives, you can specify more than one solution to resolve the -scripts separately, but still produce a single package. +| Option | Type | Containing | +| ------------- | ------- | ----------------------------------------------------- | +| scripts | list | $out-relative string paths to resolve | +| inputs | list | packages to resolve executables from | +| interpreter | string | 'none' or abspath for shebang | +| prologue | file | text to insert before the first code-line | +| epilogue | file | text to isnert after the last code-line | +| flags | list | strings to pass as flags | +| fake | attrset | [directives](#controlling-resolution-with-directives) | +| fix | attrset | [directives](#controlling-resolution-with-directives) | +| keep | attrset | [directives](#controlling-resolution-with-directives) | -Let's take a closer look: +## Controlling resolution with directives -```nix - solutions = { - # each solution has a short name; this is what you'd use to - # override the settings of this solution, and it may also show up - # in (some) error messages. - profile = { - # specify one or more $out-relative script paths (unlike many - # builders, resholve will modify the output files during fixup - # to correctly resolve scripts that source within the package) - scripts = [ "bin/shellswain.bash" ]; - # "none" for no shebang, "${bash}/bin/bash" for bash, etc. - interpreter = "none"; - # packages resholve should resolve executables from - inputs = [ bashup-events44 ]; - }; - }; -``` +In order to resolve a script, resholve will make you disambiguate how it should +handle any potential problems it encounters with directives. There are currently +3 types: +1. `fake` directives tell resholve to pretend it knows about an identifier + such as a function, builtin, external command, etc. if there's a good reason + it doesn't already know about it. Common examples: + - builtins for a non-bash shell + - loadable builtins + - platform-specific external commands in cross-platform conditionals +2. `fix` directives give resholve permission to fix something that it can't + safely fix automatically. Common examples: + - resolving commands in aliases (this is appropriate for standalone scripts + that use aliases non-interactively--but it would prevent profile/rc + scripts from using the latest current-system symlinks.) + - resolve commands in a variable definition + - resolve an absolute command path from inputs as if it were a bare reference +3. `keep` directives tell resholve not to raise an error (i.e., ignore) + something it would usually object to. Common examples: + - variables used as/within the first word of a command + - pre-existing absolute or user-relative (~) command paths + - dynamic (variable) arguments to commands known to accept/run other commands -resholve has a (growing) number of options for handling more complex -scripts. I won't cover these in excruciating detail here. You can find -more information about these in `man resholve` via `nixpkgs.resholve`. +> NOTE: resholve has a (growing) number of directives detailed in `man resholve` +> via `nixpkgs.resholve`. -Instead, we'll look at the general form of the solutions attrset: +Each of these 3 types is represented by its own attrset, where you can think +of the key as a scope. The value should be: +- `true` for any directives that the resholve CLI accepts as a single word +- a list of strings for all other options + - # optional - fake = { fake directives }; - fix = { fix directives }; - keep = { keep directives }; - # file to inject before first code-line of script - prologue = file; - # file to inject after last code-line of script - epilogue = file; - # extra command-line flags passed to resholve; generally this API - # should align with what resholve supports, but flags may help if - # you need to override the version of resholve. - flags = [ ]; - }; -}; -``` - -The main way you'll adjust how resholve handles your scripts are the -fake, fix, and keep directives. The manpage covers their purpose and -how to format them on the command-line, so I'll focus on how you'll -need to translate them into Nix types. +This will hopefully make more sense when you see it. Here are CLI examples +from the manpage, and the Nix equivalents: ```nix # --fake 'f:setUp;tearDown builtin:setopt source:/etc/bashrc' fake = { - function = [ "setUp" "tearDown" ]; - builtin = [ "setopt" ]; - source = [ "/etc/bashrc" ]; + # fake accepts the initial of valid identifier types as a CLI convienience. + # Use full names in the Nix API. + function = [ "setUp" "tearDown" ]; + builtin = [ "setopt" ]; + source = [ "/etc/bashrc" ]; }; # --fix 'aliases xargs:ls $GIT:gix' fix = { - # all single-word directives use `true` as value - aliases = true; - xargs = [ "ls" ]; - "$GIT" = [ "gix" ]; + # all single-word directives use `true` as value + aliases = true; + xargs = [ "ls" ]; + "$GIT" = [ "gix" ]; }; # --keep 'which:git;ls .:$HOME $LS:exa /etc/bashrc ~/.bashrc' keep = { - which = [ "git" "ls" ]; - "." = [ "$HOME" ]; - "$LS" = [ "exa" ]; - "/etc/bashrc" = true; - "~/.bashrc" = true; + which = [ "git" "ls" ]; + "." = [ "$HOME" ]; + "$LS" = [ "exa" ]; + "/etc/bashrc" = true; + "~/.bashrc" = true; }; ```