1use std::borrow::Cow;
2use std::collections::BTreeSet;
3
4use either::Either;
5
6use uv_configuration::{Constraints, Excludes, Overrides};
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) overrides: Overrides,
28
29 pub(super) excludes: Excludes,
31
32 pub(super) preferences: Preferences,
38
39 pub(super) project: Option<PackageName>,
41
42 pub(super) workspace_members: BTreeSet<PackageName>,
44
45 pub(super) exclusions: Exclusions,
50
51 pub(super) lookaheads: Vec<RequestedRequirements>,
57}
58
59impl Manifest {
60 #[must_use]
62 pub fn with_recorder(mut self, recorder: Option<ResolutionRecorder>) -> Self {
63 self.recorder = recorder;
64 self
65 }
66
67 pub fn new(
68 requirements: Vec<Requirement>,
69 constraints: Constraints,
70 overrides: Overrides,
71 excludes: Excludes,
72 preferences: Preferences,
73 project: Option<PackageName>,
74 workspace_members: BTreeSet<PackageName>,
75 exclusions: Exclusions,
76 lookaheads: Vec<RequestedRequirements>,
77 ) -> Self {
78 Self {
79 recorder: None,
80 requirements,
81 constraints,
82 overrides,
83 excludes,
84 preferences,
85 project,
86 workspace_members,
87 exclusions,
88 lookaheads: Vec::new(),
89 }
90 .with_lookaheads(lookaheads)
91 }
92
93 pub fn simple(requirements: Vec<Requirement>) -> Self {
94 Self {
95 recorder: None,
96 requirements,
97 constraints: Constraints::default(),
98 overrides: Overrides::default(),
99 excludes: Excludes::default(),
100 preferences: Preferences::default(),
101 project: None,
102 exclusions: Exclusions::default(),
103 workspace_members: BTreeSet::new(),
104 lookaheads: Vec::new(),
105 }
106 }
107
108 #[must_use]
109 pub fn with_constraints(mut self, constraints: Constraints) -> Self {
110 self.constraints = constraints;
111 self
112 }
113
114 #[must_use]
115 pub fn with_lookaheads(mut self, mut lookaheads: Vec<RequestedRequirements>) -> Self {
116 for lookahead in &mut lookaheads {
119 if self.workspace_members.contains(lookahead.package())
120 || self.project.as_ref() == Some(lookahead.package())
121 {
122 for requirement in lookahead.requirements_mut() {
123 requirement.set_force_relative(false);
124 }
125 }
126 }
127 self.lookaheads = lookaheads;
128 self
129 }
130
131 pub(crate) fn requirements<'a>(
139 &'a self,
140 env: &'a ResolverEnvironment,
141 mode: DependencyMode,
142 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
143 self.requirements_no_overrides(env, mode)
144 .chain(self.overrides(env, mode))
145 }
146
147 pub(crate) fn candidate_selection_requirements<'a>(
153 &'a self,
154 env: &'a ResolverEnvironment,
155 mode: DependencyMode,
156 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
157 self.requirements(env, mode).chain(
158 self.overrides
159 .scoped_requirements()
160 .filter(|(package, version, requirement)| {
161 !self.excludes.contains_for_scope(
162 &self.overrides,
163 package,
164 *version,
165 &requirement.name,
166 )
167 })
168 .map(|(_, _, requirement)| Cow::Borrowed(requirement))
169 .filter(move |requirement| {
170 requirement.evaluate_markers(env.marker_environment(), &[])
171 }),
172 )
173 }
174
175 pub(crate) fn requirements_no_overrides<'a>(
177 &'a self,
178 env: &'a ResolverEnvironment,
179 mode: DependencyMode,
180 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
181 match mode {
182 DependencyMode::Transitive => Either::Left(
184 self.lookaheads
185 .iter()
186 .flat_map(move |lookahead| {
187 self.overrides
188 .apply_for(
189 lookahead.package(),
190 lookahead.version(),
191 lookahead.requirements(),
192 )
193 .filter(|requirement| {
194 !self.excludes.contains_for(
195 lookahead.package(),
196 lookahead.version(),
197 &requirement.name,
198 )
199 })
200 .filter(move |requirement| {
201 requirement
202 .evaluate_markers(env.marker_environment(), lookahead.extras())
203 })
204 })
205 .chain(
206 self.overrides
207 .apply(&self.requirements)
208 .filter(|requirement| !self.excludes.contains(&requirement.name))
209 .filter(move |requirement| {
210 requirement.evaluate_markers(env.marker_environment(), &[])
211 }),
212 )
213 .chain(
214 self.constraints
215 .requirements()
216 .filter(|requirement| !self.excludes.contains(&requirement.name))
217 .filter(move |requirement| {
218 requirement.evaluate_markers(env.marker_environment(), &[])
219 })
220 .map(Cow::Borrowed),
221 ),
222 ),
223 DependencyMode::Direct => Either::Right(
225 self.overrides
226 .apply(&self.requirements)
227 .chain(self.constraints.requirements().map(Cow::Borrowed))
228 .filter(|requirement| !self.excludes.contains(&requirement.name))
229 .filter(move |requirement| {
230 requirement.evaluate_markers(env.marker_environment(), &[])
231 }),
232 ),
233 }
234 }
235
236 pub(crate) fn overrides<'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(
245 self.overrides
246 .global_requirements()
247 .filter(|requirement| !self.excludes.contains(&requirement.name))
248 .filter(move |requirement| {
249 requirement.evaluate_markers(env.marker_environment(), &[])
250 })
251 .map(Cow::Borrowed),
252 ),
253 DependencyMode::Direct => Either::Right(
255 self.overrides
256 .global_requirements()
257 .filter(|requirement| !self.excludes.contains(&requirement.name))
258 .filter(move |requirement| {
259 requirement.evaluate_markers(env.marker_environment(), &[])
260 })
261 .map(Cow::Borrowed),
262 ),
263 }
264 }
265
266 pub(crate) fn user_requirements<'a>(
277 &'a self,
278 env: &'a ResolverEnvironment,
279 mode: DependencyMode,
280 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
281 match mode {
282 DependencyMode::Transitive => Either::Left(
285 self.lookaheads
286 .iter()
287 .filter(|lookahead| lookahead.direct())
288 .flat_map(move |lookahead| {
289 self.overrides
290 .apply_for(
291 lookahead.package(),
292 lookahead.version(),
293 lookahead.requirements(),
294 )
295 .filter(|requirement| {
296 !self.excludes.contains_for(
297 lookahead.package(),
298 lookahead.version(),
299 &requirement.name,
300 )
301 })
302 .filter(move |requirement| {
303 requirement
304 .evaluate_markers(env.marker_environment(), lookahead.extras())
305 })
306 })
307 .chain(
308 self.overrides
309 .apply(&self.requirements)
310 .filter(move |requirement| {
311 requirement.evaluate_markers(env.marker_environment(), &[])
312 }),
313 ),
314 ),
315
316 DependencyMode::Direct => {
318 Either::Right(self.overrides.apply(self.requirements.iter()).filter(
319 move |requirement| requirement.evaluate_markers(env.marker_environment(), &[]),
320 ))
321 }
322 }
323 }
324
325 pub fn num_requirements(&self) -> usize {
327 self.requirements.len()
328 }
329}