mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-12-06 19:29:21 +01:00
Add shared_directories preset parameter (#35)
This commit is contained in:
27
src/main.rs
27
src/main.rs
@@ -25,7 +25,7 @@ use std::process::{exit, Command as ProcessCommand};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use storage::EncryptedDevice;
|
||||
use storage::{BlockDevice, Filesystem, FilesystemType, LoopDevice};
|
||||
use storage::{BlockDevice, Filesystem, FilesystemType, LoopDevice, MountStack};
|
||||
use structopt::StructOpt;
|
||||
use tempfile::tempdir;
|
||||
use tool::Tool;
|
||||
@@ -264,10 +264,33 @@ fn create(command: args::CreateCommand) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
for script in presets.scripts {
|
||||
let mut bind_mount_stack = MountStack::new();
|
||||
if let Some(shared_dirs) = &script.shared_dirs {
|
||||
for dir in shared_dirs {
|
||||
// Create shared directories mount points inside chroot
|
||||
std::fs::create_dir_all(
|
||||
mount_point
|
||||
.path()
|
||||
.join(PathBuf::from("shared_dirs/"))
|
||||
.join(dir.file_name().unwrap()),
|
||||
)
|
||||
.context(ErrorKind::PresetScript)?;
|
||||
|
||||
// Bind mount shared directories
|
||||
let target = mount_point
|
||||
.path()
|
||||
.join(PathBuf::from("shared_dirs/"))
|
||||
.join(dir.file_name().unwrap());
|
||||
bind_mount_stack
|
||||
.bind_mount(dir.clone(), target, None)
|
||||
.context(ErrorKind::Mounting)?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut script_file =
|
||||
tempfile::NamedTempFile::new_in(mount_point.path()).context(ErrorKind::PresetScript)?;
|
||||
script_file
|
||||
.write_all(script.as_bytes())
|
||||
.write_all(script.script_text.as_bytes())
|
||||
.and_then(|_| script_file.as_file_mut().metadata())
|
||||
.and_then(|metadata| {
|
||||
let mut permissions = metadata.permissions();
|
||||
|
||||
@@ -12,6 +12,7 @@ struct Preset {
|
||||
packages: Option<Vec<String>>,
|
||||
script: Option<String>,
|
||||
environment_variables: Option<Vec<String>>,
|
||||
shared_directories: Option<Vec<PathBuf>>,
|
||||
}
|
||||
|
||||
fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
|
||||
@@ -22,7 +23,9 @@ fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
|
||||
if path.is_dir() {
|
||||
visit_dirs(&path, filevec)?;
|
||||
} else {
|
||||
filevec.push(entry.path());
|
||||
if entry.path().extension() == Some(&std::ffi::OsString::from("toml")) {
|
||||
filevec.push(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,9 +43,10 @@ impl Preset {
|
||||
fn process(
|
||||
&self,
|
||||
packages: &mut HashSet<String>,
|
||||
scripts: &mut Vec<String>,
|
||||
scripts: &mut Vec<Script>,
|
||||
environment_variables: &mut HashSet<String>,
|
||||
) {
|
||||
path: &PathBuf,
|
||||
) -> Result<(), ErrorKind> {
|
||||
if let Some(preset_packages) = &self.packages {
|
||||
packages.extend(preset_packages.clone());
|
||||
}
|
||||
@@ -51,19 +55,52 @@ impl Preset {
|
||||
environment_variables.extend(preset_environment_variables.clone());
|
||||
}
|
||||
|
||||
scripts.extend(self.script.clone());
|
||||
if let Some(script_text) = &self.script {
|
||||
scripts.push(Script {
|
||||
script_text: script_text.clone(),
|
||||
shared_dirs: self
|
||||
.shared_directories
|
||||
.clone()
|
||||
.map(|x| {
|
||||
// Convert directories to absolute paths
|
||||
// If any shared directory is not a directory then throw an error
|
||||
x.iter()
|
||||
.cloned()
|
||||
.map(|y| {
|
||||
let full_path = path.parent().unwrap().join(&y);
|
||||
if full_path.is_dir() {
|
||||
Ok(full_path)
|
||||
} else {
|
||||
Err(ErrorKind::Preset(format!(
|
||||
"Preset: {} - shared directory: {} is not directory",
|
||||
path.display(),
|
||||
y.display()
|
||||
)))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, ErrorKind>>()
|
||||
})
|
||||
.map_or(Ok(None), |r| r.map(Some))?,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Script {
|
||||
pub script_text: String,
|
||||
pub shared_dirs: Option<Vec<PathBuf>>,
|
||||
}
|
||||
|
||||
pub struct PresetsCollection {
|
||||
pub packages: HashSet<String>,
|
||||
pub scripts: Vec<String>,
|
||||
pub scripts: Vec<Script>,
|
||||
}
|
||||
|
||||
impl PresetsCollection {
|
||||
pub fn load(list: &[PathBuf]) -> Result<Self, Error> {
|
||||
let mut packages = HashSet::new();
|
||||
let mut scripts = Vec::new();
|
||||
let mut scripts: Vec<Script> = Vec::new();
|
||||
let mut environment_variables = HashSet::new();
|
||||
|
||||
for preset in list {
|
||||
@@ -83,17 +120,18 @@ impl PresetsCollection {
|
||||
&mut packages,
|
||||
&mut scripts,
|
||||
&mut environment_variables,
|
||||
);
|
||||
&path,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
Preset::load(&preset)?.process(
|
||||
&mut packages,
|
||||
&mut scripts,
|
||||
&mut environment_variables,
|
||||
);
|
||||
&preset,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
let missing_envrionments: Vec<String> = environment_variables
|
||||
.into_iter()
|
||||
.filter(|var| env::var(var).is_err())
|
||||
|
||||
@@ -38,6 +38,24 @@ impl<'a> MountStack<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bind_mount(
|
||||
&mut self,
|
||||
source: PathBuf,
|
||||
target: PathBuf,
|
||||
options: Option<&str>,
|
||||
) -> nix::Result<()> {
|
||||
debug!("Mounting {:?} to {:?}", source, target);
|
||||
mount::<_, _, str, _>(
|
||||
Some(&source),
|
||||
&target,
|
||||
None,
|
||||
MsFlags::MS_BIND | MsFlags::MS_NOATIME, // Read-only flag has no effect for bind mounts
|
||||
options,
|
||||
)?;
|
||||
self.targets.push(target);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn _umount(&mut self) -> Result<(), Error> {
|
||||
let mut result = Ok(());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user