endcap-sl-software-ri-gener.../src/io.rs

96 lines
3.2 KiB
Rust

//! File IO for generated codes.
use std::{collections::HashMap, fs, io, path, process};
use thiserror::Error;
use crate::types::XmlGitInfo;
#[derive(Debug, Error)]
pub enum XmlGitInfoError {
#[error("io error while getting xml git info: {msg} {source}")]
IOError {
msg: &'static str,
#[source]
source: io::Error,
},
#[error("git failed: {msg}: {stderr}")]
CommandFailed { msg: &'static str, stderr: String },
}
impl XmlGitInfoError {
fn io_error(e: io::Error, msg: &'static str) -> Self {
XmlGitInfoError::IOError { msg, source: e }
}
}
pub(crate) fn get_xml_gitinfo(xml_path: &path::Path) -> Result<XmlGitInfo, XmlGitInfoError> {
let describe = process::Command::new("git")
.args(["describe", "--always", "--dirty"])
.current_dir(xml_path.parent().unwrap())
.output()
.map_err(|e| XmlGitInfoError::io_error(e, "git describe"))?;
let describe = if describe.status.success() {
String::from_utf8_lossy(&describe.stdout).trim().to_owned()
} else {
return Err(XmlGitInfoError::CommandFailed {
msg: "git describe",
stderr: String::from_utf8_lossy(&describe.stderr).into_owned(),
});
};
let timestamp = process::Command::new("git")
.args(["log", "-1", "--pretty=format:'%cI'"])
.current_dir(xml_path.parent().unwrap())
.output()
.map_err(|e| XmlGitInfoError::io_error(e, "git log (timestamp)"))?;
let timestamp = if timestamp.status.success() {
String::from_utf8_lossy(&timestamp.stdout).trim().to_owned()
} else {
return Err(XmlGitInfoError::CommandFailed {
msg: "git log (timestamp)",
stderr: String::from_utf8_lossy(&timestamp.stderr).into_owned(),
});
};
let sha = process::Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(xml_path.parent().unwrap())
.output()
.map_err(|e| XmlGitInfoError::io_error(e, "git rev-parse (sha)"))?;
let git_sha = if sha.status.success() {
String::from_utf8_lossy(&sha.stdout).trim().to_owned()
} else {
return Err(XmlGitInfoError::CommandFailed {
msg: "git rev-parse (sha)",
stderr: String::from_utf8_lossy(&sha.stderr).into_owned(),
});
};
Ok(XmlGitInfo {
describe,
commit_timestamp: timestamp,
sha: git_sha,
})
}
/// Write formatted codes generated with [`Module::generate_code`](crate::types::Module::generate_code).
pub fn write_to_files(
files: HashMap<path::PathBuf, syn::File>,
out_path: &path::Path,
) -> io::Result<()> {
if !out_path.is_dir() {
return Err(io::Error::from(io::ErrorKind::NotADirectory));
}
if fs::read_dir(out_path)?.next().is_some() {
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!("out path `{}` is not empty", out_path.display()),
));
}
for (file_path, code) in files {
fs::DirBuilder::new()
.recursive(true)
.create(out_path.join(&file_path).parent().unwrap())?;
fs::write(out_path.join(&file_path), prettyplease::unparse(&code))?;
}
Ok(())
}