1 : #include "derivations.hh"
2 : #include "store-api.hh"
3 : #include "aterm.hh"
4 : #include "globals.hh"
5 : #include "util.hh"
6 :
7 : #include "derivations-ast.hh"
8 : #include "derivations-ast.cc"
9 :
10 :
11 : namespace nix {
12 :
13 :
14 339 : Hash hashTerm(ATerm t)
15 : {
16 339 : return hashString(htSHA256, atPrint(t));
17 : }
18 :
19 :
20 179 : Path writeDerivation(const Derivation & drv, const string & name)
21 : {
22 179 : PathSet references;
23 179 : references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
24 244 : for (DerivationInputs::const_iterator i = drv.inputDrvs.begin();
25 : i != drv.inputDrvs.end(); ++i)
26 65 : references.insert(i->first);
27 : /* Note that the outputs of a derivation are *not* references
28 : (that can be missing (of course) and should not necessarily be
29 : held during a garbage collection). */
30 179 : string suffix = name + drvExtension;
31 179 : string contents = atPrint(unparseDerivation(drv));
32 : return readOnlyMode
33 : ? computeStorePathForText(suffix, contents, references)
34 179 : : store->addTextToStore(suffix, contents, references);
35 : }
36 :
37 :
38 1249 : static void checkPath(const string & s)
39 : {
40 1249 : if (s.size() == 0 || s[0] != '/')
41 0 : throw Error(format("bad path `%1%' in derivation") % s);
42 1249 : }
43 :
44 :
45 735 : static void parseStrings(ATermList paths, StringSet & out, bool arePaths)
46 : {
47 1544 : for (ATermIterator i(paths); i; ++i) {
48 809 : if (ATgetType(*i) != AT_APPL)
49 0 : throw badTerm("not a path", *i);
50 809 : string s = aterm2String(*i);
51 1323 : if (arePaths) checkPath(s);
52 809 : out.insert(s);
53 : }
54 735 : }
55 :
56 :
57 : /* Shut up warnings. */
58 : void throwBadDrv(ATerm t) __attribute__ ((noreturn));
59 :
60 0 : void throwBadDrv(ATerm t)
61 : {
62 0 : throw badTerm("not a valid derivation", t);
63 : }
64 :
65 :
66 440 : Derivation parseDerivation(ATerm t)
67 : {
68 440 : Derivation drv;
69 : ATermList outs, inDrvs, inSrcs, args, bnds;
70 : ATerm builder, platform;
71 :
72 440 : if (!matchDerive(t, outs, inDrvs, inSrcs, platform, builder, args, bnds))
73 0 : throwBadDrv(t);
74 :
75 880 : for (ATermIterator i(outs); i; ++i) {
76 : ATerm id, path, hashAlgo, hash;
77 440 : if (!matchDerivationOutput(*i, id, path, hashAlgo, hash))
78 0 : throwBadDrv(t);
79 440 : DerivationOutput out;
80 440 : out.path = aterm2String(path);
81 440 : checkPath(out.path);
82 440 : out.hashAlgo = aterm2String(hashAlgo);
83 440 : out.hash = aterm2String(hash);
84 440 : drv.outputs[aterm2String(id)] = out;
85 : }
86 :
87 735 : for (ATermIterator i(inDrvs); i; ++i) {
88 : ATerm drvPath;
89 : ATermList ids;
90 295 : if (!matchDerivationInput(*i, drvPath, ids))
91 0 : throwBadDrv(t);
92 295 : Path drvPath2 = aterm2String(drvPath);
93 295 : checkPath(drvPath2);
94 295 : StringSet ids2;
95 295 : parseStrings(ids, ids2, false);
96 295 : drv.inputDrvs[drvPath2] = ids2;
97 : }
98 :
99 440 : parseStrings(inSrcs, drv.inputSrcs, true);
100 :
101 440 : drv.builder = aterm2String(builder);
102 440 : drv.platform = aterm2String(platform);
103 :
104 3028 : for (ATermIterator i(args); i; ++i) {
105 1074 : if (ATgetType(*i) != AT_APPL)
106 0 : throw badTerm("string expected", *i);
107 1074 : drv.args.push_back(aterm2String(*i));
108 : }
109 :
110 6944 : for (ATermIterator i(bnds); i; ++i) {
111 : ATerm s1, s2;
112 3032 : if (!matchEnvBinding(*i, s1, s2))
113 0 : throw badTerm("tuple of strings expected", *i);
114 3032 : drv.env[aterm2String(s1)] = aterm2String(s2);
115 : }
116 :
117 0 : return drv;
118 : }
119 :
120 :
121 518 : ATerm unparseDerivation(const Derivation & drv)
122 : {
123 518 : ATermList outputs = ATempty;
124 1036 : for (DerivationOutputs::const_reverse_iterator i = drv.outputs.rbegin();
125 : i != drv.outputs.rend(); ++i)
126 : outputs = ATinsert(outputs,
127 : makeDerivationOutput(
128 : toATerm(i->first),
129 : toATerm(i->second.path),
130 : toATerm(i->second.hashAlgo),
131 518 : toATerm(i->second.hash)));
132 :
133 518 : ATermList inDrvs = ATempty;
134 715 : for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin();
135 : i != drv.inputDrvs.rend(); ++i)
136 : inDrvs = ATinsert(inDrvs,
137 : makeDerivationInput(
138 : toATerm(i->first),
139 197 : toATermList(i->second)));
140 :
141 518 : ATermList args = ATempty;
142 1577 : for (Strings::const_reverse_iterator i = drv.args.rbegin();
143 : i != drv.args.rend(); ++i)
144 1059 : args = ATinsert(args, toATerm(*i));
145 :
146 518 : ATermList env = ATempty;
147 3999 : for (StringPairs::const_reverse_iterator i = drv.env.rbegin();
148 : i != drv.env.rend(); ++i)
149 : env = ATinsert(env,
150 : makeEnvBinding(
151 : toATerm(i->first),
152 3481 : toATerm(i->second)));
153 :
154 : return makeDerive(
155 : outputs,
156 : inDrvs,
157 : toATermList(drv.inputSrcs),
158 : toATerm(drv.platform),
159 : toATerm(drv.builder),
160 : args,
161 518 : env);
162 : }
163 :
164 :
165 1009 : bool isDerivation(const string & fileName)
166 : {
167 1009 : return hasSuffix(fileName, drvExtension);
168 : }
169 :
170 0 :
171 1106 : }
|