Writing your own dependency provider
The OfflineDependencyProvider
is very useful for testing
and playing with the API, but would not be usable in more complex
settings like Cargo for example.
In such cases, a dependency provider may need to retrieve
package information from caches, from the disk or from network requests.
Then, you might want to implement DependencyProvider
for your own type.
The DependencyProvider
trait is defined as follows.
As you can see, implementing the DependencyProvider
trait requires you
to implement two functions, choose_package_version
and get_dependencies
.
The first one, choose_package_version
is called by the resolver when a new
package has to be tried.
At that point, the resolver call choose_package_version
with a list
of potential packages and their associated acceptable version ranges.
It's then the role of the dependency retriever to pick a package
and a suitable version in that range.
The simplest decision strategy would be to just pick the first package,
and first compatible version. Provided there exists a method
fn available_versions(package: &P) -> impl Iterator<Item = &V>
for your type,
it could be implemented as follows.
We discuss advanced decision making strategies later.
The second required method is the get_dependencies
method.
For a given package version, this method should return
the corresponding dependencies.
Retrieving those dependencies may fail due to IO or other issues,
and in such cases the function should return an error.
Even if it does not fail, we want to distinguish the cases
where the dependency provider does not know the answer
and the cases where the package has no dependencies.
For this reason, the return type in case of a success is the
Dependencies
enum, defined as follows.
Finally, there is an optional should_cancel
method.
As described in its documentation,
this method is regularly called in the solver loop,
and defaults to doing nothing.
But if needed, you can override it to provide custom behavior,
such as giving some feedback, or stopping early to prevent ddos.
Any useful behavior would require mutability of self
,
and that is possible thanks to interior mutability.
Read on the next section for more info on that!