* Sync with the trunk.
This commit is contained in:
		
						commit
						aa45027818
					
				
					 109 changed files with 3350 additions and 4010 deletions
				
			
		| 
						 | 
				
			
			@ -12,17 +12,12 @@ pkginclude_HEADERS = \
 | 
			
		|||
 | 
			
		||||
libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la ${aterm_lib} ${sqlite_lib}
 | 
			
		||||
 | 
			
		||||
BUILT_SOURCES = derivations-ast.cc derivations-ast.hh
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = derivations-ast.def derivations-ast.cc schema.sql
 | 
			
		||||
EXTRA_DIST = schema.sql
 | 
			
		||||
 | 
			
		||||
AM_CXXFLAGS = -Wall \
 | 
			
		||||
 -I$(srcdir)/.. ${aterm_include} ${sqlite_include} -I$(srcdir)/../libutil -I${top_srcdir}/externals/sqlite-3.6.22/
 | 
			
		||||
 ${sqlite_include} -I$(srcdir)/.. -I$(srcdir)/../libutil
 | 
			
		||||
 | 
			
		||||
local-store.lo: schema.sql.hh
 | 
			
		||||
 | 
			
		||||
%.sql.hh: %.sql
 | 
			
		||||
	../bin2c/bin2c schema < $< > $@ || (rm $@ && exit 1)
 | 
			
		||||
 | 
			
		||||
derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def
 | 
			
		||||
	$(perl) $(srcdir)/../aterm-helper.pl derivations-ast.hh derivations-ast.cc < $(srcdir)/derivations-ast.def
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
init initDerivationsHelpers
 | 
			
		||||
 | 
			
		||||
Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm |
 | 
			
		||||
 | 
			
		||||
| string string | ATerm | EnvBinding |
 | 
			
		||||
| string ATermList | ATerm | DerivationInput |
 | 
			
		||||
| string string string string | ATerm | DerivationOutput |
 | 
			
		||||
 | 
			
		||||
Closure | ATermList ATermList | ATerm | OldClosure |
 | 
			
		||||
| string ATermList | ATerm | OldClosureElem |
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +1,12 @@
 | 
			
		|||
#include "derivations.hh"
 | 
			
		||||
#include "store-api.hh"
 | 
			
		||||
#include "aterm.hh"
 | 
			
		||||
#include "globals.hh"
 | 
			
		||||
#include "util.hh"
 | 
			
		||||
 | 
			
		||||
#include "derivations-ast.hh"
 | 
			
		||||
