about summary refs log blame commit diff
path: root/src/libstore/storeexpr.cc
blob: 0b92be0e71170a6d557479dd1e12b03fa9a443af (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                     
                   
 


                           
 
                      
 
                                  


 
                                              
 

                                       
 
                                           
                                        
 
                                              


                                                                          
     
    
                


 
                                                      
 
                                          



                                            
                                            
                      



     
                                                 
 

                                     
 
                 

                                                                
                              
    
                                                           
                                       
                                        
                                                                  
    

                                                                
                                                                
                                            
                                            

                                                                      
                                     
 

 

                                                    
 
                           
 
                                       
                     
 
                                     
 
                                          
                   
                       
                                              
                                                       
                         
                                    
                                                 

     
                          
                


 
                                                             
 
                                    
                            
 
                                                                  
                     
 

                                         
 

                                                 
    
                                         
                                     
                                                 
                                                    

     
                                         

                                         
                                                           
                                                            

     
                


 
                                 
 
                 
                                    
                                       
                                               

                                                    
              


 
                                                    
 
                          
                                                   
                               
                                                  
                        


 
                                                    
 
                                                  

                              

                                                                
                               

                                               
                                               
 
                                     
 

 
                                                             
 
                             

                                                             
                                                        
 
                            

                                                                
                           


                                                  
 
                      

                                         

                                                  
                        
                        
 

 
                                            
 
                                        
                                          
                                                
                                                
                 
 
#include "storeexpr.hh"
#include "globals.hh"
#include "store.hh"

#include "storeexpr-ast.hh"
#include "storeexpr-ast.cc"


Hash hashTerm(ATerm t)
{
    return hashString(atPrint(t));
}


Path writeTerm(ATerm t, const string & suffix)
{
    /* The id of a term is its hash. */
    Hash h = hashTerm(t);

    Path path = canonPath(nixStore + "/" + 
        (string) h + suffix + ".store");

    if (!readOnlyMode && !isValidPath(path)) {
        char * s = ATwriteToString(t);
        if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
        addTextToStore(path, string(s));
    }
    
    return path;
}


static void parsePaths(ATermList paths, PathSet & out)
{
    for (ATermIterator i(paths); i; ++i) {
        if (ATgetType(*i) != AT_APPL)
            throw badTerm("not a path", *i);
        string s = aterm2String(*i);
        if (s.size() == 0 || s[0] != '/')
            throw badTerm("not a path", *i);
        out.insert(s);
    }
}


static void checkClosure(const Closure & closure)
{
    if (closure.elems.size() == 0)
        throw Error("empty closure");

    PathSet decl;
    for (ClosureElems::const_iterator i = closure.elems.begin();
         i != closure.elems.end(); i++)
        decl.insert(i->first);
    
    for (PathSet::const_iterator i = closure.roots.begin();
         i != closure.roots.end(); i++)
        if (decl.find(*i) == decl.end())
            throw Error(format("undefined root path `%1%'") % *i);
    
    for (ClosureElems::const_iterator i = closure.elems.begin();
         i != closure.elems.end(); i++)
        for (PathSet::const_iterator j = i->second.refs.begin();
             j != i->second.refs.end(); j++)
            if (decl.find(*j) == decl.end())
                throw Error(
		    format("undefined path `%1%' referenced by `%2%'")
		    % *j % i->first);
}


/* Parse a closure. */
static bool parseClosure(ATerm t, Closure & closure)
{
    ATermList roots, elems;

    if (!matchClosure(t, roots, elems))
        return false;

    parsePaths(roots, closure.roots);

    for (ATermIterator i(elems); i; ++i) {
        ATerm path;
        ATermList refs;
        if (!matchClosureElem(*i, path, refs))
            throw badTerm("not a closure element", *i);
        ClosureElem elem;
        parsePaths(refs, elem.refs);
        closure.elems[aterm2String(path)] = elem;
    }

    checkClosure(closure);
    return true;
}


static bool parseDerivation(ATerm t, Derivation & derivation)
{
    ATermList outs, ins, args, bnds;
    ATerm builder, platform;

    if (!matchDerive(t, outs, ins, platform, builder, args, bnds))
        return false;

    parsePaths(outs, derivation.outputs);
    parsePaths(ins, derivation.inputs);

    derivation.builder = aterm2String(builder);
    derivation.platform = aterm2String(platform);
    
    for (ATermIterator i(args); i; ++i) {
        if (ATgetType(*i) != AT_APPL)
            throw badTerm("string expected", *i);
        derivation.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);
        derivation.env[aterm2String(s1)] = aterm2String(s2);
    }

    return true;
}


StoreExpr parseStoreExpr(ATerm t)
{
    StoreExpr ne;
    if (parseClosure(t, ne.closure))
        ne.type = StoreExpr::neClosure;
    else if (parseDerivation(t, ne.derivation))
        ne.type = StoreExpr::neDerivation;
    else throw badTerm("not a store expression", t);
    return ne;
}


static ATermList unparsePaths(const PathSet & paths)
{
    ATermList l = ATempty;
    for (PathSet::const_iterator i = paths.begin();
         i != paths.end(); i++)
        l = ATinsert(l, string2ATerm(i->c_str()));
    return ATreverse(l);
}


static ATerm unparseClosure(const Closure & closure)
{
    ATermList roots = unparsePaths(closure.roots);
    
    ATermList elems = ATempty;
    for (ClosureElems::const_iterator i = closure.elems.begin();
         i != closure.elems.end(); i++)
        elems = ATinsert(elems,
            makeClosureElem(
                string2ATerm(i->first.c_str()),
                unparsePaths(i->second.refs)));

    return makeClosure(roots, elems);
}


static ATerm unparseDerivation(const Derivation & derivation)
{
    ATermList args = ATempty;
    for (Strings::const_iterator i = derivation.args.begin();
         i != derivation.args.end(); i++)
        args = ATinsert(args, string2ATerm(i->c_str()));

    ATermList env = ATempty;
    for (StringPairs::const_iterator i = derivation.env.begin();
         i != derivation.env.end(); i++)
        env = ATinsert(env,
            makeEnvBinding(
                string2ATerm(i->first.c_str()),
                string2ATerm(i->second.c_str())));

    return makeDerive(
        unparsePaths(derivation.outputs),
        unparsePaths(derivation.inputs),
        string2ATerm(derivation.platform.c_str()),
        string2ATerm(derivation.builder.c_str()),
        ATreverse(args),
        ATreverse(env));
}


ATerm unparseStoreExpr(const StoreExpr & ne)
{
    if (ne.type == StoreExpr::neClosure)
        return unparseClosure(ne.closure);
    else if (ne.type == StoreExpr::neDerivation)
        return unparseDerivation(ne.derivation);
    else abort();
}