Skip to content

Commit

Permalink
Try symlinking proxies first
Browse files Browse the repository at this point in the history
Fallback to hardlinking if that doesn't work
  • Loading branch information
ChrisDenton committed Sep 16, 2024
1 parent ccc668c commit 3d178ad
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 17 deletions.
12 changes: 6 additions & 6 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,8 +731,8 @@ pub(crate) fn install_proxies(process: &Process) -> Result<()> {
let mut tool_handles = Vec::new();
let mut link_afterwards = Vec::new();

// Try to hardlink all the Rust exes to the rustup exe. Some systems,
// like Android, does not support hardlinks, so we fallback to symlinks.
// Try to symlink all the Rust exes to the rustup exe. Some systems,
// like Windows, do not always support symlinks, so we fallback to hard links.
//
// Note that this function may not be running in the context of a fresh
// self update but rather as part of a normal update to fill in missing
Expand All @@ -751,7 +751,7 @@ pub(crate) fn install_proxies(process: &Process) -> Result<()> {
// actually delete files (they'll say they're deleted but they won't
// actually be on Windows). As a result we manually drop all the
// `tool_handles` later on. This'll allow us, afterwards, to actually
// overwrite all the previous hard links with new ones.
// overwrite all the previous soft or hard links with new ones.
for tool in TOOLS {
let tool_path = bin_path.join(format!("{tool}{EXE_SUFFIX}"));
if let Ok(handle) = Handle::from_path(&tool_path) {
Expand All @@ -766,7 +766,7 @@ pub(crate) fn install_proxies(process: &Process) -> Result<()> {
for tool in DUP_TOOLS {
let tool_path = bin_path.join(format!("{tool}{EXE_SUFFIX}"));
if let Ok(handle) = Handle::from_path(&tool_path) {
// Like above, don't clobber anything that's already hardlinked to
// Like above, don't clobber anything that's already linked to
// avoid extraneous errors from being returned.
if rustup == handle {
continue;
Expand All @@ -790,12 +790,12 @@ pub(crate) fn install_proxies(process: &Process) -> Result<()> {
continue;
}
}
utils::hard_or_symlink_file(&rustup_path, &tool_path)?;
utils::symlink_or_hardlink_file(&rustup_path, &tool_path)?;
}

drop(tool_handles);
for path in link_afterwards {
utils::hard_or_symlink_file(&rustup_path, &path)?;
utils::symlink_or_hardlink_file(&rustup_path, &path)?;
}

Ok(())
Expand Down
25 changes: 14 additions & 11 deletions src/utils/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,19 +312,23 @@ where
})
}

pub(crate) fn hard_or_symlink_file(src: &Path, dest: &Path) -> Result<()> {
pub(crate) fn symlink_or_hardlink_file(src: &Path, dest: &Path) -> Result<()> {
// The error is only used by macos
let Err(_err) = symlink_file(src, dest) else {
return Ok(());
};

// Some mac filesystems can do hardlinks to symlinks, some can't.
// See rust-lang/rustup#3136 for why it's better never to use them.
#[cfg(target_os = "macos")]
let force_symlink = fs::symlink_metadata(src)
if fs::symlink_metadata(src)
.map(|m| m.file_type().is_symlink())
.unwrap_or(false);
#[cfg(not(target_os = "macos"))]
let force_symlink = false;
if force_symlink || hardlink_file(src, dest).is_err() {
symlink_file(src, dest)?;
.unwrap_or(false)
{
return Err(_err);
}
Ok(())

hardlink_file(src, dest)
}

pub fn hardlink_file(src: &Path, dest: &Path) -> Result<()> {
Expand All @@ -344,11 +348,10 @@ fn symlink_file(src: &Path, dest: &Path) -> Result<()> {

#[cfg(windows)]
fn symlink_file(src: &Path, dest: &Path) -> Result<()> {
// we are supposed to not use symlink on windows
Err(anyhow!(RustupError::LinkingFile {
std::os::windows::fs::symlink_file(src, dest).with_context(|| RustupError::LinkingFile {
src: PathBuf::from(src),
dest: PathBuf::from(dest),
}))
})
}

pub(crate) fn copy_dir<'a, N>(
Expand Down

0 comments on commit 3d178ad

Please sign in to comment.