Skip to content

Commit 89f9dff

Browse files
konstinzanieb
andauthored
Add DerivationTree.packages() -> HashSet<&P> (#219)
* Add `DerivationTree.packages() -> HashSet<&P>` * Review * Add `.packages()` to a test --------- Co-authored-by: Zanie Blue <[email protected]>
1 parent fce8e02 commit 89f9dff

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/report.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::sync::Arc;
99

1010
use crate::package::Package;
1111
use crate::term::Term;
12-
use crate::type_aliases::Map;
12+
use crate::type_aliases::{Map, Set};
1313
use crate::version_set::VersionSet;
1414

1515
/// Reporter trait.
@@ -71,6 +71,32 @@ pub struct Derived<P: Package, VS: VersionSet, M: Eq + Clone + Debug + Display>
7171
}
7272

7373
impl<P: Package, VS: VersionSet, M: Eq + Clone + Debug + Display> DerivationTree<P, VS, M> {
74+
/// Get all packages referred to in the derivation tree.
75+
pub fn packages(&self) -> Set<&P> {
76+
let mut packages = Set::default();
77+
match self {
78+
Self::External(external) => match external {
79+
External::FromDependencyOf(p, _, p2, _) => {
80+
packages.insert(p);
81+
packages.insert(p2);
82+
}
83+
External::NoVersions(p, _)
84+
| External::NotRoot(p, _)
85+
| External::Custom(p, _, _) => {
86+
packages.insert(p);
87+
}
88+
},
89+
Self::Derived(derived) => {
90+
// Less efficient than recursing with a `&mut Set<&P>`, but it's sufficient for
91+
// small to medium-sized inputs such as a single `DerivationTree`.
92+
packages.extend(derived.terms.keys());
93+
packages.extend(derived.cause1.packages().iter());
94+
packages.extend(derived.cause2.packages().iter());
95+
}
96+
}
97+
packages
98+
}
99+
74100
/// Merge the [NoVersions](External::NoVersions) external incompatibilities
75101
/// with the other one they are matched with
76102
/// in a derived incompatibility.

tests/examples.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use pubgrub::error::PubGrubError;
44
use pubgrub::range::Range;
55
use pubgrub::report::{DefaultStringReporter, Reporter as _};
66
use pubgrub::solver::{resolve, OfflineDependencyProvider};
7-
use pubgrub::type_aliases::Map;
7+
use pubgrub::type_aliases::{Map, Set};
88
use pubgrub::version::SemanticVersion;
99

1010
type NumVS = Range<u32>;
@@ -217,13 +217,20 @@ fn confusing_with_lots_of_holes() {
217217
let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
218218

219219
// root depends on foo...
220-
dependency_provider.add_dependencies("root", 1u32, vec![("foo", Range::full())]);
220+
dependency_provider.add_dependencies(
221+
"root",
222+
1u32,
223+
vec![("foo", Range::full()), ("baz", Range::full())],
224+
);
221225

222226
for i in 1..6 {
223227
// foo depends on bar...
224228
dependency_provider.add_dependencies("foo", i as u32, vec![("bar", Range::full())]);
225229
}
226230

231+
// This package is part of the dependency tree, but it's not part of the conflict
232+
dependency_provider.add_dependencies("baz", 1u32, vec![]);
233+
227234
let Err(PubGrubError::NoSolution(mut derivation_tree)) =
228235
resolve(&dependency_provider, "root", 1u32)
229236
else {
@@ -239,4 +246,9 @@ And because there is no version of foo in <1 | >1, <2 | >2, <3 | >3, <4 | >4, <5
239246
&DefaultStringReporter::report(&derivation_tree),
240247
"Because foo depends on bar and root 1 depends on foo, root 1 is forbidden."
241248
);
249+
assert_eq!(
250+
derivation_tree.packages(),
251+
// baz isn't shown.
252+
Set::from_iter(&["root", "foo", "bar"])
253+
);
242254
}

0 commit comments

Comments
 (0)