Flox Package Database 1
CRUD Operations on Nix Package Metadata
Loading...
Searching...
No Matches
registry.hh
Go to the documentation of this file.
1/* ========================================================================== *
2 *
3 * @file flox/registry.hh
4 *
5 * @brief A set of user inputs used to set input preferences during search
6 * and resolution.
7 *
8 *
9 * -------------------------------------------------------------------------- */
10
11#pragma once
12
13#include <algorithm>
14#include <functional>
15#include <map>
16#include <vector>
17
18#include <nix/fetchers.hh>
19#include <nix/flake/flakeref.hh>
20#include <nlohmann/json.hpp>
21
22#include "compat/concepts.hh"
24#include "flox/core/types.hh"
25#include "flox/core/util.hh"
26#include "flox/flox-flake.hh"
28
29
30/* -------------------------------------------------------------------------- */
31
32namespace flox {
33
34/* -------------------------------------------------------------------------- */
35
38{
39
44 std::optional<std::vector<Subtree>> subtrees;
45
46 /* Base class boilerplate */
47 virtual ~InputPreferences() = default;
48 InputPreferences() = default;
49 InputPreferences( const InputPreferences & ) = default;
50 InputPreferences( InputPreferences && ) = default;
51
53 operator=( const InputPreferences & )
54 = default;
56 operator=( InputPreferences && )
57 = default;
58
59 explicit InputPreferences(
60 const std::optional<std::vector<Subtree>> & subtrees )
62 {}
63
65 virtual void
66 clear();
67
77 pkgdb::PkgQueryArgs &
78 fillPkgQueryArgs( pkgdb::PkgQueryArgs & pqa ) const;
79
86 void
87 merge( const InputPreferences & overrides );
88
89 [[nodiscard]] bool
90 operator==( const InputPreferences & other ) const
91 {
92 return this->subtrees == other.subtrees;
93 }
94
95 [[nodiscard]] bool
96 operator!=( const InputPreferences & other ) const
97 {
98 return ! ( ( *this ) == other );
99 }
100
101
102}; /* End struct `InputPreferences' */
103
104
105/* -------------------------------------------------------------------------- */
106
108void
109from_json( const nlohmann::json & jfrom, InputPreferences & prefs );
110
112void
113to_json( nlohmann::json & jto, const InputPreferences & prefs );
114
115
116/* -------------------------------------------------------------------------- */
117
122template<typename T>
124 = std::is_base_of<InputPreferences, T>::value && requires( T obj ) {
125 {
126 obj.getFlakeRef()
127 } -> std::convertible_to<nix::ref<nix::FlakeRef>>;
128 };
129
130
131/* -------------------------------------------------------------------------- */
132
135{
136
137 /* From `InputPreferences':
138 * std::optional<std::vector<Subtree>> subtrees;
139 */
140
141 std::shared_ptr<nix::FlakeRef> from;
143 RegistryInput() = default;
144
145 RegistryInput( const std::optional<std::vector<Subtree>> & subtrees,
146 const nix::FlakeRef & from )
148 , from( std::make_shared<nix::FlakeRef>( from ) )
149 {}
150
151 explicit RegistryInput( const nix::FlakeRef & from )
152 : from( std::make_shared<nix::FlakeRef>( from ) )
153 {}
154
155
157 [[nodiscard]] nix::ref<nix::FlakeRef>
159 {
160 return static_cast<nix::ref<nix::FlakeRef>>( this->from );
161 };
162
163 [[nodiscard]] bool
164 operator==( const RegistryInput & other ) const
165 {
166 if ( static_cast<InputPreferences>( *this )
167 != static_cast<InputPreferences>( other ) )
168 {
169 return false;
170 }
171
172 if ( this->from == other.from ) { return true; }
173
174 if ( ( this->from == nullptr ) || ( other.from == nullptr ) )
175 {
176 return false;
177 }
178
179 return ( *this->from ) == ( *other.from );
180 }
181
182 [[nodiscard]] bool
183 operator!=( const RegistryInput & other ) const
184 {
185 return ! ( ( *this ) == other );
186 }
187
188
189}; /* End struct `RegistryInput' */
190
191
192/* -------------------------------------------------------------------------- */
193
195void
196from_json( const nlohmann::json & jfrom, RegistryInput & rip );
197
199void
200to_json( nlohmann::json & jto, const RegistryInput & rip );
201
202
203/* -------------------------------------------------------------------------- */
204
222template<typename T>
224 /* Must have a `using input_type = <TYPENAME>;' definition. */
225 requires { typename T::input_type; } &&
226 /* `input_type' must satisfy `input_preferences_typesname' concept. */
228 /* Must provide a function, `mkInput' that constructs an `input_type'. */
229 requires( T ref, const std::string & name, const RegistryInput & rip ) {
230 {
231 ref.mkInput( name, rip )
232 } -> std::convertible_to<std::shared_ptr<typename T::input_type>>;
233 };
234
235
236/* -------------------------------------------------------------------------- */
237
243{
244
245public:
246
248
250 [[nodiscard]] static std::shared_ptr<RegistryInput>
251 mkInput( const std::string & /* unused */, const RegistryInput & input )
252 {
253 return std::make_shared<RegistryInput>( input );
254 }
255
256
257}; /* End class `RegistryInputFactory' */
258
259static_assert( registry_input_factory<RegistryInputFactory> );
260
261
262/* -------------------------------------------------------------------------- */
263
297{
298
300 std::map<std::string, RegistryInput> inputs;
301
304
310 std::vector<std::string> priority;
311
312
313 /* Base class boilerplate. */
314 virtual ~RegistryRaw() = default;
315 RegistryRaw() = default;
316 RegistryRaw( const RegistryRaw & ) = default;
317 RegistryRaw( RegistryRaw && ) = default;
318
320 operator=( const RegistryRaw & )
321 = default;
323 operator=( RegistryRaw && )
324 = default;
325
326 explicit RegistryRaw( std::map<std::string, RegistryInput> inputs,
328 std::vector<std::string> priority = {} )
329 : inputs( std::move( inputs ) )
330 , defaults( std::move( defaults ) )
331 , priority( std::move( priority ) )
332 {}
333
334 explicit RegistryRaw( std::map<std::string, RegistryInput> inputs,
335 std::vector<std::string> priority = {} )
336 : RegistryRaw( std::move( inputs ),
337 InputPreferences {},
338 std::move( priority ) )
339 {}
340
373 [[nodiscard]] virtual std::vector<std::reference_wrapper<const std::string>>
374 getOrder() const;
375
377 virtual void
378 clear();
379
387 pkgdb::PkgQueryArgs &
388 fillPkgQueryArgs( const std::string & input,
389 pkgdb::PkgQueryArgs & pqa ) const;
390
397 void
398 merge( const RegistryRaw & overrides );
399
400 [[nodiscard]] bool
401 operator==( const RegistryRaw & other ) const;
402
403 [[nodiscard]] bool
404 operator!=( const RegistryRaw & other ) const
405 {
406 return ! ( *this == other );
407 }
408
409
410}; /* End struct `RegistryRaw' */
411
412
413/* -------------------------------------------------------------------------- */
414
416void
417from_json( const nlohmann::json & jfrom, RegistryRaw & reg );
418
420void
421to_json( nlohmann::json & jto, const RegistryRaw & reg );
422
423/* -------------------------------------------------------------------------- */
424
432 "invalid registry" )
436/* -------------------------------------------------------------------------- */
437
438
448template<registry_input_factory FactoryType>
449class Registry
450{
451
452private:
453
458 RegistryRaw registryRaw;
459
461 std::vector<
462 std::pair<std::string, std::shared_ptr<typename FactoryType::input_type>>>
463 inputs;
464
465
466public:
467
468 using input_type = typename FactoryType::input_type;
469
470
475 explicit Registry( RegistryRaw registry, FactoryType & factory )
476 : registryRaw( std::move( registry ) )
477 {
478 for ( const std::reference_wrapper<const std::string> & _name :
479 this->registryRaw.getOrder() )
480 {
481 const auto & pair = std::find_if(
482 this->registryRaw.inputs.begin(),
483 this->registryRaw.inputs.end(),
484 [&]( const auto & pair ) { return pair.first == _name.get(); } );
485
486 /* Throw an exception if a registry input is an indirect reference. */
487 if ( pair->second.getFlakeRef()->input.getType() == "indirect" )
488 {
490 "registry contained an indirect reference" );
491 }
492
493 /* Fill default/fallback values if none are defined. */
494 RegistryInput input = pair->second;
495 if ( ! input.subtrees.has_value() )
496 {
497 input.subtrees = this->registryRaw.defaults.subtrees;
498 }
499
500 /* Construct the input */
501 this->inputs.emplace_back(
502 std::make_pair( pair->first,
503 factory.mkInput( pair->first, input ) ) );
504 }
505 }
506
513 [[nodiscard]] std::shared_ptr<typename FactoryType::input_type>
514 get( const std::string & name ) const noexcept
515 {
516 const auto maybeInput
517 = std::find_if( this->inputs.begin(),
518 this->inputs.end(),
519 [&]( const auto & pair ) { return pair.first == name; } );
520 if ( maybeInput == this->inputs.end() ) { return nullptr; }
521 return maybeInput->second;
522 }
523
529 [[nodiscard]] std::shared_ptr<typename FactoryType::input_type>
530 at( const std::string & name ) const
531 {
532 const std::shared_ptr<typename FactoryType::input_type> maybeInput
533 = this->get( name );
534 if ( maybeInput == nullptr )
535 {
536 throw std::out_of_range( "No such input '" + name + "'" );
537 }
538 return maybeInput;
539 }
540
542 [[nodiscard]] const RegistryRaw &
543 getRaw() const
544 {
545 return this->registryRaw;
546 }
547
548 /* Forwarded container functions. */
549
551 [[nodiscard]] auto
552 size() const
553 {
554 return this->inputs.size();
555 }
556
558 [[nodiscard]] auto
559 empty() const
560 {
561 return this->inputs.empty();
562 }
563
565 [[nodiscard]] auto
566 begin()
567 {
568 return this->inputs.begin();
569 }
570
572 [[nodiscard]] auto
573 end()
574 {
575 return this->inputs.end();
576 }
577
579 [[nodiscard]] auto
580 begin() const
581 {
582 return this->inputs.cbegin();
583 }
584
589 [[nodiscard]] auto
590 end() const
591 {
592 return this->inputs.cend();
593 }
594
596 [[nodiscard]] auto
597 cbegin() const
598 {
599 return this->inputs.cbegin();
600 }
601
606 [[nodiscard]] auto
607 cend() const
608 {
609 return this->inputs.cend();
610 }
611
612
613}; /* End class `Registry' */
614
615
616/* -------------------------------------------------------------------------- */
617
623{
624
625 /* From `RegistryInput':
626 * public:
627 * std::optional<std::vector<Subtree>> subtrees;
628 * std::shared_ptr<nix::FlakeRef> from;
629 */
630
631private:
632
633 nix::ref<nix::Store> store;
634 std::shared_ptr<FloxFlake> flake;
639 std::optional<std::vector<Subtree>> enabledSubtrees;
640
641
642public:
643
648 FloxFlakeInput( const nix::ref<nix::Store> & store,
649 const RegistryInput & input )
650 : RegistryInput( input ), store( store )
651 {}
652
653
655 [[nodiscard]] nix::ref<FloxFlake>
656 getFlake();
657
658
668 [[nodiscard]] const std::vector<Subtree> &
669 getSubtrees();
670
671
672 [[nodiscard]] RegistryInput
673 getLockedInput();
674
675
676}; /* End struct `FloxFlakeInput' */
677
678
679/* -------------------------------------------------------------------------- */
680
683{
684
685public:
686
688
691
693 explicit FloxFlakeInputFactory( const nix::ref<nix::Store> & store )
695 {}
696
698 [[nodiscard]] std::shared_ptr<FloxFlakeInput>
699 mkInput( const std::string & /* unused */, const RegistryInput & input )
700 {
701 return std::make_shared<FloxFlakeInput>( this->getStore(), input );
702 }
703
704
705}; /* End class `FloxFlakeInputFactory' */
706
707
708static_assert( registry_input_factory<FloxFlakeInputFactory> );
709
710
711/* -------------------------------------------------------------------------- */
712
719class FlakeRegistry : public Registry<FloxFlakeInputFactory>
720{
721
722public:
723
724 FlakeRegistry( RegistryRaw registryRaw, FloxFlakeInputFactory & factory )
725 : Registry<FloxFlakeInputFactory>( std::move( registryRaw ), factory )
726 {}
727
728 [[nodiscard]] std::map<std::string, RegistryInput>
729 getLockedInputs();
730
731
732}; /* End class `FlakeRegistry' */
733
734
735/* -------------------------------------------------------------------------- */
736
739lockRegistry( const RegistryRaw & unlocked,
740 const nix::ref<nix::Store> & store = NixStoreMixin().getStore() );
741
742
743/* -------------------------------------------------------------------------- */
744
753
754
755/* -------------------------------------------------------------------------- */
756
757} // namespace flox
758
759
760/* -------------------------------------------------------------------------- *
761 *
762 *
763 *
764 * ========================================================================== */
A registry containing FloxFlakeInput members.
Definition: registry.hh:720
A factory for flox::FloxFlakeInput objects.
Definition: registry.hh:683
FloxFlakeInputFactory(const nix::ref< nix::Store > &store)
Construct a factory using a nix store connection.
Definition: registry.hh:693
FloxFlakeInputFactory()=default
Construct a factory using a new nix store connection.
std::shared_ptr< FloxFlakeInput > mkInput(const std::string &, const RegistryInput &input)
Construct an input from a flox::RegistryInput.
Definition: registry.hh:699
A simple flox::RegistryInput that opens a nix evaluator for a flake.
Definition: registry.hh:623
std::optional< std::vector< Subtree > > enabledSubtrees
Definition: registry.hh:639
nix::ref< FloxFlake > getFlake()
Get a handle for a flake with a nix evaluator.
Definition: registry.cc:260
std::shared_ptr< FloxFlake > flake
Definition: registry.hh:634
const std::vector< Subtree > & getSubtrees()
Get a list of enabled subtrees.
Definition: registry.cc:275
nix::ref< nix::Store > store
Definition: registry.hh:633
FloxFlakeInput(const nix::ref< nix::Store > &store, const RegistryInput &input)
Construct a flox::FloxFlakeInput from a nix store connection and flox::RegistryInput.
Definition: registry.hh:648
An exception thrown when a registry has invalid contents.
Mixin which provides a lazy handle to a nix store connection.
Definition: nix-state.hh:59
std::shared_ptr< nix::Store > store
Definition: nix-state.hh:63
nix::ref< nix::Store > getStore()
Lazily open a nix store connection.
Definition: nix-state.hh:106
The simplest flox::RegistryInput factory which just copies inputs.
Definition: registry.hh:243
static std::shared_ptr< RegistryInput > mkInput(const std::string &, const RegistryInput &input)
Construct an input from a flox::RegistryInput.
Definition: registry.hh:251
Restricts types to those which are derived from flox::InputPreferences.
Definition: registry.hh:124
Restricts types to those which can construct flox::RegistryInput values.
Definition: registry.hh:223
Provides backports of some concepts features that are missing in Clang v11.
Definitions of various std::exception children used for throwing errors with nice messages and typed ...
#define FLOX_DEFINE_EXCEPTION(NAME, ERROR_CODE, CATEGORY_MSG)
Generate a class definition with an error code and category message.
Definition: exceptions.hh:206
Defines a convenience wrapper that provides various operations on a flake.
Interfaces for use by flox.
Definition: command.cc:29
RegistryRaw lockRegistry(const RegistryRaw &unlocked, const nix::ref< nix::Store > &store)
Lock an unlocked registry.
Definition: registry.cc:365
@ EC_INVALID_REGISTRY
Definition: exceptions.hh:43
RegistryRaw getGARegistry()
Get a hard coded registry for use with flox's GA release.
Definition: registry.cc:377
void from_json(const nlohmann::json &jfrom, RawPackage &pkg)
Convert a JSON object to a flox::RawPackage.
Definition: raw-package.cc:27
void to_json(nlohmann::json &jto, const FloxException &err)
Convert a flox::FloxException to a JSON object.
Definition: exceptions.cc:27
Interfaces for constructing complex ‘Packages’ queries.
Preferences associated with a registry input.
Definition: registry.hh:38
void merge(const InputPreferences &overrides)
Merges this flox::InputPreferences with another InputPreferences, overriding values in this InputPref...
Definition: registry.cc:33
virtual void clear()
Reset to default state.
Definition: registry.cc:24
std::optional< std::vector< Subtree > > subtrees
Definition: registry.hh:44
pkgdb::PkgQueryArgs & fillPkgQueryArgs(pkgdb::PkgQueryArgs &pqa) const
Fill a flox::pkgdb::PkgQueryArgs struct with preferences to lookup packages filtered by InputPreferen...
Definition: registry.cc:52
Preferences associated with a named registry input.
Definition: registry.hh:135
std::shared_ptr< nix::FlakeRef > from
Definition: registry.hh:141
nix::ref< nix::FlakeRef > getFlakeRef() const
Get the flake reference associated with this input.
Definition: registry.hh:158
A set of user inputs used to set input preferences during search and resolution.
Definition: registry.hh:297
virtual std::vector< std::reference_wrapper< const std::string > > getOrder() const
Return an ordered list of input names.
Definition: registry.cc:73
void merge(const RegistryRaw &overrides)
Merge this flox::RegistryRaw struct with another flox::RegistryRaw, overriding any existing values wi...
Definition: registry.cc:247
std::vector< std::string > priority
Definition: registry.hh:310
pkgdb::PkgQueryArgs & fillPkgQueryArgs(const std::string &input, pkgdb::PkgQueryArgs &pqa) const
Fill a flox::pkgdb::PkgQueryArgs struct with preferences to lookup packages in a particular input.
Definition: registry.cc:225
virtual void clear()
Reset to default state.
Definition: registry.cc:62
InputPreferences defaults
Definition: registry.hh:303
std::map< std::string, RegistryInput > inputs
Definition: registry.hh:300
Miscellaneous typedefs and aliases.
Miscellaneous helper functions.