Rebase: Uninstall existing non-editable versions when installing editable requirements bug (#682)

Separate branch for rebasing #677 onto main because i don't trust the
rebase enough to force push.

Closes #677.

---

If you install `black` from PyPI, then `-e ../black`, we need to
uninstall the existing `black`. This sounds simple, but that in turn
requires that we _know_ `-e ../black` maps to the package `black`, so
that we can mark it for uninstallation in the install plan. This, in
turn, means that we need to build editable dependencies prior to the
install plan.

This is just a bunch of reorganization to fix that specific bug
(installing multiple versions of `black` if you run through the above
workflow): we now run through the list of editables upfront, mark those
that are already installed, build those that aren't, and then ensure
that `InstallPlan` correctly removes those that need to be removed, etc.

Closes #676.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
konsti
2023-12-18 10:28:14 +01:00
committed by GitHub
parent 0bb2c92246
commit f4f67ebde0
13 changed files with 626 additions and 279 deletions
@@ -2,7 +2,6 @@ use rustc_hash::FxHashMap;
use pep508_rs::Requirement;
use puffin_normalize::PackageName;
use requirements_txt::EditableRequirement;
use crate::{BuiltDist, Dist, PathSourceDist, SourceDist};
@@ -60,31 +59,6 @@ impl Resolution {
requirements.sort_unstable_by(|a, b| a.name.cmp(&b.name));
requirements
}
/// Return the set of [`EditableRequirement`]s that this resolution represents.
pub fn editable_requirements(&self) -> Vec<EditableRequirement> {
let mut requirements = self
.0
.values()
.filter_map(|dist| {
let Dist::Source(SourceDist::Path(PathSourceDist {
url,
path,
editable: true,
..
})) = dist
else {
return None;
};
Some(EditableRequirement::Path {
path: path.clone(),
url: url.clone(),
})
})
.collect::<Vec<_>>();
requirements.sort_unstable_by(|a, b| a.url().cmp(b.url()));
requirements
}
}
impl From<Dist> for Requirement {