1use std::fs;
2use std::fs::File;
3use std::io;
4use std::io::{Read, Write};
5use std::path::PathBuf;
6
7use dirs;
8use lazy_static::lazy_static;
9
10use crate::nix;
11use crate::proc::CommandError;
12
13const UUID: &str = "bfe01d7a-c700-4529-acf1-88065df2cd25";
16
17lazy_static! {
18 static ref CACHE_PATH: Option<PathBuf> = {
19 Some(
20 [
21 dirs::cache_dir()?,
22 format!("nix-query-{}.cache", UUID).into(),
23 ]
24 .iter()
25 .collect(),
26 )
27 };
28}
29
30pub const NIX_ATTRS_COUNT_ESTIMATE: usize = 100_000;
31pub const NIX_ATTRS_FILE_SIZE_ESTIMATE: usize = 5_000_000;
33
34pub fn cache_exists() -> bool {
35 CACHE_PATH.as_ref().map(|p| p.is_file()).unwrap_or(false)
36}
37
38#[derive(Debug)]
39pub enum CacheIoError {
40 NoCachePath,
41 Command(CommandError),
42 Io(Box<io::Error>),
43}
44
45impl From<io::Error> for CacheIoError {
46 fn from(e: io::Error) -> CacheIoError {
47 CacheIoError::Io(Box::new(e))
48 }
49}
50
51pub fn clear_cache() -> Result<(), CacheIoError> {
52 match fs::remove_file(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?) {
53 Ok(()) => Ok(()),
54 Err(io_err) =>
55 {
57 if let io::ErrorKind::NotFound = io_err.kind() {
58 Ok(())
59 } else {
60 Err(io_err.into())
61 }
62 }
63 }
64}
65
66pub fn write_cache(nix_attrs: &[u8]) -> Result<(), CacheIoError> {
67 File::create(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?)?
68 .write_all(nix_attrs)
69 .map_err(Into::into)
70}
71
72pub fn read_cache() -> Result<String, CacheIoError> {
73 let mut cache_file = File::open(CACHE_PATH.as_ref().ok_or(CacheIoError::NoCachePath)?)?;
74 let mut ret = String::with_capacity(NIX_ATTRS_FILE_SIZE_ESTIMATE);
75 cache_file.read_to_string(&mut ret)?;
76 Ok(ret)
77}
78
79pub fn ensure_cache() -> Result<String, CacheIoError> {
80 if !cache_exists() {
81 let attrs = nix::nix_query_all().map_err(CacheIoError::Command)?;
82 write_cache(attrs.as_bytes())?;
83 Ok(attrs)
84 } else {
85 read_cache()
86 }
87}