mirror of
https://github.com/Noratrieb/website.git
synced 2026-01-14 08:55:01 +01:00
97 lines
3.2 KiB
Rust
97 lines
3.2 KiB
Rust
use color_eyre::{
|
|
eyre::{bail, Context},
|
|
Result,
|
|
};
|
|
use std::{fs, io, os::unix::ffi::OsStrExt, path::{Path, PathBuf}, process::Command};
|
|
|
|
pub fn run_process(cmd: &mut Command) -> Result<String> {
|
|
fn run_process_inner(cmd: &mut Command) -> Result<String> {
|
|
let name = cmd.get_program().to_os_string();
|
|
let output = cmd
|
|
.output()
|
|
.wrap_err(format!("failed to spawn process {name:?}"))?;
|
|
|
|
if !output.status.success() {
|
|
bail!(
|
|
"command returned error: {}",
|
|
String::from_utf8(output.stderr).wrap_err("stderr is not UTF-8")?
|
|
);
|
|
}
|
|
|
|
String::from_utf8(output.stdout).wrap_err("stdout is not UTF-8")
|
|
}
|
|
run_process_inner(cmd).wrap_err(format!(
|
|
"{} {}",
|
|
cmd.get_program().to_str().unwrap(),
|
|
cmd.get_args()
|
|
.map(|arg| format!("'{}'", arg.to_str().unwrap()))
|
|
.collect::<Vec<_>>()
|
|
.join(" ")
|
|
))
|
|
}
|
|
|
|
pub fn create_dir_if_not_exist(p: &Path) -> Result<()> {
|
|
match std::fs::create_dir(p) {
|
|
Ok(()) => debug!(?p, "Created directory"),
|
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {}
|
|
e => return e.wrap_err("failed to create submodules"),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn cp_r(from: &Path, to: &Path) -> Result<()> {
|
|
copy_fn(from, to, |content, _, _| Ok(content))
|
|
}
|
|
|
|
pub struct CopyOpts {
|
|
pub dest_path: PathBuf,
|
|
}
|
|
|
|
pub fn copy_fn(
|
|
from: &Path,
|
|
to: &Path,
|
|
mut map: impl FnMut(Vec<u8>, Option<&str>, &mut CopyOpts) -> Result<Vec<u8>>,
|
|
) -> Result<()> {
|
|
let mut worklist = vec![from.to_owned()];
|
|
|
|
while let Some(ref item) = worklist.pop() {
|
|
let mut process = || -> Result<()> {
|
|
let meta = fs::metadata(item).wrap_err("getting metadata")?;
|
|
let relative = item.strip_prefix(from).wrap_err("subpath stripping")?;
|
|
let dest = to.join(relative);
|
|
|
|
if meta.is_dir() {
|
|
let items = fs::read_dir(item).wrap_err("read_dir")?;
|
|
for item in items {
|
|
let item = item.wrap_err("entry")?;
|
|
worklist.push(item.path());
|
|
}
|
|
|
|
match fs::create_dir_all(&dest) {
|
|
Ok(()) => {}
|
|
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {}
|
|
e => return e.wrap_err_with(|| format!("creating {}", dest.display())),
|
|
}
|
|
} else {
|
|
let content = fs::read(item).wrap_err("reading file")?;
|
|
let ext = match item.extension() {
|
|
Some(ext) => Some(
|
|
std::str::from_utf8(ext.as_bytes())
|
|
.wrap_err("file extension is invalid UTF-8")?,
|
|
),
|
|
None => None,
|
|
};
|
|
let mut opts = CopyOpts {
|
|
dest_path: dest.clone(),
|
|
};
|
|
let result = map(content, ext, &mut opts).wrap_err("applying mapping")?;
|
|
fs::write(opts.dest_path, result)
|
|
.wrap_err_with(|| format!("creating {}", dest.display()))?;
|
|
}
|
|
Ok(())
|
|
};
|
|
process().wrap_err_with(|| format!("copying {}", item.display()))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|