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

                             
 
 


               
                      
 
                                            


 
                                                                 
 







                                                                     
                                              
                                                     


 
                                       

                                     
                                                                


    
                                                                         
 
                                          


                                            
                                   
                      



     



                                                     
 
                                               


 
                                   
 

                                               
                            
 

                                                                             
 


                                                                 
                           




                                              
                                            

     












                                                    
 

                                          
    
                                         
                                     
                                                 
                                             

     
                                         

                                         
                                                           
                                                     

     
               


 
                                                        
 
                          

                                                            
                                     
             


 
                                               
 
                                

                                                                            






                                            
                               

                                                                             




                                            
                             

                                                               
                                           
 
                            

                                                                  
                           
                           

                                     
 
                      

                
                                      

                              

             
 







                                                                                


 
#include "derivations.hh"
#include "store.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;
    references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
    for (DerivationInputs::const_iterator i = drv.inputDrvs.begin();
         i != drv.inputDrvs.end(); ++i)
        references.insert(i->first);
    /* Note that the outputs of a derivation are *not* references
       (that can be missing (of course) and should not necessarily be
       held during a garbage collection). */
    return addTextToStore(name + drvExtension,
        atPrint(unparseDerivation(drv)), references);
}


static void checkPath(const string & s)
{
    if (s.size() == 0 || s[0] != '/')
        throw Error(format("bad path `%1%' in derivation") % s);
}
    

static void parseStrings(ATermList paths, StringSet & out, 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);
    }
}


/* 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 drv;
    ATermList outs, inDrvs, inSrcs, args, bnds;
    ATerm builder, platform;

    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);
        DerivationOutput out;
        out.path = aterm2String(path);
        checkPath(out.path);
        out.hashAlgo = aterm2String(hashAlgo);
        out.hash = aterm2String(hash);
        drv.outputs[aterm2String(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;
    }
    
    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);
    }

    return drv;
}


static ATermList unparseStrings(const StringSet & paths)
{
    ATermList l = ATempty;
    for (PathSet::const_reverse_iterator i = paths.rbegin();
         i != paths.rend(); ++i)
        l = ATinsert(l, toATerm(*i));
    return l;
}


ATerm unparseDerivation(const Derivation & drv)
{
    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)));

    ATermList inDrvs = ATempty;
    for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin();
         i != drv.inputDrvs.rend(); ++i)
        inDrvs = ATinsert(inDrvs,
            makeDerivationInput(
                toATerm(i->first),
                unparseStrings(i->second)));
    
    ATermList args = ATempty;
    for (Strings::const_reverse_iterator i = drv.args.rbegin();
         i != drv.args.rend(); ++i)
        args = ATinsert(args, toATerm(*i));

    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,
        unparseStrings(drv.inputSrcs),
        toATerm(drv.platform),
        toATerm(drv.builder),
        args,
        env);
}


bool isDerivation(const string & fileName)
{
    return
        fileName.size() >= drvExtension.size() &&
        string(fileName, fileName.size() - drvExtension.size()) == drvExtension;
}

 
}