@@ -300,9 +300,11 @@ pub(crate) async fn install(
300
300
None
301
301
} ;
302
302
303
+ let installations: Vec < _ > = downloaded. iter ( ) . chain ( satisfied. iter ( ) . copied ( ) ) . collect ( ) ;
304
+
303
305
// Ensure that the installations are _complete_ for both downloaded installations and existing
304
306
// installations that match the request
305
- for installation in downloaded . iter ( ) . chain ( satisfied . iter ( ) . copied ( ) ) {
307
+ for installation in installations . iter ( ) {
306
308
installation. ensure_externally_managed ( ) ?;
307
309
installation. ensure_canonical_executables ( ) ?;
308
310
@@ -353,7 +355,13 @@ pub(crate) async fn install(
353
355
) ;
354
356
355
357
// Figure out what installation it references, if any
356
- let existing = find_matching_bin_link ( & existing_installations, & target) ;
358
+ let existing = find_matching_bin_link (
359
+ installations
360
+ . iter ( )
361
+ . copied ( )
362
+ . chain ( existing_installations. iter ( ) ) ,
363
+ & target,
364
+ ) ;
357
365
358
366
match existing {
359
367
None => {
@@ -373,7 +381,7 @@ pub(crate) async fn install(
373
381
target. simplified_display( )
374
382
) ;
375
383
}
376
- Some ( existing) if existing == installation => {
384
+ Some ( existing) if existing == * installation => {
377
385
// The existing link points to the same installation, so we're done unless
378
386
// they requested we reinstall
379
387
if !( reinstall || force) {
@@ -429,6 +437,17 @@ pub(crate) async fn install(
429
437
430
438
// Replace the existing link
431
439
fs_err:: remove_file ( & to) ?;
440
+
441
+ if let Some ( existing) = existing {
442
+ // Ensure we do not report installation of this executable for an existing
443
+ // key if we undo it
444
+ changelog
445
+ . installed_executables
446
+ . entry ( existing. key ( ) . clone ( ) )
447
+ . or_default ( )
448
+ . remove ( & target) ;
449
+ }
450
+
432
451
installation. create_bin_link ( & target) ?;
433
452
debug ! (
434
453
"Updated executable at `{}` to {}" ,
@@ -562,6 +581,10 @@ pub(crate) fn format_executables(
562
581
return String :: new ( ) ;
563
582
} ;
564
583
584
+ if installed. is_empty ( ) {
585
+ return String :: new ( ) ;
586
+ }
587
+
565
588
let names = installed
566
589
. iter ( )
567
590
. filter_map ( |path| path. file_name ( ) )
@@ -612,7 +635,7 @@ fn warn_if_not_on_path(bin: &Path) {
612
635
/// Like [`ManagedPythonInstallation::is_bin_link`], but this method will only resolve the
613
636
/// given path one time.
614
637
fn find_matching_bin_link < ' a > (
615
- installations : & ' a [ ManagedPythonInstallation ] ,
638
+ mut installations : impl Iterator < Item = & ' a ManagedPythonInstallation > ,
616
639
path : & Path ,
617
640
) -> Option < & ' a ManagedPythonInstallation > {
618
641
let target = if cfg ! ( unix) {
@@ -630,7 +653,5 @@ fn find_matching_bin_link<'a>(
630
653
unreachable ! ( "Only Windows and Unix are supported" )
631
654
} ;
632
655
633
- installations
634
- . iter ( )
635
- . find ( |installation| installation. executable ( ) == target)
656
+ installations. find ( |installation| installation. executable ( ) == target)
636
657
}
0 commit comments