Arbiter
Dependency manager library that supports decentralization
Requirement.h
Go to the documentation of this file.
1 #ifndef ARBITER_REQUIREMENT_H
2 #define ARBITER_REQUIREMENT_H
3 
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7 
8 #include <arbiter/Value.h>
9 
10 #include <stdbool.h>
11 #include <stddef.h>
12 
13 // forward declarations
15 struct ArbiterSelectedVersion;
16 
17 /**
18  * How strict to be in matching compatible versions.
19  */
20 typedef enum
21 {
22  /**
23  * Determine compatibility according to a strict interpretation of SemVer.
24  */
26 
27  /**
28  * According to SemVer, technically all 0.y.z releases can break backwards
29  * compatibility, meaning that minor and patch versions have to match
30  * exactly in order to be "compatible."
31  *
32  * This looser variant permits newer patch versions, which is probably
33  * closer to what the user wants.
34  */
36 } ArbiterRequirementStrictness;
37 
38 /**
39  * Represents a requirement for a specific version or set of versions.
40  */
41 typedef struct ArbiterRequirement ArbiterRequirement;
42 
43 /**
44  * A predicate used to determine whether the given version suitably satisfies
45  * the requirement.
46  */
47 typedef bool (*ArbiterRequirementPredicate)(const struct ArbiterSelectedVersion *version, const void *context);
48 
49 /**
50  * Creates a requirement which will match any version.
51  *
52  * The returned requirement must be freed with ArbiterFree().
53  */
54 ArbiterRequirement *ArbiterCreateRequirementAny (void);
55 
56 /**
57  * Creates a requirement which will match versions not less than the specified
58  * version.
59  *
60  * The returned requirement must be freed with ArbiterFree().
61  */
62 ArbiterRequirement *ArbiterCreateRequirementAtLeast (const struct ArbiterSemanticVersion *version);
63 
64 /**
65  * Creates a requirement which will match versions that are "compatible with"
66  * the given version, according to Semantic Versioning rules about backwards
67  * compatibility.
68  *
69  * Exceptions to the SemVer rules can be applied by using a value other than
70  * `ArbiterRequirementStrictnessStrict` for `strictness`.
71  *
72  * The returned requirement must be freed with ArbiterFree().
73  */
74 ArbiterRequirement *ArbiterCreateRequirementCompatibleWith (const struct ArbiterSemanticVersion *version, ArbiterRequirementStrictness strictness);
75 
76 /**
77  * Creates a requirement which will only match the specified version, including
78  * any prerelease version and build metadata.
79  *
80  * The returned requirement must be freed with ArbiterFree().
81  */
82 ArbiterRequirement *ArbiterCreateRequirementExactly (const struct ArbiterSemanticVersion *version);
83 
84 /**
85  * Creates a requirement which only matches against `ArbiterSelectedVersion`s
86  * that have metadata equal to `metadata`.
87  *
88  * The returned requirement must be freed with ArbiterFree().
89  */
90 ArbiterRequirement *ArbiterCreateRequirementUnversioned (ArbiterUserValue metadata);
91 
92 /**
93  * Creates a requirement which will evaluate a custom predicate whenever
94  * a specific version is checked against it.
95  *
96  * The predicate may be invoked many times during dependency resolution, so it
97  * should not take a long time to complete.
98  *
99  * The returned requirement must be freed with ArbiterFree().
100  */
101 ArbiterRequirement *ArbiterCreateRequirementCustom (ArbiterRequirementPredicate predicate, ArbiterUserContext context);
102 
103 /**
104  * Creates a compound requirement that evaluates each of a list of requirements.
105  * All of the requirements must be satisfied for the compound requirement to be
106  * satisfied.
107  *
108  * The objects in the C array can be safely freed after calling this function.
109  *
110  * The returned requirement must be freed with ArbiterFree().
111  */
112 ArbiterRequirement *ArbiterCreateRequirementCompound (const ArbiterRequirement * const *requirements, size_t count);
113 
114 /**
115  * Creates a requirement with a custom priority, changing how the base
116  * requirement intersects with other requirements in the dependency graph.
117  *
118  * Normally, if two requirements A and B are found for the same project in the
119  * graph, they are intersected to create a requirement which satisfies both
120  * A and B. If no intersection is possible, dependency resolution fails.
121  *
122  * Priorities short-circuit this intersection process. If requirement A has
123  * a lower _priority index_ (meaning that it is higher priority) than
124  * requirement B: requirement A will be used, requirement B will be discarded,
125  * and no intersection will be performed.
126  *
127  * **This can lead to surprising behavior that violates users' expectations**,
128  * but is nonetheless occasionally useful. For example, users sometimes want to
129  * be able to specify a particular version to use which lies outside of any
130  * semantic versioning scheme (e.g., an arbitrary branch or local checkout), in
131  * which case it makes sense to disable some semantic version requirements in
132  * the dependency graph.
133  *
134  * _Note:_ prioritized requirements may be used to filter the list of available
135  * versions, even if they are lower priority than the default and may get
136  * discarded. This means that requirements should avoid rejecting valid versions
137  * for the project being considered, or else an unsatisfiable constraints error
138  * may result.
139  *
140  * baseRequirement - A requirement specifying which versions will satisfy the
141  * new requirement. Must not be NULL.
142  * priorityIndex - A "priority index" for the new requirement. Lower numbers
143  * indicate higher priority (just like setpriority() on Unix).
144  * Requirements without an explicit priority set are assumed
145  * to have priority index 0, meaning negative priorities will
146  * override the default and positive priorities will _be
147  * overridden_ by the default.
148  *
149  * The returned requirement must be freed with ArbiterFree().
150  */
151 ArbiterRequirement *ArbiterCreateRequirementPrioritized (const ArbiterRequirement *baseRequirement, int priorityIndex);
152 
153 /**
154  * Determines whether the given requirement is satisfied by the given version.
155  */
156 bool ArbiterRequirementSatisfiedBy (const ArbiterRequirement *requirement, const struct ArbiterSelectedVersion *version);
157 
158 /**
159  * Returns the priority of the given requirement. See
160  * ArbiterCreateRequirementPrioritized() for more information.
161  */
162 int ArbiterRequirementPriority (const ArbiterRequirement *requirement);
163 
164 #ifdef __cplusplus
165 }
166 #endif
167 
168 #endif
ArbiterRequirement * ArbiterCreateRequirementUnversioned(ArbiterUserValue metadata)
Creates a requirement which only matches against ArbiterSelectedVersions that have metadata equal to ...
ArbiterRequirement * ArbiterCreateRequirementAtLeast(const struct ArbiterSemanticVersion *version)
Creates a requirement which will match versions not less than the specified version.
ArbiterRequirement * ArbiterCreateRequirementAny(void)
Creates a requirement which will match any version.
bool operator>=(const ArbiterSemanticVersion &other) const noexcept
Definition: Version.h:52
bool ArbiterRequirementSatisfiedBy(const ArbiterRequirement *requirement, const struct ArbiterSelectedVersion *version)
Determines whether the given requirement is satisfied by the given version.
ArbiterRequirement * ArbiterCreateRequirementCompound(const ArbiterRequirement *const *requirements, size_t count)
Creates a compound requirement that evaluates each of a list of requirements.
ArbiterRequirement * ArbiterCreateRequirementCompatibleWith(const struct ArbiterSemanticVersion *version, ArbiterRequirementStrictness strictness)
Creates a requirement which will match versions that are "compatible with" the given version...
virtual std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const =0
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
According to SemVer, technically all 0.y.z releases can break backwards compatibility, meaning that minor and patch versions have to match exactly in order to be "compatible.".
Definition: Requirement.h:35
ArbiterRequirement * ArbiterCreateRequirementCustom(ArbiterRequirementPredicate predicate, ArbiterUserContext context)
Creates a requirement which will evaluate a custom predicate whenever a specific version is checked a...
ArbiterRequirement * ArbiterCreateRequirementExactly(const struct ArbiterSemanticVersion *version)
Creates a requirement which will only match the specified version, including any prerelease version a...
ArbiterRequirement * ArbiterCreateRequirementPrioritized(const ArbiterRequirement *baseRequirement, int priorityIndex)
Creates a requirement with a custom priority, changing how the base requirement intersects with other...
int ArbiterRequirementPriority(const ArbiterRequirement *requirement)
Returns the priority of the given requirement.
Determine compatibility according to a strict interpretation of SemVer.
Definition: Requirement.h:25