LTP GCOV extension - code coverage report
Current view: directory - src/libexpr - get-drvs.cc
Test: app.info
Date: 2006-10-11 Instrumented lines: 90
Code covered: 77.8 % Executed lines: 70

       1                 : #include "get-drvs.hh"
       2                 : #include "nixexpr-ast.hh"
       3                 : #include "util.hh"
       4                 : 
       5                 : 
       6                 : namespace nix {
       7                 : 
       8                 : 
       9                 : string DrvInfo::queryDrvPath(EvalState & state) const
      10              86 : {
      11              86 :     if (drvPath == "") {
      12              66 :         Expr a = attrs->get(toATerm("drvPath"));
      13              66 :         (string &) drvPath = a ? evalPath(state, a) : "";
      14                 :     }
      15              84 :     return drvPath;
      16                 : }
      17                 : 
      18                 : 
      19                 : string DrvInfo::queryOutPath(EvalState & state) const
      20              95 : {
      21              95 :     if (outPath == "") {
      22              31 :         Expr a = attrs->get(toATerm("outPath"));
      23              31 :         if (!a) throw TypeError("output path missing");
      24              31 :         (string &) outPath = evalPath(state, a);
      25                 :     }
      26              95 :     return outPath;
      27                 : }
      28                 : 
      29                 : 
      30                 : MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
      31               5 : {
      32               5 :     MetaInfo meta;
      33                 :     
      34               5 :     Expr a = attrs->get(toATerm("meta"));
      35               5 :     if (!a) return meta; /* fine, empty meta information */
      36                 : 
      37               5 :     ATermMap attrs2(16); /* !!! */
      38               5 :     queryAllAttrs(evalExpr(state, a), attrs2);
      39                 : 
      40              10 :     for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
      41               5 :         ATerm s = coerceToString(evalExpr(state, i->value));
      42               5 :         if (s)
      43               5 :             meta[aterm2String(i->key)] = aterm2String(s);
      44                 :         /* For future compatibility, ignore attribute values that are
      45                 :            not strings. */
      46                 :     }
      47                 : 
      48               5 :     return meta;
      49                 : }
      50                 : 
      51                 : 
      52                 : /* Cache for already evaluated derivations.  Usually putting ATerms in
      53                 :    a STL container is unsafe (they're not scanning for GC roots), but
      54                 :    here it doesn't matter; everything in this set is reachable from
      55                 :    the stack as well. */
      56                 : typedef set<Expr> Exprs;
      57                 : 
      58                 : 
      59                 : /* Evaluate expression `e'.  If it evaluates to an attribute set of
      60                 :    type `derivation', then put information about it in `drvs' (unless
      61                 :    it's already in `doneExprs').  The result boolean indicates whether
      62                 :    it makes sense for the caller to recursively search for derivations
      63                 :    in `e'. */
      64                 : static bool getDerivation(EvalState & state, Expr e,
      65                 :     const string & attrPath, DrvInfos & drvs, Exprs & doneExprs)
      66             184 : {
      67             184 :     try {
      68                 :         
      69             184 :         ATermList es;
      70             184 :         e = evalExpr(state, e);
      71             184 :         if (!matchAttrs(e, es)) return true;
      72                 : 
      73             134 :         boost::shared_ptr<ATermMap> attrs(new ATermMap(32)); /* !!! */
      74             134 :         queryAllAttrs(e, *attrs, false);
      75                 :     
      76             134 :         Expr a = attrs->get(toATerm("type"));
      77             134 :         if (!a || evalString(state, a) != "derivation") return true;
      78                 : 
      79                 :         /* Remove spurious duplicates (e.g., an attribute set like
      80                 :            `rec { x = derivation {...}; y = x;}'. */
      81             134 :         if (doneExprs.find(e) != doneExprs.end()) return false;
      82             134 :         doneExprs.insert(e);
      83                 : 
      84             250 :         DrvInfo drv;
      85                 :     
      86             134 :         a = attrs->get(toATerm("name"));
      87                 :         /* !!! We really would like to have a decent back trace here. */
      88             134 :         if (!a) throw TypeError("derivation name missing");
      89             134 :         drv.name = evalString(state, a);
      90                 : 
      91             134 :         a = attrs->get(toATerm("system"));
      92             134 :         if (!a)
      93               0 :             drv.system = "unknown";
      94                 :         else
      95             134 :             drv.system = evalString(state, a);
      96                 : 
      97             134 :         drv.attrs = attrs;
      98                 : 
      99             134 :         drv.attrPath = attrPath;
     100                 : 
     101             134 :         drvs.push_back(drv);
     102             134 :         return false;
     103                 :     
     104               0 :     } catch (AssertionError & e) {
     105               0 :         return false;
     106                 :     }
     107                 : }
     108                 : 
     109                 : 
     110                 : bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
     111              16 : {
     112             756 :     Exprs doneExprs;
     113              16 :     DrvInfos drvs;
     114              16 :     getDerivation(state, e, "", drvs, doneExprs);
     115              16 :     if (drvs.size() != 1) return false;
     116              86 :     drv = drvs.front();
     117              16 :     return true;
     118                 : }
     119                 : 
     120                 : 
     121                 : static string addToPath(const string & s1, const string & s2)
     122              99 : {
     123              99 :     return s1.empty() ? s2 : s1 + "." + s2;
     124                 : }
     125                 : 
     126                 : 
     127                 : static void getDerivations(EvalState & state, Expr e,
     128                 :     const string & pathPrefix, const ATermMap & autoArgs,
     129                 :     DrvInfos & drvs, Exprs & doneExprs)
     130              69 : {
     131              69 :     e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs));
     132                 : 
     133                 :     /* Process the expression. */
     134              69 :     ATermList es;
     135              69 :     DrvInfo drv;
     136                 : 
     137              69 :     if (!getDerivation(state, e, pathPrefix, drvs, doneExprs))
     138              19 :         return;
     139                 : 
     140              50 :     if (matchAttrs(e, es)) {
     141               0 :         ATermMap drvMap(ATgetLength(es));
     142               0 :         queryAllAttrs(e, drvMap);
     143                 :         
     144               0 :         for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
     145               0 :             startNest(nest, lvlDebug,
     146                 :                 format("evaluating attribute `%1%'") % aterm2String(i->key));
     147               0 :             string pathPrefix2 = addToPath(pathPrefix, aterm2String(i->key));
     148               0 :             if (getDerivation(state, i->value, pathPrefix2, drvs, doneExprs)) {
     149                 :                 /* If the value of this attribute is itself an
     150                 :                    attribute set, should we recurse into it?  => Only
     151                 :                    if it has a `recurseForDerivations = true'
     152                 :                    attribute. */
     153               0 :                 ATermList es;
     154               0 :                 Expr e = evalExpr(state, i->value);
     155               0 :                 if (matchAttrs(e, es)) {
     156               0 :                     ATermMap attrs(ATgetLength(es));
     157               0 :                     queryAllAttrs(e, attrs, false);
     158               0 :                     Expr e2 = attrs.get(toATerm("recurseForDerivations"));
     159               0 :                     if (e2 && evalBool(state, e2))
     160               0 :                         getDerivations(state, e, pathPrefix2, autoArgs, drvs, doneExprs);
     161                 :                 }
     162                 :             }
     163                 :         }
     164                 :         
     165               0 :         return;
     166                 :     }
     167                 : 
     168              50 :     if (matchList(e, es)) {
     169              50 :         int n = 0;
     170             149 :         for (ATermIterator i(es); i; ++i, ++n) {
     171              99 :             startNest(nest, lvlDebug,
     172                 :                 format("evaluating list element"));
     173              99 :             string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
     174              99 :             if (getDerivation(state, *i, pathPrefix2, drvs, doneExprs))
     175               0 :                 getDerivations(state, *i, pathPrefix2, autoArgs, drvs, doneExprs);
     176                 :         }
     177              50 :         return;
     178                 :     }
     179                 : 
     180               0 :     throw TypeError("expression does not evaluate to a derivation (or a set or list of those)");
     181                 : }
     182                 : 
     183                 : 
     184                 : void getDerivations(EvalState & state, Expr e, const string & pathPrefix,
     185                 :     const ATermMap & autoArgs, DrvInfos & drvs)
     186              69 : {
     187              69 :     Exprs doneExprs;
     188              69 :     getDerivations(state, e, pathPrefix, autoArgs, drvs, doneExprs);
     189                 : }
     190                 : 
     191                 :  
     192                 : }

Generated by: LTP GCOV extension version 1.1