1use std::borrow::Cow;
2use std::collections::BTreeSet;
3
4use either::Either;
5
6use uv_configuration::{Constraints, Excludes, Overrides};
7use uv_distribution_types::Requirement;
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(crate) requirements: Vec<Requirement>,
19
20 pub(crate) constraints: Constraints,
22
23 pub(crate) overrides: Overrides,
25
26 pub(crate) excludes: Excludes,
28
29 pub(crate) preferences: Preferences,
35
36 pub(crate) project: Option<PackageName>,
38
39 pub(crate) workspace_members: BTreeSet<PackageName>,
41
42 pub(crate) exclusions: Exclusions,
47
48 pub(crate) lookaheads: Vec<RequestedRequirements>,
54}
55
56impl Manifest {
57 pub fn new(
58 requirements: Vec<Requirement>,
59 constraints: Constraints,
60 overrides: Overrides,
61 excludes: Excludes,
62 preferences: Preferences,
63 project: Option<PackageName>,
64 workspace_members: BTreeSet<PackageName>,
65 exclusions: Exclusions,
66 lookaheads: Vec<RequestedRequirements>,
67 ) -> Self {
68 Self {
69 requirements,
70 constraints,
71 overrides,
72 excludes,
73 preferences,
74 project,
75 workspace_members,
76 exclusions,
77 lookaheads,
78 }
79 }
80
81 pub fn simple(requirements: Vec<Requirement>) -> Self {
82 Self {
83 requirements,
84 constraints: Constraints::default(),
85 overrides: Overrides::default(),
86 excludes: Excludes::default(),
87 preferences: Preferences::default(),
88 project: None,
89 exclusions: Exclusions::default(),
90 workspace_members: BTreeSet::new(),
91 lookaheads: Vec::new(),
92 }
93 }
94
95 #[must_use]
96 pub fn with_constraints(mut self, constraints: Constraints) -> Self {
97 self.constraints = constraints;
98 self
99 }
100
101 #[must_use]
102 pub fn with_lookaheads(mut self, lookaheads: Vec<RequestedRequirements>) -> Self {
103 self.lookaheads = lookaheads;
104 self
105 }
106
107 pub fn requirements<'a>(
115 &'a self,
116 env: &'a ResolverEnvironment,
117 mode: DependencyMode,
118 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
119 self.requirements_no_overrides(env, mode)
120 .chain(self.overrides(env, mode))
121 }
122
123 pub fn requirements_no_overrides<'a>(
125 &'a self,
126 env: &'a ResolverEnvironment,
127 mode: DependencyMode,
128 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
129 match mode {
130 DependencyMode::Transitive => Either::Left(
132 self.lookaheads
133 .iter()
134 .flat_map(move |lookahead| {
135 self.overrides
136 .apply(lookahead.requirements())
137 .filter(|requirement| !self.excludes.contains(&requirement.name))
138 .filter(move |requirement| {
139 requirement
140 .evaluate_markers(env.marker_environment(), lookahead.extras())
141 })
142 })
143 .chain(
144 self.overrides
145 .apply(&self.requirements)
146 .filter(|requirement| !self.excludes.contains(&requirement.name))
147 .filter(move |requirement| {
148 requirement.evaluate_markers(env.marker_environment(), &[])
149 }),
150 )
151 .chain(
152 self.constraints
153 .requirements()
154 .filter(|requirement| !self.excludes.contains(&requirement.name))
155 .filter(move |requirement| {
156 requirement.evaluate_markers(env.marker_environment(), &[])
157 })
158 .map(Cow::Borrowed),
159 ),
160 ),
161 DependencyMode::Direct => Either::Right(
163 self.overrides
164 .apply(&self.requirements)
165 .chain(self.constraints.requirements().map(Cow::Borrowed))
166 .filter(|requirement| !self.excludes.contains(&requirement.name))
167 .filter(move |requirement| {
168 requirement.evaluate_markers(env.marker_environment(), &[])
169 }),
170 ),
171 }
172 }
173
174 pub fn overrides<'a>(
176 &'a self,
177 env: &'a ResolverEnvironment,
178 mode: DependencyMode,
179 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
180 match mode {
181 DependencyMode::Transitive => Either::Left(
183 self.overrides
184 .requirements()
185 .filter(|requirement| !self.excludes.contains(&requirement.name))
186 .filter(move |requirement| {
187 requirement.evaluate_markers(env.marker_environment(), &[])
188 })
189 .map(Cow::Borrowed),
190 ),
191 DependencyMode::Direct => Either::Right(
193 self.overrides
194 .requirements()
195 .filter(|requirement| !self.excludes.contains(&requirement.name))
196 .filter(move |requirement| {
197 requirement.evaluate_markers(env.marker_environment(), &[])
198 })
199 .map(Cow::Borrowed),
200 ),
201 }
202 }
203
204 pub fn user_requirements<'a>(
215 &'a self,
216 env: &'a ResolverEnvironment,
217 mode: DependencyMode,
218 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
219 match mode {
220 DependencyMode::Transitive => Either::Left(
223 self.lookaheads
224 .iter()
225 .filter(|lookahead| lookahead.direct())
226 .flat_map(move |lookahead| {
227 self.overrides
228 .apply(lookahead.requirements())
229 .filter(move |requirement| {
230 requirement
231 .evaluate_markers(env.marker_environment(), lookahead.extras())
232 })
233 })
234 .chain(
235 self.overrides
236 .apply(&self.requirements)
237 .filter(move |requirement| {
238 requirement.evaluate_markers(env.marker_environment(), &[])
239 }),
240 ),
241 ),
242
243 DependencyMode::Direct => {
245 Either::Right(self.overrides.apply(self.requirements.iter()).filter(
246 move |requirement| requirement.evaluate_markers(env.marker_environment(), &[]),
247 ))
248 }
249 }
250 }
251
252 pub fn direct_requirements<'a>(
258 &'a self,
259 env: &'a ResolverEnvironment,
260 ) -> impl Iterator<Item = Cow<'a, Requirement>> + 'a {
261 self.overrides
262 .apply(self.requirements.iter())
263 .filter(move |requirement| requirement.evaluate_markers(env.marker_environment(), &[]))
264 }
265
266 pub fn apply<'a>(
271 &'a self,
272 requirements: impl IntoIterator<Item = &'a Requirement>,
273 ) -> impl Iterator<Item = Cow<'a, Requirement>> {
274 self.constraints.apply(self.overrides.apply(requirements))
275 }
276
277 pub fn num_requirements(&self) -> usize {
279 self.requirements.len()
280 }
281}