From 512d0c2ace2c3e1a878e235b55fc55400298f74e Mon Sep 17 00:00:00 2001 From: Marcel Schneider Date: Sun, 1 Mar 2020 17:54:54 +0100 Subject: [PATCH] implement kind of cache --- src/app.rs | 20 ++++++++++++- src/cache.rs | 31 +++++++++++--------- src/template.rs | 76 +++++++------------------------------------------ 3 files changed, 47 insertions(+), 80 deletions(-) diff --git a/src/app.rs b/src/app.rs index 7c1cda8..9661b19 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,11 +5,13 @@ use std::path::PathBuf; // 3rd-party crate imports +use directories::ProjectDirs; use structopt::StructOpt; use log::{debug, error, info, trace, warn}; // Local Imports +use crate::cache::{Cache, File as FileCache}; use crate::errors::*; use crate::gitignore::Gitignore; use crate::helpers::{git_dir, BoilerplateOpts, HELP_TEMPLATE}; @@ -98,7 +100,23 @@ fn run_get(lang: &str) -> Result<()> { /// Runs the command `list-templates` #[allow(clippy::print_stdout)] fn run_list_templates() -> Result<()> { - let tmpl = GithubTemplates::new().chain_err(|| "Error while getting Templates")?; + let cache_root: PathBuf = match ProjectDirs::from("org", "webschneider", env!("CARGO_PKG_NAME")) + { + Some(dirs) => PathBuf::from(dirs.cache_dir()), + None => "/tmp".into(), + }; + + let cache: FileCache = FileCache::new(&cache_root, std::time::Duration::from_secs(60 * 24 * 2)) + .chain_err(|| "Error while creating FileCache")?; + let tmpl = if cache.exists("templates.json") { + cache.get("templates.json")? + } else { + let tmpls = GithubTemplates::new().chain_err(|| "Error while getting Templates")?; + cache + .set("templates.json", &tmpls) + .chain_err(|| "Error while writing templates to cache")?; + tmpls + }; let names = tmpl.list_names(); println!("{}", names.join("\n")); Ok(()) diff --git a/src/cache.rs b/src/cache.rs index 05beb91..753ddeb 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,4 +1,5 @@ use crate::errors::*; +use crate::template::GithubTemplates; use core::time::Duration; use log::{debug, trace}; use serde::Serialize; @@ -7,15 +8,18 @@ use std::io::{BufReader, BufWriter}; use std::path::PathBuf; use std::time::SystemTime; -pub trait Cache { - fn set(&self, key: &str, data: S) -> Result<()> - where S: Serialize; - fn get(&self, key: &str) -> Result> - where D: serde::de::DeserializeOwned; +pub trait Cache +where T: Serialize + serde::de::DeserializeOwned { + /// Stores the `data` under the given `key` + fn set(&self, key: &str, data: &T) -> Result<()>; + /// Retrieves the data under the given `key` + fn get(&self, key: &str) -> Result; + /// Checks whether the given key exists fn exists(&self, key: &str) -> bool; } /// A File cache +#[derive(Debug)] pub struct File { /// The root path to the files root: PathBuf, @@ -38,10 +42,9 @@ impl File { } Ok(Self { root: root.clone(), ttl }) } -} -impl Cache for File { - fn exists(&self, key: &str) -> bool { + /// Checks whether an element for the given key exists + pub fn exists(&self, key: &str) -> bool { trace!("Check existence of {} in file cache", key); let mut path = self.root.clone(); path.push(key); @@ -62,8 +65,8 @@ impl Cache for File { true } - fn set(&self, key: &str, data: S) -> Result<()> - where S: serde::Serialize { + /// Stores a `data` under the specified `key` + pub fn set(&self, key: &str, data: &GithubTemplates) -> Result<()> { let mut path: PathBuf = self.root.clone(); path.push(key); trace!("Serializing data to cache file {}", path.to_string_lossy()); @@ -76,17 +79,17 @@ impl Cache for File { Ok(()) } - fn get(&self, key: &str) -> Result> - where D: serde::de::DeserializeOwned { + /// Retrieves data for `key` + pub fn get(&self, key: &str) -> Result { let mut path = self.root.clone(); path.push(key); debug!("Retrieving {} from file cache", key); let f = FsFile::open(path) .chain_err(|| format!("Error while opening cache file for key {}", key))?; let reader = BufReader::new(f); - let obj: Vec = serde_json::from_reader(reader) + let obj: GithubTemplates = serde_json::from_reader(reader) .chain_err(|| "Error while reading templates from file cache")?; - debug!("Deserialized {} templates from file cache", obj.len()); + debug!("Deserialized {} templates from file cache", "some"); Ok(obj) } } diff --git a/src/template.rs b/src/template.rs index 1c7ebc4..f61d1e1 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,20 +1,20 @@ //! This module contains structs for working with the github templates -use directories::ProjectDirs; +use crate::cache::Cache; use log::{debug, trace}; use reqwest::blocking::Client; use reqwest::header::{ACCEPT, CONTENT_TYPE, USER_AGENT}; use serde::{Deserialize, Serialize}; -use std::fs::File; -use std::io::prelude::*; -use std::io::{BufReader, BufWriter}; -use std::path::PathBuf; -use std::time::{Duration, SystemTime}; use crate::errors::*; +type CacheContents = Vec