1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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))
}
}
|