@@ -64,7 +64,7 @@ pub(crate) async fn install(
64
64
. inspect ( |installation| debug ! ( "Found existing installation {}" , installation. key( ) ) )
65
65
. collect ( ) ;
66
66
let mut unfilled_requests = Vec :: new ( ) ;
67
- let mut uninstalled = Vec :: new ( ) ;
67
+ let mut uninstalled = BTreeSet :: new ( ) ;
68
68
for ( request, download_request) in requests. iter ( ) . zip ( download_requests) {
69
69
if matches ! ( requests. as_slice( ) , [ PythonRequest :: Default ] ) {
70
70
writeln ! ( printer. stderr( ) , "Searching for Python installations" ) ?;
@@ -91,7 +91,7 @@ pub(crate) async fn install(
91
91
}
92
92
if reinstall {
93
93
fs:: remove_dir_all ( installation. path ( ) ) ?;
94
- uninstalled. push ( installation. key ( ) . clone ( ) ) ;
94
+ uninstalled. insert ( installation. key ( ) ) ;
95
95
unfilled_requests. push ( download_request) ;
96
96
}
97
97
} else {
@@ -151,7 +151,7 @@ pub(crate) async fn install(
151
151
} ) ;
152
152
}
153
153
154
- let mut installed = vec ! [ ] ;
154
+ let mut installed = BTreeSet :: new ( ) ;
155
155
let mut errors = vec ! [ ] ;
156
156
while let Some ( ( key, result) ) = tasks. next ( ) . await {
157
157
match result {
@@ -162,7 +162,7 @@ pub(crate) async fn install(
162
162
DownloadResult :: Fetched ( path) => path,
163
163
} ;
164
164
165
- installed. push ( key. clone ( ) ) ;
165
+ installed. insert ( key) ;
166
166
167
167
// Ensure the installations have externally managed markers
168
168
let managed = ManagedPythonInstallation :: new ( path. clone ( ) ) ?;
@@ -176,7 +176,8 @@ pub(crate) async fn install(
176
176
}
177
177
178
178
if !installed. is_empty ( ) {
179
- if let [ installed] = installed. as_slice ( ) {
179
+ if installed. len ( ) == 1 {
180
+ let installed = installed. iter ( ) . next ( ) . unwrap ( ) ;
180
181
// Ex) "Installed Python 3.9.7 in 1.68s"
181
182
writeln ! (
182
183
printer. stderr( ) ,
@@ -190,29 +191,38 @@ pub(crate) async fn install(
190
191
) ?;
191
192
} else {
192
193
// Ex) "Installed 2 versions in 1.68s"
193
- let s = if installed. len ( ) == 1 { "" } else { "s" } ;
194
194
writeln ! (
195
195
printer. stderr( ) ,
196
196
"{}" ,
197
197
format!(
198
198
"Installed {} {}" ,
199
- format!( "{} version{s} " , installed. len( ) ) . bold( ) ,
199
+ format!( "{} versions " , installed. len( ) ) . bold( ) ,
200
200
format!( "in {}" , elapsed( start. elapsed( ) ) ) . dimmed( )
201
201
)
202
202
. dimmed( )
203
203
) ?;
204
204
}
205
205
206
+ let reinstalled = uninstalled
207
+ . intersection ( & installed)
208
+ . copied ( )
209
+ . collect :: < BTreeSet < _ > > ( ) ;
210
+ let uninstalled = uninstalled. difference ( & reinstalled) . copied ( ) ;
211
+ let installed = installed. difference ( & reinstalled) . copied ( ) ;
212
+
206
213
for event in uninstalled
207
- . into_iter ( )
208
214
. map ( |key| ChangeEvent {
209
- key,
215
+ key : key . clone ( ) ,
210
216
kind : ChangeEventKind :: Removed ,
211
217
} )
212
- . chain ( installed. into_iter ( ) . map ( |key| ChangeEvent {
213
- key,
218
+ . chain ( installed. map ( |key| ChangeEvent {
219
+ key : key . clone ( ) ,
214
220
kind : ChangeEventKind :: Added ,
215
221
} ) )
222
+ . chain ( reinstalled. iter ( ) . map ( |& key| ChangeEvent {
223
+ key : key. clone ( ) ,
224
+ kind : ChangeEventKind :: Reinstalled ,
225
+ } ) )
216
226
. sorted_unstable_by ( |a, b| a. key . cmp ( & b. key ) . then_with ( || a. kind . cmp ( & b. kind ) ) )
217
227
{
218
228
match event. kind {
@@ -222,6 +232,9 @@ pub(crate) async fn install(
222
232
ChangeEventKind :: Removed => {
223
233
writeln ! ( printer. stderr( ) , " {} {}" , "-" . red( ) , event. key. bold( ) ) ?;
224
234
}
235
+ ChangeEventKind :: Reinstalled => {
236
+ writeln ! ( printer. stderr( ) , " {} {}" , "~" . yellow( ) , event. key. bold( ) , ) ?;
237
+ }
225
238
}
226
239
}
227
240
}
0 commit comments