|
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