use anyhow::Result;
use std::path::Path;
pub fn junction_or_symlink(src: &Path, dst: &Path) -> Result<()> {
if dst.exists() {
if dst.is_dir() {
let _ = std::fs::remove_dir_all(dst);
} else {
std::fs::remove_file(dst)?;
}
}
if src.is_dir() {
#[cfg(windows)]
{
junction::create(src, dst)?;
}
#[cfg(not(windows))]
{
std::os::unix::fs::symlink(src, dst)?;
}
} else {
std::fs::copy(src, dst)?;
}
Ok(())
}
pub fn merge_plugin(src: &Path, dst_root: &Path) -> Result<()> {
for entry in std::fs::read_dir(src)? {
let entry = entry?;
let name = entry.file_name();
let name_str = name.to_string_lossy();
if name_str.starts_with('.') {
continue;
}
let entry_src = entry.path();
if entry_src.is_dir() {
let target_dst = dst_root.join(&name);
if !target_dst.exists() {
std::fs::create_dir_all(&target_dst)?;
}
for sub in std::fs::read_dir(&entry_src)? {
let sub = sub?;
let sub_src = sub.path();
let sub_dst = target_dst.join(sub.file_name());
junction_or_symlink(&sub_src, &sub_dst)?;
}
} else {
let file_dst = dst_root.join(&name);
std::fs::copy(&entry_src, &file_dst)?;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::tempdir;
#[test]
fn test_merge_plugins() {
let root = tempdir().unwrap();
let merged = root.path().join("merged");
let plugin_a = root.path().join("plugin_a");
fs::create_dir_all(plugin_a.join("lua/plugin_a")).unwrap();
fs::write(plugin_a.join("lua/plugin_a/init.lua"), "print('a')").unwrap();
let plugin_b = root.path().join("plugin_b");
fs::create_dir_all(plugin_b.join("plugin")).unwrap();
fs::write(plugin_b.join("plugin/b.vim"), "echo 'b'").unwrap();
merge_plugin(&plugin_a, &merged).unwrap();
merge_plugin(&plugin_b, &merged).unwrap();
assert!(merged.join("lua/plugin_a/init.lua").exists());
assert!(merged.join("plugin/b.vim").exists());
}
#[test]
fn test_junction_creation() {
let root = tempdir().unwrap();
let src = root.path().join("src");
let dst = root.path().join("dst");
fs::create_dir_all(&src).unwrap();
fs::write(src.join("hello.txt"), "hello").unwrap();
junction_or_symlink(&src, &dst).unwrap();
assert!(dst.join("hello.txt").exists());
let content = fs::read_to_string(dst.join("hello.txt")).unwrap();
assert_eq!(content, "hello");
}
}