Skip to content

Commit

Permalink
fix: Make path dependencies with the same name stays locked
Browse files Browse the repository at this point in the history
  • Loading branch information
linyihai committed Mar 11, 2024
1 parent a15a507 commit c07cf47
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
72 changes: 59 additions & 13 deletions src/cargo/core/resolver/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,11 @@ impl EncodableResolve {
if !all_pkgs.insert(enc_id.clone()) {
anyhow::bail!("package `{}` is specified twice in the lockfile", pkg.name);
}
let id = match pkg.source.as_deref().or_else(|| path_deps.get(&pkg.name)) {
let id = match pkg
.source
.as_deref()
.or_else(|| get_source_id(&path_deps, pkg))
{
// We failed to find a local package in the workspace.
// It must have been removed and should be ignored.
None => {
Expand Down Expand Up @@ -364,7 +368,11 @@ impl EncodableResolve {

let mut unused_patches = Vec::new();
for pkg in self.patch.unused {
let id = match pkg.source.as_deref().or_else(|| path_deps.get(&pkg.name)) {
let id = match pkg
.source
.as_deref()
.or_else(|| get_source_id(&path_deps, &pkg))
{
Some(&src) => PackageId::try_new(&pkg.name, &pkg.version, src)?,
None => continue,
};
Expand Down Expand Up @@ -395,7 +403,7 @@ impl EncodableResolve {
version = ResolveVersion::V2;
}

Ok(Resolve::new(
return Ok(Resolve::new(
g,
replacements,
HashMap::new(),
Expand All @@ -404,11 +412,42 @@ impl EncodableResolve {
unused_patches,
version,
HashMap::new(),
))
));

fn get_source_id<'a>(
path_deps: &'a HashMap<String, HashMap<semver::Version, SourceId>>,
pkg: &'a EncodableDependency,
) -> Option<&'a SourceId> {
{
if let Some(source_id) = path_deps.iter().find_map(|(name, version_source)| {
// First look for cases where the version and name are the same
if name == &pkg.name {
if let Ok(pkg_version) = pkg.version.parse::<semver::Version>() {
if let Some(source_id) = version_source.get(&pkg_version) {
return Some(source_id);
}
}
}
None
}) {
Some(source_id)
} else {
// Next look for cases where the name is the same
path_deps.iter().find_map(|(name, version_source)| {
if name == &pkg.name {
return version_source.values().next();
}
None
})
}
}
}
}
}

fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>> {
fn build_path_deps(
ws: &Workspace<'_>,
) -> CargoResult<HashMap<String, HashMap<semver::Version, SourceId>>> {
// If a crate is **not** a path source, then we're probably in a situation
// such as `cargo install` with a lock file from a remote dependency. In
// that case we don't need to fixup any path dependencies (as they're not
Expand All @@ -418,13 +457,15 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
.filter(|p| p.package_id().source_id().is_path())
.collect::<Vec<_>>();

let mut ret = HashMap::new();
let mut ret: HashMap<String, HashMap<semver::Version, SourceId>> = HashMap::new();
let mut visited = HashSet::new();
for member in members.iter() {
ret.insert(
member.package_id().name().to_string(),
member.package_id().source_id(),
);
ret.entry(member.package_id().name().to_string())
.or_insert_with(HashMap::new)
.insert(
member.package_id().version().clone(),
member.package_id().source_id(),
);
visited.insert(member.package_id().source_id());
}
for member in members.iter() {
Expand All @@ -444,7 +485,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
fn build_pkg(
pkg: &Package,
ws: &Workspace<'_>,
ret: &mut HashMap<String, SourceId>,
ret: &mut HashMap<String, HashMap<semver::Version, SourceId>>,
visited: &mut HashSet<SourceId>,
) {
for dep in pkg.dependencies() {
Expand All @@ -455,7 +496,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
fn build_dep(
dep: &Dependency,
ws: &Workspace<'_>,
ret: &mut HashMap<String, SourceId>,
ret: &mut HashMap<String, HashMap<semver::Version, SourceId>>,
visited: &mut HashSet<SourceId>,
) {
let id = dep.source_id();
Expand All @@ -467,7 +508,12 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
Err(_) => return,
};
let Ok(pkg) = ws.load(&path) else { return };
ret.insert(pkg.name().to_string(), pkg.package_id().source_id());
ret.entry(pkg.package_id().name().to_string())
.or_insert_with(HashMap::new)
.insert(
pkg.package_id().version().clone(),
pkg.package_id().source_id(),
);
visited.insert(pkg.package_id().source_id());
build_pkg(&pkg, ws, ret, visited);
}
Expand Down
8 changes: 4 additions & 4 deletions tests/testsuite/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2939,12 +2939,12 @@ foo v0.0.0 ([ROOT]/foo)
"\
foo v0.0.0 ([ROOT]/foo)
├── bar v1.0.999 ([ROOT]/foo/bar-1-as-3)
│ └── bar v3.0.1
│ └── bar v3.0.0
└── bar v2.0.999 ([ROOT]/foo/bar-2-as-3)
└── bar v3.0.1
└── bar v3.0.0
",
)
.run();

assert_ne!(p.read_file("Cargo.lock"), p.read_file("Cargo.lock.orig"));
}
assert_eq!(p.read_file("Cargo.lock"), p.read_file("Cargo.lock.orig"));
}

0 comments on commit c07cf47

Please sign in to comment.