nix/doctor: test whether the current profile generation points somewhere

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 <raito@lix.systems>
Co-authored-by: Qyriad <qyriad@qyriad.me>
This commit is contained in:
Raito Bezarius
2025-11-03 14:41:47 +00:00
committed by Qyriad
co-authored by Qyriad
parent a30d87eadc
commit d4f404ded3
2 changed files with 42 additions and 0 deletions
@@ -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.
+30
View File
@@ -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<GenerationNumber> 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()