From b081133dcc7eee7178e9346957339bfec481064b Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Mon, 14 Dec 2015 13:31:24 +0100
Subject: [PATCH] Move GC roots to /nix/var/nix/gcroots/hydra

The uid split a while back caused the web interface to create GC roots
in /nix/var/nix/gcroots/per-user/hydra-www, where they wouldn't be
purged by hydra-update-gc-roots. Thus restarted builds would
accumulate forever. The fix is to keep the roots in a shared directory
with gid=hydra.
---
 hydra-module.nix            | 27 +++++++++++++++++++++++++++
 src/lib/Hydra/Helper/Nix.pm | 21 ++++++++++++++++-----
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/hydra-module.nix b/hydra-module.nix
index a1644753..30082e0f 100644
--- a/hydra-module.nix
+++ b/hydra-module.nix
@@ -144,6 +144,12 @@ in
         default = {};
         description = "Extra environment variables for Hydra.";
       };
+
+      gcRootsDir = mkOption {
+        type = types.path;
+        default = "/nix/var/nix/gcroots/hydra";
+        description = "Directory that holds Hydra garbage collector roots.";
+      };
     };
 
   };
@@ -189,6 +195,7 @@ in
         ${optionalString (cfg.logo != null) ''
           hydra_logo ${cfg.logo}
         ''}
+        gc_roots_dir ${cfg.gcRootsDir}
       '';
 
     environment.systemPackages = [ cfg.package ];
@@ -230,6 +237,26 @@ in
               touch ${baseDir}/.db-created
             fi
           ''}
+
+          if [ ! -e ${cfg.gcRootsDir} ]; then
+
+            # Move legacy roots directory.
+            if [ -e /nix/var/nix/gcroots/per-user/hydra/hydra-roots ]; then
+              mv /nix/var/nix/gcroots/per-user/hydra/hydra-roots ${cfg.gcRootsDir}
+            fi
+
+            mkdir -p ${cfg.gcRootsDir}
+          fi
+
+          # Move legacy hydra-www roots.
+          if [ -e /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots ]; then
+            find /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots/ -type f \
+              | xargs -r mv -f -t ${cfg.gcRootsDir}/
+            rmdir /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots
+          fi
+
+          chown hydra.hydra ${cfg.gcRootsDir}
+          chmod 2775 ${cfg.gcRootsDir}
         '';
         serviceConfig.ExecStart = "${cfg.package}/bin/hydra-init";
         serviceConfig.PermissionsStartOnly = true;
diff --git a/src/lib/Hydra/Helper/Nix.pm b/src/lib/Hydra/Helper/Nix.pm
index ca41d99b..010635b1 100644
--- a/src/lib/Hydra/Helper/Nix.pm
+++ b/src/lib/Hydra/Helper/Nix.pm
@@ -32,11 +32,18 @@ sub getHydraHome {
 }
 
 
+my $hydraConfig;
+
 sub getHydraConfig {
+    return $hydraConfig if defined $hydraConfig;
     my $conf = $ENV{"HYDRA_CONFIG"} || (Hydra::Model::DB::getHydraPath . "/hydra.conf");
-    return {} unless -f $conf;
-    my %config = new Config::General($conf)->getall;
-    return \%config;
+    if (-f $conf) {
+        my %h = new Config::General($conf)->getall;
+        $hydraConfig = \%h;
+    } else {
+        $hydraConfig = {};
+    }
+    return $hydraConfig;
 }
 
 
@@ -68,8 +75,12 @@ sub getSCMCacheDir {
 
 
 sub getGCRootsDir {
-    die unless defined $ENV{LOGNAME};
-    my $dir = ($ENV{NIX_STATE_DIR} || "/nix/var/nix" ) . "/gcroots/per-user/$ENV{LOGNAME}/hydra-roots";
+    my $config = getHydraConfig();
+    my $dir = $config->{gc_roots_dir};
+    unless (defined $dir) {
+        die unless defined $ENV{LOGNAME};
+        $dir = ($ENV{NIX_STATE_DIR} || "/nix/var/nix" ) . "/gcroots/per-user/$ENV{LOGNAME}/hydra-roots";
+    }
     mkpath $dir if !-e $dir;
     return $dir;
 }