1use std::borrow::Cow;
2use std::path::Path;
3
4use uv_distribution_filename::SourceDistExtension;
5use uv_git_types::GitUrl;
6use uv_pep440::{Version, VersionSpecifiers};
7use uv_pep508::VerbatimUrl;
8
9use uv_normalize::PackageName;
10use uv_redacted::DisplaySafeUrl;
11
12use crate::{
13 DirectorySourceDist, GitDirectorySourceDist, GitPathSourceDist, Name, PathSourceDist,
14 SourceDist,
15};
16
17#[derive(Debug, Clone)]
24pub enum BuildableSource<'a> {
25 Dist(&'a SourceDist),
26 Url(SourceUrl<'a>),
27}
28
29impl BuildableSource<'_> {
30 pub fn name(&self) -> Option<&PackageName> {
32 match self {
33 Self::Dist(dist) => Some(dist.name()),
34 Self::Url(_) => None,
35 }
36 }
37
38 pub fn source_tree(&self) -> Option<&Path> {
40 match self {
41 Self::Dist(dist) => dist.source_tree(),
42 Self::Url(url) => url.source_tree(),
43 }
44 }
45
46 pub fn version(&self) -> Option<&Version> {
48 match self {
49 Self::Dist(SourceDist::Registry(dist)) => Some(&dist.version),
50 Self::Dist(SourceDist::Path(dist)) => dist.version.as_ref(),
51 Self::Dist(_) => None,
52 Self::Url(_) => None,
53 }
54 }
55
56 pub fn as_dist(&self) -> Option<&SourceDist> {
58 match self {
59 Self::Dist(dist) => Some(dist),
60 Self::Url(_) => None,
61 }
62 }
63
64 pub fn is_editable(&self) -> bool {
66 match self {
67 Self::Dist(dist) => dist.is_editable(),
68 Self::Url(url) => url.is_editable(),
69 }
70 }
71
72 pub fn is_first_party(&self) -> bool {
74 match self {
75 Self::Dist(dist) => dist.is_first_party(),
76 Self::Url(_) => false,
77 }
78 }
79
80 pub fn is_source_tree(&self) -> bool {
82 match self {
83 Self::Dist(dist) => matches!(dist, SourceDist::Directory(_)),
84 Self::Url(url) => matches!(url, SourceUrl::Directory(_)),
85 }
86 }
87
88 pub fn requires_python(&self) -> Option<&VersionSpecifiers> {
90 let Self::Dist(SourceDist::Registry(dist)) = self else {
91 return None;
92 };
93 dist.file.requires_python.as_deref()
94 }
95}
96
97impl std::fmt::Display for BuildableSource<'_> {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match self {
100 Self::Dist(dist) => write!(f, "{dist}"),
101 Self::Url(url) => write!(f, "{url}"),
102 }
103 }
104}
105
106#[derive(Debug, Clone)]
108pub enum SourceUrl<'a> {
109 Direct(DirectSourceUrl<'a>),
110 GitDirectory(GitDirectorySourceUrl<'a>),
111 GitPath(GitPathSourceUrl<'a>),
112 Path(PathSourceUrl<'a>),
113 Directory(DirectorySourceUrl<'a>),
114}
115
116impl SourceUrl<'_> {
117 pub fn url(&self) -> &DisplaySafeUrl {
119 match self {
120 Self::Direct(dist) => dist.url,
121 Self::GitDirectory(dist) => dist.url,
122 Self::GitPath(dist) => dist.url,
123 Self::Path(dist) => dist.url,
124 Self::Directory(dist) => dist.url,
125 }
126 }
127
128 fn source_tree(&self) -> Option<&Path> {
130 match self {
131 Self::Directory(dist) => Some(dist.install_path),
132 _ => None,
133 }
134 }
135
136 fn is_editable(&self) -> bool {
138 matches!(
139 self,
140 Self::Directory(DirectorySourceUrl {
141 editable: Some(true),
142 ..
143 })
144 )
145 }
146}
147
148impl std::fmt::Display for SourceUrl<'_> {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 match self {
151 Self::Direct(url) => write!(f, "{url}"),
152 Self::GitDirectory(url) => write!(f, "{url}"),
153 Self::GitPath(url) => write!(f, "{url}"),
154 Self::Path(url) => write!(f, "{url}"),
155 Self::Directory(url) => write!(f, "{url}"),
156 }
157 }
158}
159
160#[derive(Debug, Clone)]
161pub struct DirectSourceUrl<'a> {
162 pub url: &'a DisplaySafeUrl,
163 pub subdirectory: Option<&'a Path>,
164 pub ext: SourceDistExtension,
165}
166
167impl std::fmt::Display for DirectSourceUrl<'_> {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(f, "{url}", url = self.url)
170 }
171}
172
173#[derive(Debug, Clone)]
174pub struct GitPathSourceUrl<'a> {
175 pub url: &'a VerbatimUrl,
177 pub git: &'a GitUrl,
178 pub path: Cow<'a, Path>,
179 pub ext: SourceDistExtension,
180}
181
182impl std::fmt::Display for GitPathSourceUrl<'_> {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 write!(f, "{url}", url = self.url)
185 }
186}
187
188impl<'a> From<&'a GitPathSourceDist> for GitPathSourceUrl<'a> {
189 fn from(dist: &'a GitPathSourceDist) -> Self {
190 Self {
191 url: &dist.url,
192 git: &dist.git,
193 path: Cow::Borrowed(&dist.install_path),
194 ext: dist.ext,
195 }
196 }
197}
198
199#[derive(Debug, Clone)]
200pub struct GitDirectorySourceUrl<'a> {
201 pub url: &'a VerbatimUrl,
203 pub git: &'a GitUrl,
204 pub subdirectory: Option<&'a Path>,
206}
207
208impl std::fmt::Display for GitDirectorySourceUrl<'_> {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 write!(f, "{url}", url = self.url)
211 }
212}
213
214impl<'a> From<&'a GitDirectorySourceDist> for GitDirectorySourceUrl<'a> {
215 fn from(dist: &'a GitDirectorySourceDist) -> Self {
216 Self {
217 url: &dist.url,
218 git: &dist.git,
219 subdirectory: dist.subdirectory.as_deref(),
220 }
221 }
222}
223
224#[derive(Debug, Clone)]
225pub struct PathSourceUrl<'a> {
226 pub url: &'a DisplaySafeUrl,
227 pub path: Cow<'a, Path>,
228 pub ext: SourceDistExtension,
229}
230
231impl std::fmt::Display for PathSourceUrl<'_> {
232 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233 write!(f, "{url}", url = self.url)
234 }
235}
236
237impl<'a> From<&'a PathSourceDist> for PathSourceUrl<'a> {
238 fn from(dist: &'a PathSourceDist) -> Self {
239 Self {
240 url: &dist.url,
241 path: Cow::Borrowed(&dist.install_path),
242 ext: dist.ext,
243 }
244 }
245}
246
247#[derive(Debug, Clone)]
248pub struct DirectorySourceUrl<'a> {
249 pub url: &'a DisplaySafeUrl,
250 pub install_path: &'a Path,
251 pub editable: Option<bool>,
252}
253
254impl std::fmt::Display for DirectorySourceUrl<'_> {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 write!(f, "{url}", url = self.url)
257 }
258}
259
260impl<'a> From<&'a DirectorySourceDist> for DirectorySourceUrl<'a> {
261 fn from(dist: &'a DirectorySourceDist) -> Self {
262 Self {
263 url: &dist.url,
264 install_path: &dist.install_path,
265 editable: dist.editable,
266 }
267 }
268}