mirror of https://github.com/astral-sh/ruff
Make cache configurable (#6)
This commit is contained in:
parent
0a034ddb57
commit
35d1d24399
|
|
@ -4,13 +4,15 @@ use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ::rust_python_linter::fs::collect_python_files;
|
use ::rust_python_linter::fs::collect_python_files;
|
||||||
use ::rust_python_linter::linter::check_path;
|
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 anyhow::Result;
|
||||||
use clap::{Parser, ValueHint};
|
use clap::{Parser, ValueHint};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use notify::{watcher, RecursiveMode, Watcher};
|
use notify::{watcher, RecursiveMode, Watcher};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use rust_python_linter::message::Message;
|
|
||||||
use walkdir::DirEntry;
|
use walkdir::DirEntry;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
|
|
@ -23,44 +25,11 @@ struct Cli {
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
#[clap(short, long, action)]
|
#[clap(short, long, action)]
|
||||||
watch: bool,
|
watch: bool,
|
||||||
|
#[clap(short, long, action)]
|
||||||
|
no_cache: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
fn run_once(files: &[PathBuf], cache: bool) -> Result<Vec<Message>> {
|
||||||
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<Vec<Message>> {
|
|
||||||
// Collect all the files to check.
|
// Collect all the files to check.
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let files: Vec<DirEntry> = files.iter().flat_map(collect_python_files).collect();
|
let files: Vec<DirEntry> = files.iter().flat_map(collect_python_files).collect();
|
||||||
|
|
@ -71,7 +40,7 @@ fn run_once(files: &[PathBuf]) -> Result<Vec<Message>> {
|
||||||
let messages: Vec<Message> = files
|
let messages: Vec<Message> = files
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.map(|entry| {
|
.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());
|
error!("Failed to check {}: {e:?}", entry.path().to_string_lossy());
|
||||||
vec![]
|
vec![]
|
||||||
})
|
})
|
||||||
|
|
@ -123,7 +92,7 @@ fn main() -> Result<()> {
|
||||||
clearscreen::clear()?;
|
clearscreen::clear()?;
|
||||||
timestamped_println!("Starting linter in watch mode...\n");
|
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)?;
|
report_continuously(&messages)?;
|
||||||
|
|
||||||
// Configure the file watcher.
|
// Configure the file watcher.
|
||||||
|
|
@ -140,14 +109,14 @@ fn main() -> Result<()> {
|
||||||
clearscreen::clear()?;
|
clearscreen::clear()?;
|
||||||
timestamped_println!("File change detected...\n");
|
timestamped_println!("File change detected...\n");
|
||||||
|
|
||||||
let messages = run_once(&cli.files)?;
|
let messages = run_once(&cli.files, !cli.no_cache)?;
|
||||||
report_continuously(&messages)?;
|
report_continuously(&messages)?;
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let messages = run_once(&cli.files)?;
|
let messages = run_once(&cli.files, !cli.no_cache)?;
|
||||||
report_once(&messages)?;
|
report_once(&messages)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
src/cache.rs
48
src/cache.rs
|
|
@ -26,6 +26,42 @@ struct CheckResult {
|
||||||
messages: Vec<Message>,
|
messages: Vec<Message>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<bool> for Mode {
|
||||||
|
fn from(value: bool) -> Self {
|
||||||
|
match value {
|
||||||
|
true => Mode::ReadWrite,
|
||||||
|
false => Mode::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn cache_dir() -> &'static str {
|
fn cache_dir() -> &'static str {
|
||||||
"./.cache"
|
"./.cache"
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +70,11 @@ fn cache_key(path: &Path) -> Cow<str> {
|
||||||
path.to_string_lossy()
|
path.to_string_lossy()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(path: &Path) -> Option<Vec<Message>> {
|
pub fn get(path: &Path, mode: &Mode) -> Option<Vec<Message>> {
|
||||||
|
if !mode.allow_read() {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
match cacache::read_sync(cache_dir(), cache_key(path)) {
|
match cacache::read_sync(cache_dir(), cache_key(path)) {
|
||||||
Ok(encoded) => match path.metadata() {
|
Ok(encoded) => match path.metadata() {
|
||||||
Ok(m) => match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
Ok(m) => match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
||||||
|
|
@ -53,7 +93,11 @@ pub fn get(path: &Path) -> Option<Vec<Message>> {
|
||||||
None
|
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() {
|
if let Ok(metadata) = path.metadata() {
|
||||||
let check_result = CheckResultRef {
|
let check_result = CheckResultRef {
|
||||||
metadata: &CacheMetadata {
|
metadata: &CacheMetadata {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
mod cache;
|
mod cache;
|
||||||
mod checker;
|
pub mod checker;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod linter;
|
pub mod linter;
|
||||||
|
pub mod logging;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
mod parser;
|
pub mod parser;
|
||||||
mod visitor;
|
pub mod visitor;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use anyhow::Result;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::cache::Mode;
|
||||||
use crate::checker::check_ast;
|
use crate::checker::check_ast;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::{cache, parser};
|
use crate::{cache, parser};
|
||||||
|
|
@ -20,9 +21,9 @@ struct CheckResult {
|
||||||
messages: Vec<Message>,
|
messages: Vec<Message>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_path(path: &Path) -> Result<Vec<Message>> {
|
pub fn check_path(path: &Path, mode: &Mode) -> Result<Vec<Message>> {
|
||||||
// Check the cache.
|
// 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());
|
debug!("Cache hit for: {}", path.to_string_lossy());
|
||||||
return Ok(messages);
|
return Ok(messages);
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +38,7 @@ pub fn check_path(path: &Path) -> Result<Vec<Message>> {
|
||||||
filename: path.to_string_lossy().to_string(),
|
filename: path.to_string_lossy().to_string(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
cache::set(path, &messages);
|
cache::set(path, &messages, mode);
|
||||||
|
|
||||||
Ok(messages)
|
Ok(messages)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue