]> git.scottworley.com Git - nix-profile-gc/blobdiff - modules/profile-gc.nix
Appease shellcheck
[nix-profile-gc] / modules / profile-gc.nix
index 488bc0ad00162ee134bacd56e239a518d1365c6e..6963264ae29d6133623241e49e7a75315fb49ce6 100644 (file)
@@ -1,3 +1,18 @@
+# nix-profile-gc: More gently remove old profiles
+# Copyright (C) 2022 Scott Worley <scottworley@scottworley.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 { lib, config, pkgs, ... }:
 let
   inherit (lib) escapeShellArg;
 { lib, config, pkgs, ... }:
 let
   inherit (lib) escapeShellArg;
@@ -14,7 +29,7 @@ in {
       dryRun = lib.mkOption {
         description = "Say what would have been deleted rather than actually deleting profiles";
         type = lib.types.bool;
       dryRun = lib.mkOption {
         description = "Say what would have been deleted rather than actually deleting profiles";
         type = lib.types.bool;
-        default = true;
+        default = false;
       };
       keepLast = lib.mkOption {
         description = ''
       };
       keepLast = lib.mkOption {
         description = ''
@@ -49,16 +64,23 @@ in {
           awhile (so keepLatest won't protect them) generates a bunch of broken profiles (so
           keepLast won't protect them) while trying to get up to date.
 
           awhile (so keepLatest won't protect them) generates a bunch of broken profiles (so
           keepLast won't protect them) while trying to get up to date.
 
-          This is approximate and has a useful granularity of an hour
-          (config.systemd.timers.profile-gc-log-active.timerConfig.OnActiveSec).
-          Do not set less than this.
+          This threshold is approximate, see activeMeasurementGranularity.
+          Do not set less than activeMeasurementGranularity!
         '';
         '';
-        # We admonish the user "Do not set less than this." and check it at runtime rather
-        # than verifying this with an assertion now because parsing these durations at
-        # configuration-time requires import-from-derivation, which we want to avoid.  :(
+        # We admonish the user "Do not set less than activeMeasurementGranularity!" and check
+        # it at runtime rather than verifying this with an assertion at evaluation time because
+        # parsing these durations at evaluation-time requires import-from-derivation, which we
+        # want to avoid.  :(
         type = lib.types.str;
         default = "5 days";
       };
         type = lib.types.str;
         default = "5 days";
       };
+      activeMeasurementGranularity = lib.mkOption {
+        description = ''
+          How often to make a note of the currently-active profiles.  This is the useful
+          granularity and minimum value of activeThreshold.
+        '';
+        default = "1 hour";
+      };
       keepLatest = lib.mkOption {
         description = ''
           Keep all profiles younger than this duration (systemd.time format).
       keepLatest = lib.mkOption {
         description = ''
           Keep all profiles younger than this duration (systemd.time format).
@@ -98,7 +120,7 @@ in {
       fi
 
       alive_threshold="$(< ${parse-duration cfg.activeThreshold})"
       fi
 
       alive_threshold="$(< ${parse-duration cfg.activeThreshold})"
-      alive_loginterval="$(< ${parse-duration config.systemd.timers.profile-gc-log-active.timerConfig.OnActiveSec})"
+      alive_loginterval="$(< ${parse-duration cfg.activeMeasurementGranularity})"
       if (( alive_threshold < alive_loginterval ));then
         echo "Liveness threshold is too low.  Not doing any profile garbage collection." >&2
         exit 0
       if (( alive_threshold < alive_loginterval ));then
         echo "Liveness threshold is too low.  Not doing any profile garbage collection." >&2
         exit 0
@@ -131,7 +153,7 @@ in {
       }
 
       declare -A active_targets
       }
 
       declare -A active_targets
-      while read target;do
+      while read -r target;do
         active_targets[$target]=1
       done < <(
         verbose_topn ${cfg.logdir}/active-system "" ${escapeShellArg cfg.keepLastActiveSystem}
         active_targets[$target]=1
       done < <(
         verbose_topn ${cfg.logdir}/active-system "" ${escapeShellArg cfg.keepLastActiveSystem}
@@ -140,12 +162,12 @@ in {
 
       now=$(${pkgs.coreutils}/bin/date +%s)
       age_threshold="$(< ${parse-duration cfg.keepLatest})"
 
       now=$(${pkgs.coreutils}/bin/date +%s)
       age_threshold="$(< ${parse-duration cfg.keepLatest})"
-      while read profile;do
+      while read -r profile;do
         echo "Contemplating profiles for $profile:" >&2
         unset active
         declare -A active
         echo "Contemplating profiles for $profile:" >&2
         unset active
         declare -A active
-        while read p;do
-          active[$p]=1
+        while read -r pname;do
+          active[$pname]=1
         done < <(verbose_topn ${cfg.logdir}/active-profiles "$profile" ${escapeShellArg cfg.keepLastActive})
         current=$(${pkgs.coreutils}/bin/readlink "$profile")
         currentgen=''${current%-link}
         done < <(verbose_topn ${cfg.logdir}/active-profiles "$profile" ${escapeShellArg cfg.keepLastActive})
         current=$(${pkgs.coreutils}/bin/readlink "$profile")
         currentgen=''${current%-link}
@@ -157,15 +179,16 @@ in {
             echo "(Disregarding unrelated profile $p)" >&2
             continue
           fi
             echo "(Disregarding unrelated profile $p)" >&2
             continue
           fi
-          if [[ "$p" == "$current" ]];then
+          pname=$(${pkgs.coreutils}/bin/basename "$p")
+          if [[ "$pname" == "$current" ]];then
             echo "Keeeping current profile $p" >&2
             continue
           fi
             echo "Keeeping current profile $p" >&2
             continue
           fi
-          if [[ "''${active_targets[$(${pkgs.coreutils}/bin/readlink "$p")]}" ]];then
+          if [[ "''${active_targets[$(${pkgs.coreutils}/bin/readlink "$p")]:-}" ]];then
             echo "Keeeping active system/boot profile $p" >&2
             continue
           fi
             echo "Keeeping active system/boot profile $p" >&2
             continue
           fi
-          if [[ "''${active[$p]}" ]];then
+          if [[ "''${active[$pname]:-}" ]];then
             echo "Keeeping active profile $p" >&2
             continue
           fi
             echo "Keeeping active profile $p" >&2
             continue
           fi
@@ -186,11 +209,12 @@ in {
             rm "$p"
           ''}
         done
             rm "$p"
           ''}
         done
-      done < <(${pkgs.findutils}/bin/find ''${NIX_STATE_DIR:-/nix/var/nix}/profiles/ -type l -not -name '*[0-9]-link')
+      done < <(${pkgs.findutils}/bin/find "''${NIX_STATE_DIR:-/nix/var/nix}/profiles/" -type l -not -name '*[0-9]-link')
     '';
     systemd.timers.profile-gc-log-active = {
       wantedBy = [ "timers.target" ];
     '';
     systemd.timers.profile-gc-log-active = {
       wantedBy = [ "timers.target" ];
-      timerConfig.OnActiveSec = "1 hour";
+      timerConfig.OnActiveSec = cfg.activeMeasurementGranularity;
+      timerConfig.OnUnitActiveSec = cfg.activeMeasurementGranularity;
     };
     systemd.services.profile-gc-log-active = {
       description =
     };
     systemd.services.profile-gc-log-active = {
       description =