Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions crates/uv-pypi-types/src/conflicts.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use indexmap::IndexSet;
use petgraph::{
algo::toposort,
graph::{DiGraph, NodeIndex},
};
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::fmt;
Expand Down Expand Up @@ -87,6 +88,22 @@ impl Conflicts {
package: &PackageName,
groups: &DependencyGroups,
) {
// Nothing to infer without a conflicting group and at least one
// group include.
if !self.0.iter().any(|set| {
set.iter()
.any(|item| matches!(item.kind(), ConflictKind::Group(_)))
}) {
return;
}
if !groups.iter().any(|(_, specifiers)| {
specifiers
.iter()
.any(|specifier| matches!(specifier, DependencyGroupSpecifier::IncludeGroup { .. }))
}) {
return;
}

let mut graph = DiGraph::new();
let mut group_node_idxs: FxHashMap<&GroupName, NodeIndex> = FxHashMap::default();
let mut node_conflict_items: FxHashMap<NodeIndex, Rc<ConflictItem>> = FxHashMap::default();
Expand All @@ -97,7 +114,7 @@ impl Conflicts {
FxHashMap::default();

// Track all existing conflict sets to avoid duplicates.
let mut conflict_sets: FxHashSet<ConflictSet> = FxHashSet::default();
let mut conflict_sets: IndexSet<ConflictSet, FxBuildHasher> = IndexSet::default();

// Add groups in directly defined conflict sets to the graph.
let mut seen: FxHashSet<&GroupName> = FxHashSet::default();
Expand All @@ -120,6 +137,7 @@ impl Conflicts {
node_conflict_items.insert(node_id, item.clone());
}
}
let seeded = conflict_sets.len();

// Create conflict items for remaining groups and add them to the graph.
for group in groups.keys() {
Expand Down Expand Up @@ -199,11 +217,8 @@ impl Conflicts {
conflict_sets.extend(new_conflict_sets);
}

// Add all newly discovered conflict sets (excluding the originals already in self.0)
for set in &self.0 {
conflict_sets.remove(set);
}
self.0.extend(conflict_sets);
// Everything past the seeded originals is newly inferred.
self.0.extend(conflict_sets.into_iter().skip(seeded));
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/uv-pypi-types/src/dependency_groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ impl DependencyGroups {
}

/// Returns an iterator over the dependency groups.
pub fn iter(&self) -> impl Iterator<Item = (&GroupName, &Vec<DependencyGroupSpecifier>)> {
pub(crate) fn iter(
&self,
) -> impl Iterator<Item = (&GroupName, &Vec<DependencyGroupSpecifier>)> {
self.0.iter()
}
}
Expand Down
8 changes: 0 additions & 8 deletions hawk.toml
Original file line number Diff line number Diff line change
Expand Up @@ -282,14 +282,6 @@ reason = "read by the AWS request signer"

# Keep conventional collection accessors together.

[[override]]
lint = "hawk::dead_public"
crate = "uv_pypi_types"
item = "dependency_groups::DependencyGroups::iter"
kind = "inherent_method"
level = "expect"
reason = "required alongside IntoIterator by Clippy"

[[override]]
lint = "hawk::dead_public"
crate = "uv_resolver"
Expand Down
Loading