From d4f404ded33bec98641d073797a6cbd9cf52dd6c Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Thu, 8 May 2025 17:56:16 +0200 Subject: [PATCH] nix/doctor: test whether the current profile generation points somewhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps users to debug whether their current profile symlinks are correctly set. Expected outputs look like this: ``` ❯ sudo ./outputs/out/bin/nix doctor [snip] [PASS] All profiles are gcroots. [PASS] Client protocol matches store protocol. [INFO] You are trusted by store uri: local [FAIL] Error: current generation cannot be discovered for profile: '/nix/var/nix/profiles/default' ``` ``` ❯ ./outputs/out/bin/nix doctor [snip] [PASS] All profiles are gcroots. [PASS] Client protocol matches store protocol. [INFO] You are trusted by store uri: daemon [PASS] You have 28 generations for profile '/nix/var/nix/profiles/per-user/raito/profile' The current generation number is '290' ``` Change-Id: I50c69cbeac3291d668f4c2332803411579adc944 Signed-off-by: Raito Bezarius Co-authored-by: Qyriad --- .../rl-next/assess-profile-generations.md | 12 ++++++++ lix/nix/doctor.cc | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 doc/manual/rl-next/assess-profile-generations.md diff --git a/doc/manual/rl-next/assess-profile-generations.md b/doc/manual/rl-next/assess-profile-generations.md new file mode 100644 index 000000000..ef25cc4ce --- /dev/null +++ b/doc/manual/rl-next/assess-profile-generations.md @@ -0,0 +1,12 @@ +--- +synopsis: Assess current profile generations pointers in `nix doctor` +cls: [3108] +category: Improvements +credits: [raito] +--- + +Added a new check to `nix doctor` that verifies whether the current generation of +a Nix profile can be resolved. This helps users diagnose issues with broken or +misconfigured profile symlinks. + +This helps determining if you have broken symlinks or misconfigured packaging. diff --git a/lix/nix/doctor.cc b/lix/nix/doctor.cc index 05b5d5203..594a46bde 100644 --- a/lix/nix/doctor.cc +++ b/lix/nix/doctor.cc @@ -8,6 +8,7 @@ #include "lix/libstore/local-fs-store.hh" #include "lix/libstore/worker-protocol.hh" #include "lix/libutil/exit.hh" +#include "lix/libstore/profiles.hh" #include "doctor.hh" namespace nix { @@ -69,6 +70,10 @@ struct CmdDoctor : StoreCommand } success &= checkStoreProtocol(aio().blockOn(store->getProtocol())); checkTrustedUser(store); + { + Path profile = getEnv("NIX_PROFILE").value_or(getDefaultProfile()); + checkValidCurrentProfileGeneration(profile); + } if (!success) throw Exit(2); @@ -152,6 +157,31 @@ struct CmdDoctor : StoreCommand std::string_view trustedness = trustedMay ? (*trustedMay ? "trusted" : "not trusted") : "unknown trust"; checkInfo(fmt("You are %s by store uri: %s", trustedness, store->getUri())); } + + void checkValidCurrentProfileGeneration(const Path & profile) + { + Generations generations; + std::optional currentGeneration; + std::string errStr; + + try { + std::tie(generations, currentGeneration) = findGenerations(profile); + } catch (SysError const & e) { + errStr = fmt(": %s", e.msg()); + } + + if (!currentGeneration) { + std::stringstream ss; + ss << "Error: current generation cannot be discovered for profile: '" << profile << "'"; + ss << errStr << "\n"; + checkFail(ss.str()); + } else { + std::stringstream ss; + ss << "You have " << generations.size() << " generations for profile '" << profile << "'\n"; + ss << "The current generation number is '" << *currentGeneration << "'\n"; + checkPass(ss.str()); + } + } }; void registerNixDoctor()