1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-24 03:09:35 +01:00

Make rootFS's showPath() render the paths from the original accessors

This makes paths in error messages behave similar to lazy-trees,
e.g. instead of store paths like

       error: attribute 'foobar' missing
       at /nix/store/ddzfiipzqlrh3gnprmqbadnsnrxsmc9i-source/machine/configuration.nix:209:7:
          208|
          209|       pkgs.foobar
             |       ^
          210|     ];

you now get

       error: attribute 'foobar' missing
       at /home/eelco/Misc/eelco-configurations/machine/configuration.nix:209:7:
          208|
          209|       pkgs.foobar
             |       ^
          210|     ];
This commit is contained in:
Eelco Dolstra 2025-02-20 01:09:49 +01:00
parent 5506428e67
commit b28bc7ae64
10 changed files with 122 additions and 22 deletions

View file

@ -14,6 +14,7 @@
#include "profiles.hh"
#include "print.hh"
#include "filtering-source-accessor.hh"
#include "forwarding-source-accessor.hh"
#include "memory-source-accessor.hh"
#include "gc-small-vector.hh"
#include "url.hh"
@ -180,6 +181,34 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
}
}
struct PathDisplaySourceAccessor : ForwardingSourceAccessor
{
ref<EvalState::StorePathAccessors> storePathAccessors;
PathDisplaySourceAccessor(
ref<SourceAccessor> next,
ref<EvalState::StorePathAccessors> storePathAccessors)
: ForwardingSourceAccessor(next)
, storePathAccessors(storePathAccessors)
{
}
std::string showPath(const CanonPath & path) override
{
/* Find the accessor that produced `path`, if any, and use it
to render a more informative path
(e.g. `«github:foo/bar»/flake.nix` rather than
`/nix/store/hash.../flake.nix`). */
auto ub = storePathAccessors->upper_bound(path);
if (ub != storePathAccessors->begin())
ub--;
if (ub != storePathAccessors->end() && path.isWithin(ub->first))
return ub->second->showPath(path.removePrefix(ub->first));
else
return next->showPath(path);
}
};
static constexpr size_t BASE_ENV_SIZE = 128;
EvalState::EvalState(
@ -245,6 +274,7 @@ EvalState::EvalState(
}
, repair(NoRepair)
, emptyBindings(0)
, storePathAccessors(make_ref<StorePathAccessors>())
, rootFS(
({
/* In pure eval mode, we provide a filesystem that only
@ -270,6 +300,8 @@ EvalState::EvalState(
: makeUnionSourceAccessor({accessor, storeFS});
}
accessor = make_ref<PathDisplaySourceAccessor>(accessor, storePathAccessors);
/* Apply access control if needed. */
if (settings.restrictEval || settings.pureEval)
accessor = AllowListSourceAccessor::create(accessor, {},

View file

@ -262,6 +262,16 @@ public:
/** `"unknown"` */
Value vStringUnknown;
using StorePathAccessors = std::map<CanonPath, ref<SourceAccessor>>;
/**
* A map back to the original `SourceAccessor`s used to produce
* store paths. We keep track of this to produce error messages
* that refer to the original flakerefs.
* FIXME: use Sync.
*/
ref<StorePathAccessors> storePathAccessors;
/**
* The accessor for the root filesystem.
*/

View file

@ -64,7 +64,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
auto input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
auto [storePath, input2] = input.fetchToStore(state.store);
auto [storePath, accessor, input2] = input.fetchToStore(state.store);
auto attrs2 = state.buildBindings(8);
state.mkStorePathString(storePath, attrs2.alloc(state.sOutPath));

View file

@ -200,10 +200,12 @@ static void fetchTree(
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
}
auto [storePath, input2] = input.fetchToStore(state.store);
auto [storePath, accessor, input2] = input.fetchToStore(state.store);
state.allowPath(storePath);
state.storePathAccessors->insert_or_assign(CanonPath(state.store->printStorePath(storePath)), accessor);
emitTreeAttrs(state, storePath, input2, v, params.emptyRevFallback, false);
}