use std::fs::File;
use std::{fs, io};
use scallop::builtins::BuiltinFn;
use scallop::{Error, ExecStatus};
use tempfile::tempdir;
use crate::io::stdin;
use crate::utils::is_single_component;
pub(super) fn new(args: &[&str], cmd: BuiltinFn) -> scallop::Result<ExecStatus> {
let [source, name] = args[..] else {
return Err(Error::Base(format!("requires 2 args, got {}", args.len())));
};
if !is_single_component(name) {
return Err(Error::Base(format!("invalid filename: {name}")));
}
let tmp_dir =
tempdir().map_err(|e| Error::Base(format!("failed creating tempdir: {e}")))?;
let dest = tmp_dir.path().join(name);
if source == "-" {
let mut file = File::create(&dest)
.map_err(|e| Error::Base(format!("failed opening file: {dest:?}: {e}")))?;
io::copy(&mut stdin(), &mut file).map_err(|e| {
Error::Base(format!("failed writing stdin to file: {dest:?}: {e}"))
})?;
} else {
fs::copy(source, &dest).map_err(|e| {
Error::Base(format!("failed copying file {source:?} to {dest:?}: {e}"))
})?;
}
let path = dest
.to_str()
.ok_or_else(|| Error::Base(format!("invalid utf8 path: {dest:?}")))?;
cmd(&[path])
}
#[cfg(test)]
mod tests {
use crate::test::assert_err_re;
use super::super::functions::newbin;
use super::*;
#[test]
fn invalid_args() {
let r = new(&["bin", "pkgcraft"], newbin);
assert_err_re!(r, "^failed copying file \"bin\" .*$");
for f in ["bin/pkgcraft", "bin//pkgcraft", "/bin/pkgcraft", "pkgcraft/", "/"] {
let r = new(&["bin", f], newbin);
assert_err_re!(r, format!("^invalid filename: {f}$"));
}
}
}