use std::{fs, io, path::Path};
use std::sync::{Condvar, Mutex};
use tracing::warn;
pub struct Semaphore {
counter: Mutex<usize>,
cvar: Condvar,
max: usize,
}
impl Semaphore {
pub fn new(max: usize) -> Self {
Self {
counter: Mutex::new(0),
cvar: Condvar::new(),
max,
}
}
pub fn acquire(&self) {
let mut count = self.counter.lock().unwrap();
while *count >= self.max {
count = self.cvar.wait(count).unwrap();
}
*count += 1;
}
pub fn release(&self) {
let mut count = self.counter.lock().unwrap();
*count -= 1;
self.cvar.notify_one();
}
}
pub fn rcopy<A: AsRef<Path>, B: AsRef<Path>>(
src: A,
dst: B,
exclude: Vec<String>,
) -> io::Result<()> {
let src = src.as_ref();
let dst = dst.as_ref();
if src.is_file() {
fs::copy(src, dst)?;
return Ok(());
}
if !dst.exists() {
fs::create_dir_all(dst)?;
}
for entry in fs::read_dir(src)? {
let entry = entry?;
let file_type = entry.file_type()?;
let src_path = entry.path();
let dest_path = dst.join(entry.file_name());
let name = src_path
.to_string_lossy()
.to_string()
.replace(src.to_string_lossy().to_string().as_str(), "")
.to_string();
if exclude.contains(&name) {
continue;
}
if file_type.is_dir() {
rcopy(&src_path, &dest_path, exclude.clone())?;
} else if file_type.is_file() {
fs::copy(&src_path, &dest_path)?;
} else if file_type.is_symlink() {
let link = fs::read_link(&src_path)?;
create_symlink(link, dest_path)?;
} else {
warn!("Unimplmented filetype copy attemp");
}
}
Ok(())
}
#[cfg(unix)]
pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
std::os::unix::fs::symlink(src, dst)
}
#[cfg(windows)]
pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
use std::fs;
let src = src.as_ref();
if src.is_dir() {
std::os::windows::fs::symlink_dir(src, dst)
} else {
std::os::windows::fs::symlink_file(src, dst)
}
}