From 320541bb11b52ca6f045eb09cafbbee8722c0d89 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 10 Jun 2024 19:27:12 +0800 Subject: [PATCH 01/17] refactor: create_document error handling Signed-off-by: tison --- fmt/src/document/factory.rs | 3 ++- fmt/src/document/mod.rs | 31 ++++++++++++++++++++++--------- fmt/src/header/parser.rs | 9 ++++----- fmt/src/processor.rs | 24 ++++++------------------ fmt/tests/tests.rs | 7 +++++-- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index a0f1173..d5948b4 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -17,6 +17,7 @@ use std::{ path::Path, }; +use crate::Result; use crate::{config::Mapping, document::Document, header::model::HeaderDef}; pub struct DocumentFactory { @@ -42,7 +43,7 @@ impl DocumentFactory { } } - pub fn create_document(&self, filepath: &Path) -> std::io::Result { + pub fn create_document(&self, filepath: &Path) -> Result> { let lower_file_name = filepath .file_name() .map(|n| n.to_string_lossy().to_lowercase()) diff --git a/fmt/src/document/mod.rs b/fmt/src/document/mod.rs index bffbf13..da1ea40 100644 --- a/fmt/src/document/mod.rs +++ b/fmt/src/document/mod.rs @@ -15,10 +15,12 @@ use std::{borrow::Cow, collections::HashMap, fs, fs::File, io::BufRead, path::PathBuf}; use snafu::ResultExt; +use tracing::debug; +use crate::error::CreateDocumentSnafu; +use crate::header::parser::{parse_header, FileContent}; use crate::{ error::SaveDocumentSnafu, - header, header::{matcher::HeaderMatcher, model::HeaderDef, parser::HeaderParser}, Result, }; @@ -41,14 +43,25 @@ impl Document { header_def: HeaderDef, keywords: &[String], properties: HashMap, - ) -> std::io::Result { - let parser = header::parser::parse_header(&filepath, &header_def, keywords)?; - Ok(Self { - filepath, - header_def, - properties, - parser, - }) + ) -> Result> { + match FileContent::new(&filepath) { + Ok(content) => Ok(Some(Self { + filepath, + header_def, + properties, + parser: parse_header(content, &header_def, keywords), + })), + Err(e) => { + if matches!(e.kind(), std::io::ErrorKind::InvalidData) { + debug!("skip non-textual file: {}", filepath.display()); + Ok(None) + } else { + Err(e).context(CreateDocumentSnafu { + path: filepath.display().to_string(), + }) + } + } + } } pub fn is_unsupported(&self) -> bool { diff --git a/fmt/src/header/parser.rs b/fmt/src/header/parser.rs index f5eaf44..03e8007 100644 --- a/fmt/src/header/parser.rs +++ b/fmt/src/header/parser.rs @@ -30,11 +30,10 @@ pub struct HeaderParser { } pub fn parse_header( - file: &Path, + mut file_content: FileContent, header_def: &HeaderDef, keywords: &[String], -) -> std::io::Result { - let mut file_content = FileContent::new(file)?; +) -> HeaderParser { let mut line = file_content.next_line(); // 1. find begin position @@ -64,11 +63,11 @@ pub fn parse_header( None }; - Ok(HeaderParser { + HeaderParser { begin_pos, end_pos, file_content, - }) + } } fn find_first_position( diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index f29e270..a9f2499 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -18,15 +18,11 @@ use std::{ }; use snafu::{ensure, ResultExt}; -use tracing::debug; use crate::{ config::Config, document::{factory::DocumentFactory, model::default_mapping, Document}, - error::{ - CreateDocumentSnafu, DeserializeSnafu, InvalidConfigSnafu, LoadConfigSnafu, - TryMatchHeaderSnafu, - }, + error::{DeserializeSnafu, InvalidConfigSnafu, LoadConfigSnafu, TryMatchHeaderSnafu}, header::{ matcher::HeaderMatcher, model::{default_headers, deserialize_header_definitions}, @@ -113,19 +109,11 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) DocumentFactory::new(mapping, definitions, config.properties, config.keywords); for file in selected_files { - let document = document_factory.create_document(&file); - let document = match document { - Ok(document) => document, - Err(e) => { - if matches!(e.kind(), std::io::ErrorKind::InvalidData) { - debug!("skip non-textual file: {}", file.display()); - callback.on_unknown(&file)?; - continue; - } else { - return Err(e).context(CreateDocumentSnafu { - path: file.display().to_string(), - }); - } + let document = match document_factory.create_document(&file)? { + Some(document) => document, + None => { + callback.on_unknown(&file)?; + continue; } }; diff --git a/fmt/tests/tests.rs b/fmt/tests/tests.rs index bf6d5ec..dfe68cc 100644 --- a/fmt/tests/tests.rs +++ b/fmt/tests/tests.rs @@ -15,6 +15,7 @@ use std::path::Path; use hawkeye_fmt::header::{model::default_headers, parser::parse_header}; +use hawkeye_fmt::header::parser::FileContent; #[test] fn test_remove_file_only_header() { @@ -23,7 +24,8 @@ fn test_remove_file_only_header() { let def = defs.get("script_style").unwrap().clone(); let keywords = vec!["copyright".to_string()]; - let document = parse_header(file, &def, &keywords).unwrap(); + let file_content = FileContent::new(file)?; + let document = parse_header(file_content, &def, &keywords).unwrap(); let end_pos = document.end_pos.unwrap(); let content = document.file_content.content(); assert!(content[end_pos..].trim().is_empty()); @@ -36,7 +38,8 @@ fn test_two_headers_should_only_remove_the_first() { let def = defs.get("doubleslash_style").unwrap().clone(); let keywords = vec!["copyright".to_string()]; - let document = parse_header(file, &def, &keywords).unwrap(); + let file_content = FileContent::new(file)?; + let document = parse_header(file_content, &def, &keywords).unwrap(); let end_pos = document.end_pos.unwrap(); let content = document.file_content.content(); assert!(content[end_pos..].contains("Copyright 2015 The Prometheus Authors")); From b34adcc7b6469113b029df143e29ec9786581945 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 10 Jun 2024 20:31:45 +0800 Subject: [PATCH 02/17] refactor: git context Signed-off-by: tison --- fmt/src/config/mod.rs | 1 + fmt/src/document/factory.rs | 18 +++++++++++-- fmt/src/document/mod.rs | 14 +++-------- fmt/src/git.rs | 50 ++++++++++++++++++++++++++++--------- fmt/src/processor.rs | 16 ++++++------ fmt/src/selection.rs | 16 ++++++------ fmt/tests/tests.rs | 10 ++++---- 7 files changed, 80 insertions(+), 45 deletions(-) diff --git a/fmt/src/config/mod.rs b/fmt/src/config/mod.rs index 2e5460d..a55f927 100644 --- a/fmt/src/config/mod.rs +++ b/fmt/src/config/mod.rs @@ -56,6 +56,7 @@ pub struct Config { #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] pub struct Git { + pub attrs: FeatureGate, pub ignore: FeatureGate, } diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index d5948b4..42b0c4a 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -12,11 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use snafu::ResultExt; +use std::borrow::Cow; use std::{ collections::{HashMap, HashSet}, path::Path, }; +use crate::error::CreateDocumentSnafu; use crate::Result; use crate::{config::Mapping, document::Document, header::model::HeaderDef}; @@ -57,13 +60,24 @@ impl DocumentFactory { let header_def = self .definitions .get(&header_type) - .ok_or_else(|| std::io::Error::other(format!("header type {header_type} not found")))?; + .ok_or_else(|| std::io::Error::other(format!("header type {header_type} not found"))) + .context(CreateDocumentSnafu { + path: filepath.display().to_string(), + })?; + + let mut properties = self.properties.clone(); + let filename = filepath + .file_name() + .map(|s| s.to_string_lossy()) + .unwrap_or_else(|| Cow::Borrowed("")) + .to_string(); + properties.insert("hawkeye.core.filename".to_string(), filename); Document::new( filepath.to_path_buf(), header_def.clone(), &self.keywords, - self.properties.clone(), + properties, ) } } diff --git a/fmt/src/document/mod.rs b/fmt/src/document/mod.rs index da1ea40..b92c45e 100644 --- a/fmt/src/document/mod.rs +++ b/fmt/src/document/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{borrow::Cow, collections::HashMap, fs, fs::File, io::BufRead, path::PathBuf}; +use std::{collections::HashMap, fs, fs::File, io::BufRead, path::PathBuf}; use snafu::ResultExt; use tracing::debug; @@ -46,10 +46,10 @@ impl Document { ) -> Result> { match FileContent::new(&filepath) { Ok(content) => Ok(Some(Self { + parser: parse_header(content, &header_def, keywords), filepath, header_def, properties, - parser: parse_header(content, &header_def, keywords), })), Err(e) => { if matches!(e.kind(), std::io::ErrorKind::InvalidData) { @@ -145,15 +145,7 @@ impl Document { } pub(crate) fn merge_properties(&self, s: &str) -> String { - let mut properties = self.properties.clone(); - let filename = self - .filepath - .file_name() - .map(|s| s.to_string_lossy()) - .unwrap_or_else(|| Cow::Borrowed("")) - .to_string(); - properties.insert("hawkeye.core.filename".to_string(), filename); - merge_properties(&properties, s) + merge_properties(&self.properties, s) } } diff --git a/fmt/src/git.rs b/fmt/src/git.rs index cc4ca8b..9848f67 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -18,41 +18,67 @@ use gix::Repository; use snafu::IntoError; use tracing::info; +use crate::config::FeatureGate; use crate::{ config, error::{GixDiscoverOpSnafu, InvalidConfigSnafu}, Result, }; -pub fn discover(basedir: &Path, config: config::Git) -> Result> { - if config.ignore.is_disable() { - return Ok(None); +#[derive(Debug, Clone)] +pub struct GitContext { + pub repo: Option, + pub config: config::Git, +} + +pub fn discover(basedir: &Path, config: config::Git) -> Result { + let feature = resolve_features(&config); + + if feature.is_disable() { + return Ok(GitContext { repo: None, config }); } - let is_auto = config.ignore.is_auto(); match gix::discover(basedir) { Ok(repo) => match repo.worktree() { None => { let message = "bare repository detected"; - if is_auto { - info!("git.ignore=auto is resolved to fallback; {message}"); - Ok(None) + if feature.is_auto() { + info!(?config, "git config is resolved to disabled; {message}"); + Ok(GitContext { repo: None, config }) } else { InvalidConfigSnafu { message }.fail() } } Some(_) => { - info!("git.ignore=auto is resolved to enabled"); - Ok(Some(repo)) + info!("git config is resolved to enabled"); + Ok(GitContext { + repo: Some(repo), + config, + }) } }, Err(err) => { - if is_auto { - info!(?err, "git.ignore=auto is resolved to disabled"); - Ok(None) + if feature.is_auto() { + info!(?err, ?config, "git config is resolved to disabled"); + Ok(GitContext { repo: None, config }) } else { Err(GixDiscoverOpSnafu {}.into_error(Box::new(err))) } } } } + +fn resolve_features(config: &config::Git) -> FeatureGate { + let features = [config.attrs, config.ignore]; + for feature in features.iter() { + if feature.is_enable() { + return FeatureGate::Enable; + } + } + for feature in features.iter() { + if feature.is_auto() { + return FeatureGate::Auto; + } + } + FeatureGate::Disable +} diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index a9f2499..295c1cd 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -23,6 +23,7 @@ use crate::{ config::Config, document::{factory::DocumentFactory, model::default_mapping, Document}, error::{DeserializeSnafu, InvalidConfigSnafu, LoadConfigSnafu, TryMatchHeaderSnafu}, + git, header::{ matcher::HeaderMatcher, model::{default_headers, deserialize_header_definitions}, @@ -66,11 +67,7 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) } ); - let header_matcher = { - let header_source = HeaderSource::from_config(&config)?; - HeaderMatcher::new(header_source.content) - }; - + let git_context = git::discover(&basedir, config.git)?; let selected_files = { let selection = Selection::new( basedir, @@ -78,13 +75,13 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) &config.includes, &config.excludes, config.use_default_excludes, - config.git, + git_context, ); selection.select()? }; let mapping = { - let mut mapping = config.mapping; + let mut mapping = config.mapping.clone(); if config.use_default_mapping { let default_mapping = default_mapping(); mapping.extend(default_mapping); @@ -105,6 +102,11 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) defs }; + let header_matcher = { + let header_source = HeaderSource::from_config(&config)?; + HeaderMatcher::new(header_source.content) + }; + let document_factory = DocumentFactory::new(mapping, definitions, config.properties, config.keywords); diff --git a/fmt/src/selection.rs b/fmt/src/selection.rs index 579bac2..327adb2 100644 --- a/fmt/src/selection.rs +++ b/fmt/src/selection.rs @@ -19,21 +19,20 @@ use snafu::{ensure, ResultExt}; use tracing::debug; use walkdir::WalkDir; +use crate::git::GitContext; use crate::{ - config, error::{ GixCheckExcludeOpSnafu, GixExcludeOpSnafu, ResolveAbsolutePathSnafu, SelectFilesSnafu, SelectWithIgnoreSnafu, TraverseDirSnafu, }, - git, Result, + Result, }; pub struct Selection { basedir: PathBuf, includes: Vec, excludes: Vec, - - git: config::Git, + git_context: GitContext, } impl Selection { @@ -43,7 +42,7 @@ impl Selection { includes: &[String], excludes: &[String], use_default_excludes: bool, - git: config::Git, + git_context: GitContext, ) -> Selection { let includes = if includes.is_empty() { INCLUDES.iter().map(|s| s.to_string()).collect() @@ -65,7 +64,7 @@ impl Selection { basedir, includes, excludes, - git, + git_context, } } @@ -101,13 +100,14 @@ impl Selection { }, ); - let result = match git::discover(&self.basedir, self.git)? { + let ignore = self.git_context.config.ignore.is_auto(); + let result = match self.git_context.repo { None => select_files_with_ignore( &self.basedir, &includes, &excludes, &reverse_excludes, - self.git.ignore.is_auto(), + ignore, )?, Some(repo) => { select_files_with_git(&self.basedir, &includes, &excludes, &reverse_excludes, repo)? diff --git a/fmt/tests/tests.rs b/fmt/tests/tests.rs index dfe68cc..2097e3d 100644 --- a/fmt/tests/tests.rs +++ b/fmt/tests/tests.rs @@ -14,8 +14,8 @@ use std::path::Path; -use hawkeye_fmt::header::{model::default_headers, parser::parse_header}; use hawkeye_fmt::header::parser::FileContent; +use hawkeye_fmt::header::{model::default_headers, parser::parse_header}; #[test] fn test_remove_file_only_header() { @@ -24,8 +24,8 @@ fn test_remove_file_only_header() { let def = defs.get("script_style").unwrap().clone(); let keywords = vec!["copyright".to_string()]; - let file_content = FileContent::new(file)?; - let document = parse_header(file_content, &def, &keywords).unwrap(); + let file_content = FileContent::new(file).unwrap(); + let document = parse_header(file_content, &def, &keywords); let end_pos = document.end_pos.unwrap(); let content = document.file_content.content(); assert!(content[end_pos..].trim().is_empty()); @@ -38,8 +38,8 @@ fn test_two_headers_should_only_remove_the_first() { let def = defs.get("doubleslash_style").unwrap().clone(); let keywords = vec!["copyright".to_string()]; - let file_content = FileContent::new(file)?; - let document = parse_header(file_content, &def, &keywords).unwrap(); + let file_content = FileContent::new(file).unwrap(); + let document = parse_header(file_content, &def, &keywords); let end_pos = document.end_pos.unwrap(); let content = document.file_content.content(); assert!(content[end_pos..].contains("Copyright 2015 The Prometheus Authors")); From 307471d45237f2d2c850fdd7592e3fb97d4ed097 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 10 Jun 2024 20:54:05 +0800 Subject: [PATCH 03/17] feat: resolve git file attrs Signed-off-by: tison --- fmt/src/document/factory.rs | 28 +++++++++++++++++++++++----- fmt/src/document/mod.rs | 10 ++++++---- fmt/src/git.rs | 2 +- fmt/src/processor.rs | 12 +++++++++--- fmt/src/selection.rs | 2 +- fmt/tests/tests.rs | 6 ++++-- 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index 42b0c4a..d577250 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -12,16 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use snafu::ResultExt; -use std::borrow::Cow; use std::{ + borrow::Cow, collections::{HashMap, HashSet}, path::Path, }; -use crate::error::CreateDocumentSnafu; -use crate::Result; -use crate::{config::Mapping, document::Document, header::model::HeaderDef}; +use snafu::ResultExt; + +use crate::{ + config::Mapping, document::Document, error::CreateDocumentSnafu, git::GitContext, + header::model::HeaderDef, Result, +}; pub struct DocumentFactory { mapping: HashSet, @@ -29,6 +31,7 @@ pub struct DocumentFactory { properties: HashMap, keywords: Vec, + git_context: GitContext, } impl DocumentFactory { @@ -37,12 +40,14 @@ impl DocumentFactory { definitions: HashMap, properties: HashMap, keywords: Vec, + git_context: GitContext, ) -> Self { Self { mapping, definitions, properties, keywords, + git_context, } } @@ -72,6 +77,7 @@ impl DocumentFactory { .unwrap_or_else(|| Cow::Borrowed("")) .to_string(); properties.insert("hawkeye.core.filename".to_string(), filename); + properties.extend(resolve_git_file_attrs(&self.git_context, filepath)?); Document::new( filepath.to_path_buf(), @@ -81,3 +87,15 @@ impl DocumentFactory { ) } } + +fn resolve_git_file_attrs( + _git_context: &GitContext, + _path: &Path, +) -> Result> { + let properties = HashMap::new(); + + // TODO - implement these: + // properties.insert("hawkeye.git.file_created".to_string(), ...); + // properties.insert("hawkeye.git.file_modified".to_string(), ...); + Ok(properties) +} diff --git a/fmt/src/document/mod.rs b/fmt/src/document/mod.rs index b92c45e..c1cba0a 100644 --- a/fmt/src/document/mod.rs +++ b/fmt/src/document/mod.rs @@ -17,11 +17,13 @@ use std::{collections::HashMap, fs, fs::File, io::BufRead, path::PathBuf}; use snafu::ResultExt; use tracing::debug; -use crate::error::CreateDocumentSnafu; -use crate::header::parser::{parse_header, FileContent}; use crate::{ - error::SaveDocumentSnafu, - header::{matcher::HeaderMatcher, model::HeaderDef, parser::HeaderParser}, + error::{CreateDocumentSnafu, SaveDocumentSnafu}, + header::{ + matcher::HeaderMatcher, + model::HeaderDef, + parser::{parse_header, FileContent, HeaderParser}, + }, Result, }; diff --git a/fmt/src/git.rs b/fmt/src/git.rs index 9848f67..fd83ad5 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -18,9 +18,9 @@ use gix::Repository; use snafu::IntoError; use tracing::info; -use crate::config::FeatureGate; use crate::{ config, + config::FeatureGate, error::{GixDiscoverOpSnafu, InvalidConfigSnafu}, Result, }; diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index 295c1cd..b4c361b 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -68,6 +68,7 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) ); let git_context = git::discover(&basedir, config.git)?; + let selected_files = { let selection = Selection::new( basedir, @@ -75,7 +76,7 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) &config.includes, &config.excludes, config.use_default_excludes, - git_context, + git_context.clone(), ); selection.select()? }; @@ -107,8 +108,13 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) HeaderMatcher::new(header_source.content) }; - let document_factory = - DocumentFactory::new(mapping, definitions, config.properties, config.keywords); + let document_factory = DocumentFactory::new( + mapping, + definitions, + config.properties, + config.keywords, + git_context, + ); for file in selected_files { let document = match document_factory.create_document(&file)? { diff --git a/fmt/src/selection.rs b/fmt/src/selection.rs index 327adb2..eb11d3c 100644 --- a/fmt/src/selection.rs +++ b/fmt/src/selection.rs @@ -19,12 +19,12 @@ use snafu::{ensure, ResultExt}; use tracing::debug; use walkdir::WalkDir; -use crate::git::GitContext; use crate::{ error::{ GixCheckExcludeOpSnafu, GixExcludeOpSnafu, ResolveAbsolutePathSnafu, SelectFilesSnafu, SelectWithIgnoreSnafu, TraverseDirSnafu, }, + git::GitContext, Result, }; diff --git a/fmt/tests/tests.rs b/fmt/tests/tests.rs index 2097e3d..1b08fd3 100644 --- a/fmt/tests/tests.rs +++ b/fmt/tests/tests.rs @@ -14,8 +14,10 @@ use std::path::Path; -use hawkeye_fmt::header::parser::FileContent; -use hawkeye_fmt::header::{model::default_headers, parser::parse_header}; +use hawkeye_fmt::header::{ + model::default_headers, + parser::{parse_header, FileContent}, +}; #[test] fn test_remove_file_only_header() { From e9bac68f659b60d4879d77b9f998e70df1ae8165 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 10 Jun 2024 22:17:31 +0800 Subject: [PATCH 04/17] upgrade for gix 0.63 Signed-off-by: tison --- Cargo.lock | 103 ++++++++++++++++++++++--------------------- fmt/Cargo.toml | 2 +- fmt/src/selection.rs | 7 ++- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d5b0a4..3e779bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -269,9 +269,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "filetime" @@ -312,9 +312,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.61.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e0e59a44bf00de058ee98d6ecf3c9ed8f8842c1da642258ae4120d41ded8f7" +checksum = "984c5018adfa7a4536ade67990b3ebc6e11ab57b3d6cd9968de0947ca99b4b06" dependencies = [ "gix-actor", "gix-commitgraph", @@ -355,9 +355,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.31.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3a3bde455ad2ee8ba8a195745241ce0b770a8a26faae59fcf409d01b28c46" +checksum = "d69c59d392c7e6c94385b6fd6089d6df0fe945f32b4357687989f3aee253cd7f" dependencies = [ "bstr", "gix-date", @@ -401,9 +401,9 @@ dependencies = [ [[package]] name = "gix-config" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62129c75e4b6229fe15fb9838cdc00c655e87105b651e4edd7c183fc5288b5d1" +checksum = "53fafe42957e11d98e354a66b6bd70aeea00faf2f62dd11164188224a507c840" dependencies = [ "bstr", "gix-config-value", @@ -435,9 +435,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180b130a4a41870edfbd36ce4169c7090bca70e195da783dea088dd973daa59c" +checksum = "367ee9093b0c2b04fd04c5c7c8b6a1082713534eab537597ae343663a518fa99" dependencies = [ "bstr", "itoa", @@ -447,9 +447,9 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.42.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78e605593c2ef74980a534ade0909c7dc57cca72baa30cbb67d2dda621f99ac4" +checksum = "40b9bd8b2d07b6675a840b56a6c177d322d45fa082672b0dad8f063b25baf0a4" dependencies = [ "bstr", "gix-hash", @@ -459,9 +459,9 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64bab49087ed3710caf77e473dc0efc54ca33d8ccc6441359725f121211482b1" +checksum = "fc27c699b63da66b50d50c00668bc0b7e90c3a382ef302865e891559935f3dbf" dependencies = [ "bstr", "dunce", @@ -475,9 +475,9 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.38.1" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4254037d20a247a0367aa79333750146a369719f0c6617fec4f5752cc62b37" +checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" dependencies = [ "crc32fast", "flate2", @@ -494,10 +494,11 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634b8a743b0aae03c1a74ee0ea24e8c5136895efac64ce52b3ea106e1c6f0613" +checksum = "c3338ff92a2164f5209f185ec0cd316f571a72676bb01d27e22f2867ba69f77a" dependencies = [ + "fastrand", "gix-features", "gix-utils", ] @@ -550,9 +551,9 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.31.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549621f13d9ccf325a7de45506a3266af0d08f915181c5687abb5e8669bfd2e6" +checksum = "2d8c5a5f1c58edcbc5692b174cda2703aba82ed17d7176ff4c1752eb48b1b167" dependencies = [ "bitflags 2.5.0", "bstr", @@ -566,6 +567,7 @@ dependencies = [ "gix-object", "gix-traverse", "gix-utils", + "gix-validate", "hashbrown", "itoa", "libc", @@ -577,9 +579,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "13.1.1" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c359f81f01b8352063319bcb39789b7ea0887b406406381106e38c4a34d049" +checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" dependencies = [ "gix-tempfile", "gix-utils", @@ -588,9 +590,9 @@ dependencies = [ [[package]] name = "gix-macros" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dff438f14e67e7713ab9332f5fd18c8f20eb7eb249494f6c2bf170522224032" +checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17" dependencies = [ "proc-macro2", "quote", @@ -599,9 +601,9 @@ dependencies = [ [[package]] name = "gix-object" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4f8efae72030df1c4a81d02dbe2348e748d9b9a11e108ed6efbd846326e051" +checksum = "1fe2dc4a41191c680c942e6ebd630c8107005983c4679214fdb1007dcf5ae1df" dependencies = [ "bstr", "gix-actor", @@ -618,9 +620,9 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.59.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b55378c719693380f66d9dd21ce46721eed2981d8789fc698ec1ada6fa176e" +checksum = "e92b9790e2c919166865d0825b26cc440a387c175bed1b43a2fa99c0e9d45e98" dependencies = [ "arc-swap", "gix-date", @@ -638,9 +640,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.49.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6391aeaa030ad64aba346a9f5c69bb1c4e5c6fb4411705b03b40b49d8614ec30" +checksum = "7a8da51212dbff944713edb2141ed7e002eea326b8992070374ce13a6cb610b3" dependencies = [ "clru", "gix-chunk", @@ -682,9 +684,9 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.43.0" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4aba68b925101cb45d6df328979af0681364579db889098a0de75b36c77b65" +checksum = "3394a2997e5bc6b22ebc1e1a87b41eeefbcfcff3dbfa7c4bd73cb0ac8f1f3e2e" dependencies = [ "gix-actor", "gix-date", @@ -718,9 +720,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e34196e1969bd5d36e2fbc4467d893999132219d503e23474a8ad2b221cb1e8" +checksum = "63e08f8107ed1f93a83bcfbb4c38084c7cb3f6cd849793f1d5eec235f9b13b2b" dependencies = [ "bstr", "gix-date", @@ -734,9 +736,9 @@ dependencies = [ [[package]] name = "gix-revwalk" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7d393ae814eeaae41a333c0ff684b243121cc61ccdc5bbe9897094588047d" +checksum = "4181db9cfcd6d1d0fd258e91569dbb61f94cb788b441b5294dd7f1167a3e788f" dependencies = [ "gix-commitgraph", "gix-date", @@ -761,9 +763,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "13.1.1" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a761d76594f4443b675e85928e4902dec333273836bd386906f01e7e346a0d11" +checksum = "d3b0e276cd08eb2a22e9f286a4f13a222a01be2defafa8621367515375644b99" dependencies = [ "gix-fs", "libc", @@ -774,16 +776,17 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b838b2db8f62c9447d483a4c28d251b67fee32741a82cb4d35e9eb4e9fdc5ab" +checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" [[package]] name = "gix-traverse" -version = "0.38.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95aef84bc777025403a09788b1e4815c06a19332e9e5d87a955e1ed7da9bf0cf" +checksum = "f20cb69b63eb3e4827939f42c05b7756e3488ef49c25c412a876691d568ee2a0" dependencies = [ + "bitflags 2.5.0", "gix-commitgraph", "gix-date", "gix-hash", @@ -796,9 +799,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0b24f3ecc79a5a53539de9c2e99425d0ef23feacdcf3faac983aa9a2f26849" +checksum = "0db829ebdca6180fbe32be7aed393591df6db4a72dbbc0b8369162390954d1cf" dependencies = [ "bstr", "gix-features", @@ -810,9 +813,9 @@ dependencies = [ [[package]] name = "gix-utils" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066432d4c277f9877f091279a597ea5331f68ca410efc874f0bdfb1cd348f92" +checksum = "35192df7fd0fa112263bad8021e2df7167df4cc2a6e6d15892e1e55621d3d4dc" dependencies = [ "fastrand", "unicode-normalization", @@ -820,9 +823,9 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545" +checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf" dependencies = [ "bstr", "thiserror", @@ -830,9 +833,9 @@ dependencies = [ [[package]] name = "gix-worktree" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe78e03af9eec168eb187e05463a981c57f0a915f64b1788685a776bd2ef969c" +checksum = "53f6b7de83839274022aff92157d7505f23debf739d257984a300a35972ca94e" dependencies = [ "bstr", "gix-features", diff --git a/fmt/Cargo.toml b/fmt/Cargo.toml index b2094fc..522add5 100644 --- a/fmt/Cargo.toml +++ b/fmt/Cargo.toml @@ -23,7 +23,7 @@ license.workspace = true repository.workspace = true [dependencies] -gix = { version = "0.61", default-features = false, features = ["excludes"] } +gix = { version = "0.63", default-features = false, features = ["excludes"] } ignore = "0.4.22" regex = "1.10.3" serde = { version = "1.0.197", features = ["derive"] } diff --git a/fmt/src/selection.rs b/fmt/src/selection.rs index eb11d3c..ab7c693 100644 --- a/fmt/src/selection.rs +++ b/fmt/src/selection.rs @@ -219,8 +219,13 @@ fn select_files_with_git( let rela_path = path .strip_prefix(&workdir) .expect("git repository encloses iteration"); + let mode = Some(if file_type.is_dir() { + gix::index::entry::Mode::DIR + } else { + gix::index::entry::Mode::FILE + }); let platform = excludes - .at_path(rela_path, Some(file_type.is_dir())) + .at_path(rela_path, mode) .context(GixCheckExcludeOpSnafu)?; if file_type.is_dir() { From f6bb60c53b25a08d91ad4930559ff24f97a8549f Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 09:52:18 +0800 Subject: [PATCH 05/17] do impl Signed-off-by: tison --- Cargo.lock | 199 +++++++++++++++++++++++++++++++++++- fmt/Cargo.toml | 7 +- fmt/src/config/mod.rs | 14 ++- fmt/src/document/factory.rs | 88 +++++++++++++--- fmt/src/error.rs | 8 ++ 5 files changed, 297 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e779bb..4ae19c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -83,6 +84,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + [[package]] name = "arc-swap" version = "1.7.1" @@ -230,6 +237,19 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "deranged" version = "0.3.11" @@ -245,6 +265,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -310,6 +339,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gix" version = "0.63.0" @@ -317,12 +357,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "984c5018adfa7a4536ade67990b3ebc6e11ab57b3d6cd9968de0947ca99b4b06" dependencies = [ "gix-actor", + "gix-attributes", + "gix-command", "gix-commitgraph", "gix-config", "gix-date", "gix-diff", "gix-discover", "gix-features", + "gix-filter", "gix-fs", "gix-glob", "gix-hash", @@ -335,11 +378,13 @@ dependencies = [ "gix-odb", "gix-pack", "gix-path", + "gix-pathspec", "gix-ref", "gix-refspec", "gix-revision", "gix-revwalk", "gix-sec", + "gix-submodule", "gix-tempfile", "gix-trace", "gix-traverse", @@ -367,6 +412,23 @@ dependencies = [ "winnow", ] +[[package]] +name = "gix-attributes" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eefb48f42eac136a4a0023f49a54ec31be1c7a9589ed762c45dcb9b953f7ecc8" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "gix-quote", + "gix-trace", + "kstring", + "smallvec", + "thiserror", + "unicode-bom", +] + [[package]] name = "gix-bitmap" version = "0.2.11" @@ -385,6 +447,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gix-command" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c22e086314095c43ffe5cdc5c0922d5439da4fd726f3b0438c56147c34dc225" +dependencies = [ + "bstr", + "gix-path", + "gix-trace", + "shell-words", +] + [[package]] name = "gix-commitgraph" version = "0.24.2" @@ -452,8 +526,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9bd8b2d07b6675a840b56a6c177d322d45fa082672b0dad8f063b25baf0a4" dependencies = [ "bstr", + "gix-command", + "gix-filter", + "gix-fs", "gix-hash", "gix-object", + "gix-path", + "gix-tempfile", + "gix-trace", + "gix-worktree", + "imara-diff", "thiserror", ] @@ -492,6 +574,27 @@ dependencies = [ "walkdir", ] +[[package]] +name = "gix-filter" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00ce6ea5ac8fca7adbc63c48a1b9e0492c222c386aa15f513405f1003f2f4ab2" +dependencies = [ + "bstr", + "encoding_rs", + "gix-attributes", + "gix-command", + "gix-hash", + "gix-object", + "gix-packetline-blocking", + "gix-path", + "gix-quote", + "gix-trace", + "gix-utils", + "smallvec", + "thiserror", +] + [[package]] name = "gix-fs" version = "0.11.1" @@ -532,7 +635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" dependencies = [ "gix-hash", - "hashbrown", + "hashbrown 0.14.3", "parking_lot", ] @@ -568,7 +671,7 @@ dependencies = [ "gix-traverse", "gix-utils", "gix-validate", - "hashbrown", + "hashbrown 0.14.3", "itoa", "libc", "memmap2", @@ -658,6 +761,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gix-packetline-blocking" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31d42378a3d284732e4d589979930d0d253360eccf7ec7a80332e5ccb77e14a" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror", +] + [[package]] name = "gix-path" version = "0.10.7" @@ -671,6 +786,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gix-pathspec" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76cab098dc10ba2d89f634f66bf196dea4d7db4bf10b75c7a9c201c55a2ee19" +dependencies = [ + "bitflags 2.5.0", + "bstr", + "gix-attributes", + "gix-config-value", + "gix-glob", + "gix-path", + "thiserror", +] + [[package]] name = "gix-quote" version = "0.4.12" @@ -761,12 +891,28 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "gix-submodule" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921cd49924ac14b6611b22e5fb7bbba74d8780dc7ad26153304b64d1272460ac" +dependencies = [ + "bstr", + "gix-config", + "gix-path", + "gix-pathspec", + "gix-refspec", + "gix-url", + "thiserror", +] + [[package]] name = "gix-tempfile" version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3b0e276cd08eb2a22e9f286a4f13a222a01be2defafa8621367515375644b99" dependencies = [ + "dashmap", "gix-fs", "libc", "once_cell", @@ -838,6 +984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53f6b7de83839274022aff92157d7505f23debf739d257984a300a35972ca94e" dependencies = [ "bstr", + "gix-attributes", "gix-features", "gix-fs", "gix-glob", @@ -846,6 +993,7 @@ dependencies = [ "gix-index", "gix-object", "gix-path", + "gix-validate", ] [[package]] @@ -861,6 +1009,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" @@ -887,11 +1041,13 @@ dependencies = [ name = "hawkeye-fmt" version = "5.5.1" dependencies = [ + "anyhow", "gix", "ignore", "regex", "serde", "snafu", + "time", "toml", "tracing", "walkdir", @@ -944,6 +1100,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "imara-diff" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8" +dependencies = [ + "ahash", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.5" @@ -951,7 +1117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -960,6 +1126,15 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1316,6 +1491,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "smallvec" version = "1.13.2" @@ -1343,6 +1524,12 @@ dependencies = [ "syn", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.0" @@ -1611,6 +1798,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" diff --git a/fmt/Cargo.toml b/fmt/Cargo.toml index 522add5..3246ba7 100644 --- a/fmt/Cargo.toml +++ b/fmt/Cargo.toml @@ -23,11 +23,16 @@ license.workspace = true repository.workspace = true [dependencies] -gix = { version = "0.63", default-features = false, features = ["excludes"] } +anyhow = "1.0" +gix = { version = "0.63", default-features = false, features = [ + "blob-diff", + "excludes", +] } ignore = "0.4.22" regex = "1.10.3" serde = { version = "1.0.197", features = ["derive"] } snafu.workspace = true +time = "0.3" toml.workspace = true tracing.workspace = true walkdir = "2.5.0" diff --git a/fmt/src/config/mod.rs b/fmt/src/config/mod.rs index a55f927..d4c51e7 100644 --- a/fmt/src/config/mod.rs +++ b/fmt/src/config/mod.rs @@ -54,17 +54,25 @@ pub struct Config { pub additional_headers: Vec, } -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub struct Git { pub attrs: FeatureGate, pub ignore: FeatureGate, } -#[derive(Debug, Clone, Copy, Default, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +impl Default for Git { + fn default() -> Self { + Git { + attrs: FeatureGate::Disable, // expensive + ignore: FeatureGate::Auto, + } + } +} + +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum FeatureGate { /// Determinate whether turn on the feature. - #[default] Auto, /// Force enable the feature. Enable, diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index d577250..2e0f172 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -15,14 +15,20 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, + convert::Infallible, path::Path, }; use snafu::ResultExt; +use time::format_description; use crate::{ - config::Mapping, document::Document, error::CreateDocumentSnafu, git::GitContext, - header::model::HeaderDef, Result, + config::Mapping, + document::Document, + error::{CreateDocumentSnafu, GitFileAttrsSnafu}, + git::GitContext, + header::model::HeaderDef, + Result, }; pub struct DocumentFactory { @@ -71,13 +77,29 @@ impl DocumentFactory { })?; let mut properties = self.properties.clone(); + let filename = filepath .file_name() .map(|s| s.to_string_lossy()) .unwrap_or_else(|| Cow::Borrowed("")) .to_string(); properties.insert("hawkeye.core.filename".to_string(), filename); - properties.extend(resolve_git_file_attrs(&self.git_context, filepath)?); + + let year_formatter = format_description::parse("[year]").expect("cannot parse format"); + let git_file_attrs = + resolve_git_file_attrs(&self.git_context, filepath).context(GitFileAttrsSnafu)?; + if let Some(time) = git_file_attrs.created_time { + properties.insert( + "hawkeye.git.fileCreatedYear".to_string(), + time.format(year_formatter.as_slice()), + ); + } + if let Some(time) = git_file_attrs.modified_time { + properties.insert( + "hawkeye.git.fileModifiedYear".to_string(), + time.format(year_formatter.as_slice()), + ); + } Document::new( filepath.to_path_buf(), @@ -88,14 +110,56 @@ impl DocumentFactory { } } -fn resolve_git_file_attrs( - _git_context: &GitContext, - _path: &Path, -) -> Result> { - let properties = HashMap::new(); +#[derive(Debug)] +struct GitFileAttrs { + created_time: Option, + modified_time: Option, +} + +fn resolve_git_file_attrs(git_context: &GitContext, path: &Path) -> anyhow::Result { + let mut attrs = GitFileAttrs { + created_time: None, + modified_time: None, + }; + + if let Some(ref repo) = git_context.repo { + let workdir = repo.work_dir().expect("workdir cannot be absent"); + let workdir = workdir.canonicalize()?; + let rela_path = path.strip_prefix(&workdir)?; + let location = rela_path.display().to_string(); + + let mode = gix::diff::blob::pipeline::Mode::ToGit; + let mut cache = repo.diff_resource_cache(mode, Default::default())?; + + let head = repo.head_commit()?; + let mut prev_commit = head.clone(); + + for info in head.ancestors().all()? { + let info = info?; + let this_commit = info.object()?; + let tree = this_commit.tree()?; + let mut changes = tree.changes()?; + changes.track_path().for_each_to_obtain_tree_with_cache( + &prev_commit.tree()?, + &mut cache, + |change| { + if change.location == location { + let time = this_commit.time().expect("commit always has time"); + attrs.created_time = match attrs.created_time { + None => Some(time), + Some(t) => Some(t.min(time)), + }; + attrs.modified_time = match attrs.modified_time { + None => Some(time), + Some(t) => Some(t.max(time)), + }; + } + Ok::<_, Infallible>(Default::default()) + }, + )?; + prev_commit = this_commit; + } + } - // TODO - implement these: - // properties.insert("hawkeye.git.file_created".to_string(), ...); - // properties.insert("hawkeye.git.file_modified".to_string(), ...); - Ok(properties) + Ok(attrs) } diff --git a/fmt/src/error.rs b/fmt/src/error.rs index 3f5da05..c1c5399 100644 --- a/fmt/src/error.rs +++ b/fmt/src/error.rs @@ -139,4 +139,12 @@ pub enum Error { #[snafu(implicit)] loc: snafu::Location, }, + + #[snafu(display("cannot obtain file attrs from Git: {}", source))] + GitFileAttrs { + #[snafu(source)] + source: anyhow::Error, + #[snafu(implicit)] + loc: snafu::Location, + }, } From a7dc8d27d8762c18a14c1f4db35b29a12363500f Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 09:57:03 +0800 Subject: [PATCH 06/17] try use the new properties Signed-off-by: tison --- licenserc.toml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/licenserc.toml b/licenserc.toml index 003f7fe..ad4fcb1 100644 --- a/licenserc.toml +++ b/licenserc.toml @@ -12,7 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -headerPath = "Apache-2.0.txt" +inlineHeader = """ +Copyright ${inceptionYear} ${copyrightOwner} + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Copyright ${hawkeye.git.fileCreatedYear} - ${hawkeye.git.fileModifiedYear}, ${copyrightOwner} and the ${projectName} contributors +SPDX-License-Identifier: Apache-2.0 +""" excludes = [ # Plain text files AS IS @@ -26,6 +43,11 @@ excludes = [ ".github/workflows/release.yml", ] +[git] +attrs = 'auto' +ignore = 'auto' + [properties] inceptionYear = 2024 copyrightOwner = "tison " +projectName = "HawkEye" From dc416f516ac7098073a86b33dec0a7f26256933e Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 09:58:44 +0800 Subject: [PATCH 07/17] apply Signed-off-by: tison --- .cargo/config.toml | 3 +++ .editorconfig | 3 +++ .github/actions/docker-push-by-digest/action.yml | 3 +++ .github/actions/docker-release/action.yml | 3 +++ .github/semantic.yml | 3 +++ .github/workflows/ci.yml | 3 +++ .github/workflows/docker.yml | 3 +++ Cargo.toml | 3 +++ Dockerfile | 3 +++ action.yml | 3 +++ cli/Cargo.toml | 3 +++ cli/build.rs | 3 +++ cli/src/cli.rs | 3 +++ cli/src/main.rs | 3 +++ fmt/Cargo.toml | 3 +++ fmt/src/config/mod.rs | 3 +++ fmt/src/document/defaults.toml | 3 +++ fmt/src/document/factory.rs | 3 +++ fmt/src/document/mod.rs | 3 +++ fmt/src/document/model.rs | 3 +++ fmt/src/error.rs | 3 +++ fmt/src/git.rs | 3 +++ fmt/src/header/defaults.toml | 3 +++ fmt/src/header/matcher.rs | 3 +++ fmt/src/header/mod.rs | 3 +++ fmt/src/header/model.rs | 3 +++ fmt/src/header/parser.rs | 3 +++ fmt/src/lib.rs | 3 +++ fmt/src/license/mod.rs | 3 +++ fmt/src/processor.rs | 3 +++ fmt/src/selection.rs | 3 +++ fmt/tests/tests.rs | 3 +++ licenserc.toml | 3 +++ rust-toolchain.toml | 3 +++ rustfmt.toml | 3 +++ tests/it.py | 3 +++ 36 files changed, 108 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 77507dc..22a2e63 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 # See also https://github.com/rust-lang/rust/issues/44991 diff --git a/.editorconfig b/.editorconfig index 8ec2430..8108462 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 root = true diff --git a/.github/actions/docker-push-by-digest/action.yml b/.github/actions/docker-push-by-digest/action.yml index f8be373..fea6ae3 100644 --- a/.github/actions/docker-push-by-digest/action.yml +++ b/.github/actions/docker-push-by-digest/action.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 name: Docker push by digest description: Build and push Docker image by digest diff --git a/.github/actions/docker-release/action.yml b/.github/actions/docker-release/action.yml index 76ab29a..2d4bd1b 100644 --- a/.github/actions/docker-release/action.yml +++ b/.github/actions/docker-release/action.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 name: Docker release description: Release Docker Images diff --git a/.github/semantic.yml b/.github/semantic.yml index 3aafb9d..45727d4 100644 --- a/.github/semantic.yml +++ b/.github/semantic.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright ${hawkeye.git.fileCreatedYear} - ${hawkeye.git.fileModifiedYear}, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 # The pull request's title should be fulfilled the following pattern: # diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc817a9..1963d40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 name: CI on: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 886f32c..eee72cf 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 name: Release diff --git a/Cargo.toml b/Cargo.toml index c2a444f..75453a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [workspace] members = [ diff --git a/Dockerfile b/Dockerfile index 44cc49b..5554413 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 FROM public.ecr.aws/docker/library/rust:1.76.0-alpine3.19 as build ENV RUSTFLAGS="-C target-feature=-crt-static" diff --git a/action.yml b/action.yml index 14a00b4..8f289dd 100644 --- a/action.yml +++ b/action.yml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 name: HawkEye Action description: 'Check, format, or remove license headers.' diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 6305590..c8f9b1a 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [package] name = "hawkeye" diff --git a/cli/build.rs b/cli/build.rs index f1bd573..f8c16e4 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{borrow::Cow, sync::OnceLock}; diff --git a/cli/src/cli.rs b/cli/src/cli.rs index d6bca43..60cae41 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::path::{Path, PathBuf}; diff --git a/cli/src/main.rs b/cli/src/main.rs index 90b5644..4e1fd1f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use clap::{crate_description, FromArgMatches, Subcommand}; use tracing::level_filters::LevelFilter; diff --git a/fmt/Cargo.toml b/fmt/Cargo.toml index 3246ba7..bf9b2ef 100644 --- a/fmt/Cargo.toml +++ b/fmt/Cargo.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [package] name = "hawkeye-fmt" diff --git a/fmt/src/config/mod.rs b/fmt/src/config/mod.rs index d4c51e7..2062846 100644 --- a/fmt/src/config/mod.rs +++ b/fmt/src/config/mod.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{ collections::{HashMap, HashSet}, diff --git a/fmt/src/document/defaults.toml b/fmt/src/document/defaults.toml index ab96055..32ac41f 100644 --- a/fmt/src/document/defaults.toml +++ b/fmt/src/document/defaults.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [ACTIONSCRIPT] pattern = "as" diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index 2e0f172..0d455b8 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{ borrow::Cow, diff --git a/fmt/src/document/mod.rs b/fmt/src/document/mod.rs index c1cba0a..38270f9 100644 --- a/fmt/src/document/mod.rs +++ b/fmt/src/document/mod.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{collections::HashMap, fs, fs::File, io::BufRead, path::PathBuf}; diff --git a/fmt/src/document/model.rs b/fmt/src/document/model.rs index d915743..9721d8e 100644 --- a/fmt/src/document/model.rs +++ b/fmt/src/document/model.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; diff --git a/fmt/src/error.rs b/fmt/src/error.rs index c1c5399..44c773b 100644 --- a/fmt/src/error.rs +++ b/fmt/src/error.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use snafu::Snafu; diff --git a/fmt/src/git.rs b/fmt/src/git.rs index fd83ad5..2e9b0fb 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::path::Path; diff --git a/fmt/src/header/defaults.toml b/fmt/src/header/defaults.toml index 881e2bd..9ed4707 100644 --- a/fmt/src/header/defaults.toml +++ b/fmt/src/header/defaults.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [SHARPSTAR_STYLE] firstLine = '#*' diff --git a/fmt/src/header/matcher.rs b/fmt/src/header/matcher.rs index 476e9ae..cae8085 100644 --- a/fmt/src/header/matcher.rs +++ b/fmt/src/header/matcher.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::fmt::{Display, Formatter}; diff --git a/fmt/src/header/mod.rs b/fmt/src/header/mod.rs index 24031a8..3f03b12 100644 --- a/fmt/src/header/mod.rs +++ b/fmt/src/header/mod.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 pub mod matcher; pub mod model; diff --git a/fmt/src/header/model.rs b/fmt/src/header/model.rs index b287385..8b00369 100644 --- a/fmt/src/header/model.rs +++ b/fmt/src/header/model.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; diff --git a/fmt/src/header/parser.rs b/fmt/src/header/parser.rs index 03e8007..a81fb2b 100644 --- a/fmt/src/header/parser.rs +++ b/fmt/src/header/parser.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{ fmt::{Display, Formatter}, diff --git a/fmt/src/lib.rs b/fmt/src/lib.rs index 37affca..3d1aa5d 100644 --- a/fmt/src/lib.rs +++ b/fmt/src/lib.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use crate::error::Error; diff --git a/fmt/src/license/mod.rs b/fmt/src/license/mod.rs index 58e93ce..0f3a780 100644 --- a/fmt/src/license/mod.rs +++ b/fmt/src/license/mod.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use snafu::OptionExt; diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index b4c361b..63f5f14 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::{ fs, diff --git a/fmt/src/selection.rs b/fmt/src/selection.rs index ab7c693..ba2fefd 100644 --- a/fmt/src/selection.rs +++ b/fmt/src/selection.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::path::{Path, PathBuf}; diff --git a/fmt/tests/tests.rs b/fmt/tests/tests.rs index 1b08fd3..8f1b684 100644 --- a/fmt/tests/tests.rs +++ b/fmt/tests/tests.rs @@ -11,6 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copyright 2024 - 2024, tison and the HawkEye contributors +// SPDX-License-Identifier: Apache-2.0 use std::path::Path; diff --git a/licenserc.toml b/licenserc.toml index ad4fcb1..2faff9e 100644 --- a/licenserc.toml +++ b/licenserc.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 inlineHeader = """ Copyright ${inceptionYear} ${copyrightOwner} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 093997d..3f4c18f 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 [toolchain] channel = "stable" diff --git a/rustfmt.toml b/rustfmt.toml index 8a8512b..8328a59 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 imports_granularity = "Crate" group_imports = "StdExternalCrate" diff --git a/tests/it.py b/tests/it.py index 9dd6a63..b221547 100755 --- a/tests/it.py +++ b/tests/it.py @@ -12,6 +12,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# Copyright 2024 - 2024, tison and the HawkEye contributors +# SPDX-License-Identifier: Apache-2.0 from pathlib import Path import subprocess From 3db43cae15ef4d482af31a425e3c55d044dc80fd Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:05:18 +0800 Subject: [PATCH 08/17] update docs Signed-off-by: tison --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fcae20e..05a9f6d 100644 --- a/README.md +++ b/README.md @@ -180,9 +180,18 @@ inceptionYear = 2023 # 'auto' means this feature tries to be enabled with: # * gix - if `basedir` is in a Git repository. # * ignore crate's gitignore rules - if `basedir` is not in a Git repository. -# 'enabled' means always enabled with gix; failed if it is impossible. +# 'enable' means always enabled with gix; failed if it is impossible. # default: 'auto' ignore = 'auto' +# If enabled, populate file attrs determinated by Git; possible value: ['auto', 'enable', 'disable'] +# Attributes contains: +# * 'hawkeye.git.fileCreatedYear' +# * 'hawkeye.git.fileModifiedYear' +# 'auto' means this feature tries to be enabled with: +# * gix - if `basedir` is in a Git repository. +# 'enable' means always enabled with gix; failed if it is impossible. +# default: 'disable' +attrs = 'disable' ``` ### Header style file From dad2360bb4af2ffd4f3505ae7cd1dd0b9dde6190 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:07:13 +0800 Subject: [PATCH 09/17] apply for all Signed-off-by: tison --- .github/semantic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/semantic.yml b/.github/semantic.yml index 45727d4..68a6c08 100644 --- a/.github/semantic.yml +++ b/.github/semantic.yml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Copyright ${hawkeye.git.fileCreatedYear} - ${hawkeye.git.fileModifiedYear}, tison and the HawkEye contributors +# Copyright 2024 - 2024, tison and the HawkEye contributors # SPDX-License-Identifier: Apache-2.0 # The pull request's title should be fulfilled the following pattern: From ddd19b0ba9a82bd9a1a82074d0b5ba609544bd7b Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:22:47 +0800 Subject: [PATCH 10/17] speed up Signed-off-by: tison --- fmt/src/document/factory.rs | 82 +++++-------------------------------- fmt/src/git.rs | 63 +++++++++++++++++++++++++++- fmt/src/processor.rs | 13 +++++- 3 files changed, 84 insertions(+), 74 deletions(-) diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index 0d455b8..c264b85 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -18,7 +18,6 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, - convert::Infallible, path::Path, }; @@ -26,12 +25,8 @@ use snafu::ResultExt; use time::format_description; use crate::{ - config::Mapping, - document::Document, - error::{CreateDocumentSnafu, GitFileAttrsSnafu}, - git::GitContext, - header::model::HeaderDef, - Result, + config::Mapping, document::Document, error::CreateDocumentSnafu, git::GitFileAttrs, + header::model::HeaderDef, Result, }; pub struct DocumentFactory { @@ -40,7 +35,7 @@ pub struct DocumentFactory { properties: HashMap, keywords: Vec, - git_context: GitContext, + git_file_attrs: HashMap, } impl DocumentFactory { @@ -49,14 +44,14 @@ impl DocumentFactory { definitions: HashMap, properties: HashMap, keywords: Vec, - git_context: GitContext, + git_file_attrs: HashMap, ) -> Self { Self { mapping, definitions, properties, keywords, - git_context, + git_file_attrs, } } @@ -89,18 +84,17 @@ impl DocumentFactory { properties.insert("hawkeye.core.filename".to_string(), filename); let year_formatter = format_description::parse("[year]").expect("cannot parse format"); - let git_file_attrs = - resolve_git_file_attrs(&self.git_context, filepath).context(GitFileAttrsSnafu)?; - if let Some(time) = git_file_attrs.created_time { + if let Some(attrs) = self + .git_file_attrs + .get(filepath.to_str().expect("path is never empty")) + { properties.insert( "hawkeye.git.fileCreatedYear".to_string(), - time.format(year_formatter.as_slice()), + attrs.created_time.format(year_formatter.as_slice()), ); - } - if let Some(time) = git_file_attrs.modified_time { properties.insert( "hawkeye.git.fileModifiedYear".to_string(), - time.format(year_formatter.as_slice()), + attrs.modified_time.format(year_formatter.as_slice()), ); } @@ -112,57 +106,3 @@ impl DocumentFactory { ) } } - -#[derive(Debug)] -struct GitFileAttrs { - created_time: Option, - modified_time: Option, -} - -fn resolve_git_file_attrs(git_context: &GitContext, path: &Path) -> anyhow::Result { - let mut attrs = GitFileAttrs { - created_time: None, - modified_time: None, - }; - - if let Some(ref repo) = git_context.repo { - let workdir = repo.work_dir().expect("workdir cannot be absent"); - let workdir = workdir.canonicalize()?; - let rela_path = path.strip_prefix(&workdir)?; - let location = rela_path.display().to_string(); - - let mode = gix::diff::blob::pipeline::Mode::ToGit; - let mut cache = repo.diff_resource_cache(mode, Default::default())?; - - let head = repo.head_commit()?; - let mut prev_commit = head.clone(); - - for info in head.ancestors().all()? { - let info = info?; - let this_commit = info.object()?; - let tree = this_commit.tree()?; - let mut changes = tree.changes()?; - changes.track_path().for_each_to_obtain_tree_with_cache( - &prev_commit.tree()?, - &mut cache, - |change| { - if change.location == location { - let time = this_commit.time().expect("commit always has time"); - attrs.created_time = match attrs.created_time { - None => Some(time), - Some(t) => Some(t.min(time)), - }; - attrs.modified_time = match attrs.modified_time { - None => Some(time), - Some(t) => Some(t.max(time)), - }; - } - Ok::<_, Infallible>(Default::default()) - }, - )?; - prev_commit = this_commit; - } - } - - Ok(attrs) -} diff --git a/fmt/src/git.rs b/fmt/src/git.rs index 2e9b0fb..5217367 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -15,7 +15,11 @@ // Copyright 2024 - 2024, tison and the HawkEye contributors // SPDX-License-Identifier: Apache-2.0 -use std::path::Path; +use std::{ + collections::{hash_map::Entry, HashMap}, + convert::Infallible, + path::Path, +}; use gix::Repository; use snafu::IntoError; @@ -85,3 +89,60 @@ fn resolve_features(config: &config::Git) -> FeatureGate { } FeatureGate::Disable } + +#[derive(Debug)] +pub struct GitFileAttrs { + pub created_time: gix::date::Time, + pub modified_time: gix::date::Time, +} + +pub fn resolve_file_attrs(repo: &Repository) -> anyhow::Result> { + let mut attrs = HashMap::new(); + + let workdir = repo.work_dir().expect("workdir cannot be absent"); + let workdir = workdir.canonicalize()?; + + let mode = gix::diff::blob::pipeline::Mode::ToGit; + let mut cache = repo.diff_resource_cache(mode, Default::default())?; + + let head = repo.head_commit()?; + let mut prev_commit = head.clone(); + + for info in head.ancestors().all()? { + let info = info?; + let this_commit = info.object()?; + let tree = this_commit.tree()?; + let mut changes = tree.changes()?; + changes.track_path().for_each_to_obtain_tree_with_cache( + &prev_commit.tree()?, + &mut cache, + |change| { + let filepath = workdir.join(change.location.to_string()); + let filepath = filepath.display().to_string(); + + let time = this_commit.time().expect("commit always has time"); + match attrs.entry(filepath) { + Entry::Occupied(mut ent) => { + let attrs: &GitFileAttrs = ent.get(); + ent.insert(GitFileAttrs { + created_time: time.min(attrs.created_time), + modified_time: time.max(attrs.modified_time), + }); + } + Entry::Vacant(ent) => { + ent.insert(GitFileAttrs { + created_time: time, + modified_time: time, + }); + } + } + + Ok::<_, Infallible>(Default::default()) + }, + )?; + prev_commit = this_commit; + cache.clear_resource_cache(); + } + + Ok(attrs) +} diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index 63f5f14..141f304 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -16,6 +16,7 @@ // SPDX-License-Identifier: Apache-2.0 use std::{ + collections::HashMap, fs, path::{Path, PathBuf}, }; @@ -25,7 +26,10 @@ use snafu::{ensure, ResultExt}; use crate::{ config::Config, document::{factory::DocumentFactory, model::default_mapping, Document}, - error::{DeserializeSnafu, InvalidConfigSnafu, LoadConfigSnafu, TryMatchHeaderSnafu}, + error::{ + DeserializeSnafu, GitFileAttrsSnafu, InvalidConfigSnafu, LoadConfigSnafu, + TryMatchHeaderSnafu, + }, git, header::{ matcher::HeaderMatcher, @@ -111,12 +115,17 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) HeaderMatcher::new(header_source.content) }; + let git_file_attrs = match git_context.repo { + None => HashMap::new(), + Some(ref repo) => git::resolve_file_attrs(repo).context(GitFileAttrsSnafu)?, + }; + let document_factory = DocumentFactory::new( mapping, definitions, config.properties, config.keywords, - git_context, + git_file_attrs, ); for file in selected_files { From 7de3c3566f4b3176e712318bd57af11349b63e83 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:25:43 +0800 Subject: [PATCH 11/17] update ci Signed-off-by: tison --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1963d40..40c080a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: korandoru/hawkeye@v4 - uses: Swatinem/rust-cache@v2 - uses: dtolnay/rust-toolchain@nightly - name: Check Clippy @@ -65,7 +64,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest, buildjet-4vcpu-ubuntu-2204-arm ] + os: [ ubuntu-latest ] runs-on: ${{matrix.os}} name: Docker sanity check on ${{ matrix.os }} steps: From 57f31699d8dc858280a492ab38f80382685b65d6 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:31:39 +0800 Subject: [PATCH 12/17] checkout full history Signed-off-by: tison --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40c080a..bfd4e76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,8 @@ jobs: name: Docker sanity check on ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + depth: 0 - name: Build and load uses: docker/build-push-action@v5 with: @@ -99,6 +101,8 @@ jobs: name: Smoke test on ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + depth: 0 - uses: Swatinem/rust-cache@v2 - name: Dog feed license check shell: bash @@ -121,6 +125,8 @@ jobs: name: Smoke test for GitHub Actions on ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + depth: 0 - name: Check and fail if unknown uses: ./ with: From c9d3ab60cf819b4e1633fa5a7388957c5d9c7af7 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:34:36 +0800 Subject: [PATCH 13/17] checkout full history Signed-off-by: tison --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfd4e76..6cf8ddc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - depth: 0 + fetch-depth: 0 - name: Build and load uses: docker/build-push-action@v5 with: @@ -102,7 +102,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - depth: 0 + fetch-depth: 0 - uses: Swatinem/rust-cache@v2 - name: Dog feed license check shell: bash @@ -126,7 +126,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - depth: 0 + fetch-depth: 0 - name: Check and fail if unknown uses: ./ with: From 82d399941e17ff293c142e80d8eaae30babea369 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:42:06 +0800 Subject: [PATCH 14/17] speed up Signed-off-by: tison --- fmt/src/document/factory.rs | 10 ++++++---- fmt/src/git.rs | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fmt/src/document/factory.rs b/fmt/src/document/factory.rs index c264b85..81c92bc 100644 --- a/fmt/src/document/factory.rs +++ b/fmt/src/document/factory.rs @@ -22,7 +22,7 @@ use std::{ }; use snafu::ResultExt; -use time::format_description; +use time::{format_description, format_description::FormatItem}; use crate::{ config::Mapping, document::Document, error::CreateDocumentSnafu, git::GitFileAttrs, @@ -36,6 +36,7 @@ pub struct DocumentFactory { keywords: Vec, git_file_attrs: HashMap, + year_formatter: Vec>, } impl DocumentFactory { @@ -46,12 +47,14 @@ impl DocumentFactory { keywords: Vec, git_file_attrs: HashMap, ) -> Self { + let year_formatter = format_description::parse("[year]").expect("cannot parse format"); Self { mapping, definitions, properties, keywords, git_file_attrs, + year_formatter, } } @@ -83,18 +86,17 @@ impl DocumentFactory { .to_string(); properties.insert("hawkeye.core.filename".to_string(), filename); - let year_formatter = format_description::parse("[year]").expect("cannot parse format"); if let Some(attrs) = self .git_file_attrs .get(filepath.to_str().expect("path is never empty")) { properties.insert( "hawkeye.git.fileCreatedYear".to_string(), - attrs.created_time.format(year_formatter.as_slice()), + attrs.created_time.format(self.year_formatter.as_slice()), ); properties.insert( "hawkeye.git.fileModifiedYear".to_string(), - attrs.modified_time.format(year_formatter.as_slice()), + attrs.modified_time.format(self.year_formatter.as_slice()), ); } diff --git a/fmt/src/git.rs b/fmt/src/git.rs index 5217367..b316641 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -111,6 +111,8 @@ pub fn resolve_file_attrs(repo: &Repository) -> anyhow::Result anyhow::Result { let attrs: &GitFileAttrs = ent.get(); From e576dad548bd1ff6e3163da3b2ab662c7b76ca53 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:52:44 +0800 Subject: [PATCH 15/17] speed up more Signed-off-by: tison --- fmt/src/git.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fmt/src/git.rs b/fmt/src/git.rs index b316641..977864e 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -106,17 +106,17 @@ pub fn resolve_file_attrs(repo: &Repository) -> anyhow::Result anyhow::Result(Default::default()) }, )?; - prev_commit = this_commit; + prev_tree = tree; cache.clear_resource_cache(); } From dc7f8ea03f45e0931bf9e92f0e18f1777c7c6b94 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 10:56:07 +0800 Subject: [PATCH 16/17] Revert "speed up more" This reverts commit e576dad548bd1ff6e3163da3b2ab662c7b76ca53. --- fmt/src/git.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fmt/src/git.rs b/fmt/src/git.rs index 977864e..b316641 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -106,17 +106,17 @@ pub fn resolve_file_attrs(repo: &Repository) -> anyhow::Result anyhow::Result(Default::default()) }, )?; - prev_tree = tree; + prev_commit = this_commit; cache.clear_resource_cache(); } From 2d91f3a9ba374e33dfea725aae4e83a8d845755f Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 11 Jun 2024 11:01:09 +0800 Subject: [PATCH 17/17] fixup Signed-off-by: tison --- fmt/src/git.rs | 13 ++++++++++++- fmt/src/processor.rs | 6 +----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/fmt/src/git.rs b/fmt/src/git.rs index b316641..fdac915 100644 --- a/fmt/src/git.rs +++ b/fmt/src/git.rs @@ -96,9 +96,20 @@ pub struct GitFileAttrs { pub modified_time: gix::date::Time, } -pub fn resolve_file_attrs(repo: &Repository) -> anyhow::Result> { +pub fn resolve_file_attrs( + git_context: GitContext, +) -> anyhow::Result> { let mut attrs = HashMap::new(); + if git_context.config.attrs.is_disable() { + return Ok(attrs); + } + + let repo = match git_context.repo { + Some(repo) => repo, + None => return Ok(attrs), + }; + let workdir = repo.work_dir().expect("workdir cannot be absent"); let workdir = workdir.canonicalize()?; diff --git a/fmt/src/processor.rs b/fmt/src/processor.rs index 141f304..4085d32 100644 --- a/fmt/src/processor.rs +++ b/fmt/src/processor.rs @@ -16,7 +16,6 @@ // SPDX-License-Identifier: Apache-2.0 use std::{ - collections::HashMap, fs, path::{Path, PathBuf}, }; @@ -115,10 +114,7 @@ pub fn check_license_header(run_config: PathBuf, callback: &mut C) HeaderMatcher::new(header_source.content) }; - let git_file_attrs = match git_context.repo { - None => HashMap::new(), - Some(ref repo) => git::resolve_file_attrs(repo).context(GitFileAttrsSnafu)?, - }; + let git_file_attrs = git::resolve_file_attrs(git_context).context(GitFileAttrsSnafu)?; let document_factory = DocumentFactory::new( mapping,