Skip to content

Commit 36e4181

Browse files
committed
Catch versions incoherences from source dists only
1 parent a1fa5b8 commit 36e4181

File tree

9 files changed

+64
-8
lines changed

9 files changed

+64
-8
lines changed

crates/uv-distribution-types/src/buildable.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,13 @@ impl BuildableSource<'_> {
3737
match self {
3838
Self::Dist(SourceDist::Registry(dist)) => Some(&dist.version),
3939
Self::Dist(SourceDist::Path(dist)) => dist.version.as_ref(),
40-
Self::Dist(_) => None,
41-
Self::Url(_) => None,
40+
Self::Dist(SourceDist::Directory(dist)) => dist.version.as_ref(),
41+
Self::Dist(SourceDist::Git(dist)) => dist.version.as_ref(),
42+
Self::Dist(SourceDist::DirectUrl(dist)) => dist.version.as_ref(),
43+
Self::Url(SourceUrl::Git(url)) => url.version,
44+
Self::Url(SourceUrl::Direct(url)) => url.version,
45+
Self::Url(SourceUrl::Path(url)) => url.version,
46+
Self::Url(SourceUrl::Directory(url)) => url.version,
4247
}
4348
}
4449

@@ -132,6 +137,7 @@ impl std::fmt::Display for SourceUrl<'_> {
132137
#[derive(Debug, Clone)]
133138
pub struct DirectSourceUrl<'a> {
134139
pub url: &'a Url,
140+
pub version: Option<&'a Version>,
135141
pub subdirectory: Option<&'a Path>,
136142
pub ext: SourceDistExtension,
137143
}
@@ -146,6 +152,7 @@ impl std::fmt::Display for DirectSourceUrl<'_> {
146152
pub struct GitSourceUrl<'a> {
147153
/// The URL with the revision and subdirectory fragment.
148154
pub url: &'a VerbatimUrl,
155+
pub version: Option<&'a Version>,
149156
pub git: &'a GitUrl,
150157
/// The URL without the revision and subdirectory fragment.
151158
pub subdirectory: Option<&'a Path>,
@@ -161,6 +168,7 @@ impl<'a> From<&'a GitSourceDist> for GitSourceUrl<'a> {
161168
fn from(dist: &'a GitSourceDist) -> Self {
162169
Self {
163170
url: &dist.url,
171+
version: dist.version.as_ref(),
164172
git: &dist.git,
165173
subdirectory: dist.subdirectory.as_deref(),
166174
}
@@ -170,6 +178,7 @@ impl<'a> From<&'a GitSourceDist> for GitSourceUrl<'a> {
170178
#[derive(Debug, Clone)]
171179
pub struct PathSourceUrl<'a> {
172180
pub url: &'a Url,
181+
pub version: Option<&'a Version>,
173182
pub path: Cow<'a, Path>,
174183
pub ext: SourceDistExtension,
175184
}
@@ -184,6 +193,7 @@ impl<'a> From<&'a PathSourceDist> for PathSourceUrl<'a> {
184193
fn from(dist: &'a PathSourceDist) -> Self {
185194
Self {
186195
url: &dist.url,
196+
version: dist.version.as_ref(),
187197
path: Cow::Borrowed(&dist.install_path),
188198
ext: dist.ext,
189199
}
@@ -193,6 +203,7 @@ impl<'a> From<&'a PathSourceDist> for PathSourceUrl<'a> {
193203
#[derive(Debug, Clone)]
194204
pub struct DirectorySourceUrl<'a> {
195205
pub url: &'a Url,
206+
pub version: Option<&'a Version>,
196207
pub install_path: Cow<'a, Path>,
197208
pub editable: bool,
198209
}
@@ -207,6 +218,7 @@ impl<'a> From<&'a DirectorySourceDist> for DirectorySourceUrl<'a> {
207218
fn from(dist: &'a DirectorySourceDist) -> Self {
208219
Self {
209220
url: &dist.url,
221+
version: dist.version.as_ref(),
210222
install_path: Cow::Borrowed(&dist.install_path),
211223
editable: dist.editable,
212224
}

crates/uv-distribution-types/src/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ pub struct DirectUrlSourceDist {
294294
/// Unlike [`DirectUrlBuiltDist`], we can't require a full filename with a version here, people
295295
/// like using e.g. `foo @ https://github.com/org/repo/archive/master.zip`
296296
pub name: PackageName,
297+
/// The expected version, if known.
298+
pub version: Option<Version>,
297299
/// The URL without the subdirectory fragment.
298300
pub location: Box<Url>,
299301
/// The subdirectory within the archive in which the source distribution is located.
@@ -308,6 +310,8 @@ pub struct DirectUrlSourceDist {
308310
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
309311
pub struct GitSourceDist {
310312
pub name: PackageName,
313+
/// The expected version, if known.
314+
pub version: Option<Version>,
311315
/// The URL without the revision and subdirectory fragment.
312316
pub git: Box<GitUrl>,
313317
/// The subdirectory within the Git repository in which the source distribution is located.
@@ -333,6 +337,8 @@ pub struct PathSourceDist {
333337
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
334338
pub struct DirectorySourceDist {
335339
pub name: PackageName,
340+
/// The expected version, if known.
341+
pub version: Option<Version>,
336342
/// The absolute path to the distribution which we use for installing.
337343
pub install_path: PathBuf,
338344
/// Whether the package should be installed in editable mode.
@@ -374,6 +380,7 @@ impl Dist {
374380
DistExtension::Source(ext) => {
375381
Ok(Self::Source(SourceDist::DirectUrl(DirectUrlSourceDist {
376382
name,
383+
version: None,
377384
location: Box::new(location),
378385
subdirectory,
379386
ext,
@@ -462,6 +469,7 @@ impl Dist {
462469
// Determine whether the path represents an archive or a directory.
463470
Ok(Self::Source(SourceDist::Directory(DirectorySourceDist {
464471
name,
472+
version: None,
465473
install_path,
466474
editable,
467475
r#virtual,
@@ -478,6 +486,7 @@ impl Dist {
478486
) -> Result<Dist, Error> {
479487
Ok(Self::Source(SourceDist::Git(GitSourceDist {
480488
name,
489+
version: None,
481490
git: Box::new(git),
482491
subdirectory,
483492
url,

crates/uv-distribution/src/source/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
138138
source,
139139
&PathSourceUrl {
140140
url: &url,
141+
version: Some(&dist.version),
141142
path: Cow::Owned(path),
142143
ext: dist.ext,
143144
},
@@ -287,6 +288,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
287288
source,
288289
&PathSourceUrl {
289290
url: &url,
291+
version: Some(&dist.version),
290292
path: Cow::Owned(path),
291293
ext: dist.ext,
292294
},

crates/uv-installer/src/plan.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,11 @@ impl<'a> Planner<'a> {
264264
// Find the most-compatible wheel from the cache, since we don't know
265265
// the filename in advance.
266266
if let Some(wheel) = built_index.url(sdist)? {
267-
if wheel.filename.name == sdist.name {
267+
if wheel.filename.name == sdist.name
268+
&& dist
269+
.version()
270+
.is_some_and(|version| version == &wheel.filename.version)
271+
{
268272
let cached_dist = wheel.into_url_dist(sdist);
269273
debug!("URL source requirement already cached: {cached_dist}");
270274
cached.push(CachedDist::Url(cached_dist));
@@ -282,7 +286,11 @@ impl<'a> Planner<'a> {
282286
// Find the most-compatible wheel from the cache, since we don't know
283287
// the filename in advance.
284288
if let Some(wheel) = built_index.git(sdist) {
285-
if wheel.filename.name == sdist.name {
289+
if wheel.filename.name == sdist.name
290+
&& dist
291+
.version()
292+
.is_some_and(|version| version == &wheel.filename.version)
293+
{
286294
let cached_dist = wheel.into_git_dist(sdist);
287295
debug!("Git source requirement already cached: {cached_dist}");
288296
cached.push(CachedDist::Url(cached_dist));
@@ -305,7 +313,11 @@ impl<'a> Planner<'a> {
305313
// Find the most-compatible wheel from the cache, since we don't know
306314
// the filename in advance.
307315
if let Some(wheel) = built_index.path(sdist)? {
308-
if wheel.filename.name == sdist.name {
316+
if wheel.filename.name == sdist.name
317+
&& dist
318+
.version()
319+
.is_some_and(|version| version == &wheel.filename.version)
320+
{
309321
let cached_dist = wheel.into_path_dist(sdist);
310322
debug!("Path source requirement already cached: {cached_dist}");
311323
cached.push(CachedDist::Url(cached_dist));
@@ -328,7 +340,11 @@ impl<'a> Planner<'a> {
328340
// Find the most-compatible wheel from the cache, since we don't know
329341
// the filename in advance.
330342
if let Some(wheel) = built_index.directory(sdist)? {
331-
if wheel.filename.name == sdist.name {
343+
if wheel.filename.name == sdist.name
344+
&& dist
345+
.version()
346+
.is_some_and(|version| version == &wheel.filename.version)
347+
{
332348
let cached_dist = wheel.into_directory_dist(sdist);
333349
debug!("Directory source requirement already cached: {cached_dist}");
334350
cached.push(CachedDist::Url(cached_dist));

crates/uv-requirements/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub(crate) fn required_dist(
6262
url,
6363
} => Dist::Source(SourceDist::Git(GitSourceDist {
6464
name: requirement.name.clone(),
65+
version: None,
6566
git: Box::new(git.clone()),
6667
subdirectory: subdirectory.clone(),
6768
url: url.clone(),

crates/uv-requirements/src/source_tree.rs

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
176176
};
177177
let source = SourceUrl::Directory(DirectorySourceUrl {
178178
url: &url,
179+
version: None,
179180
install_path: Cow::Borrowed(source_tree),
180181
editable: false,
181182
});

crates/uv-requirements/src/unnamed.rs

+4
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> {
238238

239239
SourceUrl::Directory(DirectorySourceUrl {
240240
url: &requirement.url.verbatim,
241+
version: None,
241242
install_path: Cow::Borrowed(&parsed_directory_url.install_path),
242243
editable: parsed_directory_url.editable,
243244
})
@@ -249,6 +250,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> {
249250
};
250251
SourceUrl::Path(PathSourceUrl {
251252
url: &requirement.url.verbatim,
253+
version: None,
252254
path: Cow::Borrowed(&parsed_path_url.install_path),
253255
ext,
254256
})
@@ -260,12 +262,14 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> {
260262
};
261263
SourceUrl::Direct(DirectSourceUrl {
262264
url: &parsed_archive_url.url,
265+
version: None,
263266
subdirectory: parsed_archive_url.subdirectory.as_deref(),
264267
ext,
265268
})
266269
}
267270
ParsedUrl::Git(parsed_git_url) => SourceUrl::Git(GitSourceUrl {
268271
url: &requirement.url.verbatim,
272+
version: None,
269273
git: &parsed_git_url.url,
270274
subdirectory: parsed_git_url.subdirectory.as_deref(),
271275
}),

crates/uv-resolver/src/lock/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,7 @@ impl Package {
23362336
let install_path = absolute_path(workspace_root, path)?;
23372337
let dir_dist = DirectorySourceDist {
23382338
name: self.id.name.clone(),
2339+
version: self.id.version.clone(),
23392340
url: verbatim_url(&install_path, &self.id)?,
23402341
install_path,
23412342
editable: false,
@@ -2347,6 +2348,7 @@ impl Package {
23472348
let install_path = absolute_path(workspace_root, path)?;
23482349
let dir_dist = DirectorySourceDist {
23492350
name: self.id.name.clone(),
2351+
version: self.id.version.clone(),
23502352
url: verbatim_url(&install_path, &self.id)?,
23512353
install_path,
23522354
editable: true,
@@ -2358,6 +2360,7 @@ impl Package {
23582360
let install_path = absolute_path(workspace_root, path)?;
23592361
let dir_dist = DirectorySourceDist {
23602362
name: self.id.name.clone(),
2363+
version: self.id.version.clone(),
23612364
url: verbatim_url(&install_path, &self.id)?,
23622365
install_path,
23632366
editable: false,
@@ -2387,6 +2390,7 @@ impl Package {
23872390

23882391
let git_dist = GitSourceDist {
23892392
name: self.id.name.clone(),
2393+
version: self.id.version.clone(),
23902394
url: VerbatimUrl::from_url(url),
23912395
git: Box::new(git_url),
23922396
subdirectory: git.subdirectory.clone(),
@@ -2407,6 +2411,7 @@ impl Package {
24072411
});
24082412
let direct_dist = DirectUrlSourceDist {
24092413
name: self.id.name.clone(),
2414+
version: self.id.version.clone(),
24102415
location: Box::new(location),
24112416
subdirectory: subdirectory.clone(),
24122417
ext,

crates/uv/src/commands/project/sync.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -742,11 +742,16 @@ fn apply_editable_mode(resolution: Resolution, editable: EditableMode) -> Resolu
742742

743743
// Filter out any editable distributions.
744744
EditableMode::NonEditable => resolution.map(|dist| {
745-
let ResolvedDist::Installable { dist, version } = dist else {
745+
let ResolvedDist::Installable {
746+
dist,
747+
version: installable_version,
748+
} = dist
749+
else {
746750
return None;
747751
};
748752
let Dist::Source(SourceDist::Directory(DirectorySourceDist {
749753
name,
754+
version,
750755
install_path,
751756
editable: true,
752757
r#virtual: false,
@@ -759,12 +764,13 @@ fn apply_editable_mode(resolution: Resolution, editable: EditableMode) -> Resolu
759764
Some(ResolvedDist::Installable {
760765
dist: Arc::new(Dist::Source(SourceDist::Directory(DirectorySourceDist {
761766
name: name.clone(),
767+
version: version.clone(),
762768
install_path: install_path.clone(),
763769
editable: false,
764770
r#virtual: false,
765771
url: url.clone(),
766772
}))),
767-
version: version.clone(),
773+
version: installable_version.clone(),
768774
})
769775
}),
770776
}

0 commit comments

Comments
 (0)