#include "derivations-ast.cc"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Hash hashTerm(ATerm t)
 | 
			
		||||
{
 | 
			
		||||
    return hashString(htSHA256, atPrint(t));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Path writeDerivation(const Derivation & drv, const string & name)
 | 
			
		||||
{
 | 
			
		||||
    PathSet references;
 | 
			
		||||
| 
						 | 
				
			
			@ -27,137 +17,151 @@ Path writeDerivation(const Derivation & drv, const string & name)
 | 
			
		|||
       (that can be missing (of course) and should not necessarily be
 | 
			
		||||
       held during a garbage collection). */
 | 
			
		||||
    string suffix = name + drvExtension;
 | 
			
		||||
    string contents = atPrint(unparseDerivation(drv));
 | 
			
		||||
    string contents = unparseDerivation(drv);
 | 
			
		||||
    return readOnlyMode
 | 
			
		||||
        ? computeStorePathForText(suffix, contents, references)
 | 
			
		||||
        : store->addTextToStore(suffix, contents, references);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void checkPath(const string & s)
 | 
			
		||||
static Path parsePath(std::istream & str)
 | 
			
		||||
{
 | 
			
		||||
    string s = parseString(str);
 | 
			
		||||
    if (s.size() == 0 || s[0] != '/')
 | 
			
		||||
        throw Error(format("bad path `%1%' in derivation") % s);
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
static void parseStrings(ATermList paths, StringSet & out, bool arePaths)
 | 
			
		||||
static StringSet parseStrings(std::istream & str, bool arePaths)
 | 
			
		||||
{
 | 
			
		||||
    for (ATermIterator i(paths); i; ++i) {
 | 
			
		||||
        if (ATgetType(*i) != AT_APPL)
 | 
			
		||||
            throw badTerm("not a path", *i);
 | 
			
		||||
        string s = aterm2String(*i);
 | 
			
		||||
        if (arePaths) checkPath(s);
 | 
			
		||||
        out.insert(s);
 | 
			
		||||
    }
 | 
			
		||||
    StringSet res;
 | 
			
		||||
    while (!endOfList(str))
 | 
			
		||||
        res.insert(arePaths ? parsePath(str) : parseString(str));
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Shut up warnings. */
 | 
			
		||||
void throwBadDrv(ATerm t) __attribute__ ((noreturn));
 | 
			
		||||
 | 
			
		||||
void throwBadDrv(ATerm t) 
 | 
			
		||||
{
 | 
			
		||||
    throw badTerm("not a valid derivation", t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Derivation parseDerivation(ATerm t)
 | 
			
		||||
Derivation parseDerivation(const string & s)
 | 
			
		||||
{
 | 
			
		||||
    Derivation drv;
 | 
			
		||||
    ATermList outs, inDrvs, inSrcs, args, bnds;
 | 
			
		||||
    ATerm builder, platform;
 | 
			
		||||
    std::istringstream str(s);
 | 
			
		||||
    expect(str, "Derive([");
 | 
			
		||||
 | 
			
		||||
    if (!matchDerive(t, outs, inDrvs, inSrcs, platform, builder, args, bnds))
 | 
			
		||||
        throwBadDrv(t);
 | 
			
		||||
 | 
			
		||||
    for (ATermIterator i(outs); i; ++i) {
 | 
			
		||||
        ATerm id, path, hashAlgo, hash;
 | 
			
		||||
        if (!matchDerivationOutput(*i, id, path, hashAlgo, hash))
 | 
			
		||||
            throwBadDrv(t);
 | 
			
		||||
    /* Parse the list of outputs. */
 | 
			
		||||
    while (!endOfList(str)) {
 | 
			
		||||
        DerivationOutput out;
 | 
			
		||||
        out.path = aterm2String(path);
 | 
			
		||||
        checkPath(out.path);
 | 
			
		||||
        out.hashAlgo = aterm2String(hashAlgo);
 | 
			
		||||
        out.hash = aterm2String(hash);
 | 
			
		||||
        drv.outputs[aterm2String(id)] = out;
 | 
			
		||||
        expect(str, "("); string id = parseString(str);
 | 
			
		||||
        expect(str, ","); out.path = parsePath(str);
 | 
			
		||||
        expect(str, ","); out.hashAlgo = parseString(str);
 | 
			
		||||
        expect(str, ","); out.hash = parseString(str);
 | 
			
		||||
        expect(str, ")");
 | 
			
		||||
        drv.outputs[id] = out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (ATermIterator i(inDrvs); i; ++i) {
 | 
			
		||||
        ATerm drvPath;
 | 
			
		||||
        ATermList ids;
 | 
			
		||||
        if (!matchDerivationInput(*i, drvPath, ids))
 | 
			
		||||
            throwBadDrv(t);
 | 
			
		||||
        Path drvPath2 = aterm2String(drvPath);
 | 
			
		||||
        checkPath(drvPath2);
 | 
			
		||||
        StringSet ids2;
 | 
			
		||||
        parseStrings(ids, ids2, false);
 | 
			
		||||
        drv.inputDrvs[drvPath2] = ids2;
 | 
			
		||||
    /* Parse the list of input derivations. */
 | 
			
		||||
    expect(str, ",[");
 | 
			
		||||
    while (!endOfList(str)) {
 | 
			
		||||
        expect(str, "(");
 | 
			
		||||
        Path drvPath = parsePath(str);
 | 
			
		||||
        expect(str, ",[");
 | 
			
		||||
        drv.inputDrvs[drvPath] = parseStrings(str, false);
 | 
			
		||||
        expect(str, ")");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expect(str, ",["); drv.inputSrcs = parseStrings(str, true);
 | 
			
		||||
    expect(str, ","); drv.platform = parseString(str);
 | 
			
		||||
    expect(str, ","); drv.builder = parseString(str);
 | 
			
		||||
 | 
			
		||||
    /* Parse the builder arguments. */
 | 
			
		||||
    expect(str, ",[");
 | 
			
		||||
    while (!endOfList(str))
 | 
			
		||||
        drv.args.push_back(parseString(str));
 | 
			
		||||
 | 
			
		||||
    /* Parse the environment variables. */
 | 
			
		||||
    expect(str, ",[");
 | 
			
		||||
    while (!endOfList(str)) {
 | 
			
		||||
        expect(str, "("); string name = parseString(str);
 | 
			
		||||
        expect(str, ","); string value = parseString(str);
 | 
			
		||||
        expect(str, ")");
 | 
			
		||||
        drv.env[name] = value;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    parseStrings(inSrcs, drv.inputSrcs, true);
 | 
			
		||||
 | 
			
		||||
    drv.builder = aterm2String(builder);
 | 
			
		||||
    drv.platform = aterm2String(platform);
 | 
			
		||||
    
 | 
			
		||||
    for (ATermIterator i(args); i; ++i) {
 | 
			
		||||
        if (ATgetType(*i) != AT_APPL)
 | 
			
		||||
            throw badTerm("string expected", *i);
 | 
			
		||||
        drv.args.push_back(aterm2String(*i));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (ATermIterator i(bnds); i; ++i) {
 | 
			
		||||
        ATerm s1, s2;
 | 
			
		||||
        if (!matchEnvBinding(*i, s1, s2))
 | 
			
		||||
            throw badTerm("tuple of strings expected", *i);
 | 
			
		||||
        drv.env[aterm2String(s1)] = aterm2String(s2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expect(str, ")");
 | 
			
		||||
    return drv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ATerm unparseDerivation(const Derivation & drv)
 | 
			
		||||
static void printString(string & res, const string & s)
 | 
			
		||||
{
 | 
			
		||||
    ATermList outputs = ATempty;
 | 
			
		||||
    for (DerivationOutputs::const_reverse_iterator i = drv.outputs.rbegin();
 | 
			
		||||
         i != drv.outputs.rend(); ++i)
 | 
			
		||||
        outputs = ATinsert(outputs,
 | 
			
		||||
            makeDerivationOutput(
 | 
			
		||||
                toATerm(i->first),
 | 
			
		||||
                toATerm(i->second.path),
 | 
			
		||||
                toATerm(i->second.hashAlgo),
 | 
			
		||||
                toATerm(i->second.hash)));
 | 
			
		||||
    res += '"';
 | 
			
		||||
    for (const char * i = s.c_str(); *i; i++)
 | 
			
		||||
        if (*i == '\"' || *i == '\\') { res += "\\"; res += *i; }
 | 
			
		||||
        else if (*i == '\n') res += "\\n";
 | 
			
		||||
        else if (*i == '\r') res += "\\r";
 | 
			
		||||
        else if (*i == '\t') res += "\\t";
 | 
			
		||||
        else res += *i;
 | 
			
		||||
    res += '"';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    ATermList inDrvs = ATempty;
 | 
			
		||||
    for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin();
 | 
			
		||||
         i != drv.inputDrvs.rend(); ++i)
 | 
			
		||||
        inDrvs = ATinsert(inDrvs,
 | 
			
		||||
            makeDerivationInput(
 | 
			
		||||
                toATerm(i->first),
 | 
			
		||||
                toATermList(i->second)));
 | 
			
		||||
 | 
			
		||||
template<class ForwardIterator>
 | 
			
		||||
static void printStrings(string & res, ForwardIterator i, ForwardIterator j)
 | 
			
		||||
{
 | 
			
		||||
    res += '[';
 | 
			
		||||
    bool first = true;
 | 
			
		||||
    for ( ; i != j; ++i) {
 | 
			
		||||
        if (first) first = false; else res += ',';
 | 
			
		||||
        printString(res, *i);
 | 
			
		||||
    }
 | 
			
		||||
    res += ']';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string unparseDerivation(const Derivation & drv)
 | 
			
		||||
{
 | 
			
		||||
    string s;
 | 
			
		||||
    s.reserve(65536);
 | 
			
		||||
    s += "Derive([";
 | 
			
		||||
 | 
			
		||||
    bool first = true;
 | 
			
		||||
    foreach (DerivationOutputs::const_iterator, i, drv.outputs) {
 | 
			
		||||
        if (first) first = false; else s += ',';
 | 
			
		||||
        s += '('; printString(s, i->first);
 | 
			
		||||
        s += ','; printString(s, i->second.path);
 | 
			
		||||
        s += ','; printString(s, i->second.hashAlgo);
 | 
			
		||||
        s += ','; printString(s, i->second.hash);
 | 
			
		||||
        s += ')';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s += "],[";
 | 
			
		||||
    first = true;
 | 
			
		||||
    foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) {
 | 
			
		||||
        if (first) first = false; else s += ',';
 | 
			
		||||
        s += '('; printString(s, i->first);
 | 
			
		||||
        s += ','; printStrings(s, i->second.begin(), i->second.end());
 | 
			
		||||
        s += ')';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s += "],";
 | 
			
		||||
    printStrings(s, drv.inputSrcs.begin(), drv.inputSrcs.end());
 | 
			
		||||
    
 | 
			
		||||
    ATermList args = ATempty;
 | 
			
		||||
    for (Strings::const_reverse_iterator i = drv.args.rbegin();
 | 
			
		||||
         i != drv.args.rend(); ++i)
 | 
			
		||||
        args = ATinsert(args, toATerm(*i));
 | 
			
		||||
    s += ','; printString(s, drv.platform);
 | 
			
		||||
    s += ','; printString(s, drv.builder);
 | 
			
		||||
    s += ','; printStrings(s, drv.args.begin(), drv.args.end());
 | 
			
		||||
 | 
			
		||||
    ATermList env = ATempty;
 | 
			
		||||
    for (StringPairs::const_reverse_iterator i = drv.env.rbegin();
 | 
			
		||||
         i != drv.env.rend(); ++i)
 | 
			
		||||
        env = ATinsert(env,
 | 
			
		||||
            makeEnvBinding(
 | 
			
		||||
                toATerm(i->first),
 | 
			
		||||
                toATerm(i->second)));
 | 
			
		||||
 | 
			
		||||
    return makeDerive(
 | 
			
		||||
        outputs,
 | 
			
		||||
        inDrvs,
 | 
			
		||||
        toATermList(drv.inputSrcs),
 | 
			
		||||
        toATerm(drv.platform),
 | 
			
		||||
        toATerm(drv.builder),
 | 
			
		||||
        args,
 | 
			
		||||
        env);
 | 
			
		||||
    s += ",[";
 | 
			
		||||
    first = true;
 | 
			
		||||
    foreach (StringPairs::const_iterator, i, drv.env) {
 | 
			
		||||
        if (first) first = false; else s += ',';
 | 
			
		||||
        s += '('; printString(s, i->first);
 | 
			
		||||
        s += ','; printString(s, i->second);
 | 
			
		||||
        s += ')';
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    s += "])";
 | 
			
		||||
    
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,10 @@
 | 
			
		|||
#ifndef __DERIVATIONS_H
 | 
			
		||||
#define __DERIVATIONS_H
 | 
			
		||||
 | 
			
		||||
typedef union _ATerm * ATerm;
 | 
			
		||||
 | 
			
		||||
#include "hash.hh"
 | 
			
		||||
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include "types.hh"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,17 +51,14 @@ struct Derivation
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Hash an aterm. */
 | 
			
		||||
Hash hashTerm(ATerm t);
 | 
			
		||||
 | 
			
		||||
/* Write a derivation to the Nix store, and return its path. */
 | 
			
		||||
Path writeDerivation(const Derivation & drv, const string & name);
 | 
			
		||||
 | 
			
		||||
/* Parse a derivation. */
 | 
			
		||||
Derivation parseDerivation(ATerm t);
 | 
			
		||||
Derivation parseDerivation(const string & s);
 | 
			
		||||
 | 
			
		||||
/* Parse a derivation. */
 | 
			
		||||
ATerm unparseDerivation(const Derivation & drv);
 | 
			
		||||
/* Print a derivation. */
 | 
			
		||||
string unparseDerivation(const Derivation & drv);
 | 
			
		||||
 | 
			
		||||
/* Check whether a file name ends with the extensions for
 | 
			
		||||
   derivations. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@
 | 
			
		|||
#include "globals.hh"
 | 
			
		||||
#include "archive.hh"
 | 
			
		||||
#include "pathlocks.hh"
 | 
			
		||||
#include "derivations-ast.hh"
 | 
			
		||||
#include "worker-protocol.hh"
 | 
			
		||||
#include "derivations.hh"
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -446,9 +445,7 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info)
 | 
			
		|||
       efficiently query whether a path is an output of some
 | 
			
		||||
       derivation. */
 | 
			
		||||
    if (isDerivation(info.path)) {
 | 
			
		||||
        ATerm t = ATreadFromNamedFile(info.path.c_str());
 | 
			
		||||
        if (!t) throw Error(format("cannot read derivation `%1%'") % info.path);
 | 
			
		||||
        Derivation drv = parseDerivation(t);
 | 
			
		||||
        Derivation drv = parseDerivation(readFile(info.path));
 | 
			
		||||
        foreach (DerivationOutputs::iterator, i, drv.outputs) {
 | 
			
		||||
            SQLiteStmtUse use(stmtAddDerivationOutput);
 | 
			
		||||
            stmtAddDerivationOutput.bind(id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,6 @@
 | 
			
		|||
#include "store-api.hh"
 | 
			
		||||
#include "local-store.hh"
 | 
			
		||||
 | 
			
		||||
#include <aterm2.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,9 +10,7 @@ Derivation derivationFromPath(const Path & drvPath)
 | 
			
		|||
{
 | 
			
		||||
    assertStorePath(drvPath);
 | 
			
		||||
    store->ensurePath(drvPath);
 | 
			
		||||
    ATerm t = ATreadFromNamedFile(drvPath.c_str());
 | 
			
		||||
    if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath);
 | 
			
		||||
    return parseDerivation(t);
 | 
			
		||||
    return parseDerivation(readFile(drvPath));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue