From 87399d28fe585d39e925cd34d662cd3d0b5b6be6 Mon Sep 17 00:00:00 2001 From: technofab Date: Thu, 1 Jan 2026 15:56:25 +0100 Subject: [PATCH] feat: add package to exclude gitignored hooks tools like renovate can run soonix:update after updating stuff, but the gitignored hooks cannot be committed anyways, so why bother building them --- lib/module.nix | 172 +++++++++++++++++++++++------------------- tests/soonix_test.nix | 22 ++++++ 2 files changed, 116 insertions(+), 78 deletions(-) diff --git a/lib/module.nix b/lib/module.nix index 4546319..803912a 100644 --- a/lib/module.nix +++ b/lib/module.nix @@ -153,83 +153,93 @@ in { config = let hooks = config.hooks; - hookNames = builtins.attrNames hooks; + # allow excluding gitignore since stuff like renovate can't use/commit it anyways + getHookNames = {includeGitignored ? true}: + if includeGitignored + then (builtins.attrNames hooks) + else + map + (hook: hook.name) + (builtins.filter (hook: !hook.hook.gitignore) (builtins.attrValues hooks)); - runHooks = concatMapStringsSep "\n" (hookName: let - hook = hooks.${hookName}; - modes = { - link = - # sh - '' - if [[ ! -L "${hook.output}" ]] || [[ "$(readlink "${hook.output}")" != "${hook.generatedDerivation}" ]]; then - _soonix_log "info" "${hookName}" "Creating symlink: ${hook.output} -> ${hook.generatedDerivation}" - mkdir -p "$(dirname "${hook.output}")" - ln -sf "${hook.generatedDerivation}" "${hook.output}" - _changed=true - else - _soonix_log "info" "${hookName}" "Symlink up to date: ${hook.output}" - fi - ''; - copy = - # sh - '' - if [[ ! -f "${hook.output}" ]] || ! cmp -s "${hook.generatedDerivation}" "${hook.output}"; then - _soonix_log "info" "${hookName}" "Copying file: ${hook.generatedDerivation} -> ${hook.output}" - mkdir -p "$(dirname "${hook.output}")" - # required since they're read only - rm -f "${hook.output}" - cp "${hook.generatedDerivation}" "${hook.output}" - _changed=true - else - _soonix_log "info" "${hookName}" "File up to date: ${hook.output}" - fi - ''; - }; + runHooks = args: + concatMapStringsSep "\n" (hookName: let + hook = hooks.${hookName}; + modes = { + link = + # sh + '' + if [[ ! -L "${hook.output}" ]] || [[ "$(readlink "${hook.output}")" != "${hook.generatedDerivation}" ]]; then + _soonix_log "info" "${hookName}" "Creating symlink: ${hook.output} -> ${hook.generatedDerivation}" + mkdir -p "$(dirname "${hook.output}")" + ln -sf "${hook.generatedDerivation}" "${hook.output}" + _changed=true + else + _soonix_log "info" "${hookName}" "Symlink up to date: ${hook.output}" + fi + ''; + copy = + # sh + '' + if [[ ! -f "${hook.output}" ]] || ! cmp -s "${hook.generatedDerivation}" "${hook.output}"; then + _soonix_log "info" "${hookName}" "Copying file: ${hook.generatedDerivation} -> ${hook.output}" + mkdir -p "$(dirname "${hook.output}")" + # required since they're read only + rm -f "${hook.output}" + cp "${hook.generatedDerivation}" "${hook.output}" + _changed=true + else + _soonix_log "info" "${hookName}" "File up to date: ${hook.output}" + fi + ''; + }; - optionalGitignore = - if hook.hook.gitignore - then '' - _soonix_add_to_gitignore "${hook.output}" + optionalGitignore = + if hook.hook.gitignore + then '' + _soonix_add_to_gitignore "${hook.output}" + '' + else ""; + in + builtins.addErrorContext "[soonix] while generating script for ${hookName}" + # sh '' - else ""; - in - # sh - '' - # Process hook: ${hookName} - while IFS= read -r line; do - case "$line" in - UPDATED) _soonix_updated+=("${hookName}") ;; - UPTODATE) _soonix_uptodate+=("${hookName}") ;; - *) echo "$line" ;; - esac - done < <( - set -euo pipefail - _changed=false + # Process hook: ${hookName} + while IFS= read -r line; do + case "$line" in + UPDATED) _soonix_updated+=("${hookName}") ;; + UPTODATE) _soonix_uptodate+=("${hookName}") ;; + *) echo "$line" ;; + esac + done < <( + set -euo pipefail + _changed=false - ${modes.${hook.hook.mode} or (throw "Mode ${hook.hook.mode} doesnt exist")} + ${modes.${hook.hook.mode} or (throw "Mode ${hook.hook.mode} doesnt exist")} - # Add to gitignore if requested - ${optionalGitignore} + # Add to gitignore if requested + ${optionalGitignore} - # Run extra commands if file changed - if [[ "$_changed" == "true" && -n "${hook.hook.extra}" ]]; then - _soonix_log "info" "${hookName}" "Running extra command: ${hook.hook.extra}" - eval "${hook.hook.extra}" - fi + # Run extra commands if file changed + if [[ "$_changed" == "true" && -n "${hook.hook.extra}" ]]; then + _soonix_log "info" "${hookName}" "Running extra command: ${hook.hook.extra}" + eval "${hook.hook.extra}" + fi - if [[ "$_changed" == "true" ]]; then - echo "UPDATED" - else - echo "UPTODATE" - fi - ) || { - _soonix_log "error" "${hookName}" "Failed to process hook" - _soonix_failed+=("${hookName}") - } - '') - hookNames; + if [[ "$_changed" == "true" ]]; then + echo "UPDATED" + else + echo "UPTODATE" + fi + ) || { + _soonix_log "error" "${hookName}" "Failed to process hook" + _soonix_failed+=("${hookName}") + } + '') + (getHookNames args); - generatedShellHook = + generateShellHook = args: + builtins.addErrorContext "[soonix] while generating shell hook" # sh '' _soonix_log() { @@ -265,7 +275,7 @@ in { _soonix_failed=() _soonix_uptodate=() - ${runHooks} + ${runHooks args} local output=$'\E[msoonix:\E[38;5;8m' local status=0 @@ -297,8 +307,8 @@ in { in rec { # nothing to do if no hooks exist shellHook = - if (builtins.length hookNames > 0) - then generatedShellHook + if (builtins.length (builtins.attrNames config.hooks) > 0) + then generateShellHook {} else ""; shellHookFile = pkgs.writeShellScript "shellHook" shellHook; devshellModule = { @@ -307,11 +317,17 @@ in { }; finalFiles = buildAllFiles allFiles; # make it simpler to update the hooks without any devshell - packages."soonix:update" = pkgs.writeShellScriptBin "soonix:update" '' - function _soonix() { - ${shellHook} - } - _soonix - ''; + packages = let + mkPackage = args: + pkgs.writeShellScriptBin "soonix:update" '' + function _soonix() { + ${generateShellHook args} + } + _soonix + ''; + in { + "soonix:update" = mkPackage {}; + "soonix:update:excludegitignore" = mkPackage {includeGitignored = false;}; + }; }; } diff --git a/tests/soonix_test.nix b/tests/soonix_test.nix index e59498e..15f1fc4 100644 --- a/tests/soonix_test.nix +++ b/tests/soonix_test.nix @@ -69,6 +69,28 @@ in { assert_file_contains ${shellHook} "gomplate" ''; } + { + name = "packages"; + type = "script"; + script = let + conf = (soonix.make {inherit hooks;}).config; + baseBin = conf.packages."soonix:update" + "/bin/soonix:update"; + exclBin = conf.packages."soonix:update:excludegitignore" + "/bin/soonix:update"; + in + # sh + '' + ${ntlib.helpers.path [pkgs.gnugrep]} + ${ntlib.helpers.scriptHelpers} + + assert -f "${baseBin}" "should exist" + assert -f "${exclBin}" "should exist" + + assert_file_contains "${baseBin}" "gotmpl" + assert_file_contains "${baseBin}" "test.json" + assert_file_not_contains "${exclBin}" "gotmpl" + assert_file_contains "${exclBin}" "test.json" + ''; + } ]; }; }