1use std::fmt::{Display, Formatter};
2use std::path::Path;
3use std::sync::Arc;
4
5use uv_normalize::PackageName;
6use uv_pep440::Version;
7use uv_pypi_types::Yanked;
8
9use crate::{
10 BuiltDist, Dist, DistributionId, DistributionMetadata, Identifier, IndexUrl, InstalledDist,
11 Name, PrioritizedDist, RegistryBuiltWheel, RegistrySourceDist, ResourceId, SourceDist,
12 VersionOrUrlRef,
13};
14
15#[derive(Debug, Clone, Hash)]
19pub enum ResolvedDist {
20 Installed {
21 dist: Arc<InstalledDist>,
22 },
23 Installable {
24 dist: Arc<Dist>,
25 version: Option<Version>,
26 },
27}
28
29#[derive(Debug, Clone)]
31pub enum ResolvedDistRef<'a> {
32 Installed {
33 dist: &'a InstalledDist,
34 },
35 InstallableRegistrySourceDist {
36 sdist: &'a RegistrySourceDist,
38 prioritized: &'a PrioritizedDist,
40 },
41 InstallableRegistryBuiltDist {
42 wheel: &'a RegistryBuiltWheel,
44 prioritized: &'a PrioritizedDist,
46 },
47}
48
49impl ResolvedDist {
50 pub fn is_editable(&self) -> bool {
52 match self {
53 Self::Installable { dist, .. } => dist.is_editable(),
54 Self::Installed { dist } => dist.is_editable(),
55 }
56 }
57
58 pub fn is_local(&self) -> bool {
60 match self {
61 Self::Installable { dist, .. } => dist.is_local(),
62 Self::Installed { dist } => dist.is_local(),
63 }
64 }
65
66 pub fn index(&self) -> Option<&IndexUrl> {
68 match self {
69 Self::Installable { dist, .. } => dist.index(),
70 Self::Installed { .. } => None,
71 }
72 }
73
74 pub fn yanked(&self) -> Option<&Yanked> {
76 match self {
77 Self::Installable { dist, .. } => match dist.as_ref() {
78 Dist::Source(SourceDist::Registry(sdist)) => sdist.file.yanked.as_deref(),
79 Dist::Built(BuiltDist::Registry(wheel)) => {
80 wheel.best_wheel().file.yanked.as_deref()
81 }
82 _ => None,
83 },
84 Self::Installed { .. } => None,
85 }
86 }
87
88 pub fn version(&self) -> Option<&Version> {
90 match self {
91 Self::Installable { version, dist } => dist.version().or(version.as_ref()),
92 Self::Installed { dist } => Some(dist.version()),
93 }
94 }
95
96 pub fn source_tree(&self) -> Option<&Path> {
98 match self {
99 Self::Installable { dist, .. } => dist.source_tree(),
100 Self::Installed { .. } => None,
101 }
102 }
103}
104
105impl ResolvedDistRef<'_> {
106 pub fn to_owned(&self) -> ResolvedDist {
107 match self {
108 Self::InstallableRegistrySourceDist { sdist, prioritized } => {
109 let source = prioritized.source_dist().expect("a source distribution");
112 assert_eq!(
113 (&sdist.name, &sdist.version),
114 (&source.name, &source.version),
115 "expected chosen sdist to match prioritized sdist"
116 );
117 ResolvedDist::Installable {
118 dist: Arc::new(Dist::Source(SourceDist::Registry(source))),
119 version: Some(sdist.version.clone()),
120 }
121 }
122 Self::InstallableRegistryBuiltDist {
123 wheel, prioritized, ..
124 } => {
125 assert_eq!(
126 Some(&wheel.filename),
127 prioritized.best_wheel().map(|(wheel, _)| &wheel.filename),
128 "expected chosen wheel to match best wheel"
129 );
130 let built = prioritized.built_dist().expect("at least one wheel");
133 ResolvedDist::Installable {
134 dist: Arc::new(Dist::Built(BuiltDist::Registry(built))),
135 version: Some(wheel.filename.version.clone()),
136 }
137 }
138 Self::Installed { dist } => ResolvedDist::Installed {
139 dist: Arc::new((*dist).clone()),
140 },
141 }
142 }
143
144 pub fn index(&self) -> Option<&IndexUrl> {
146 match self {
147 Self::InstallableRegistrySourceDist { sdist, .. } => Some(&sdist.index),
148 Self::InstallableRegistryBuiltDist { wheel, .. } => Some(&wheel.index),
149 Self::Installed { .. } => None,
150 }
151 }
152}
153
154impl Display for ResolvedDistRef<'_> {
155 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
156 match self {
157 Self::InstallableRegistrySourceDist { sdist, .. } => Display::fmt(sdist, f),
158 Self::InstallableRegistryBuiltDist { wheel, .. } => Display::fmt(wheel, f),
159 Self::Installed { dist } => Display::fmt(dist, f),
160 }
161 }
162}
163
164impl Name for ResolvedDistRef<'_> {
165 fn name(&self) -> &PackageName {
166 match self {
167 Self::InstallableRegistrySourceDist { sdist, .. } => sdist.name(),
168 Self::InstallableRegistryBuiltDist { wheel, .. } => wheel.name(),
169 Self::Installed { dist } => dist.name(),
170 }
171 }
172}
173
174impl DistributionMetadata for ResolvedDistRef<'_> {
175 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
176 match self {
177 Self::Installed { dist } => VersionOrUrlRef::Version(dist.version()),
178 Self::InstallableRegistrySourceDist { sdist, .. } => sdist.version_or_url(),
179 Self::InstallableRegistryBuiltDist { wheel, .. } => wheel.version_or_url(),
180 }
181 }
182}
183
184impl Identifier for ResolvedDistRef<'_> {
185 fn distribution_id(&self) -> DistributionId {
186 match self {
187 Self::Installed { dist } => dist.distribution_id(),
188 Self::InstallableRegistrySourceDist { sdist, .. } => sdist.distribution_id(),
189 Self::InstallableRegistryBuiltDist { wheel, .. } => wheel.distribution_id(),
190 }
191 }
192
193 fn resource_id(&self) -> ResourceId {
194 match self {
195 Self::Installed { dist } => dist.resource_id(),
196 Self::InstallableRegistrySourceDist { sdist, .. } => sdist.resource_id(),
197 Self::InstallableRegistryBuiltDist { wheel, .. } => wheel.resource_id(),
198 }
199 }
200}
201
202impl Name for ResolvedDist {
203 fn name(&self) -> &PackageName {
204 match self {
205 Self::Installable { dist, .. } => dist.name(),
206 Self::Installed { dist } => dist.name(),
207 }
208 }
209}
210
211impl DistributionMetadata for ResolvedDist {
212 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
213 match self {
214 Self::Installed { dist } => dist.version_or_url(),
215 Self::Installable { dist, .. } => dist.version_or_url(),
216 }
217 }
218}
219
220impl Identifier for ResolvedDist {
221 fn distribution_id(&self) -> DistributionId {
222 match self {
223 Self::Installed { dist } => dist.distribution_id(),
224 Self::Installable { dist, .. } => dist.distribution_id(),
225 }
226 }
227
228 fn resource_id(&self) -> ResourceId {
229 match self {
230 Self::Installed { dist } => dist.resource_id(),
231 Self::Installable { dist, .. } => dist.resource_id(),
232 }
233 }
234}
235
236impl Display for ResolvedDist {
237 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
238 match self {
239 Self::Installed { dist } => dist.fmt(f),
240 Self::Installable { dist, .. } => dist.fmt(f),
241 }
242 }
243}