mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-12-06 19:29:21 +01:00
Recursively import presets from provided directory (#33)
Allow a directory to be passed as a preset, in which case all files inside the directory (recursively) are treated as presets, loaded in lexicographical order. This allows one to compose a system by mixing in different presets, and easily change their order of execution.
This commit is contained in:
@@ -37,7 +37,7 @@ pub struct CreateCommand {
|
||||
#[structopt(parse(from_os_str))]
|
||||
pub path: Option<PathBuf>,
|
||||
|
||||
/// Additional pacakges to install
|
||||
/// Additional packages to install
|
||||
#[structopt(short = "p", long = "extra-packages", value_name = "package")]
|
||||
pub extra_packages: Vec<String>,
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ use serde::Deserialize;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -13,6 +14,21 @@ struct Preset {
|
||||
environment_variables: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
|
||||
if dir.is_dir() {
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
visit_dirs(&path, filevec)?;
|
||||
} else {
|
||||
filevec.push(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Preset {
|
||||
fn load(path: &Path) -> Result<Self, Error> {
|
||||
let data = fs::read_to_string(path)
|
||||
@@ -20,6 +36,23 @@ impl Preset {
|
||||
Ok(toml::from_str(&data)
|
||||
.with_context(|_| ErrorKind::Preset(format!("{}", path.display())))?)
|
||||
}
|
||||
|
||||
fn process(
|
||||
&self,
|
||||
packages: &mut HashSet<String>,
|
||||
scripts: &mut Vec<String>,
|
||||
environment_variables: &mut HashSet<String>,
|
||||
) {
|
||||
if let Some(preset_packages) = &self.packages {
|
||||
packages.extend(preset_packages.clone());
|
||||
}
|
||||
|
||||
if let Some(preset_environment_variables) = &self.environment_variables {
|
||||
environment_variables.extend(preset_environment_variables.clone());
|
||||
}
|
||||
|
||||
scripts.extend(self.script.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PresetsCollection {
|
||||
@@ -34,21 +67,31 @@ impl PresetsCollection {
|
||||
let mut environment_variables = HashSet::new();
|
||||
|
||||
for preset in list {
|
||||
let Preset {
|
||||
script,
|
||||
packages: preset_packages,
|
||||
environment_variables: preset_environment_variables,
|
||||
} = Preset::load(&preset)?;
|
||||
if preset.is_dir() {
|
||||
// Build vector of paths to files, then sort by path name
|
||||
// Recursively load directories of preset files
|
||||
let mut dir_paths: Vec<PathBuf> = Vec::new();
|
||||
visit_dirs(&preset, &mut dir_paths)
|
||||
.with_context(|_| ErrorKind::Preset(format!("{}", preset.display())))?;
|
||||
|
||||
if let Some(preset_packages) = preset_packages {
|
||||
packages.extend(preset_packages);
|
||||
// Order not guaranteed so we sort
|
||||
// In the future may want to support numerical sort i.e. 15_... < 100_...
|
||||
dir_paths.sort();
|
||||
|
||||
for path in dir_paths {
|
||||
Preset::load(&path)?.process(
|
||||
&mut packages,
|
||||
&mut scripts,
|
||||
&mut environment_variables,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Preset::load(&preset)?.process(
|
||||
&mut packages,
|
||||
&mut scripts,
|
||||
&mut environment_variables,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(preset_environment_variables) = preset_environment_variables {
|
||||
environment_variables.extend(preset_environment_variables);
|
||||
}
|
||||
|
||||
scripts.extend(script);
|
||||
}
|
||||
|
||||
let missing_envrionments: Vec<String> = environment_variables
|
||||
|
||||
Reference in New Issue
Block a user