1
1
use std:: fmt:: Formatter ;
2
2
3
3
use pubgrub:: range:: Range ;
4
- use pubgrub:: report:: { DefaultStringReporter , Reporter } ;
4
+ use pubgrub:: report:: { DefaultStringReporter , DerivationTree , Reporter } ;
5
+ use pypi_types:: IndexUrl ;
6
+ use rustc_hash:: FxHashMap ;
5
7
use thiserror:: Error ;
6
8
use url:: Url ;
7
9
8
10
use distribution_types:: { BuiltDist , PathBuiltDist , PathSourceDist , SourceDist } ;
9
11
use pep508_rs:: Requirement ;
10
12
use puffin_distribution:: DistributionDatabaseError ;
11
13
use puffin_normalize:: PackageName ;
14
+ use puffin_traits:: OnceMap ;
12
15
13
16
use crate :: pubgrub:: { PubGrubPackage , PubGrubVersion } ;
17
+ use crate :: version_map:: VersionMap ;
14
18
use crate :: PubGrubReportFormatter ;
15
19
16
20
#[ derive( Error , Debug ) ]
@@ -30,9 +34,6 @@ pub enum ResolveError {
30
34
#[ error( transparent) ]
31
35
Join ( #[ from] tokio:: task:: JoinError ) ,
32
36
33
- #[ error( transparent) ]
34
- PubGrub ( #[ from] RichPubGrubError ) ,
35
-
36
37
#[ error( "Package metadata name `{metadata}` does not match given name `{given}`" ) ]
37
38
NameMismatch {
38
39
given : PackageName ,
@@ -65,6 +66,37 @@ pub enum ResolveError {
65
66
66
67
#[ error( "Failed to build: {0}" ) ]
67
68
Build ( Box < PathSourceDist > , #[ source] DistributionDatabaseError ) ,
69
+
70
+ #[ error( transparent) ]
71
+ NoSolution ( #[ from] NoSolutionError ) ,
72
+
73
+ #[ error( "Retrieving dependencies of {package} {version} failed" ) ]
74
+ ErrorRetrievingDependencies {
75
+ /// Package whose dependencies we want.
76
+ package : Box < PubGrubPackage > ,
77
+ /// Version of the package for which we want the dependencies.
78
+ version : Box < PubGrubVersion > ,
79
+ /// Error raised by the implementer of [DependencyProvider](crate::solver::DependencyProvider).
80
+ source : Box < dyn std:: error:: Error + Send + Sync > ,
81
+ } ,
82
+
83
+ #[ error( "{package} {version} depends on itself" ) ]
84
+ SelfDependency {
85
+ /// Package whose dependencies we want.
86
+ package : Box < PubGrubPackage > ,
87
+ /// Version of the package for which we want the dependencies.
88
+ version : Box < PubGrubVersion > ,
89
+ } ,
90
+
91
+ #[ error( "Decision making failed" ) ]
92
+ ErrorChoosingPackageVersion ( Box < dyn std:: error:: Error + Send + Sync > ) ,
93
+
94
+ #[ error( "We should cancel" ) ]
95
+ ErrorInShouldCancel ( Box < dyn std:: error:: Error + Send + Sync > ) ,
96
+
97
+ /// Something unexpected happened.
98
+ #[ error( "{0}" ) ]
99
+ Failure ( String ) ,
68
100
}
69
101
70
102
impl < T > From < futures:: channel:: mpsc:: TrySendError < T > > for ResolveError {
@@ -73,28 +105,83 @@ impl<T> From<futures::channel::mpsc::TrySendError<T>> for ResolveError {
73
105
}
74
106
}
75
107
76
- /// A wrapper around [`pubgrub::error::PubGrubError`] that displays a resolution failure report.
108
+ impl From < pubgrub:: error:: PubGrubError < PubGrubPackage , Range < PubGrubVersion > > > for ResolveError {
109
+ fn from ( value : pubgrub:: error:: PubGrubError < PubGrubPackage , Range < PubGrubVersion > > ) -> Self {
110
+ match value {
111
+ pubgrub:: error:: PubGrubError :: ErrorChoosingPackageVersion ( inner) => {
112
+ ResolveError :: ErrorChoosingPackageVersion ( inner)
113
+ }
114
+ pubgrub:: error:: PubGrubError :: ErrorInShouldCancel ( inner) => {
115
+ ResolveError :: ErrorInShouldCancel ( inner)
116
+ }
117
+ pubgrub:: error:: PubGrubError :: ErrorRetrievingDependencies {
118
+ package,
119
+ version,
120
+ source,
121
+ } => ResolveError :: ErrorRetrievingDependencies {
122
+ package : Box :: new ( package) ,
123
+ version : Box :: new ( version) ,
124
+ source,
125
+ } ,
126
+ pubgrub:: error:: PubGrubError :: Failure ( inner) => ResolveError :: Failure ( inner) ,
127
+ pubgrub:: error:: PubGrubError :: NoSolution ( derivation_tree) => {
128
+ ResolveError :: NoSolution ( NoSolutionError {
129
+ derivation_tree,
130
+ available_versions : FxHashMap :: default ( ) ,
131
+ } )
132
+ }
133
+ pubgrub:: error:: PubGrubError :: SelfDependency { package, version } => {
134
+ ResolveError :: SelfDependency {
135
+ package : Box :: new ( package) ,
136
+ version : Box :: new ( version) ,
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ /// A wrapper around [`pubgrub::error::PubGrubError::NoSolution`] that displays a resolution failure report.
77
144
#[ derive( Debug ) ]
78
- pub struct RichPubGrubError {
79
- source : pubgrub:: error:: PubGrubError < PubGrubPackage , Range < PubGrubVersion > > ,
145
+ pub struct NoSolutionError {
146
+ derivation_tree : DerivationTree < PubGrubPackage , Range < PubGrubVersion > > ,
147
+ available_versions : FxHashMap < PubGrubPackage , Vec < PubGrubVersion > > ,
80
148
}
81
149
82
- impl std:: error:: Error for RichPubGrubError { }
150
+ impl std:: error:: Error for NoSolutionError { }
83
151
84
- impl std:: fmt:: Display for RichPubGrubError {
152
+ impl std:: fmt:: Display for NoSolutionError {
85
153
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
86
- if let pubgrub:: error:: PubGrubError :: NoSolution ( derivation_tree) = & self . source {
87
- let formatter = PubGrubReportFormatter ;
88
- let report = DefaultStringReporter :: report_with_formatter ( derivation_tree, & formatter) ;
89
- write ! ( f, "{report}" )
90
- } else {
91
- write ! ( f, "{}" , self . source)
92
- }
154
+ let formatter = PubGrubReportFormatter {
155
+ available_versions : & self . available_versions ,
156
+ } ;
157
+ let report =
158
+ DefaultStringReporter :: report_with_formatter ( & self . derivation_tree , & formatter) ;
159
+ write ! ( f, "{report}" )
93
160
}
94
161
}
95
162
96
- impl From < pubgrub:: error:: PubGrubError < PubGrubPackage , Range < PubGrubVersion > > > for ResolveError {
97
- fn from ( value : pubgrub:: error:: PubGrubError < PubGrubPackage , Range < PubGrubVersion > > ) -> Self {
98
- ResolveError :: PubGrub ( RichPubGrubError { source : value } )
163
+ impl NoSolutionError {
164
+ /// Update the available versions attached to the error using the given package version index.
165
+ ///
166
+ /// Only packages used in the error's deriviation tree will be retrieved.
167
+ pub ( crate ) fn update_available_versions (
168
+ mut self ,
169
+ package_versions : & OnceMap < PackageName , ( IndexUrl , VersionMap ) > ,
170
+ ) -> Self {
171
+ for package in self . derivation_tree . packages ( ) {
172
+ if let PubGrubPackage :: Package ( name, ..) = package {
173
+ if let Some ( entry) = package_versions. get ( name) {
174
+ let ( _, version_map) = entry. value ( ) ;
175
+ self . available_versions . insert (
176
+ package. clone ( ) ,
177
+ version_map
178
+ . iter ( )
179
+ . map ( |( version, _) | version. clone ( ) )
180
+ . collect ( ) ,
181
+ ) ;
182
+ }
183
+ }
184
+ }
185
+ self
99
186
}
100
187
}
0 commit comments