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