Skip to main content

uv_distribution_types/
cached.rs

1use std::path::Path;
2
3use uv_cache_info::CacheInfo;
4use uv_distribution_filename::WheelFilename;
5use uv_normalize::PackageName;
6use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
7
8use crate::{
9    BuildInfo, BuiltDist, Dist, DistributionMetadata, Hashed, InstalledMetadata, InstalledVersion,
10    Name, ParsedUrl, SourceDist, VersionId, VersionOrUrlRef,
11};
12
13/// A built distribution (wheel) that exists in the local cache.
14#[derive(Debug, Clone, Hash, PartialEq, Eq)]
15#[expect(clippy::large_enum_variant)]
16pub enum CachedDist {
17    /// The distribution exists in a registry, like `PyPI`.
18    Registry(CachedRegistryDist),
19    /// The distribution exists at an arbitrary URL.
20    Url(CachedDirectUrlDist),
21}
22
23#[derive(Debug, Clone, Hash, PartialEq, Eq)]
24pub struct CachedRegistryDist {
25    pub filename: WheelFilename,
26    pub path: Box<Path>,
27    pub hashes: HashDigests,
28    pub cache_info: CacheInfo,
29    pub build_info: Option<BuildInfo>,
30}
31
32#[derive(Debug, Clone, Hash, PartialEq, Eq)]
33pub struct CachedDirectUrlDist {
34    pub filename: WheelFilename,
35    pub url: VerbatimParsedUrl,
36    pub path: Box<Path>,
37    pub hashes: HashDigests,
38    pub cache_info: CacheInfo,
39    pub build_info: Option<BuildInfo>,
40}
41
42impl CachedDist {
43    /// Initialize a [`CachedDist`] from a [`Dist`].
44    pub fn from_remote(
45        remote: Dist,
46        filename: WheelFilename,
47        hashes: HashDigests,
48        cache_info: CacheInfo,
49        build_info: Option<BuildInfo>,
50        path: Box<Path>,
51    ) -> Self {
52        match remote {
53            Dist::Built(BuiltDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
54                filename,
55                path,
56                hashes,
57                cache_info,
58                build_info,
59            }),
60            Dist::Built(BuiltDist::DirectUrl(dist)) => Self::Url(CachedDirectUrlDist {
61                filename,
62                url: VerbatimParsedUrl {
63                    parsed_url: dist.parsed_url(),
64                    verbatim: dist.url,
65                },
66                hashes,
67                cache_info,
68                build_info,
69                path,
70            }),
71            Dist::Built(BuiltDist::Path(dist)) => Self::Url(CachedDirectUrlDist {
72                filename,
73                url: VerbatimParsedUrl {
74                    parsed_url: dist.parsed_url(),
75                    verbatim: dist.url,
76                },
77                hashes,
78                cache_info,
79                build_info,
80                path,
81            }),
82            Dist::Built(BuiltDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
83                filename,
84                url: VerbatimParsedUrl {
85                    parsed_url: dist.parsed_url(),
86                    verbatim: dist.url,
87                },
88                hashes,
89                cache_info,
90                build_info,
91                path,
92            }),
93            Dist::Source(SourceDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
94                filename,
95                path,
96                hashes,
97                cache_info,
98                build_info,
99            }),
100            Dist::Source(SourceDist::DirectUrl(dist)) => Self::Url(CachedDirectUrlDist {
101                filename,
102                url: VerbatimParsedUrl {
103                    parsed_url: dist.parsed_url(),
104                    verbatim: dist.url,
105                },
106                hashes,
107                cache_info,
108                build_info,
109                path,
110            }),
111            Dist::Source(SourceDist::GitDirectory(dist)) => Self::Url(CachedDirectUrlDist {
112                filename,
113                url: VerbatimParsedUrl {
114                    parsed_url: dist.parsed_url(),
115                    verbatim: dist.url,
116                },
117                hashes,
118                cache_info,
119                build_info,
120                path,
121            }),
122            Dist::Source(SourceDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
123                filename,
124                url: VerbatimParsedUrl {
125                    parsed_url: dist.parsed_url(),
126                    verbatim: dist.url,
127                },
128                hashes,
129                cache_info,
130                build_info,
131                path,
132            }),
133            Dist::Source(SourceDist::Path(dist)) => Self::Url(CachedDirectUrlDist {
134                filename,
135                url: VerbatimParsedUrl {
136                    parsed_url: dist.parsed_url(),
137                    verbatim: dist.url,
138                },
139                hashes,
140                cache_info,
141                build_info,
142                path,
143            }),
144            Dist::Source(SourceDist::Directory(dist)) => Self::Url(CachedDirectUrlDist {
145                filename,
146                url: VerbatimParsedUrl {
147                    parsed_url: dist.parsed_url(),
148                    verbatim: dist.url,
149                },
150                hashes,
151                cache_info,
152                build_info,
153                path,
154            }),
155        }
156    }
157
158    /// Return the [`Path`] at which the distribution is stored on-disk.
159    pub fn path(&self) -> &Path {
160        match self {
161            Self::Registry(dist) => &dist.path,
162            Self::Url(dist) => &dist.path,
163        }
164    }
165
166    /// Return the [`CacheInfo`] of the distribution.
167    pub fn cache_info(&self) -> &CacheInfo {
168        match self {
169            Self::Registry(dist) => &dist.cache_info,
170            Self::Url(dist) => &dist.cache_info,
171        }
172    }
173
174    /// Return the [`BuildInfo`] of the distribution.
175    pub fn build_info(&self) -> Option<&BuildInfo> {
176        match self {
177            Self::Registry(dist) => dist.build_info.as_ref(),
178            Self::Url(dist) => dist.build_info.as_ref(),
179        }
180    }
181
182    /// Return the [`ParsedUrl`] of the distribution, if it exists.
183    pub fn parsed_url(&self) -> Option<&ParsedUrl> {
184        match self {
185            Self::Registry(_) => None,
186            Self::Url(dist) => Some(&dist.url.parsed_url),
187        }
188    }
189
190    /// Returns the [`WheelFilename`] of the distribution.
191    pub fn filename(&self) -> &WheelFilename {
192        match self {
193            Self::Registry(dist) => &dist.filename,
194            Self::Url(dist) => &dist.filename,
195        }
196    }
197}
198
199impl Hashed for CachedRegistryDist {
200    fn hashes(&self) -> &[HashDigest] {
201        self.hashes.as_slice()
202    }
203}
204
205impl Name for CachedRegistryDist {
206    fn name(&self) -> &PackageName {
207        &self.filename.name
208    }
209}
210
211impl Name for CachedDirectUrlDist {
212    fn name(&self) -> &PackageName {
213        &self.filename.name
214    }
215}
216
217impl Name for CachedDist {
218    fn name(&self) -> &PackageName {
219        match self {
220            Self::Registry(dist) => dist.name(),
221            Self::Url(dist) => dist.name(),
222        }
223    }
224}
225
226impl DistributionMetadata for CachedRegistryDist {
227    fn version_or_url(&self) -> VersionOrUrlRef<'_> {
228        VersionOrUrlRef::Version(&self.filename.version)
229    }
230}
231
232impl DistributionMetadata for CachedDirectUrlDist {
233    fn version_or_url(&self) -> VersionOrUrlRef<'_> {
234        VersionOrUrlRef::Url(&self.url.verbatim)
235    }
236
237    fn version_id(&self) -> VersionId {
238        VersionId::from_parsed_url(&self.url.parsed_url)
239    }
240}
241
242impl DistributionMetadata for CachedDist {
243    fn version_or_url(&self) -> VersionOrUrlRef<'_> {
244        match self {
245            Self::Registry(dist) => dist.version_or_url(),
246            Self::Url(dist) => dist.version_or_url(),
247        }
248    }
249
250    fn version_id(&self) -> VersionId {
251        match self {
252            Self::Registry(dist) => dist.version_id(),
253            Self::Url(dist) => dist.version_id(),
254        }
255    }
256}
257
258impl InstalledMetadata for CachedRegistryDist {
259    fn installed_version(&self) -> InstalledVersion<'_> {
260        InstalledVersion::Version(&self.filename.version)
261    }
262}
263
264impl InstalledMetadata for CachedDirectUrlDist {
265    fn installed_version(&self) -> InstalledVersion<'_> {
266        InstalledVersion::Url(&self.url.verbatim, &self.filename.version)
267    }
268}
269
270impl InstalledMetadata for CachedDist {
271    fn installed_version(&self) -> InstalledVersion<'_> {
272        match self {
273            Self::Registry(dist) => dist.installed_version(),
274            Self::Url(dist) => dist.installed_version(),
275        }
276    }
277}