1
+ use std:: path:: Path ;
1
2
use std:: str:: FromStr ;
2
3
3
4
use rustc_hash:: FxHashMap ;
4
5
use tracing:: trace;
5
6
6
- use uv_distribution_types:: { InstalledDist , InstalledMetadata , InstalledVersion , Name } ;
7
+ use uv_distribution_types:: { IndexUrl , InstalledDist , InstalledMetadata , InstalledVersion , Name } ;
7
8
use uv_normalize:: PackageName ;
8
9
use uv_pep440:: { Operator , Version } ;
9
10
use uv_pep508:: { MarkerTree , VersionOrUrl } ;
10
11
use uv_pypi_types:: { HashDigest , HashError } ;
11
12
use uv_requirements_txt:: { RequirementEntry , RequirementsTxtRequirement } ;
12
13
13
- use crate :: ResolverEnvironment ;
14
+ use crate :: { LockError , ResolverEnvironment } ;
14
15
15
16
#[ derive( thiserror:: Error , Debug ) ]
16
17
pub enum PreferenceError {
@@ -25,6 +26,8 @@ pub struct Preference {
25
26
version : Version ,
26
27
/// The markers on the requirement itself (those after the semicolon).
27
28
marker : MarkerTree ,
29
+ /// The index URL of the package, if any.
30
+ index : Option < IndexUrl > ,
28
31
/// If coming from a package with diverging versions, the markers of the forks this preference
29
32
/// is part of, otherwise `None`.
30
33
fork_markers : Vec < MarkerTree > ,
@@ -60,6 +63,7 @@ impl Preference {
60
63
marker : requirement. marker ,
61
64
// requirements.txt doesn't have fork annotations.
62
65
fork_markers : vec ! [ ] ,
66
+ index : None ,
63
67
hashes : entry
64
68
. hashes
65
69
. iter ( )
@@ -79,21 +83,26 @@ impl Preference {
79
83
name : dist. name ( ) . clone ( ) ,
80
84
version : version. clone ( ) ,
81
85
marker : MarkerTree :: TRUE ,
86
+ index : None ,
82
87
// Installed distributions don't have fork annotations.
83
88
fork_markers : vec ! [ ] ,
84
89
hashes : Vec :: new ( ) ,
85
90
}
86
91
}
87
92
88
93
/// Create a [`Preference`] from a locked distribution.
89
- pub fn from_lock ( package : & crate :: lock:: Package ) -> Self {
90
- Self {
94
+ pub fn from_lock (
95
+ package : & crate :: lock:: Package ,
96
+ install_path : & Path ,
97
+ ) -> Result < Self , LockError > {
98
+ Ok ( Self {
91
99
name : package. id . name . clone ( ) ,
92
100
version : package. id . version . clone ( ) ,
93
101
marker : MarkerTree :: TRUE ,
102
+ index : package. index ( install_path) ?,
94
103
fork_markers : package. fork_markers ( ) . to_vec ( ) ,
95
104
hashes : Vec :: new ( ) ,
96
- }
105
+ } )
97
106
}
98
107
99
108
/// Return the [`PackageName`] of the package for this [`Preference`].
@@ -107,22 +116,29 @@ impl Preference {
107
116
}
108
117
}
109
118
119
+ #[ derive( Debug , Clone ) ]
120
+ struct Entry {
121
+ marker : Option < MarkerTree > ,
122
+ index : Option < IndexUrl > ,
123
+ pin : Pin ,
124
+ }
125
+
110
126
/// A set of pinned packages that should be preserved during resolution, if possible.
111
127
///
112
128
/// The marker is the marker of the fork that resolved to the pin, if any.
113
129
///
114
130
/// Preferences should be prioritized first by whether their marker matches and then by the order
115
131
/// they are stored, so that a lockfile has higher precedence than sibling forks.
116
132
#[ derive( Debug , Clone , Default ) ]
117
- pub struct Preferences ( FxHashMap < PackageName , Vec < ( Option < MarkerTree > , Pin ) > > ) ;
133
+ pub struct Preferences ( FxHashMap < PackageName , Vec < Entry > > ) ;
118
134
119
135
impl Preferences {
120
136
/// Create a map of pinned packages from an iterator of [`Preference`] entries.
121
137
///
122
138
/// The provided [`ResolverEnvironment`] will be used to filter the preferences
123
139
/// to an applicable subset.
124
- pub fn from_iter < PreferenceIterator : IntoIterator < Item = Preference > > (
125
- preferences : PreferenceIterator ,
140
+ pub fn from_iter (
141
+ preferences : impl IntoIterator < Item = Preference > ,
126
142
env : & ResolverEnvironment ,
127
143
) -> Self {
128
144
let mut slf = Self :: default ( ) ;
@@ -152,6 +168,7 @@ impl Preferences {
152
168
if preference. fork_markers . is_empty ( ) {
153
169
slf. insert (
154
170
preference. name ,
171
+ preference. index ,
155
172
None ,
156
173
Pin {
157
174
version : preference. version ,
@@ -162,6 +179,7 @@ impl Preferences {
162
179
for fork_marker in preference. fork_markers {
163
180
slf. insert (
164
181
preference. name . clone ( ) ,
182
+ preference. index . clone ( ) ,
165
183
Some ( fork_marker) ,
166
184
Pin {
167
185
version : preference. version . clone ( ) ,
@@ -179,13 +197,15 @@ impl Preferences {
179
197
pub ( crate ) fn insert (
180
198
& mut self ,
181
199
package_name : PackageName ,
200
+ index : Option < IndexUrl > ,
182
201
markers : Option < MarkerTree > ,
183
202
pin : impl Into < Pin > ,
184
203
) {
185
- self . 0
186
- . entry ( package_name)
187
- . or_default ( )
188
- . push ( ( markers, pin. into ( ) ) ) ;
204
+ self . 0 . entry ( package_name) . or_default ( ) . push ( Entry {
205
+ marker : markers,
206
+ index,
207
+ pin : pin. into ( ) ,
208
+ } ) ;
189
209
}
190
210
191
211
/// Returns an iterator over the preferences.
@@ -194,15 +214,19 @@ impl Preferences {
194
214
) -> impl Iterator <
195
215
Item = (
196
216
& PackageName ,
197
- impl Iterator < Item = ( Option < & MarkerTree > , & Version ) > ,
217
+ impl Iterator < Item = ( Option < & MarkerTree > , Option < & IndexUrl > , & Version ) > ,
198
218
) ,
199
219
> {
200
220
self . 0 . iter ( ) . map ( |( name, preferences) | {
201
221
(
202
222
name,
203
- preferences
204
- . iter ( )
205
- . map ( |( markers, pin) | ( markers. as_ref ( ) , pin. version ( ) ) ) ,
223
+ preferences. iter ( ) . map ( |entry| {
224
+ (
225
+ entry. marker . as_ref ( ) ,
226
+ entry. index . as_ref ( ) ,
227
+ entry. pin . version ( ) ,
228
+ )
229
+ } ) ,
206
230
)
207
231
} )
208
232
}
@@ -211,12 +235,14 @@ impl Preferences {
211
235
pub ( crate ) fn get (
212
236
& self ,
213
237
package_name : & PackageName ,
214
- ) -> impl Iterator < Item = ( Option < & MarkerTree > , & Version ) > {
215
- self . 0
216
- . get ( package_name)
217
- . into_iter ( )
218
- . flatten ( )
219
- . map ( |( markers, pin) | ( markers. as_ref ( ) , pin. version ( ) ) )
238
+ ) -> impl Iterator < Item = ( Option < & MarkerTree > , Option < & IndexUrl > , & Version ) > {
239
+ self . 0 . get ( package_name) . into_iter ( ) . flatten ( ) . map ( |entry| {
240
+ (
241
+ entry. marker . as_ref ( ) ,
242
+ entry. index . as_ref ( ) ,
243
+ entry. pin . version ( ) ,
244
+ )
245
+ } )
220
246
}
221
247
222
248
/// Return the hashes for a package, if the version matches that of the pin.
@@ -229,8 +255,8 @@ impl Preferences {
229
255
. get ( package_name)
230
256
. into_iter ( )
231
257
. flatten ( )
232
- . find ( |( _markers , pin ) | pin. version ( ) == version)
233
- . map ( |( _markers , pin ) | pin. hashes ( ) )
258
+ . find ( |entry| entry . pin . version ( ) == version)
259
+ . map ( |entry| entry . pin . hashes ( ) )
234
260
}
235
261
}
236
262
0 commit comments