diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc index 6265e9cfe..2a8af7780 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) { + PathSet dirs; + + Roots roots = store->findRoots(); + + for (auto & dir : tokenizeString(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