120 lines
4.3 KiB
Rust
120 lines
4.3 KiB
Rust
use regex::Regex;
|
|
use serde::{Deserialize, Serialize};
|
|
use snafu::ResultExt;
|
|
use std::collections::HashMap;
|
|
use std::fs;
|
|
|
|
use crate::constants::HARDWARE_CONFIG_FILE;
|
|
use crate::error::{FileReadError, FileWriteError, PeachConfigError};
|
|
use crate::utils::get_output;
|
|
use crate::RtcOption;
|
|
|
|
/// Returns a HashMap<String, String> of all the peach-packages which are currently installed
|
|
/// mapped to their version number e.g. { "peach-probe": "1.2.0", "peach-network": "1.4.0" }
|
|
pub fn get_currently_installed_microservices() -> Result<HashMap<String, String>, PeachConfigError>
|
|
{
|
|
// gets a list of all packages currently installed with dpkg
|
|
let packages = get_output(&["dpkg", "-l"])?;
|
|
|
|
// this regex matches packages which contain the word peach in them
|
|
// and has two match groups
|
|
// 1. the first match group gets the package name
|
|
// 2. the second match group gets the version number of the package
|
|
let re: Regex = Regex::new(r"\S+\s+(\S*peach\S+)\s+(\S+).*\n").unwrap();
|
|
|
|
// the following iterator, iterates through the captures matched via the regex
|
|
// and for each capture, creates a value in the hash map,
|
|
// which maps the name of the package, to its version number
|
|
// e.g. { "peach-probe": "1.2.0", "peach-network": "1.4.0" }
|
|
let peach_packages: HashMap<String, String> = re
|
|
.captures_iter(&packages)
|
|
.filter_map(|cap| {
|
|
let groups = (cap.get(1), cap.get(2));
|
|
match groups {
|
|
(Some(package), Some(version)) => {
|
|
Some((package.as_str().to_string(), version.as_str().to_string()))
|
|
}
|
|
_ => None,
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
// finally the hashmap of packages and version numbers is returned
|
|
Ok(peach_packages)
|
|
}
|
|
|
|
/// Output form of manifest
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Manifest {
|
|
// packages is a map of {package_name: version}
|
|
packages: HashMap<String, String>,
|
|
hardware: Option<HardwareConfig>,
|
|
}
|
|
|
|
/// The form that hardware configs are saved in when peach-config setup runs successfully
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct HardwareConfig {
|
|
// packages is a map of {package_name: version}
|
|
i2c: bool,
|
|
rtc: Option<RtcOption>,
|
|
}
|
|
|
|
/// Log which hardware settings were configured to a .json file
|
|
/// # Arguments
|
|
///
|
|
/// * `i2c` - a boolean flag, if true i2c will be configured
|
|
/// * `rtc` - an optional enum, if supplied indicates which real-time-clock model
|
|
/// is being used
|
|
///
|
|
/// Any error results in a PeachConfigError, otherwise the saved HardwareConfig object
|
|
/// is returned.
|
|
pub fn save_hardware_config(
|
|
i2c: bool,
|
|
rtc: Option<RtcOption>,
|
|
) -> Result<HardwareConfig, PeachConfigError> {
|
|
let hardware_config = HardwareConfig { i2c, rtc };
|
|
|
|
let json_str = serde_json::to_string(&hardware_config)?;
|
|
|
|
fs::write(HARDWARE_CONFIG_FILE, json_str).context(FileWriteError {
|
|
file: HARDWARE_CONFIG_FILE.to_string(),
|
|
})?;
|
|
|
|
Ok(hardware_config)
|
|
}
|
|
|
|
/// Load the hardware configs that were saved from the last successful run of peach-config setup
|
|
///
|
|
/// Returns an Ok(Some<HardwareConfg>) containing the configuration if one is found,
|
|
/// and returns Ok(None) if no hardware configuration was found.
|
|
fn load_hardware_config() -> Result<Option<HardwareConfig>, PeachConfigError> {
|
|
// if there is no hardware_config, return None
|
|
let hardware_config_exists = std::path::Path::new(HARDWARE_CONFIG_FILE).exists();
|
|
if !hardware_config_exists {
|
|
Ok(None)
|
|
}
|
|
// otherwise we load hardware_config from json
|
|
else {
|
|
let contents = fs::read_to_string(HARDWARE_CONFIG_FILE).context(FileReadError {
|
|
file: HARDWARE_CONFIG_FILE.to_string(),
|
|
})?;
|
|
let hardware_config: HardwareConfig = serde_json::from_str(&contents)?;
|
|
Ok(Some(hardware_config))
|
|
}
|
|
}
|
|
|
|
/// Outputs a Manifest in json form to stdout
|
|
/// which contains the currently installed peach packages
|
|
/// as well as the hardware configuration of the last run of peach-config setup.
|
|
pub fn generate_manifest() -> Result<(), PeachConfigError> {
|
|
let packages = get_currently_installed_microservices()?;
|
|
let hardware_config_option = load_hardware_config()?;
|
|
let manifest = Manifest {
|
|
packages,
|
|
hardware: hardware_config_option,
|
|
};
|
|
let output = serde_json::to_string(&manifest)?;
|
|
println!("{}", output);
|
|
Ok(())
|
|
}
|