51
pub fn copy_ownership_from_path<P: AsRef<Path>>(dst: P, src: Option<&Path>) -> Result<()> {
52
use libc::{chown, gid_t, uid_t};
53
use std::os::unix::ffi::OsStrExt;
54
use std::os::unix::fs::MetadataExt;
56
let mut src = match src {
58
None => dst.as_ref().parent().unwrap_or_else(|| Path::new(".")),
61
if src == Path::new("") {
65
let s = std::fs::metadata(src)?;
71
dst.as_ref().as_os_str().as_bytes().as_ptr() as *const i8,
78
"Unable to copy ownership from \"{}\" to \"{}\". \
79
You may want to set it manually.",
81
dst.as_ref().display()
87
pub fn is_dir(f: &std::path::Path) -> bool {
88
match std::fs::symlink_metadata(f) {
89
Ok(metadata) => metadata.is_dir(),
94
pub fn is_file(f: &std::path::Path) -> bool {
95
match std::fs::symlink_metadata(f) {
96
Ok(metadata) => metadata.is_file(),
101
pub fn is_link(f: &std::path::Path) -> bool {
102
match std::fs::symlink_metadata(f) {
103
Ok(metadata) => metadata.file_type().is_symlink(),
109
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dest: Q) -> std::io::Result<()> {
110
let src = src.as_ref();
111
let dest = dest.as_ref();
112
match std::fs::hard_link(src, dest) {
115
// TODO(jelmer): This should really be checking for
116
// e.kind() != std::io::ErrorKind::CrossesDeviceBoundary{
117
// See https://github.com/rust-lang/rust/issues/86442
118
if e.kind() != std::io::ErrorKind::Other {
121
std::fs::copy(src, dest)?;
127
#[cfg(any(target_os = "windows", target_env = "cygwin", target_os = "macos"))]
128
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dest: Q) -> io::Result<()> {
129
std::fs::copy(src.as_ref(), dest.as_ref())?;
132
pub fn copy_tree<P: AsRef<Path>, Q: AsRef<Path>>(from_path: P, to_path: Q) -> std::io::Result<()> {
133
for entry in WalkDir::new(from_path.as_ref()) {
135
let path = entry.path();
136
let dst_path = to_path
138
.join(path.strip_prefix(from_path.as_ref()).unwrap());
139
if entry.file_type().is_dir() {
140
match std::fs::create_dir(&dst_path) {
143
if e.kind() != std::io::ErrorKind::AlreadyExists || dst_path != to_path.as_ref()
149
} else if entry.file_type().is_file() {
150
std::fs::copy(path, dst_path)?;
151
} else if entry.file_type().is_symlink() {
152
let target = std::fs::read_link(path)?;
154
.strip_prefix(from_path.as_ref())
155
.unwrap_or(target.as_path());
157
std::os::unix::fs::symlink(target, dst_path)?;
159
std::os::windows::fs::symlink_file(target, dst_path)?;
161
return Err(std::io::Error::new(
162
std::io::ErrorKind::Other,
163
format!("Unsupported file type: {:?}", entry.file_type()),