bat_impl/assets/
assets_metadata.rs

1use std::fs::File;
2use std::path::Path;
3use std::time::SystemTime;
4
5use semver::Version;
6use serde::{Deserialize, Serialize};
7
8use crate::error::*;
9
10#[derive(Debug, PartialEq, Default, Serialize, Deserialize)]
11pub struct AssetsMetadata {
12    bat_version: Option<String>,
13    creation_time: Option<SystemTime>,
14}
15
16const FILENAME: &str = "metadata.yaml";
17
18impl AssetsMetadata {
19    #[cfg(feature = "build-assets")]
20    pub(crate) fn new(current_version: &str) -> AssetsMetadata {
21        AssetsMetadata {
22            bat_version: Some(current_version.to_owned()),
23            creation_time: Some(SystemTime::now()),
24        }
25    }
26
27    #[cfg(feature = "build-assets")]
28    pub(crate) fn save_to_folder(&self, path: &Path) -> Result<()> {
29        let file = File::create(path.join(FILENAME))?;
30        serde_yaml::to_writer(file, self)?;
31
32        Ok(())
33    }
34
35    fn try_load_from_folder(path: &Path) -> Result<Self> {
36        let file = File::open(path.join(FILENAME))?;
37        Ok(serde_yaml::from_reader(file)?)
38    }
39
40    /// Load metadata about the stored cache file from the given folder.
41    ///
42    /// There are several possibilities:
43    ///   - We find a metadata.yaml file and are able to parse it
44    ///       => return the contained information
45    ///   - We find a metadata.yaml file and but are not able to parse it
46    ///       => return a SerdeYamlError
47    ///   - We do not find a metadata.yaml file but a syntaxes.bin or themes.bin file
48    ///       => assume that these were created by an old version of bat and return
49    ///          AssetsMetadata::default() without version information
50    ///   - We do not find a metadata.yaml file and no cached assets
51    ///       => no user provided assets are available, return None
52    pub fn load_from_folder(path: &Path) -> Result<Option<Self>> {
53        match Self::try_load_from_folder(path) {
54            Ok(metadata) => Ok(Some(metadata)),
55            Err(e) => {
56                if let Error::SerdeYamlError(_) = e {
57                    Err(e)
58                } else if path.join("syntaxes.bin").exists() || path.join("themes.bin").exists() {
59                    Ok(Some(Self::default()))
60                } else {
61                    Ok(None)
62                }
63            }
64        }
65    }
66
67    pub fn is_compatible_with(&self, current_version: &str) -> bool {
68        let current_version =
69            Version::parse(current_version).expect("bat follows semantic versioning");
70        let stored_version = self
71            .bat_version
72            .as_ref()
73            .and_then(|ver| Version::parse(ver).ok());
74
75        if let Some(stored_version) = stored_version {
76            current_version.major == stored_version.major
77                && current_version.minor == stored_version.minor
78        } else {
79            false
80        }
81    }
82}