Skip to main content

uv_distribution_types/
resolved.rs

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, ResourceId, SourceDist, VersionId, VersionOrUrlRef,
12};
13
14/// A distribution that can be used for resolution and installation.
15///
16/// Either an already-installed distribution or a distribution that can be installed.
17#[derive(Debug, Clone, Hash)]
18pub enum ResolvedDist {
19    Installed {
20        dist: Arc<InstalledDist>,
21    },
22    Installable {
23        dist: Arc<Dist>,
24        version: Option<Version>,
25    },
26}
27
28impl ResolvedDist {
29    /// Return true if the distribution is editable.
30    pub fn is_editable(&self) -> bool {
31        match self {
32            Self::Installable { dist, .. } => dist.is_editable(),
33            Self::Installed { dist } => dist.is_editable(),
34        }
35    }
36
37    /// Return true if the distribution refers to a local file or directory.
38    pub fn is_local(&self) -> bool {
39        match self {
40            Self::Installable { dist, .. } => dist.is_local(),
41            Self::Installed { dist } => dist.is_local(),
42        }
43    }
44
45    /// Returns the [`IndexUrl`], if the distribution is from a registry.
46    pub fn index(&self) -> Option<&IndexUrl> {
47        match self {
48            Self::Installable { dist, .. } => dist.index(),
49            Self::Installed { .. } => None,
50        }
51    }
52
53    /// Returns the [`Yanked`] status of the distribution, if available.
54    pub fn yanked(&self) -> Option<&Yanked> {
55        match self {
56            Self::Installable { dist, .. } => match dist.as_ref() {
57                Dist::Source(SourceDist::Registry(sdist)) => sdist.file.yanked.as_deref(),
58                Dist::Built(BuiltDist::Registry(wheel)) => {
59                    wheel.best_wheel().file.yanked.as_deref()
60                }
61                _ => None,
62            },
63            Self::Installed { .. } => None,
64        }
65    }
66
67    /// Returns the version of the distribution, if available.
68    pub fn version(&self) -> Option<&Version> {
69        match self {
70            Self::Installable { version, dist } => dist.version().or(version.as_ref()),
71            Self::Installed { dist } => Some(dist.version()),
72        }
73    }
74
75    /// Return the source tree of the distribution, if available.
76    pub fn source_tree(&self) -> Option<&Path> {
77        match self {
78            Self::Installable { dist, .. } => dist.source_tree(),
79            Self::Installed { .. } => None,
80        }
81    }
82}
83
84impl Name for ResolvedDist {
85    fn name(&self) -> &PackageName {
86        match self {
87            Self::Installable { dist, .. } => dist.name(),
88            Self::Installed { dist } => dist.name(),
89        }
90    }
91}
92
93impl DistributionMetadata for ResolvedDist {
94    fn version_or_url(&self) -> VersionOrUrlRef<'_> {
95        match self {
96            Self::Installed { dist } => dist.version_or_url(),
97            Self::Installable { dist, .. } => dist.version_or_url(),
98        }
99    }
100
101    fn version_id(&self) -> VersionId {
102        match self {
103            Self::Installed { dist } => dist.version_id(),
104            Self::Installable { dist, .. } => dist.version_id(),
105        }
106    }
107}
108
109impl Identifier for ResolvedDist {
110    fn distribution_id(&self) -> DistributionId {
111        match self {
112            Self::Installed { dist } => dist.distribution_id(),
113            Self::Installable { dist, .. } => dist.distribution_id(),
114        }
115    }
116
117    fn resource_id(&self) -> ResourceId {
118        match self {
119            Self::Installed { dist } => dist.resource_id(),
120            Self::Installable { dist, .. } => dist.resource_id(),
121        }
122    }
123}
124
125impl Display for ResolvedDist {
126    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
127        match self {
128            Self::Installed { dist } => dist.fmt(f),
129            Self::Installable { dist, .. } => dist.fmt(f),
130        }
131    }
132}