about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDoron Behar2024-06-16 17:08:57 +0300
committerDoron Behar2024-06-28 18:03:59 +0300
commiteb49fb355e8269690bb100fae060af50138b2de3 (patch)
treeb3a5b2f871f55131c43e756323ec642e41b9ada4
parent3b97a2e9ba4dd6abb8dc624941220a40d12ebe64 (diff)
versionCheckHook: init
-rw-r--r--doc/hooks/index.md1
-rw-r--r--doc/hooks/versionCheckHook.section.md35
-rw-r--r--pkgs/by-name/ve/versionCheckHook/hook.sh60
-rw-r--r--pkgs/by-name/ve/versionCheckHook/package.nix12
4 files changed, 108 insertions, 0 deletions
diff --git a/doc/hooks/index.md b/doc/hooks/index.md
index 1534ef85ccb9..6d01c6cbcbe5 100644
--- a/doc/hooks/index.md
+++ b/doc/hooks/index.md
@@ -29,6 +29,7 @@ scons.section.md
 tetex-tex-live.section.md
 unzip.section.md
 validatePkgConfig.section.md
+versionCheckHook.section.md
 waf.section.md
 zig.section.md
 xcbuild.section.md
diff --git a/doc/hooks/versionCheckHook.section.md b/doc/hooks/versionCheckHook.section.md
new file mode 100644
index 000000000000..55b9fa916c40
--- /dev/null
+++ b/doc/hooks/versionCheckHook.section.md
@@ -0,0 +1,35 @@
+# versionCheckHook {#versioncheckhook}
+
+This hook adds a `versionCheckPhase` to the [`preInstallCheckHooks`](#ssec-installCheck-phase) that runs the main program of the derivation with a `--help` or `--version` argument, and checks that the `${version}` string is found in that output. You use it like this:
+
+```nix
+{
+  lib,
+  stdenv,
+  versionCheckHook,
+  # ...
+}:
+
+stdenv.mkDerivation (finalAttrs: {
+  # ...
+
+  nativeInstallCheckInputs = [
+    versionCheckHook
+  ];
+  doInstallCheck = true;
+
+  # ...
+})
+```
+
+Note that for [`buildPythonPackage`](#buildpythonpackage-function) and [`buildPythonApplication`](#buildpythonapplication-function), `doInstallCheck` is enabled by default.
+
+It does so in a clean environment (using `env --ignore-environment`), and it checks for the `${version}` string in both the `stdout` and the `stderr` of the command. It will report to you in the build log the output it received and it will fail the build if it failed to find `${version}`.
+
+The variables that this phase control are:
+
+- `dontVersionCheck`: Disable adding this hook to the [`preDistPhases`](#var-stdenv-preDist). Useful if you do want to load the bash functions of the hook, but run them differently.
+- `versionCheckProgram`: The full path to the program that should print the `${version}` string. Defaults roughly to `${placeholder "out"}/bin/${pname}`. Using `$out` in the value of this variable won't work, as environment variables from this variable are not expanded by the hook. Hence using `placeholder` is unavoidable.
+- `versionCheckProgramArg`: The argument that needs to be passed to `versionCheckProgram`. If undefined the hook tries first `--help` and then `--version`. Examples: `version`, `-V`, `-v`.
+- `preVersionCheck`: A hook to run before the check is done.
+- `postVersionCheck`: A hook to run after the check is done.
diff --git a/pkgs/by-name/ve/versionCheckHook/hook.sh b/pkgs/by-name/ve/versionCheckHook/hook.sh
new file mode 100644
index 000000000000..cd417493e6c2
--- /dev/null
+++ b/pkgs/by-name/ve/versionCheckHook/hook.sh
@@ -0,0 +1,60 @@
+_handleCmdOutput(){
+    local versionOutput
+    versionOutput="$(env --chdir=/ --argv0="$(basename "$1")" --ignore-environment "$@" 2>&1 || true)"
+    if [[ "$versionOutput" =~ "$version" ]]; then
+        echoPrefix="Successfully managed to"
+    else
+        echoPrefix="Did not"
+    fi
+    # The return value of this function is this variable:
+    echo "$echoPrefix"
+    # And in anycase we want these to be printed in the build log, useful for
+    # debugging, so we print these to stderr.
+    echo "$echoPrefix" find version "$version" in the output of the command \
+        "$@" >&2
+    echo "$versionOutput" >&2
+}
+versionCheckHook(){
+    runHook preVersionCheck
+    echo Executing versionCheckPhase
+
+    local cmdProgram cmdArg echoPrefix
+    if [[ -z "${versionCheckProgram-}" ]]; then
+        if [[ -z "${pname-}" ]]; then
+            echo "both \$pname and \$versionCheckProgram are empty, so" \
+                "we don't know which program to run the versionCheckPhase" \
+                "upon" >&2
+            exit 2
+        else
+            cmdProgram="${!outputBin}/bin/$pname"
+        fi
+    else
+        cmdProgram="$versionCheckProgram"
+    fi
+    if [[ ! -x "$cmdProgram" ]]; then
+        echo "versionCheckHook: $cmdProgram was not found, or is not an executable" >&2
+        exit 2
+    fi
+    if [[ -z "${versionCheckProgramArg}" ]]; then
+        for cmdArg in "--help" "--version"; do
+            echoPrefix="$(_handleCmdOutput "$cmdProgram" "$cmdArg")"
+            if [[ "$echoPrefix" == "Successfully managed to" ]]; then
+                break
+            fi
+        done
+    else
+        cmdArg="$versionCheckProgramArg"
+        echoPrefix="$(_handleCmdOutput "$cmdProgram" "$cmdArg")"
+    fi
+    if [[ "$echoPrefix" == "Did not" ]]; then
+        exit 2
+    fi
+
+    runHook postVersionCheck
+    echo Finished versionCheckPhase
+}
+
+if [[ -z "${dontVersionCheck-}" ]]; then
+    echo "Using versionCheckHook"
+    preInstallCheckHooks+=(versionCheckHook)
+fi
diff --git a/pkgs/by-name/ve/versionCheckHook/package.nix b/pkgs/by-name/ve/versionCheckHook/package.nix
new file mode 100644
index 000000000000..ed35384d7960
--- /dev/null
+++ b/pkgs/by-name/ve/versionCheckHook/package.nix
@@ -0,0 +1,12 @@
+{
+  lib,
+  makeSetupHook,
+}:
+
+makeSetupHook {
+  name = "version-check-hook";
+  meta = {
+    description = "Lookup for $version in the output of --help and --version";
+    maintainers = with lib.maintainers; [ doronbehar ];
+  };
+} ./hook.sh