projects/guix·blob python-team · refs

401 lines · 14.0 KiB

1#pragma once
2
3#include "hash.hh"
4#include "serialise.hh"
5
6#include <string>
7#include <cstdint>
8#include <map>
9#include <memory>
10
11
12namespace nix {
13
14
15typedef std::map<Path, Path> Roots;
16
17
18struct GCOptions
19{
20 /* Garbage collector operation:
21
22 - `gcReturnLive': return the set of paths reachable from
23 (i.e. in the closure of) the roots.
24
25 - `gcReturnDead': return the set of paths not reachable from
26 the roots.
27
28 - `gcDeleteDead': actually delete the latter set.
29
30 - `gcDeleteSpecific': delete the paths listed in
31 `pathsToDelete', insofar as they are not reachable.
32 */
33 typedef enum {
34 gcReturnLive,
35 gcReturnDead,
36 gcDeleteDead,
37 gcDeleteSpecific,
38 } GCAction;
39
40 GCAction action;
41
42 /* If `ignoreLiveness' is set, then reachability from the roots is
43 ignored (dangerous!). However, the paths must still be
44 unreferenced *within* the store (i.e., there can be no other
45 store paths that depend on them). */
46 bool ignoreLiveness;
47
48 /* For `gcDeleteSpecific', the paths to delete. */
49 PathSet pathsToDelete;
50
51 /* Stop after at least `maxFreed' bytes have been freed. */
52 unsigned long long maxFreed;
53
54 GCOptions();
55};
56
57
58struct GCResults
59{
60 /* Depending on the action, the GC roots, or the paths that would
61 be or have been deleted. */
62 PathSet paths;
63
64 /* For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the
65 number of bytes that would be or was freed. */
66 unsigned long long bytesFreed;
67
68 GCResults()
69 {
70 bytesFreed = 0;
71 }
72};
73
74
75struct SubstitutablePathInfo
76{
77 Path deriver;
78 PathSet references;
79 unsigned long long downloadSize; /* 0 = unknown or inapplicable */
80 unsigned long long narSize; /* 0 = unknown */
81};
82
83typedef std::map<Path, SubstitutablePathInfo> SubstitutablePathInfos;
84
85
86struct ValidPathInfo
87{
88 Path path;
89 Path deriver;
90 Hash hash;
91 PathSet references;
92 time_t registrationTime = 0;
93 uint64_t narSize = 0; // 0 = unknown
94 uint64_t id; // internal use only
95
96 bool operator == (const ValidPathInfo & i) const
97 {
98 return
99 path == i.path
100 && hash == i.hash
101 && references == i.references;
102 }
103};
104
105typedef list<ValidPathInfo> ValidPathInfos;
106
107
108enum BuildMode { bmNormal, bmRepair, bmCheck };
109
110struct BuildResult
111{
112 enum Status {
113 Built = 0,
114 Substituted,
115 AlreadyValid,
116 PermanentFailure,
117 InputRejected,
118 OutputRejected,
119 TransientFailure, // possibly transient
120 CachedFailure,
121 TimedOut,
122 MiscFailure,
123 DependencyFailed,
124 LogLimitExceeded,
125 NotDeterministic,
126 } status = MiscFailure;
127 std::string errorMsg;
128 //time_t startTime = 0, stopTime = 0;
129 bool success() {
130 return status == Built || status == Substituted || status == AlreadyValid;
131 }
132};
133
134
135class StoreAPI
136{
137public:
138
139 virtual ~StoreAPI() { }
140
141 /* Check whether a path is valid. */
142 virtual bool isValidPath(const Path & path) = 0;
143
144 /* Query which of the given paths is valid. */
145 virtual PathSet queryValidPaths(const PathSet & paths) = 0;
146
147 /* Query the set of all valid paths. */
148 virtual PathSet queryAllValidPaths() = 0;
149
150 /* Query information about a valid path. */
151 virtual ValidPathInfo queryPathInfo(const Path & path) = 0;
152
153 /* Query the hash of a valid path. */
154 virtual Hash queryPathHash(const Path & path) = 0;
155
156 /* Query the set of outgoing FS references for a store path. The
157 result is not cleared. */
158 virtual void queryReferences(const Path & path,
159 PathSet & references) = 0;
160
161 /* Queries the set of incoming FS references for a store path.
162 The result is not cleared. */
163 virtual void queryReferrers(const Path & path,
164 PathSet & referrers) = 0;
165
166 /* Query the deriver of a store path. Return the empty string if
167 no deriver has been set. */
168 virtual Path queryDeriver(const Path & path) = 0;
169
170 /* Return all currently valid derivations that have `path' as an
171 output. (Note that the result of `queryDeriver()' is the
172 derivation that was actually used to produce `path', which may
173 not exist anymore.) */
174 virtual PathSet queryValidDerivers(const Path & path) = 0;
175
176 /* Query the outputs of the derivation denoted by `path'. */
177 virtual PathSet queryDerivationOutputs(const Path & path) = 0;
178
179 /* Query the output names of the derivation denoted by `path'. */
180 virtual StringSet queryDerivationOutputNames(const Path & path) = 0;
181
182 /* Query the full store path given the hash part of a valid store
183 path, or "" if the path doesn't exist. */
184 virtual Path queryPathFromHashPart(const string & hashPart) = 0;
185
186 /* Query which of the given paths have substitutes. */
187 virtual PathSet querySubstitutablePaths(const PathSet & paths) = 0;
188
189 /* Query substitute info (i.e. references, derivers and download
190 sizes) of a set of paths. If a path does not have substitute
191 info, it's omitted from the resulting ‘infos’ map. */
192 virtual void querySubstitutablePathInfos(const PathSet & paths,
193 SubstitutablePathInfos & infos) = 0;
194
195 /* Copy the contents of a path to the store and register the
196 validity the resulting path. The resulting path is returned.
197 The function object `filter' can be used to exclude files (see
198 libutil/archive.hh). */
199 virtual Path addToStore(const string & name, const Path & srcPath,
200 bool recursive = true, HashType hashAlgo = htSHA256,
201 PathFilter & filter = defaultPathFilter, bool repair = false) = 0;
202
203 /* Like addToStore, but the contents written to the output path is
204 a regular file containing the given string. */
205 virtual Path addTextToStore(const string & name, const string & s,
206 const PathSet & references, bool repair = false) = 0;
207
208 /* Export a store path, that is, create a NAR dump of the store
209 path and append its references and its deriver. Optionally, a
210 cryptographic signature (created by OpenSSL) of the preceding
211 data is attached. */
212 virtual void exportPath(const Path & path, bool sign,
213 Sink & sink) = 0;
214
215 /* Import a sequence of NAR dumps created by exportPaths() into
216 the Nix store. */
217 virtual Paths importPaths(Source & source) = 0;
218
219 /* For each path, if it's a derivation, build it. Building a
220 derivation means ensuring that the output paths are valid. If
221 they are already valid, this is a no-op. Otherwise, validity
222 can be reached in two ways. First, if the output paths is
223 substitutable, then build the path that way. Second, the
224 output paths can be created by running the builder, after
225 recursively building any sub-derivations. For inputs that are
226 not derivations, substitute them. */
227 virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal) = 0;
228
229 /* Ensure that a path is valid. If it is not currently valid, it
230 may be made valid by running a substitute (if defined for the
231 path). */
232 virtual void ensurePath(const Path & path) = 0;
233
234 /* Add a store path as a temporary root of the garbage collector.
235 The root disappears as soon as we exit. */
236 virtual void addTempRoot(const Path & path) = 0;
237
238 /* Add an indirect root, which is merely a symlink to `path' from
239 /nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
240 to be a symlink to a store path. The garbage collector will
241 automatically remove the indirect root when it finds that
242 `path' has disappeared. */
243 virtual void addIndirectRoot(const Path & path) = 0;
244
245 /* Acquire the global GC lock, then immediately release it. This
246 function must be called after registering a new permanent root,
247 but before exiting. Otherwise, it is possible that a running
248 garbage collector doesn't see the new root and deletes the
249 stuff we've just built. By acquiring the lock briefly, we
250 ensure that either:
251
252 - The collector is already running, and so we block until the
253 collector is finished. The collector will know about our
254 *temporary* locks, which should include whatever it is we
255 want to register as a permanent lock.
256
257 - The collector isn't running, or it's just started but hasn't
258 acquired the GC lock yet. In that case we get and release
259 the lock right away, then exit. The collector scans the
260 permanent root and sees our's.
261
262 In either case the permanent root is seen by the collector. */
263 virtual void syncWithGC() = 0;
264
265 /* Find the roots of the garbage collector. Each root is a pair
266 (link, storepath) where `link' is the path of the symlink
267 outside of the Nix store that point to `storePath'. */
268 virtual Roots findRoots() = 0;
269
270 /* Perform a garbage collection. */
271 virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
272
273 /* Return the set of paths that have failed to build.*/
274 virtual PathSet queryFailedPaths() = 0;
275
276 /* Clear the "failed" status of the given paths. The special
277 value `*' causes all failed paths to be cleared. */
278 virtual void clearFailedPaths(const PathSet & paths) = 0;
279
280 /* Return a string representing information about the path that
281 can be loaded into the database using `nix-store --load-db' or
282 `nix-store --register-validity'. */
283 string makeValidityRegistration(const PathSet & paths,
284 bool showDerivers, bool showHash);
285
286 /* Optimise the disk space usage of the Nix store by hard-linking files
287 with the same contents. */
288 virtual void optimiseStore() = 0;
289
290 /* Check the integrity of the Nix store. Returns true if errors
291 remain. */
292 virtual bool verifyStore(bool checkContents, bool repair) = 0;
293
294 /* Create a profile for the given user. This is done by the daemon
295 because the 'profiles/per-user' directory is not writable by users. */
296 virtual void createUser(const std::string & userName, uid_t userId) = 0;
297};
298
299
300/* !!! These should be part of the store API, I guess. */
301
302/* Throw an exception if `path' is not directly in the Nix store. */
303void assertStorePath(const Path & path);
304/* Throw an exception if `path' is not a valid path for a store item. This
305 requires not only that it is directly in the store (like with
306 assertStorePath), but also that it has a valid hash part (32 nix-base32
307 characters) followed by a dash ('-') followed by a valid store name as per
308 isStoreName and checkStoreName. */
309void assertStorePathStrict(const Path & path);
310
311bool isInStore(const Path & path);
312bool isStorePath(const Path & path);
313
314/* Extract the name part of the given store path. */
315string storePathToName(const Path & path);
316
317/* Return true iff `name' is a valid name for a store item. If false is
318 returned, `problemDescription' is set to a string suitable for use in an
319 Error exception. */
320bool isStoreName(const string & name, string & problemDescription);
321bool isStoreName(const string & name);
322void checkStoreName(const string & name);
323
324/* Return true iff `name' is a valid basename for a store item's path, e.g. of
325 the form hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh-NAME, where 'h' represents a
326 nix-base32 character and NAME is a valid store name per isStoreName. */
327bool isStoreBasenameStrict(const string & name);
328/* Return true iff `path' is a valid path for a store item. */
329bool isStorePathStrict(const Path & path);
330
331
332/* Chop off the parts after the top-level store name, e.g.,
333 /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
334Path toStorePath(const Path & path);
335
336
337/* Constructs a unique store path name. */
338Path makeStorePath(const string & type,
339 const Hash & hash, const string & name);
340
341Path makeOutputPath(const string & id,
342 const Hash & hash, const string & name);
343
344Path makeFixedOutputPath(bool recursive,
345 HashType hashAlgo, Hash hash, string name);
346
347
348/* Preparatory part of addTextToStore().
349
350 !!! Computation of the path should take the references given to
351 addTextToStore() into account, otherwise we have a (relatively
352 minor) security hole: a caller can register a source file with
353 bogus references. If there are too many references, the path may
354 not be garbage collected when it has to be (not really a problem,
355 the caller could create a root anyway), or it may be garbage
356 collected when it shouldn't be (more serious).
357
358 Hashing the references would solve this (bogus references would
359 simply yield a different store path, so other users wouldn't be
360 affected), but it has some backwards compatibility issues (the
361 hashing scheme changes), so I'm not doing that for now. */
362Path computeStorePathForText(const string & name, const string & s,
363 const PathSet & references);
364
365/* Return true if PATH, whose content has the given HASH, refers to a
366 content-addressed file as added by 'addTextToStore' or 'addToStore'. HASH
367 is interpreted as a SHA256 nar hash when RECURSIVE is true, and as a SHA256
368 file content hash when RECURSIVE is false. */
369bool isContentAddressedPath(const Path & path, const Hash & hash,
370 const PathSet & references, bool recursive);
371
372/* Remove the temporary roots file for this process. Any temporary
373 root becomes garbage after this point unless it has been registered
374 as a (permanent) root. */
375void removeTempRoots();
376
377
378/* Register a permanent GC root. */
379Path addPermRoot(StoreAPI & store, const Path & storePath,
380 const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false);
381
382
383/* Sort a set of paths topologically under the references relation.
384 If p refers to q, then p precedes q in this list. */
385Paths topoSortPaths(StoreAPI & store, const PathSet & paths);
386
387
388/* For now, there is a single global store API object, but we'll
389 purify that in the future. */
390inline std::shared_ptr<StoreAPI> store;
391
392
393/* Display a set of paths in human-readable form (i.e., between quotes
394 and separated by commas). */
395string showPaths(const PathSet & paths);
396
397MakeError(SubstError, Error)
398MakeError(BuildError, Error) /* denotes a permanent build failure */
399
400
401}