Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions cli/tools/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,28 @@ fn upgrade_from_pr(
Ok(())
}

/// Creates the directory that the new executable is unpacked into and run from
/// by `check_exe`.
///
/// The directory is created next to `output_exe_path` when possible. That
/// directory has to be writable for the upgrade anyway, and keeping the new
/// executable on the same file system lets `replace_exe` rename it into place.
/// The system temporary directory is only a fallback, because it is often
/// mounted `noexec`, which makes running the new executable fail with
/// "Permission denied".
fn create_upgrade_temp_dir(
output_exe_path: &Path,
) -> Result<tempfile::TempDir, AnyError> {
if let Some(parent) = output_exe_path.parent()
&& let Ok(temp_dir) = tempfile::Builder::new()
.prefix(".deno-upgrade-")
.tempdir_in(parent)
{
return Ok(temp_dir);
}
tempfile::TempDir::new().context("failed to create temporary directory")
}

fn upgrade_from_branch(
branch: &str,
upgrade_flags: &UpgradeFlags,
Expand Down Expand Up @@ -1070,8 +1092,7 @@ pub async fn upgrade(
None
};

let temp_dir =
tempfile::TempDir::new().context("failed to create temporary directory")?;
let temp_dir = create_upgrade_temp_dir(output_exe_path)?;

let new_exe_path = if let Some(delta_binary) = maybe_delta_binary {
// Delta upgrade succeeded -- write the patched binary directly
Expand Down Expand Up @@ -3556,4 +3577,28 @@ mod test {
"step 2 should fetch from v2.7.12 release"
);
}

#[test]
fn upgrade_temp_dir_is_created_next_to_output_exe() {
let output_dir = tempfile::TempDir::new().unwrap();
let output_exe_path = output_dir.path().join("deno");
let temp_dir = create_upgrade_temp_dir(&output_exe_path).unwrap();
assert_eq!(temp_dir.path().parent(), Some(output_dir.path()));
let path = temp_dir.path().to_path_buf();
drop(temp_dir);
assert!(!path.exists());
}

#[test]
fn upgrade_temp_dir_falls_back_when_output_dir_is_missing() {
let output_dir = tempfile::TempDir::new().unwrap();
let output_exe_path = output_dir.path().join("missing").join("deno");
let temp_dir = create_upgrade_temp_dir(&output_exe_path).unwrap();
assert!(
!temp_dir
.path()
.starts_with(output_dir.path().join("missing"))
);
assert!(temp_dir.path().is_dir());
}
}