LTP GCOV extension - code coverage report
Current view: directory - src/libexpr - get-drvs.cc
Test: app.info
Date: 2008-11-20 Instrumented lines: 107
Code covered: 70.1 % Executed lines: 75

       1                 : #include "get-drvs.hh"
       2                 : #include "nixexpr-ast.hh"
       3                 : #include "util.hh"
       4                 : 
       5                 : 
       6                 : namespace nix {
       7                 : 
       8                 : 
       9             228 : string DrvInfo::queryDrvPath(EvalState & state) const
      10                 : {
      11             228 :     if (drvPath == "") {
      12             169 :         Expr a = attrs->get(toATerm("drvPath"));
      13                 : 
      14                 :         /* Backwards compatibility hack with user environments made by
      15                 :            Nix <= 0.10: these contain illegal Path("") expressions. */
      16                 :         ATerm t;
      17             169 :         if (a && matchPath(evalExpr(state, a), t))
      18               0 :             return aterm2String(t);
      19                 :         
      20             167 :         PathSet context;
      21             167 :         (string &) drvPath = a ? coerceToPath(state, a, context) : "";
      22                 :     }
      23             226 :     return drvPath;
      24                 : }
      25                 : 
      26                 : 
      27             277 : string DrvInfo::queryOutPath(EvalState & state) const
      28                 : {
      29             277 :     if (outPath == "") {
      30              90 :         Expr a = attrs->get(toATerm("outPath"));
      31              90 :         if (!a) throw TypeError("output path missing");
      32              90 :         PathSet context;
      33              90 :         (string &) outPath = coerceToPath(state, a, context);
      34                 :     }
      35             277 :     return outPath;
      36                 : }
      37                 : 
      38                 : 
      39             117 : MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
      40                 : {
      41             117 :     MetaInfo meta;
      42                 :     
      43             117 :     Expr a = attrs->get(toATerm("meta"));
      44             117 :     if (!a) return meta; /* fine, empty meta information */
      45                 : 
      46             108 :     ATermMap attrs2;
      47             108 :     queryAllAttrs(evalExpr(state, a), attrs2);
      48                 : 
      49             216 :     for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
      50             108 :         Expr e = evalExpr(state, i->value);
      51             108 :         string s;
      52             108 :         PathSet context;
      53             108 :         if (matchStr(e, s, context))
      54             108 :             meta[aterm2String(i->key)] = s;
      55                 :         /* For future compatibility, ignore attribute values that are
      56                 :            not strings. */
      57                 :     }
      58                 : 
      59             108 :     return meta;
      60                 : }
      61                 : 
      62                 : 
      63              48 : string DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
      64                 : {
      65                 :     /* !!! evaluates all meta attributes => inefficient */
      66              48 :     MetaInfo meta = queryMetaInfo(state);
      67              48 :     MetaInfo::iterator i = meta.find(name);
      68              48 :     return i == meta.end() ? "" : i->second;
      69                 : }
      70                 : 
      71                 : 
      72               0 : void DrvInfo::setMetaInfo(const MetaInfo & meta)
      73                 : {
      74               0 :     ATermMap metaAttrs;
      75               0 :     for (MetaInfo::const_iterator i = meta.begin(); i != meta.end(); ++i)
      76                 :         metaAttrs.set(toATerm(i->first),
      77               0 :             makeAttrRHS(makeStr(i->second), makeNoPos()));
      78               0 :     attrs->set(toATerm("meta"), makeAttrs(metaAttrs));
      79               0 : }
      80                 : 
      81                 : 
      82                 : /* Cache for already evaluated derivations.  Usually putting ATerms in
      83                 :    a STL container is unsafe (they're not scanning for GC roots), but
      84                 :    here it doesn't matter; everything in this set is reachable from
      85                 :    the stack as well. */
      86                 : typedef set<Expr> Exprs;
      87                 : 
      88                 : 
      89                 : /* Evaluate expression `e'.  If it evaluates to an attribute set of
      90                 :    type `derivation', then put information about it in `drvs' (unless
      91                 :    it's already in `doneExprs').  The result boolean indicates whether
      92                 :    it makes sense for the caller to recursively search for derivations
      93                 :    in `e'. */
      94                 : static bool getDerivation(EvalState & state, Expr e,
      95             484 :     const string & attrPath, DrvInfos & drvs, Exprs & doneExprs)
      96                 : {
      97                 :     try {
      98                 :         
      99                 :         ATermList es;
     100             484 :         e = evalExpr(state, e);
     101             484 :         if (!matchAttrs(e, es)) return true;
     102                 : 
     103             339 :         boost::shared_ptr<ATermMap> attrs(new ATermMap());
     104             339 :         queryAllAttrs(e, *attrs, false);
     105                 :         
     106             339 :         Expr a = attrs->get(toATerm("type"));
     107             678 :         if (!a || evalStringNoCtx(state, a) != "derivation") return true;
     108                 : 
     109                 :         /* Remove spurious duplicates (e.g., an attribute set like
     110                 :            `rec { x = derivation {...}; y = x;}'. */
     111             339 :         if (doneExprs.find(e) != doneExprs.end()) return false;
     112             339 :         doneExprs.insert(e);
     113                 : 
     114             339 :         DrvInfo drv;
     115                 :     
     116             339 :         a = attrs->get(toATerm("name"));
     117                 :         /* !!! We really would like to have a decent back trace here. */
     118             339 :         if (!a) throw TypeError("derivation name missing");
     119             339 :         drv.name = evalStringNoCtx(state, a);
     120                 : 
     121             339 :         a = attrs->get(toATerm("system"));
     122             339 :         if (!a)
     123               0 :             drv.system = "unknown";
     124                 :         else
     125             339 :             drv.system = evalStringNoCtx(state, a);
     126                 : 
     127             339 :         drv.attrs = attrs;
     128                 : 
     129             339 :         drv.attrPath = attrPath;
     130                 : 
     131             339 :         drvs.push_back(drv);
     132             339 :         return false;
     133                 :     
     134               0 :     } catch (AssertionError & e) {
     135               0 :         return false;
     136                 :     }
     137                 : }
     138                 : 
     139                 : 
     140              46 : bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
     141                 : {
     142              46 :     Exprs doneExprs;
     143              46 :     DrvInfos drvs;
     144              92 :     getDerivation(state, e, "", drvs, doneExprs);
     145              92 :     if (drvs.size() != 1) return false;
     146              46 :     drv = drvs.front();
     147              46 :     return true;
     148                 : }
     149                 : 
     150                 : 
     151             263 : static string addToPath(const string & s1, const string & s2)
     152                 : {
     153             263 :     return s1.empty() ? s2 : s1 + "." + s2;
     154                 : }
     155                 : 
     156                 : 
     157                 : static void getDerivations(EvalState & state, Expr e,
     158                 :     const string & pathPrefix, const ATermMap & autoArgs,
     159             175 :     DrvInfos & drvs, Exprs & doneExprs)
     160                 : {
     161             175 :     e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs));
     162                 : 
     163                 :     /* Process the expression. */
     164                 :     ATermList es;
     165             175 :     DrvInfo drv;
     166                 : 
     167             175 :     if (!getDerivation(state, e, pathPrefix, drvs, doneExprs))
     168                 :         return;
     169                 : 
     170             145 :     if (matchAttrs(e, es)) {
     171               0 :         ATermMap drvMap(ATgetLength(es));
     172               0 :         queryAllAttrs(e, drvMap);
     173                 : 
     174                 :         /* !!! undocumented hackery to support combining channels in
     175                 :            nix-env.cc. */
     176               0 :         bool combineChannels = drvMap.get(toATerm("_combineChannels"));
     177                 : 
     178                 :         /* Consider the attributes in sorted order to get more
     179                 :            deterministic behaviour in nix-env operations (e.g. when
     180                 :            there are names clashes between derivations, the derivation
     181                 :            bound to the attribute with the "lower" name should take
     182                 :            precedence). */
     183                 :         typedef std::map<string, Expr> AttrsSorted;
     184               0 :         AttrsSorted attrsSorted;
     185               0 :         foreach (ATermMap::const_iterator, i, drvMap)
     186               0 :             attrsSorted[aterm2String(i->key)] = i->value;
     187                 : 
     188               0 :         foreach (AttrsSorted::iterator, i, attrsSorted) {
     189               0 :             startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
     190               0 :             string pathPrefix2 = addToPath(pathPrefix, i->first);
     191               0 :             if (combineChannels)
     192               0 :                 getDerivations(state, i->second, pathPrefix2, autoArgs, drvs, doneExprs);
     193               0 :             else if (getDerivation(state, i->second, pathPrefix2, drvs, doneExprs)) {
     194                 :                 /* If the value of this attribute is itself an
     195                 :                    attribute set, should we recurse into it?  => Only
     196                 :                    if it has a `recurseForDerivations = true'
     197                 :                    attribute. */
     198                 :                 ATermList es;
     199               0 :                 Expr e = evalExpr(state, i->second), e2;
     200               0 :                 if (matchAttrs(e, es)) {
     201               0 :                     ATermMap attrs(ATgetLength(es));
     202               0 :                     queryAllAttrs(e, attrs, false);
     203               0 :                     if (((e2 = attrs.get(toATerm("recurseForDerivations")))
     204                 :                             && evalBool(state, e2)))
     205               0 :                         getDerivations(state, e, pathPrefix2, autoArgs, drvs, doneExprs);
     206                 :                 }
     207                 :             }
     208                 :         }
     209                 :         
     210               0 :         return;
     211                 :     }
     212                 : 
     213             145 :     if (matchList(e, es)) {
     214             145 :         int n = 0;
     215             408 :         for (ATermIterator i(es); i; ++i, ++n) {
     216             263 :             startNest(nest, lvlDebug,
     217                 :                 format("evaluating list element"));
     218             263 :             string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
     219             263 :             if (getDerivation(state, *i, pathPrefix2, drvs, doneExprs))
     220               0 :                 getDerivations(state, *i, pathPrefix2, autoArgs, drvs, doneExprs);
     221                 :         }
     222                 :         return;
     223                 :     }
     224                 : 
     225               0 :     throw TypeError("expression does not evaluate to a derivation (or a set or list of those)");
     226                 : }
     227                 : 
     228                 : 
     229                 : void getDerivations(EvalState & state, Expr e, const string & pathPrefix,
     230             175 :     const ATermMap & autoArgs, DrvInfos & drvs)
     231                 : {
     232             175 :     Exprs doneExprs;
     233             175 :     getDerivations(state, e, pathPrefix, autoArgs, drvs, doneExprs);
     234             175 : }
     235                 : 
     236               0 :  
     237                 : }

Generated by: LTP GCOV extension version 1.6