From 35d1d243995bb718f2b9237917ab6945d517cd3b Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 13 Aug 2022 11:18:20 -0400 Subject: [PATCH] Make cache configurable (#6) --- src/bin/rust_python_linter.rs | 51 +++++++---------------------------- src/cache.rs | 48 +++++++++++++++++++++++++++++++-- src/lib.rs | 7 ++--- src/linter.rs | 7 ++--- src/logging.rs | 37 +++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 49 deletions(-) create mode 100644 src/logging.rs diff --git a/src/bin/rust_python_linter.rs b/src/bin/rust_python_linter.rs index 173fb024dd..08e7d6e987 100644 --- a/src/bin/rust_python_linter.rs +++ b/src/bin/rust_python_linter.rs @@ -4,13 +4,15 @@ use std::time::{Duration, Instant}; use ::rust_python_linter::fs::collect_python_files; use ::rust_python_linter::linter::check_path; +use ::rust_python_linter::logging::set_up_logging; +use ::rust_python_linter::message::Message; +use ::rust_python_linter::timestamped_println; use anyhow::Result; use clap::{Parser, ValueHint}; use colored::Colorize; use log::{debug, error}; use notify::{watcher, RecursiveMode, Watcher}; use rayon::prelude::*; -use rust_python_linter::message::Message; use walkdir::DirEntry; #[derive(Debug, Parser)] @@ -23,44 +25,11 @@ struct Cli { verbose: bool, #[clap(short, long, action)] watch: bool, + #[clap(short, long, action)] + no_cache: bool, } -#[macro_export] -macro_rules! timestamped_println { - ($($arg:tt)*) => { - println!( - "[{}] {}", - chrono::Local::now() - .format("%H:%M:%S %p") - .to_string() - .dimmed(), - format_args!($($arg)*) - ) - } -} - -fn set_up_logging(verbose: bool) -> Result<()> { - fern::Dispatch::new() - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record.level(), - message - )) - }) - .level(if verbose { - log::LevelFilter::Debug - } else { - log::LevelFilter::Info - }) - .chain(std::io::stdout()) - .apply() - .map_err(|e| e.into()) -} - -fn run_once(files: &[PathBuf]) -> Result> { +fn run_once(files: &[PathBuf], cache: bool) -> Result> { // Collect all the files to check. let start = Instant::now(); let files: Vec = files.iter().flat_map(collect_python_files).collect(); @@ -71,7 +40,7 @@ fn run_once(files: &[PathBuf]) -> Result> { let messages: Vec = files .par_iter() .map(|entry| { - check_path(entry.path()).unwrap_or_else(|e| { + check_path(entry.path(), &cache.into()).unwrap_or_else(|e| { error!("Failed to check {}: {e:?}", entry.path().to_string_lossy()); vec![] }) @@ -123,7 +92,7 @@ fn main() -> Result<()> { clearscreen::clear()?; timestamped_println!("Starting linter in watch mode...\n"); - let messages = run_once(&cli.files)?; + let messages = run_once(&cli.files, !cli.no_cache)?; report_continuously(&messages)?; // Configure the file watcher. @@ -140,14 +109,14 @@ fn main() -> Result<()> { clearscreen::clear()?; timestamped_println!("File change detected...\n"); - let messages = run_once(&cli.files)?; + let messages = run_once(&cli.files, !cli.no_cache)?; report_continuously(&messages)?; } Err(e) => return Err(e.into()), } } } else { - let messages = run_once(&cli.files)?; + let messages = run_once(&cli.files, !cli.no_cache)?; report_once(&messages)?; } diff --git a/src/cache.rs b/src/cache.rs index d7c0aa5978..96b3527724 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -26,6 +26,42 @@ struct CheckResult { messages: Vec, } +pub enum Mode { + ReadWrite, + ReadOnly, + WriteOnly, + None, +} + +impl Mode { + fn allow_read(&self) -> bool { + match self { + Mode::ReadWrite => true, + Mode::ReadOnly => true, + Mode::WriteOnly => false, + Mode::None => false, + } + } + + fn allow_write(&self) -> bool { + match self { + Mode::ReadWrite => true, + Mode::ReadOnly => false, + Mode::WriteOnly => true, + Mode::None => false, + } + } +} + +impl From for Mode { + fn from(value: bool) -> Self { + match value { + true => Mode::ReadWrite, + false => Mode::None, + } + } +} + fn cache_dir() -> &'static str { "./.cache" } @@ -34,7 +70,11 @@ fn cache_key(path: &Path) -> Cow { path.to_string_lossy() } -pub fn get(path: &Path) -> Option> { +pub fn get(path: &Path, mode: &Mode) -> Option> { + if !mode.allow_read() { + return None; + }; + match cacache::read_sync(cache_dir(), cache_key(path)) { Ok(encoded) => match path.metadata() { Ok(m) => match bincode::deserialize::(&encoded[..]) { @@ -53,7 +93,11 @@ pub fn get(path: &Path) -> Option> { None } -pub fn set(path: &Path, messages: &[Message]) { +pub fn set(path: &Path, messages: &[Message], mode: &Mode) { + if !mode.allow_write() { + return; + }; + if let Ok(metadata) = path.metadata() { let check_result = CheckResultRef { metadata: &CacheMetadata { diff --git a/src/lib.rs b/src/lib.rs index 49fc92d7bd..7f514ed7f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ mod cache; -mod checker; +pub mod checker; pub mod fs; pub mod linter; +pub mod logging; pub mod message; -mod parser; -mod visitor; +pub mod parser; +pub mod visitor; diff --git a/src/linter.rs b/src/linter.rs index 85c8b59cea..ae2f8cca38 100644 --- a/src/linter.rs +++ b/src/linter.rs @@ -4,6 +4,7 @@ use anyhow::Result; use log::debug; use serde::{Deserialize, Serialize}; +use crate::cache::Mode; use crate::checker::check_ast; use crate::message::Message; use crate::{cache, parser}; @@ -20,9 +21,9 @@ struct CheckResult { messages: Vec, } -pub fn check_path(path: &Path) -> Result> { +pub fn check_path(path: &Path, mode: &Mode) -> Result> { // Check the cache. - if let Some(messages) = cache::get(path) { + if let Some(messages) = cache::get(path, mode) { debug!("Cache hit for: {}", path.to_string_lossy()); return Ok(messages); } @@ -37,7 +38,7 @@ pub fn check_path(path: &Path) -> Result> { filename: path.to_string_lossy().to_string(), }) .collect(); - cache::set(path, &messages); + cache::set(path, &messages, mode); Ok(messages) } diff --git a/src/logging.rs b/src/logging.rs new file mode 100644 index 0000000000..8940155a8f --- /dev/null +++ b/src/logging.rs @@ -0,0 +1,37 @@ +use anyhow::Result; +use fern; + +#[macro_export] +macro_rules! timestamped_println { + ($($arg:tt)*) => { + println!( + "[{}] {}", + chrono::Local::now() + .format("%H:%M:%S %p") + .to_string() + .dimmed(), + format_args!($($arg)*) + ) + } +} + +pub fn set_up_logging(verbose: bool) -> Result<()> { + fern::Dispatch::new() + .format(|out, message, record| { + out.finish(format_args!( + "{}[{}][{}] {}", + chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), + record.target(), + record.level(), + message + )) + }) + .level(if verbose { + log::LevelFilter::Debug + } else { + log::LevelFilter::Info + }) + .chain(std::io::stdout()) + .apply() + .map_err(|e| e.into()) +}