1use std::borrow::Cow;
2use std::collections::BTreeSet;
3
4use either::Either;
5
6use uv_configuration::{Constraints, DependencyModifierScope, DependencyModifiers};
7use uv_distribution_types::{Requirement, ResolutionRecorder};
8use uv_normalize::PackageName;
9use uv_types::RequestedRequirements;
10
11use crate::preferences::Preferences;
12use crate::{DependencyMode, Exclusions, ResolverEnvironment};
13
14#[derive(Clone, Debug)]
16pub struct Manifest {
17 pub(super) recorder: Option<ResolutionRecorder>,
19
20 pub(super) requirements: Vec<Requirement>,
22
23 pub(super) constraints: Constraints,
25
26 pub(super) modifiers: DependencyModifiers,
28
29 pub(super) preferences: Preferences,
35
36 pub(super) project: Option<PackageName>,
38
39 pub(super) workspace_members: BTreeSet<PackageName>,
41
42 pub(super) exclusions: Exclusions,
47
48 pub(super) lookaheads: Vec<RequestedRequirements>,
54}
55
56impl Manifest {
57 #[must_use]
59 pub fn with_recorder(mut self, recorder: Option<ResolutionRecorder>) -> Self {
60 self.recorder = recorder;
61 self
62 }
63
64 pub fn new(
65 requirements: Vec<Requirement>,
66 constraints: Constraints,
67 modifiers: DependencyModifiers,
68 preferences: Preferences,
69 project: Option<PackageName>,
70 workspace_members: BTreeSet<PackageName>,
71 exclusions: Exclusions,
72 lookaheads: Vec<RequestedRequirements>,
73 ) -> Self {
74 Self {
75 recorder: None,
76 requirements,
77 constraints,
78 modifiers,
79 preferences,
80 project,
81 workspace_members,
82 exclusions,
83 lookaheads: Vec::new(),
84 }
85 .with_lookaheads(lookaheads)
86 }
87
88 pub fn simple(requirements: Vec<Requirement>) -> Self {
89 Self {
90 recorder: None,
91 requirements,
92 constraints: Constraints::default(),
93 modifiers: DependencyModifiers::default(),
94 preferences: Preferences::default(),
95 project: None,
96 exclusions: Exclusions::default(),
97 workspace_members: BTreeSet::new(),
98 lookaheads: Vec::new(),
99 }
100 }
101
102 #[must_use]
103 pub fn with_constraints(mut self, constraints: Constraints) -> Self {
104 self.constraints = constraints;
105 self
106 }
107
108 #[must_use]
109 pub fn with_lookaheads(mut self, mut lookaheads: Vec<RequestedRequirements>) -> Self {
110 for lookahead in &mut lookaheads {
113 if self.workspace_members.contains(lookahead.package())
114 || self.project.as_ref() == Some(lookahead.package())
115 {
116 for requirement in lookahead.requirements_mut() {
117 requirement.set_force_relative(false);
118 }
119 }
120 }
121 self.lookaheads = lookaheads;
122 self
123 }
124
125 pub(crate) fn requirements<'a>(
133 &'a self,
134 env: &'a ResolverEnvironment,
135 mode: DependencyMode,
136 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
137 self.requirements_no_overrides(env, mode)
138 .chain(self.overrides(env))
139 }
140
141 pub(crate) fn candidate_selection_requirements<'a>(
147 &'a self,
148 env: &'a ResolverEnvironment,
149 mode: DependencyMode,
150 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
151 self.requirements(env, mode).chain(
152 self.modifiers
153 .scoped_overrides()
154 .map(Cow::Borrowed)
155 .filter(move |requirement| {
156 requirement.evaluate_markers(env.marker_environment(), &[])
157 }),
158 )
159 }
160
161 pub(crate) fn requirements_no_overrides<'a>(
163 &'a self,
164 env: &'a ResolverEnvironment,
165 mode: DependencyMode,
166 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
167 match mode {
168 DependencyMode::Transitive => Either::Left(
170 self.lookaheads
171 .iter()
172 .flat_map(move |lookahead| {
173 self.modifiers
174 .apply(
175 DependencyModifierScope::Package(
176 lookahead.package(),
177 lookahead.version(),
178 ),
179 lookahead.requirements(),
180 )
181 .filter(move |requirement| {
182 requirement
183 .evaluate_markers(env.marker_environment(), lookahead.extras())
184 })
185 })
186 .chain(
187 self.modifiers
188 .apply(DependencyModifierScope::Global, &self.requirements)
189 .filter(move |requirement| {
190 requirement.evaluate_markers(env.marker_environment(), &[])
191 }),
192 )
193 .chain(
194 self.constraints
195 .requirements()
196 .filter(|requirement| !self.modifiers.is_excluded(&requirement.name))
197 .filter(move |requirement| {
198 requirement.evaluate_markers(env.marker_environment(), &[])
199 })
200 .map(Cow::Borrowed),
201 ),
202 ),
203 DependencyMode::Direct => Either::Right(
205 self.modifiers
206 .apply(DependencyModifierScope::Global, &self.requirements)
207 .chain(self.constraints.requirements().map(Cow::Borrowed))
208 .filter(|requirement| !self.modifiers.is_excluded(&requirement.name))
209 .filter(move |requirement| {
210 requirement.evaluate_markers(env.marker_environment(), &[])
211 }),
212 ),
213 }
214 }
215
216 pub(crate) fn overrides<'a>(
218 &'a self,
219 env: &'a ResolverEnvironment,
220 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
221 self.modifiers
222 .global_overrides()
223 .filter(move |requirement| requirement.evaluate_markers(env.marker_environment(), &[]))
224 .map(Cow::Borrowed)
225 }
226
227 pub(crate) fn user_requirements<'a>(
238 &'a self,
239 env: &'a ResolverEnvironment,
240 mode: DependencyMode,
241 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
242 match mode {
243 DependencyMode::Transitive => Either::Left(
246 self.lookaheads
247 .iter()
248 .filter(|lookahead| lookahead.direct())
249 .flat_map(move |lookahead| {
250 self.modifiers
251 .apply(
252 DependencyModifierScope::Package(
253 lookahead.package(),
254 lookahead.version(),
255 ),
256 lookahead.requirements(),
257 )
258 .filter(move |requirement| {
259 requirement
260 .evaluate_markers(env.marker_environment(), lookahead.extras())
261 })
262 })
263 .chain(
264 self.modifiers
265 .apply(DependencyModifierScope::Global, &self.requirements)
266 .filter(move |requirement| {
267 requirement.evaluate_markers(env.marker_environment(), &[])
268 }),
269 ),
270 ),
271
272 DependencyMode::Direct => Either::Right(
274 self.modifiers
275 .apply(DependencyModifierScope::Global, self.requirements.iter())
276 .filter(move |requirement| {
277 requirement.evaluate_markers(env.marker_environment(), &[])
278 }),
279 ),
280 }
281 }
282
283 pub fn num_requirements(&self) -> usize {
285 self.requirements.len()
286 }
287}