diff options
Diffstat (limited to 'src/hasher.rs')
| -rw-r--r-- | src/hasher.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/hasher.rs b/src/hasher.rs new file mode 100644 index 0000000..0be1808 --- /dev/null +++ b/src/hasher.rs @@ -0,0 +1,95 @@ +use std::ffi::OsString; +use std::process::Command; + +use anyhow::{bail, Context, Result}; + +use crate::package_installer::{PackageInstaller, PackageRequest}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Invocation { + program: OsString, + arguments: Vec<OsString>, +} + +impl Invocation { + pub fn new( + program: impl Into<OsString>, + arguments: impl IntoIterator<Item = impl Into<OsString>>, + ) -> Self { + Self { + program: program.into(), + arguments: arguments.into_iter().map(Into::into).collect(), + } + } + + pub fn program(&self) -> &OsString { + &self.program + } + + pub fn arguments(&self) -> &[OsString] { + &self.arguments + } +} + +pub trait CommandRunner { + fn run(&self, invocation: Invocation) -> Result<()>; +} + +#[derive(Debug, Default, Clone, Copy)] +pub struct ProcessRunner; + +impl CommandRunner for ProcessRunner { + fn run(&self, invocation: Invocation) -> Result<()> { + let status = Command::new(&invocation.program) + .args(&invocation.arguments) + .status() + .with_context(|| format!("run {}", invocation.program.to_string_lossy()))?; + if !status.success() { + bail!( + "{} exited with {status}", + invocation.program.to_string_lossy() + ); + } + Ok(()) + } +} + +#[derive(Debug)] +pub struct HasherInstaller<R> { + runner: R, +} + +impl<R> HasherInstaller<R> { + pub fn new(runner: R) -> Self { + Self { runner } + } + + pub fn runner(&self) -> &R { + &self.runner + } +} + +impl<R: CommandRunner> PackageInstaller for HasherInstaller<R> { + fn install(&self, request: &PackageRequest) -> Result<()> { + self.runner.run(Invocation::new( + "hsh", + [ + "--mountpoints=/proc".into(), + "--initroot-only".into(), + "--apt-config".into(), + request.apt_config().as_path().as_os_str().to_owned(), + "--workdir".into(), + request.workdir().as_os_str().to_owned(), + ], + ))?; + + let mut arguments = vec![ + OsString::from("--mountpoints=/proc"), + OsString::from("--workdir"), + request.workdir().as_os_str().to_owned(), + ]; + arguments.extend(request.selectors().iter().map(OsString::from)); + arguments.extend(request.packages().iter().map(OsString::from)); + self.runner.run(Invocation::new("hsh-install", arguments)) + } +} |