Track Markers via a PubGrub package variant (#4123)

## Summary

This PR adds a lowering similar to that seen in
https://github.com/astral-sh/uv/pull/3100, but this time, for markers.
Like `PubGrubPackageInner::Extra`, we now have
`PubGrubPackageInner::Marker`. The dependencies of the `Marker` are
`PubGrubPackageInner::Package` with and without the marker.

As an example of why this is useful: assume we have `urllib3>=1.22.0` as
a direct dependency. Later, we see `urllib3 ; python_version > '3.7'` as
a transitive dependency. As-is, we might (for some reason) pick a very
old version of `urllib3` to satisfy `urllib3 ; python_version > '3.7'`,
then attempt to fetch its dependencies, which could even involve
building a very old version of `urllib3 ; python_version > '3.7'`. Once
we fetch the dependencies, we would see that `urllib3` at the same
version is _also_ a dependency (because we tack it on). In the new
scheme though, as soon as we "choose" the very old version of `urllib3 ;
python_version > '3.7'`, we'd then see that `urllib3` (the base package)
is also a dependency; so we see a conflict before we even fetch the
dependencies of the old variant.

With this, I can successfully resolve the case in #4099.

Closes https://github.com/astral-sh/uv/issues/4099.
This commit is contained in:
Charlie Marsh
2024-06-07 12:57:02 -07:00
committed by GitHub
parent 0f4f3b4714
commit bcfe88dfdc
7 changed files with 233 additions and 129 deletions
@@ -57,7 +57,7 @@ impl BatchPrefetcher {
name,
extra: None,
dev: None,
marker: _marker,
marker: None,
url: None,
} = &**next
else {
@@ -166,11 +166,15 @@ impl BatchPrefetcher {
// Only track base packages, no virtual packages from extras.
if matches!(
&*package,
PubGrubPackageInner::Package { extra: Some(_), .. }
PubGrubPackageInner::Package {
extra: None,
dev: None,
marker: None,
..
}
) {
return;
*self.tried_versions.entry(package).or_default() += 1;
}
*self.tried_versions.entry(package).or_default() += 1;
}
/// After 5, 10, 20, 40 tried versions, prefetch that many versions to start early but not