|
1 | 1 | // SPDX-License-Identifier: MPL-2.0
|
2 | 2 |
|
3 | 3 | use std::cell::RefCell;
|
| 4 | +use std::collections::BTreeMap; |
| 5 | +use std::fmt::{Debug, Display}; |
| 6 | +use std::hash::Hash; |
4 | 7 |
|
5 |
| -use pubgrub::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider, Ranges}; |
| 8 | +use pubgrub::{ |
| 9 | + resolve, Dependencies, DependencyConstraints, DependencyProvider, Map, |
| 10 | + OfflineDependencyProvider, Package, PackageArena, Ranges, |
| 11 | +}; |
6 | 12 |
|
7 | 13 | type NumVS = Ranges<u32>;
|
| 14 | +type CachedDeps<V, VS> = RefCell<Map<Package, BTreeMap<V, DependencyConstraints<VS>>>>; |
8 | 15 |
|
9 | 16 | // An example implementing caching dependency provider that will
|
10 | 17 | // store queried dependencies in memory and check them before querying more from remote.
|
11 |
| -struct CachingDependencyProvider<DP: DependencyProvider> { |
| 18 | +struct CachingDependencyProvider<DP: DependencyProvider> |
| 19 | +where |
| 20 | + DP::P: Debug + Display + Clone + Eq + Hash, |
| 21 | +{ |
12 | 22 | remote_dependencies: DP,
|
13 |
| - cached_dependencies: RefCell<OfflineDependencyProvider<DP::P, DP::VS>>, |
| 23 | + cached_dependencies: CachedDeps<DP::V, DP::VS>, |
14 | 24 | }
|
15 | 25 |
|
16 |
| -impl<DP: DependencyProvider> CachingDependencyProvider<DP> { |
| 26 | +impl<DP: DependencyProvider> CachingDependencyProvider<DP> |
| 27 | +where |
| 28 | + DP::P: Debug + Display + Clone + Eq + Hash, |
| 29 | +{ |
17 | 30 | pub fn new(remote_dependencies_provider: DP) -> Self {
|
18 | 31 | CachingDependencyProvider {
|
19 | 32 | remote_dependencies: remote_dependencies_provider,
|
20 |
| - cached_dependencies: RefCell::new(OfflineDependencyProvider::new()), |
| 33 | + cached_dependencies: Default::default(), |
21 | 34 | }
|
22 | 35 | }
|
23 | 36 | }
|
24 | 37 |
|
25 |
| -impl<DP: DependencyProvider<M = String>> DependencyProvider for CachingDependencyProvider<DP> { |
26 |
| - // Caches dependencies if they were already queried |
| 38 | +impl<DP: DependencyProvider<M = &'static str>> DependencyProvider for CachingDependencyProvider<DP> |
| 39 | +where |
| 40 | + DP::P: Debug + Display + Clone + Eq + Hash, |
| 41 | +{ |
| 42 | + // Cache dependencies if they were already queried |
27 | 43 | fn get_dependencies(
|
28 | 44 | &mut self,
|
29 |
| - package: &DP::P, |
| 45 | + package: Package, |
30 | 46 | version: &DP::V,
|
31 |
| - ) -> Result<Dependencies<DP::P, DP::VS, DP::M>, DP::Err> { |
| 47 | + package_store: &mut PackageArena<Self::P>, |
| 48 | + ) -> Result<Dependencies<DP::VS, DP::M>, DP::Err> { |
32 | 49 | let mut cache = self.cached_dependencies.borrow_mut();
|
33 |
| - match cache.get_dependencies(package, version) { |
34 |
| - Ok(Dependencies::Unavailable(_)) => { |
35 |
| - let dependencies = self.remote_dependencies.get_dependencies(package, version); |
36 |
| - match dependencies { |
37 |
| - Ok(Dependencies::Available(dependencies)) => { |
38 |
| - cache.add_dependencies( |
39 |
| - package.clone(), |
40 |
| - version.clone(), |
41 |
| - dependencies.clone(), |
42 |
| - ); |
43 |
| - Ok(Dependencies::Available(dependencies)) |
44 |
| - } |
45 |
| - Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)), |
46 |
| - error @ Err(_) => error, |
47 |
| - } |
| 50 | + if let Some(deps) = cache.get(&package).and_then(|vmap| vmap.get(version)) { |
| 51 | + return Ok(Dependencies::Available(deps.clone())); |
| 52 | + } |
| 53 | + |
| 54 | + match self |
| 55 | + .remote_dependencies |
| 56 | + .get_dependencies(package, version, package_store) |
| 57 | + { |
| 58 | + Ok(Dependencies::Available(deps)) => { |
| 59 | + cache |
| 60 | + .entry(package) |
| 61 | + .or_default() |
| 62 | + .insert(version.clone(), deps.clone()); |
| 63 | + Ok(Dependencies::Available(deps)) |
48 | 64 | }
|
49 |
| - Ok(dependencies) => Ok(dependencies), |
50 |
| - Err(_) => unreachable!(), |
| 65 | + |
| 66 | + Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)), |
| 67 | + error @ Err(_) => error, |
51 | 68 | }
|
52 | 69 | }
|
53 | 70 |
|
54 | 71 | fn choose_version(
|
55 | 72 | &mut self,
|
56 |
| - package: &DP::P, |
| 73 | + package: Package, |
57 | 74 | ranges: &DP::VS,
|
| 75 | + package_store: &PackageArena<Self::P>, |
58 | 76 | ) -> Result<Option<DP::V>, DP::Err> {
|
59 |
| - self.remote_dependencies.choose_version(package, ranges) |
| 77 | + self.remote_dependencies |
| 78 | + .choose_version(package, ranges, package_store) |
60 | 79 | }
|
61 | 80 |
|
62 | 81 | type Priority = DP::Priority;
|
63 | 82 |
|
64 |
| - fn prioritize(&mut self, package: &DP::P, ranges: &DP::VS) -> Self::Priority { |
65 |
| - self.remote_dependencies.prioritize(package, ranges) |
| 83 | + fn prioritize( |
| 84 | + &mut self, |
| 85 | + package: Package, |
| 86 | + ranges: &DP::VS, |
| 87 | + package_store: &PackageArena<Self::P>, |
| 88 | + ) -> Self::Priority { |
| 89 | + self.remote_dependencies |
| 90 | + .prioritize(package, ranges, package_store) |
66 | 91 | }
|
67 | 92 |
|
68 | 93 | type Err = DP::Err;
|
|
0 commit comments