src/symlink.rs (24 lines of code) (raw):
#[cfg(windows)]
use std::path::Path;
#[cfg(unix)]
pub(crate) use std::os::unix::fs::symlink as symlink_file;
/// Creates a symbolic link to a file.
///
/// On Windows, creating a symbolic link to a file requires Administrator
/// rights. Fall back to copying if creating the symbolic link fails.
#[cfg(windows)]
pub(crate) fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(
original: P,
link: Q,
) -> std::io::Result<()> {
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
static HAVE_PRINTED_WARNING: AtomicBool = AtomicBool::new(false);
std::os::windows::fs::symlink_file(&original, &link)
.or_else(|_| {
let _len: u64 = std::fs::copy(&original, &link)?;
// Print a warning about symbolic links, but only once per grcov run.
if HAVE_PRINTED_WARNING.compare_exchange(false, true, SeqCst, SeqCst).is_ok() {
eprintln!(
"Failed to create a symlink, but successfully copied file (as fallback).\n\
This is less efficient. You can enable symlinks without elevating to Administrator.\n\
See instructions at https://github.com/mozilla/grcov/blob/master/README.md#enabling-symlinks-on-windows");
}
Ok(())
}
)
}