Add manager script

This commit is contained in:
2021-04-06 20:28:59 +02:00
commit ecb50e1cf5
6 changed files with 1096 additions and 0 deletions

91
manager/src/linker.rs Normal file
View File

@ -0,0 +1,91 @@
use crate::Opt;
use async_recursion::async_recursion;
use futures::future::join_all;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
use tokio::fs::{create_dir, read_dir, remove_file, symlink};
use tokio::try_join;
pub async fn link_tree(opt: &Opt) -> io::Result<()> {
dir(opt, PathBuf::new()).await
}
#[async_recursion]
async fn dir(opt: &Opt, relative: PathBuf) -> io::Result<()> {
let build_path = opt.build_dir.join(&relative);
let link_path = opt.link_dir.join(&relative);
info!("traversing {:?}", build_path);
match create_dir(&link_path).await {
Ok(_) => {}
Err(e) if e.kind() == ErrorKind::AlreadyExists => {}
Err(e) => return Err(e),
}
let mut walker = read_dir(&build_path).await?;
let mut dir_tasks = vec![];
let mut file_tasks = vec![];
while let Some(entry) = walker.next_entry().await? {
let meta = entry.metadata().await?;
let new_relative = relative.join(entry.file_name());
if meta.is_dir() {
dir_tasks.push(dir(opt, new_relative));
} else if meta.is_file() {
file_tasks.push(file(opt, new_relative));
}
}
let dirs = async {
join_all(dir_tasks)
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()
};
let files = async {
join_all(file_tasks)
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()
};
try_join!(dirs, files)?;
Ok(())
}
async fn file(opt: &Opt, relative: PathBuf) -> io::Result<()> {
let build_path = opt.build_dir.join(&relative);
let link_path = opt.link_dir.join(&relative);
match remove_file(&link_path).await {
Ok(_) => {
info!("removed existing file {:?}", link_path);
}
Err(e) if e.kind() == ErrorKind::NotFound => {}
Err(e) => return Err(e),
};
info!("linking {:?} to {:?}", link_path, build_path);
let symlink_content = if build_path.is_absolute() {
build_path
} else {
// TODO: this probably doesn't work for paths containing ".."
// TODO: this doesn't work if link path is absolute
let mut relative_symlink = PathBuf::new();
for _ in link_path.iter().skip(1).filter(|&c| c == ".") {
relative_symlink.push("..");
}
relative_symlink.push(&build_path);
relative_symlink
};
symlink(symlink_content, link_path).await?;
Ok(())
}