about summary refs log tree commit diff
path: root/src/nix
diff options
context:
space:
mode:
authorDaiderd Jordan <daiderd@gmail.com>2018-09-02T10·52+0200
committerDaiderd Jordan <daiderd@gmail.com>2018-09-02T10·56+0200
commitbfdca55868ac1cd336c5d73ff944098ce82d023d (patch)
treea9afd6203591f01377fc586603649a739c01dbb3 /src/nix
parent0f18dc54797a1850bc1b91673790ad73e8f4b82f (diff)
nix doctor: add check for profile roots
In most cases profiles that are in PATH should have a gcroot.
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/doctor.cc35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index 6265e9cfef20..2a8af7780b9b 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -34,6 +34,7 @@ struct CmdDoctor : StoreCommand
         std::cout << std::endl;
 
         checkNixInPath();
+        checkProfileRoots(store);
         checkStoreProtocol(store->getProtocol());
     }
 
@@ -53,6 +54,40 @@ struct CmdDoctor : StoreCommand
         }
     }
 
+    void checkProfileRoots(ref<Store> store) {
+        PathSet dirs;
+
+        Roots roots = store->findRoots();
+
+        for (auto & dir : tokenizeString<Strings>(getEnv("PATH"), ":"))
+            try {
+                auto profileDir = canonPath(dirOf(dir), true);
+                if (hasSuffix(profileDir, "user-environment") &&
+                    store->isValidPath(profileDir)) {
+                    PathSet referrers;
+                    store->computeFSClosure({profileDir}, referrers, true,
+                            settings.gcKeepOutputs, settings.gcKeepDerivations);
+                    bool found = false;
+                    for (auto & i : roots)
+                        if (referrers.find(i.second) != referrers.end())
+                            found = true;
+                    if (!found)
+                        dirs.insert(dir);
+
+                }
+            } catch (SysError &) {}
+
+        if (!dirs.empty()) {
+            std::cout << "Warning: found profiles without a gcroot." << std::endl;
+            std::cout << "The generation this profile points to will be deleted with the next gc, resulting" << std::endl;
+            std::cout << "in broken symlinks.  Make sure your profiles are in " << settings.nixStateDir << "/profiles." << std::endl;
+            std::cout << std::endl;
+            for (auto & dir : dirs)
+                std::cout << "  " << dir << std::endl;
+            std::cout << std::endl;
+        }
+    }
+
     void checkStoreProtocol(unsigned int storeProto) {
         auto clientProto = GET_PROTOCOL_MAJOR(SERVE_PROTOCOL_VERSION) == GET_PROTOCOL_MAJOR(storeProto)
             ? SERVE_PROTOCOL_VERSION