diff --git a/src/libexpr/primops/flake.cc b/src/libexpr/primops/flake.cc index c08c30c9c..9131080bf 100644 --- a/src/libexpr/primops/flake.cc +++ b/src/libexpr/primops/flake.cc @@ -309,10 +309,17 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool impureIsAllowe state.forceAttrs(vInfo); + if (auto epoch = vInfo.attrs->get(state.symbols.create("epoch"))) { + flake.epoch = state.forceInt(*(**epoch).value, *(**epoch).pos); + if (flake.epoch > 2019) + throw Error("flake '%s' requires unsupported epoch %d; please upgrade Nix", flakeRef, flake.epoch); + } else + throw Error("flake '%s' lacks attribute 'epoch'", flakeRef); + if (auto name = vInfo.attrs->get(state.sName)) flake.id = state.forceStringNoCtx(*(**name).value, *(**name).pos); else - throw Error("flake lacks attribute 'name'"); + throw Error("flake '%s' lacks attribute 'name'", flakeRef); if (auto description = vInfo.attrs->get(state.sDescription)) flake.description = state.forceStringNoCtx(*(**description).value, *(**description).pos); @@ -337,7 +344,7 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool impureIsAllowe state.forceFunction(*(**provides).value, *(**provides).pos); flake.vProvides = (**provides).value; } else - throw Error("flake lacks attribute 'provides'"); + throw Error("flake '%s' lacks attribute 'provides'", flakeRef); return flake; } diff --git a/src/libexpr/primops/flake.hh b/src/libexpr/primops/flake.hh index 8eaac9d96..983c0eab6 100644 --- a/src/libexpr/primops/flake.hh +++ b/src/libexpr/primops/flake.hh @@ -101,7 +101,8 @@ struct Flake std::map nonFlakeRequires; Value * vProvides; // FIXME: gc // date - // content hash + unsigned int epoch; + Flake(const FlakeRef & origRef, const SourceInfo & sourceInfo) : originalRef(origRef), resolvedRef(sourceInfo.resolvedRef), revCount(sourceInfo.revCount), storePath(sourceInfo.storePath) {}; }; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index ecbb3b81f..2dcdfc663 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -83,6 +83,7 @@ void printFlakeInfo(const Flake & flake, bool json) { if (flake.revCount) j["revCount"] = *flake.revCount; j["path"] = flake.storePath; + j["epoch"] = flake.epoch; std::cout << j.dump(4) << std::endl; } else { std::cout << "ID: " << flake.id << "\n"; @@ -95,6 +96,7 @@ void printFlakeInfo(const Flake & flake, bool json) { if (flake.revCount) std::cout << "Revcount: " << *flake.revCount << "\n"; std::cout << "Path: " << flake.storePath << "\n"; + std::cout << "Epoch: " << flake.epoch << "\n"; } } diff --git a/tests/flakes.sh b/tests/flakes.sh index 5137bc39a..6c987ad14 100644 --- a/tests/flakes.sh +++ b/tests/flakes.sh @@ -146,7 +146,7 @@ nix build -o $TEST_ROOT/result file://$flake2Dir:bar # Test whether indirect dependencies work. nix build -o $TEST_ROOT/result --flake-registry $registry $flake3Dir:xyzzy -# Add dependency to flake3 +# Add dependency to flake3. rm $flake3Dir/flake.nix cat > $flake3Dir/flake.nix <&1 | grep 'unsupported epoch'