Skip to content

Commit

Permalink
run_make_support: extract copy_symlink helper
Browse files Browse the repository at this point in the history
  • Loading branch information
jieyouxu committed Dec 22, 2024
1 parent a2bcfae commit 73fbac8
Showing 1 changed file with 42 additions and 26 deletions.
68 changes: 42 additions & 26 deletions src/tools/run-make-support/src/fs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
use std::io;
use std::path::{Path, PathBuf};

/// Copy a directory into another.
/// Given a symlink at `src`, read its target, then create a new symlink at `dst` also pointing to
/// target.
pub fn copy_symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref();
let dst = dst.as_ref();
if let Err(e) = copy_symlink_raw(src, dst) {
panic!("failed to copy symlink from `{}` to `{}`: {e}", src.display(), dst.display(),);
}
}

fn copy_symlink_raw(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
// Traverse symlink once to find path of target entity.
let target_path = std::fs::read_link(src)?;

let new_symlink_path = dst.as_ref();
#[cfg(windows)]
{
use std::os::windows::fs::FileTypeExt;
if ty.is_symlink_dir() {
std::os::windows::fs::symlink_dir(&target_path, new_symlink_path)?;
} else {
// Target may be a file or another symlink, in any case we can use
// `symlink_file` here.
std::os::windows::fs::symlink_file(&target_path, new_symlink_path)?;
}
}
#[cfg(unix)]
{
std::os::unix::fs::symlink(target_path, new_symlink_path)?;
}
#[cfg(not(any(windows, unix)))]
{
// Technically there's also wasi, but I have no clue about wasi symlink
// semantics and which wasi targets / environment support symlinks.
unimplemented!("unsupported target");
}
Ok(())
}

/// Copy a directory into another. This will not traverse symlinks; instead, it will create new
/// symlinks pointing at target paths that symlinks in the original directory points to.
pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
let dst = dst.as_ref();
Expand All @@ -14,31 +54,7 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
if ty.is_dir() {
copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
} else if ty.is_symlink() {
// Traverse symlink once to find path of target entity.
let target_path = std::fs::read_link(entry.path())?;

let new_symlink_path = dst.join(entry.file_name());
#[cfg(windows)]
{
use std::os::windows::fs::FileTypeExt;
if ty.is_symlink_dir() {
std::os::windows::fs::symlink_dir(&target_path, new_symlink_path)?;
} else {
// Target may be a file or another symlink, in any case we can use
// `symlink_file` here.
std::os::windows::fs::symlink_file(&target_path, new_symlink_path)?;
}
}
#[cfg(unix)]
{
std::os::unix::fs::symlink(target_path, new_symlink_path)?;
}
#[cfg(not(any(windows, unix)))]
{
// Technically there's also wasi, but I have no clue about wasi symlink
// semantics and which wasi targets / environment support symlinks.
unimplemented!("unsupported target");
}
copy_symlink_raw(entry.path(), dst.join(entry.file_name()))?;
} else {
std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
}
Expand Down

0 comments on commit 73fbac8

Please sign in to comment.