about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc21
-rw-r--r--src/libexpr/eval.hh3
2 files changed, 21 insertions, 3 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 26739faf69e8..14e5cab7de60 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -108,6 +108,7 @@ EvalState::EvalState()
     , sMeta(symbols.create("meta"))
     , sName(symbols.create("name"))
     , sSystem(symbols.create("system"))
+    , sOverrides(symbols.create("__overrides"))
     , baseEnv(allocEnv(128))
     , baseEnvDispl(0)
     , staticBaseEnv(false, 0)
@@ -428,8 +429,8 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
            environment. */
         foreach (Attrs::iterator, i, attrs) {
             nix::Attr & a = (*v.attrs)[i->first];
-            mkCopy(a.value, env2.values[displ]);
-            mkThunk(env2.values[displ++], env2, i->second.first);
+            mkThunk(a.value, env2, i->second.first);
+            mkCopy(env2.values[displ++], a.value);
             a.pos = &i->second.second;
         }
 
@@ -443,6 +444,22 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
             a.pos = &i->second;
         }
 
+        /* If the rec contains an attribute called `__overrides', then
+           evaluate it, and add the attributes in that set to the rec.
+           This allows overriding of recursive attributes, which is
+           otherwise not possible.  (You can use the // operator to
+           replace an attribute, but other attributes in the rec will
+           still reference the original value, because that value has
+           been substituted into the bodies of the other attributes.
+           Hence we need __overrides.) */
+        Bindings::iterator overrides = v.attrs->find(state.sOverrides);
+        if (overrides != v.attrs->end()) {
+            state.forceAttrs(overrides->second.value);
+            foreach (Bindings::iterator, i, *overrides->second.value.attrs) {
+                nix::Attr & a = (*v.attrs)[i->first];
+                mkCopy(a.value, i->second.value);
+            }
+        }
     }
 
     else {
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 1a9862c29533..852485b05fa5 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -181,7 +181,8 @@ public:
 
     SymbolTable symbols;
 
-    const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sSystem;
+    const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName,
+        sSystem, sOverrides;
 
 private:
     SrcToStore srcToStore;