1 : #include "storeexpr.hh"
2 : #include "globals.hh"
3 : #include "store.hh"
4 :
5 : #include "storeexpr-ast.hh"
6 : #include "storeexpr-ast.cc"
7 :
8 :
9 : Hash hashTerm(ATerm t)
10 135 : {
11 135 : return hashString(atPrint(t));
12 : }
13 :
14 :
15 : Path writeTerm(ATerm t, const string & suffix)
16 66 : {
17 : /* The id of a term is its hash. */
18 66 : Hash h = hashTerm(t);
19 :
20 : Path path = canonPath(nixStore + "/" +
21 66 : (string) h + suffix + ".store");
22 :
23 66 : if (!readOnlyMode && !isValidPath(path)) {
24 50 : char * s = ATwriteToString(t);
25 50 : if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
26 50 : addTextToStore(path, string(s));
27 : }
28 :
29 50 : return path;
30 : }
31 :
32 :
33 : static void parsePaths(ATermList paths, PathSet & out)
34 435 : {
35 747 : for (ATermIterator i(paths); i; ++i) {
36 312 : if (ATgetType(*i) != AT_APPL)
37 0 : throw badTerm("not a path", *i);
38 312 : string s = aterm2String(*i);
39 312 : if (s.size() == 0 || s[0] != '/')
40 0 : throw badTerm("not a path", *i);
41 312 : out.insert(s);
42 : }
43 : }
44 :
45 :
46 : static void checkClosure(const Closure & closure)
47 169 : {
48 169 : if (closure.elems.size() == 0)
49 0 : throw Error("empty closure");
50 :
51 169 : PathSet decl;
52 343 : for (ClosureElems::const_iterator i = closure.elems.begin();
53 : i != closure.elems.end(); i++)
54 174 : decl.insert(i->first);
55 :
56 338 : for (PathSet::const_iterator i = closure.roots.begin();
57 : i != closure.roots.end(); i++)
58 169 : if (decl.find(*i) == decl.end())
59 0 : throw Error(format("undefined root path `%1%'") % *i);
60 :
61 343 : for (ClosureElems::const_iterator i = closure.elems.begin();
62 : i != closure.elems.end(); i++)
63 179 : for (PathSet::const_iterator j = i->second.refs.begin();
64 : j != i->second.refs.end(); j++)
65 5 : if (decl.find(*j) == decl.end())
66 0 : throw Error(
67 : format("undefined path `%1%' referenced by `%2%'")
68 : % *j % i->first);
69 : }
70 :
71 :
72 : /* Parse a closure. */
73 : static bool parseClosure(ATerm t, Closure & closure)
74 215 : {
75 215 : ATermList roots, elems;
76 :
77 215 : if (!matchClosure(t, roots, elems))
78 46 : return false;
79 :
80 169 : parsePaths(roots, closure.roots);
81 :
82 343 : for (ATermIterator i(elems); i; ++i) {
83 174 : ATerm path;
84 174 : ATermList refs;
85 174 : if (!matchClosureElem(*i, path, refs))
86 0 : throw badTerm("not a closure element", *i);
87 1026 : ClosureElem elem;
88 174 : parsePaths(refs, elem.refs);
89 638 : closure.elems[aterm2String(path)] = elem;
90 : }
91 :
92 169 : checkClosure(closure);
93 169 : return true;
94 : }
95 :
96 :
97 : static bool parseDerivation(ATerm t, Derivation & derivation)
98 46 : {
99 46 : ATermList outs, ins, args, bnds;
100 46 : ATerm builder, platform;
101 :
102 46 : if (!matchDerive(t, outs, ins, platform, builder, args, bnds))
103 0 : return false;
104 :
105 46 : parsePaths(outs, derivation.outputs);
106 46 : parsePaths(ins, derivation.inputs);
107 :
108 46 : derivation.builder = aterm2String(builder);
109 46 : derivation.platform = aterm2String(platform);
110 :
111 184 : for (ATermIterator i(args); i; ++i) {
112 138 : if (ATgetType(*i) != AT_APPL)
113 0 : throw badTerm("string expected", *i);
114 138 : derivation.args.push_back(aterm2String(*i));
115 : }
116 :
117 307 : for (ATermIterator i(bnds); i; ++i) {
118 261 : ATerm s1, s2;
119 261 : if (!matchEnvBinding(*i, s1, s2))
120 0 : throw badTerm("tuple of strings expected", *i);
121 261 : derivation.env[aterm2String(s1)] = aterm2String(s2);
122 : }
123 :
124 46 : return true;
125 : }
126 :
127 :
128 : StoreExpr parseStoreExpr(ATerm t)
129 215 : {
130 2411 : StoreExpr ne;
131 215 : if (parseClosure(t, ne.closure))
132 169 : ne.type = StoreExpr::neClosure;
133 46 : else if (parseDerivation(t, ne.derivation))
134 46 : ne.type = StoreExpr::neDerivation;
135 0 : else throw badTerm("not a store expression", t);
136 0 : return ne;
137 : }
138 :
139 :
140 : static ATermList unparsePaths(const PathSet & paths)
141 272 : {
142 272 : ATermList l = ATempty;
143 503 : for (PathSet::const_iterator i = paths.begin();
144 : i != paths.end(); i++)
145 231 : l = ATinsert(l, toATerm(*i));
146 272 : return ATreverse(l);
147 : }
148 :
149 :
150 : static ATerm unparseClosure(const Closure & closure)
151 66 : {
152 66 : ATermList roots = unparsePaths(closure.roots);
153 :
154 66 : ATermList elems = ATempty;
155 134 : for (ClosureElems::const_iterator i = closure.elems.begin();
156 : i != closure.elems.end(); i++)
157 68 : elems = ATinsert(elems,
158 : makeClosureElem(
159 : toATerm(i->first),
160 : unparsePaths(i->second.refs)));
161 :
162 66 : return makeClosure(roots, elems);
163 : }
164 :
165 :
166 : static ATerm unparseDerivation(const Derivation & derivation)
167 69 : {
168 69 : ATermList args = ATempty;
169 276 : for (Strings::const_iterator i = derivation.args.begin();
170 : i != derivation.args.end(); i++)
171 207 : args = ATinsert(args, toATerm(*i));
172 :
173 69 : ATermList env = ATempty;
174 409 : for (StringPairs::const_iterator i = derivation.env.begin();
175 : i != derivation.env.end(); i++)
176 340 : env = ATinsert(env,
177 : makeEnvBinding(
178 : toATerm(i->first),
179 : toATerm(i->second)));
180 :
181 69 : return makeDerive(
182 : unparsePaths(derivation.outputs),
183 : unparsePaths(derivation.inputs),
184 : toATerm(derivation.platform),
185 : toATerm(derivation.builder),
186 : ATreverse(args),
187 : ATreverse(env));
188 : }
189 :
190 :
191 : ATerm unparseStoreExpr(const StoreExpr & ne)
192 135 : {
193 135 : if (ne.type == StoreExpr::neClosure)
194 66 : return unparseClosure(ne.closure);
195 69 : else if (ne.type == StoreExpr::neDerivation)
196 69 : return unparseDerivation(ne.derivation);
197 0 : else abort();
198 51 : }
|