mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-22 05:28:42 +00:00

Resolved #522 * Add dep tracing v0.1.37 to binstalk * Use `tracing` instead of `log` for logging in binstalk * Rm dev dep `env_logger` since `log` is no longer used * Rm unused dep `log` from binstalk * Replace use of `log` with `tracing` in crates/bin * Enable feat std of dep log in crates/bin * Add dep tracing v0.1.37 to binstalk-downloader * Replace use of `log` with `tracing` in binstalk-downloader * Rm unused dep `log` from binstalk-downlaoder * Wrap `ops::{install, resolve}` in `tracing::instrument` * Wrap `Download::and_{extract, visit_tar}` in `instrument` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
89 lines
2.6 KiB
Rust
89 lines
2.6 KiB
Rust
use std::{fs, io, path::Path};
|
|
|
|
use tempfile::NamedTempFile;
|
|
use tracing::debug;
|
|
|
|
/// Atomically install a file.
|
|
///
|
|
/// This is a blocking function, must be called in `block_in_place` mode.
|
|
pub fn atomic_install(src: &Path, dst: &Path) -> io::Result<()> {
|
|
debug!(
|
|
"Attempting to atomically rename from '{}' to '{}'",
|
|
src.display(),
|
|
dst.display()
|
|
);
|
|
|
|
if let Err(err) = fs::rename(src, dst) {
|
|
debug!("Attempting at atomic rename failed: {err:#?}, fallback to creating tempfile.");
|
|
// src and dst is not on the same filesystem/mountpoint.
|
|
// Fallback to creating NamedTempFile on the parent dir of
|
|
// dst.
|
|
|
|
let mut src_file = fs::File::open(src)?;
|
|
|
|
let parent = dst.parent().unwrap();
|
|
debug!("Creating named tempfile at '{}'", parent.display());
|
|
let mut tempfile = NamedTempFile::new_in(parent)?;
|
|
|
|
debug!(
|
|
"Copying from '{}' to '{}'",
|
|
src.display(),
|
|
tempfile.path().display()
|
|
);
|
|
io::copy(&mut src_file, tempfile.as_file_mut())?;
|
|
|
|
debug!("Retrieving permissions of '{}'", src.display());
|
|
let permissions = src_file.metadata()?.permissions();
|
|
|
|
debug!(
|
|
"Setting permissions of '{}' to '{permissions:#?}'",
|
|
tempfile.path().display()
|
|
);
|
|
tempfile.as_file().set_permissions(permissions)?;
|
|
|
|
debug!(
|
|
"Persisting '{}' to '{}'",
|
|
tempfile.path().display(),
|
|
dst.display()
|
|
);
|
|
tempfile.persist(dst).map_err(io::Error::from)?;
|
|
} else {
|
|
debug!("Attempting at atomically succeeded.");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
|
|
#[cfg(target_family = "unix")]
|
|
let f = std::os::unix::fs::symlink;
|
|
#[cfg(target_family = "windows")]
|
|
let f = std::os::windows::fs::symlink_file;
|
|
|
|
f(original, link)
|
|
}
|
|
|
|
/// Atomically install symlink "link" to a file "dst".
|
|
///
|
|
/// This is a blocking function, must be called in `block_in_place` mode.
|
|
pub fn atomic_symlink_file(dest: &Path, link: &Path) -> io::Result<()> {
|
|
let parent = link.parent().unwrap();
|
|
|
|
debug!("Creating tempPath at '{}'", parent.display());
|
|
let temp_path = NamedTempFile::new_in(parent)?.into_temp_path();
|
|
fs::remove_file(&temp_path)?;
|
|
|
|
debug!(
|
|
"Creating symlink '{}' to file '{}'",
|
|
temp_path.display(),
|
|
dest.display()
|
|
);
|
|
symlink_file(dest, &temp_path)?;
|
|
|
|
debug!(
|
|
"Persisting '{}' to '{}'",
|
|
temp_path.display(),
|
|
link.display()
|
|
);
|
|
temp_path.persist(link).map_err(io::Error::from)
|
|
}
|