diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 23ab9fd46..d33c4eaa3 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -362,28 +362,36 @@ pub(crate) async fn install( target.simplified_display() ); - // Check if the existing link is valid - let valid_link = target - .read_link() - .and_then(|target| target.try_exists()) - .inspect_err(|err| debug!("Failed to inspect executable with error: {err}")) - .unwrap_or(true); - // Figure out what installation it references, if any - let existing = valid_link - .then(|| { - find_matching_bin_link( - installations - .iter() - .copied() - .chain(existing_installations.iter()), - &target, - ) - }) - .flatten(); + let existing = find_matching_bin_link( + installations + .iter() + .copied() + .chain(existing_installations.iter()), + &target, + ); match existing { None => { + // Determine if the link is valid, i.e., if it points to an existing + // Python we don't manage. + let valid_link = cfg!(unix) + .then(|| { + target + .read_link() + .and_then(|target| target.try_exists()) + .inspect_err(|err| { + debug!( + "Failed to inspect executable with error: {err}" + ); + }) + // If we can't verify the link, assume it is valid. + .unwrap_or(true) + }) + // On Windows, we just assume it is valid because symlinks are not + // common. + .unwrap_or(true); + // There's an existing executable we don't manage, require `--force` if valid_link { if !force {