Flox Package Database 1
CRUD Operations on Nix Package Metadata
Loading...
Searching...
No Matches
manifest.hh
Go to the documentation of this file.
1/* ========================================================================== *
2 *
3 * @file flox/resolver/manifest.hh
4 *
5 * @brief An abstract description of an environment in its unresolved state.
6 *
7 *
8 * -------------------------------------------------------------------------- */
9
10#pragma once
11
12#include <filesystem>
13#include <optional>
14#include <string>
15#include <unordered_map>
16#include <utility>
17#include <vector>
18
19#include <nix/config.hh>
20#include <nix/globals.hh>
21#include <nix/ref.hh>
22
23#include "compat/concepts.hh"
25#include "flox/core/types.hh"
27#include "flox/registry.hh"
29
30
31/* -------------------------------------------------------------------------- */
32
33/* Forward Declarations. */
34
35namespace flox::resolver {
36struct ManifestDescriptor;
37} // namespace flox::resolver
38
39namespace nix {
40class Store;
41}
42
43
44/* -------------------------------------------------------------------------- */
45
46namespace flox::resolver {
47
48/* -------------------------------------------------------------------------- */
49
51template<manifest_raw_type RawType>
52static inline RawType
53readManifestFromPath( const std::filesystem::path & manifestPath )
54{
55 if ( ! std::filesystem::exists( manifestPath ) )
56 {
57 throw InvalidManifestFileException( "no such path: "
58 + manifestPath.string() );
59 }
60 return readAndCoerceJSON( manifestPath );
61}
62
63
64/* -------------------------------------------------------------------------- */
65
77template<manifest_raw_type RawType>
79{
80
81protected:
82
83 /* We need these `protected' so they can be set by `Manifest'. */
84 // NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes)
85 // TODO: remove `manifestPath'
86 RawType manifestRaw;
87 RegistryRaw registryRaw;
88 // NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes)
89
91 template<manifest_raw_type _RawType = RawType>
92 typename std::enable_if<std::derived_from<_RawType, GlobalManifestRaw>,
93 void>::type
95 {
96 if ( this->manifestRaw.registry.has_value() )
97 {
98 this->registryRaw = *this->manifestRaw.registry;
99 }
100 }
101
103 template<manifest_raw_type _RawType = RawType>
104 typename std::enable_if<std::derived_from<_RawType, GlobalManifestRawGA>,
105 void>::type
107 {
108 this->registryRaw = getGARegistry();
109 }
110
111
112public:
113
114 using rawType = RawType;
115
116 virtual ~ManifestBase() = default;
117 ManifestBase( const ManifestBase & ) = default;
118 ManifestBase( ManifestBase && ) noexcept = default;
119
121 {
122 this->manifestRaw.check();
123 this->initRegistry();
124 }
125
126 explicit ManifestBase( RawType raw ) : manifestRaw( std::move( raw ) )
127 {
128 this->manifestRaw.check();
129 this->initRegistry();
130 }
131
132 explicit ManifestBase( const std::filesystem::path & manifestPath )
133 : manifestRaw( readManifestFromPath<RawType>( manifestPath ) )
134 {
135 this->manifestRaw.check();
136 this->initRegistry();
137 }
138
139 ManifestBase &
140 operator=( const ManifestBase & )
141 = default;
142
143 ManifestBase &
144 operator=( ManifestBase && ) noexcept
145 = default;
146
147 [[nodiscard]] const RawType &
148 getManifestRaw() const
149 {
150 return this->manifestRaw;
151 }
152
153 [[nodiscard]] const RegistryRaw &
154 getRegistryRaw() const
155 {
156 return this->registryRaw;
157 }
158
159 /* Ignore linter warning about copying params because `nix::ref` is just
160 * a pointer ( `std::shared_pointer' with a `nullptr` check ). */
161 [[nodiscard]] RegistryRaw
162 getLockedRegistry( const nix::ref<nix::Store> & store
163 = NixStoreMixin().getStore() ) const
164 {
165 return lockRegistry( this->getRegistryRaw(), store );
166 }
167
169 [[nodiscard]] std::vector<System>
171 {
172 const auto & manifest = this->getManifestRaw();
173 if ( manifest.options.has_value() && manifest.options->systems.has_value() )
174 {
175 return *manifest.options->systems;
176 }
177 return std::vector<System> { nix::settings.thisSystem.get() };
178 }
179
180 [[nodiscard]] pkgdb::PkgQueryArgs
181 getBaseQueryArgs() const
182 {
183 pkgdb::PkgQueryArgs args;
184 if ( ! this->manifestRaw.options.has_value() ) { return args; }
185
186 if ( this->manifestRaw.options->systems.has_value() )
187 {
188 args.systems = *this->manifestRaw.options->systems;
189 }
190
191 if ( this->manifestRaw.options->allow.has_value() )
192 {
193 if ( this->manifestRaw.options->allow->unfree.has_value() )
194 {
195 args.allowUnfree = *this->manifestRaw.options->allow->unfree;
196 }
197 if ( this->manifestRaw.options->allow->broken.has_value() )
198 {
199 args.allowBroken = *this->manifestRaw.options->allow->broken;
200 }
201 args.licenses = this->manifestRaw.options->allow->licenses;
202 }
203
204 if ( this->manifestRaw.options->semver.has_value()
205 && this->manifestRaw.options->semver->preferPreReleases.has_value() )
206 {
207 args.preferPreReleases
208 = *this->manifestRaw.options->semver->preferPreReleases;
209 }
210 return args;
211 }
212
213
214}; /* End class `ManifestBase' */
215
216
217/* -------------------------------------------------------------------------- */
218
219template<manifest_raw_type RawType>
220class GlobalManifestBase : public ManifestBase<RawType>
221{
222
223public:
224
225 ~GlobalManifestBase() override = default;
226 GlobalManifestBase() = default;
227 GlobalManifestBase( const GlobalManifestBase & ) = default;
229
231 operator=( const GlobalManifestBase & )
232 = default;
233
235 operator=( GlobalManifestBase && )
236 = default;
237
238 explicit GlobalManifestBase( RawType raw )
239 : ManifestBase<RawType>( std::move( raw ) )
240 {}
241
242 explicit GlobalManifestBase( const std::filesystem::path & manifestPath )
243 : ManifestBase<RawType>( manifestPath )
244 {}
245
246
247}; /* End class `GlobalManifestBase' */
248
249
250/* -------------------------------------------------------------------------- */
251
254
255
256/* -------------------------------------------------------------------------- */
257
259using InstallDescriptors = std::unordered_map<InstallID, ManifestDescriptor>;
260
266[[nodiscard]] std::vector<InstallDescriptors>
267getGroupedDescriptors( const InstallDescriptors & descriptors );
268
269
270/* -------------------------------------------------------------------------- */
271
272
274template<manifest_raw_type RawType>
276{
277
278private:
279
285
286
296 void
297 check() const
298 {
299 const auto & raw = this->getManifestRaw();
300 raw.check();
301 std::optional<std::vector<std::string>> maybeSystems;
302 if ( auto maybeOpts = raw.options; maybeOpts.has_value() )
303 {
304 maybeSystems = maybeOpts->systems;
305 }
306
307 for ( const auto & [iid, desc] : this->descriptors )
308 {
309 if ( ! desc.systems.has_value() ) { continue; }
310 if ( ! maybeSystems.has_value() )
311 {
313 "descriptor `install." + iid
314 + "' specifies `systems' but no `options.systems' are specified"
315 " in the manifest." );
316 }
317 for ( const auto & system : *desc.systems )
318 {
319 if ( std::find( maybeSystems->begin(), maybeSystems->end(), system )
320 == maybeSystems->end() )
321 {
322 std::stringstream msg;
323 msg << "descriptor `install." << iid << "' specifies system `"
324 << system
325 << "' which is not in `options.systems' in the manifest.";
326 throw InvalidManifestFileException( msg.str() );
327 }
328 }
329 }
330 }
331
333 void
335 {
336 if ( ! this->manifestRaw.install.has_value() ) { return; }
337 for ( const auto & [iid, raw] : *this->manifestRaw.install )
338 {
339 /* An empty/null descriptor uses `name' of the attribute. */
340 if ( raw.has_value() )
341 {
342 this->descriptors.emplace( iid, ManifestDescriptor( iid, *raw ) );
343 }
344 else
345 {
346 ManifestDescriptor manDesc;
347 manDesc.name = iid;
348 this->descriptors.emplace( iid, std::move( manDesc ) );
349 }
350 }
351 this->check();
352 }
353
354
355public:
356
357 ~EnvironmentManifestBase() override = default;
358 EnvironmentManifestBase() = default;
361
362 explicit EnvironmentManifestBase( RawType raw )
363 : ManifestBase<RawType>( std::move( raw ) )
364 {
365 this->initDescriptors();
366 }
367
368 explicit EnvironmentManifestBase( const std::filesystem::path & manifestPath )
369 : ManifestBase<RawType>( readManifestFromPath<RawType>( manifestPath ) )
370 {
371 this->initDescriptors();
372 }
373
374 EnvironmentManifestBase &
375 operator=( const EnvironmentManifestBase & )
376 = default;
377
378 EnvironmentManifestBase &
379 operator=( EnvironmentManifestBase && )
380 = default;
381
383 [[nodiscard]] const InstallDescriptors &
385 {
386 return this->descriptors;
387 }
388
394 [[nodiscard]] std::vector<InstallDescriptors>
396 {
397 return flox::resolver::getGroupedDescriptors( this->descriptors );
398 }
399
400
401}; /* End class `EnvironmentManifestBase' */
402
403
404/* -------------------------------------------------------------------------- */
405
406using EnvironmentManifest = EnvironmentManifestBase<ManifestRaw>;
407using EnvironmentManifestGA = EnvironmentManifestBase<ManifestRawGA>;
408
409
410/* -------------------------------------------------------------------------- */
411
412} // namespace flox::resolver
413
414
415/* -------------------------------------------------------------------------- *
416 *
417 *
418 *
419 * ========================================================================== */
Description of an environment in its unlocked form.
Definition: manifest.hh:276
InstallDescriptors descriptors
Definition: manifest.hh:284
std::vector< InstallDescriptors > getGroupedDescriptors() const
Returns all descriptors, grouping those with a group field, and returning those without a group field...
Definition: manifest.hh:395
void initDescriptors()
Initialize descriptors from manifestRaw.
Definition: manifest.hh:334
void check() const
Assert the validity of the manifest, throwing an exception if it contains invalid fields.
Definition: manifest.hh:297
const InstallDescriptors & getDescriptors() const
Get descriptors from the manifest's ‘install’ field.
Definition: manifest.hh:384
Definition: manifest.hh:221
An exception thrown when a manifest file is invalid.
A global manifest containing only registry and options fields.
Definition: manifest.hh:79
std::vector< System > getSystems() const
Get the list of systems requested by the manifest.
Definition: manifest.hh:170
std::enable_if< std::derived_from< _RawType, GlobalManifestRawGA >, void >::type initRegistry()
Initialize registryRaw from manifestRaw.
Definition: manifest.hh:106
std::enable_if< std::derived_from< _RawType, GlobalManifestRaw >, void >::type initRegistry()
Initialize registryRaw from manifestRaw.
Definition: manifest.hh:94
Provides backports of some concepts features that are missing in Clang v11.
An abstract description of an environment in its unresolved state. This representation is intended fo...
std::vector< InstallDescriptors > getGroupedDescriptors(const InstallDescriptors &descriptors)
Returns all descriptors, grouping those with a group field, and returning those without a group field...
Definition: manifest.cc:35
static RawType readManifestFromPath(const std::filesystem::path &manifestPath)
Read a flox::resolver::ManifestBase from a file.
Definition: manifest.hh:53
std::unordered_map< InstallID, ManifestDescriptor > InstallDescriptors
A map of install IDs to manifest descriptors.
Definition: manifest.hh:259
RegistryRaw lockRegistry(const RegistryRaw &unlocked, const nix::ref< nix::Store > &store)
Lock an unlocked registry.
Definition: registry.cc:365
RegistryRaw getGARegistry()
Get a hard coded registry for use with flox's GA release.
Definition: registry.cc:377
nlohmann::json readAndCoerceJSON(const std::filesystem::path &path)
Read a file and coerce its contents to JSON based on its extension.
Definition: util.cc:102
Manages a nix runtime state blob with associated helpers.
Interfaces for constructing complex ‘Packages’ queries.
A set of user inputs used to set input preferences during search and resolution.
A set of user inputs used to set input preferences during search and resolution.
Definition: registry.hh:297
A set of user defined requirements describing a package/dependency.
Definition: descriptor.hh:221
std::optional< std::string > name
Definition: descriptor.hh:226
Miscellaneous typedefs and aliases.