use std::fs::File; use std::path::Path; use std::time::SystemTime; use semver::Version; use serde_derive::{Deserialize, Serialize}; use crate::error::*; #[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct AssetsMetadata { bat_version: Option, creation_time: Option, } const FILENAME: &str = "metadata.yaml"; impl AssetsMetadata { #[cfg(feature = "build-assets")] pub(crate) fn new(current_version: &str) -> AssetsMetadata { AssetsMetadata { bat_version: Some(current_version.to_owned()), creation_time: Some(SystemTime::now()), } } #[cfg(feature = "build-assets")] pub(crate) fn save_to_folder(&self, path: &Path) -> Result<()> { let file = File::create(path.join(FILENAME))?; serde_yaml::to_writer(file, self)?; Ok(()) } fn try_load_from_folder(path: &Path) -> Result { let file = File::open(path.join(FILENAME))?; Ok(serde_yaml::from_reader(file)?) } /// Load metadata about the stored cache file from the given folder. /// /// There are several possibilities: /// - We find a metadata.yaml file and are able to parse it /// => return the contained information /// - We find a metadata.yaml file and but are not able to parse it /// => return a SerdeYamlError /// - We do not find a metadata.yaml file but a syntaxes.bin or themes.bin file /// => assume that these were created by an old version of bat and return /// AssetsMetadata::default() without version information /// - We do not find a metadata.yaml file and no cached assets /// => no user provided assets are available, return None pub fn load_from_folder(path: &Path) -> Result> { match Self::try_load_from_folder(path) { Ok(metadata) => Ok(Some(metadata)), Err(e) => { if let Error::SerdeYamlError(_) = e { Err(e) } else if path.join("syntaxes.bin").exists() || path.join("themes.bin").exists() { Ok(Some(Self::default())) } else { Ok(None) } } } } pub fn is_compatible_with(&self, current_version: &str) -> bool { let current_version = Version::parse(current_version).expect("bat follows semantic versioning"); let stored_version = self .bat_version .as_ref() .and_then(|ver| Version::parse(ver).ok()); if let Some(stored_version) = stored_version { current_version.major == stored_version.major && current_version.minor == stored_version.minor } else { false } } }