Merge branch 'config_include' into 'master'

Support including other config files from a config file

See merge request redox-os/installer!29
This commit is contained in:
Jeremy Soller
2024-01-04 15:23:21 +00:00
8 changed files with 83 additions and 48 deletions
+6 -19
View File
@@ -3,13 +3,13 @@ extern crate redox_installer;
extern crate serde;
extern crate toml;
use std::io::{Read, Write};
use std::io::Write;
use std::path::Path;
use std::{env, fs, io, process};
use arg_parser::ArgParser;
use redox_installer::PackageConfig;
use redox_installer::{Config, PackageConfig};
fn main() {
let stderr = io::stderr();
@@ -27,24 +27,11 @@ fn main() {
// If not set on the command line or the filesystem config, then build packages from source.
let repo_binary = parser.found("repo-binary");
let mut config_data = String::new();
let mut config = if let Some(path) = parser.get_opt("config") {
match fs::File::open(&path) {
Ok(mut config_file) => match config_file.read_to_string(&mut config_data) {
Ok(_) => match toml::from_str(&config_data) {
Ok(config) => config,
Err(err) => {
writeln!(stderr, "installer: {}: failed to decode: {}", path, err).unwrap();
process::exit(1);
}
},
Err(err) => {
writeln!(stderr, "installer: {}: failed to read: {}", path, err).unwrap();
process::exit(1);
}
},
match Config::from_file(Path::new(&path)) {
Ok(config) => config,
Err(err) => {
writeln!(stderr, "installer: {}: failed to open: {}", path, err).unwrap();
writeln!(stderr, "installer: {err}").unwrap();
process::exit(1);
}
}
@@ -55,7 +42,7 @@ fn main() {
// Add filesystem.toml to config
config.files.push(redox_installer::FileConfig {
path: "filesystem.toml".to_string(),
data: config_data,
data: toml::to_string_pretty(&config).unwrap(),
..Default::default()
});
+1 -18
View File
@@ -309,24 +309,7 @@ fn main() {
efi_partition_size: None,
};
let res = with_whole_disk(&disk_path, &disk_option, |mount_path| -> Result<(), failure::Error> {
let mut config: Config = {
let path = root_path.join("filesystem.toml");
match fs::read_to_string(&path) {
Ok(config_data) => {
match toml::from_str(&config_data) {
Ok(config) => {
config
},
Err(err) => {
return Err(format_err!("{}: failed to decode: {}", path.display(), err));
}
}
},
Err(err) => {
return Err(format_err!("{}: failed to read: {}", path.display(), err));
}
}
};
let mut config: Config = Config::from_file(&root_path.join("filesystem.toml"))?;
// Copy filesystem.toml, which is not packaged
let mut files = vec![
+1 -1
View File
@@ -29,7 +29,7 @@ fn chown<P: AsRef<Path>>(path: P, uid: uid_t, gid: gid_t, recursive: bool) -> Re
Ok(())
}
#[derive(Clone, Debug, Default, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct FileConfig {
pub path: String,
pub data: String,
+9 -1
View File
@@ -1,7 +1,15 @@
#[derive(Clone, Debug, Default, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct GeneralConfig {
pub prompt: bool,
// Allow config to specify cookbook recipe or binary package as default
pub repo_binary: Option<bool>,
pub efi_partition_size: Option<u32>, //MiB
}
impl GeneralConfig {
pub(super) fn merge(&mut self, other: GeneralConfig) {
self.prompt = other.prompt;
self.repo_binary = other.repo_binary.or(self.repo_binary);
self.efi_partition_size = other.efi_partition_size.or(self.efi_partition_size);
}
}
+64 -2
View File
@@ -1,12 +1,17 @@
use std::collections::BTreeMap;
use std::fs;
use std::mem;
use std::path::{Path, PathBuf};
pub mod general;
pub mod file;
pub mod general;
pub mod package;
pub mod user;
#[derive(Clone, Debug, Default, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Config {
#[serde(default)]
pub include: Vec<PathBuf>,
pub general: general::GeneralConfig,
#[serde(default)]
pub packages: BTreeMap<String, package::PackageConfig>,
@@ -15,3 +20,60 @@ pub struct Config {
#[serde(default)]
pub users: BTreeMap<String, user::UserConfig>,
}
impl Config {
pub fn from_file(path: &Path) -> Result<Self, failure::Error> {
let mut config: Config = match fs::read_to_string(&path) {
Ok(config_data) => match toml::from_str(&config_data) {
Ok(config) => config,
Err(err) => {
return Err(format_err!("{}: failed to decode: {}", path.display(), err));
}
},
Err(err) => {
return Err(format_err!("{}: failed to read: {}", path.display(), err));
}
};
let config_dir = path.parent().unwrap();
let mut configs = mem::take(&mut config.include)
.into_iter()
.map(|path| Config::from_file(&config_dir.join(path)))
.collect::<Result<Vec<Config>, failure::Error>>()?;
configs.push(config); // Put ourself last to ensure that it overwrites anything else.
config = configs.remove(0);
for other_config in configs {
config.merge(other_config);
}
Ok(config)
}
pub fn merge(&mut self, other: Config) {
assert!(self.include.is_empty());
assert!(other.include.is_empty());
let Config {
include: _,
general: other_general,
packages: other_packages,
files: other_files,
users: other_users,
} = other;
self.general.merge(other_general);
for (package, package_config) in other_packages {
self.packages.insert(package, package_config);
}
self.files.extend(other_files);
for (user, user_config) in other_users {
self.users.insert(user, user_config);
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum PackageConfig {
Empty,
+1 -1
View File
@@ -1,4 +1,4 @@
#[derive(Clone, Debug, Default, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct UserConfig {
pub password: Option<String>,
pub uid: Option<u32>,
-5
View File
@@ -137,11 +137,6 @@ path = "/usr/bin"
data = "../bin"
symlink = true
[[files]]
path = "/usr/games"
data = "../games"
symlink = true
[[files]]
path = "/usr/include"
data = "../include"