use std::fs;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::path::PathBuf;
use dirs;
use lazy_static::lazy_static;
use crate::nix;
use crate::proc::CommandError;
const UUID: &str = "bfe01d7a-c700-4529-acf1-88065df2cd25";
lazy_static! {
static ref CACHE_PATH: Option<PathBuf> = {
Some(
[
dirs::cache_dir()?,
format!("nix-query-{}.cache", UUID).into(),
]
.iter()
.collect(),
)
};
}
pub const NIX_ATTRS_COUNT_ESTIMATE: usize = 100_000;
pub const NIX_ATTRS_FILE_SIZE_ESTIMATE: usize = 5_000_000;
pub fn cache_exists() -> bool {
CACHE_PATH.as_ref().map(|p| p.is_file()).unwrap_or(false)
}
#[derive(Debug)]
pub enum CacheIoError {
NoCachePath,
Command(CommandError),
Io(Box<io::Error>),
}
impl From<io::Error> for CacheIoError {
fn from(e: io::Error) -> CacheIoError {
CacheIoError::Io(Box::new(e))
}
}
pub fn clear_cache() -> Result<(), CacheIoError> {
match fs::remove_file(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?) {
Ok(()) => Ok(()),
Err(io_err) =>
{
if let io::ErrorKind::NotFound = io_err.kind() {
Ok(())
} else {
Err(io_err.into())
}
}
}
}
pub fn write_cache(nix_attrs: &[u8]) -> Result<(), CacheIoError> {
File::create(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?)?
.write_all(nix_attrs)
.map_err(Into::into)
}
pub fn read_cache() -> Result<String, CacheIoError> {
let mut cache_file = File::open(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?)?;
let mut ret = String::with_capacity(NIX_ATTRS_FILE_SIZE_ESTIMATE);
cache_file.read_to_string(&mut ret)?;
Ok(ret)
}
pub fn ensure_cache() -> Result<String, CacheIoError> {
if !cache_exists() {
let attrs = nix::nix_query_all().map_err(CacheIoError::Command)?;
write_cache(attrs.as_bytes())?;
Ok(attrs)
} else {
read_cache()
}
}