2021-02-12 19:43:12 -05:00
|
|
|
pub struct ConfigStorage {
|
2021-03-29 14:39:48 -04:00
|
|
|
arena: std::sync::Mutex<typed_arena::Arena<kstring::KString>>,
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ConfigStorage {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
2021-03-29 14:39:48 -04:00
|
|
|
arena: std::sync::Mutex::new(typed_arena::Arena::new()),
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get<'s>(&'s self, other: &str) -> &'s str {
|
2021-03-29 14:39:48 -04:00
|
|
|
// Safe because we the references are stable once created.
|
|
|
|
//
|
|
|
|
// Trying to get this handled inside of `typed_arena` directly, see
|
|
|
|
// https://github.com/SimonSapin/rust-typed-arena/issues/49#issuecomment-809517312
|
|
|
|
unsafe {
|
|
|
|
std::mem::transmute::<&str, &str>(
|
|
|
|
self.arena
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
2021-03-29 21:28:01 -04:00
|
|
|
.alloc(kstring::KString::from_ref(other))
|
|
|
|
.as_str(),
|
2021-03-29 14:39:48 -04:00
|
|
|
)
|
|
|
|
}
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-29 21:28:01 -04:00
|
|
|
impl Default for ConfigStorage {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 19:43:12 -05:00
|
|
|
pub struct ConfigEngine<'s> {
|
2021-03-29 14:39:48 -04:00
|
|
|
storage: &'s ConfigStorage,
|
|
|
|
|
2021-04-05 08:34:05 -04:00
|
|
|
overrides: Option<crate::config::Config>,
|
2021-03-29 14:39:48 -04:00
|
|
|
isolated: bool,
|
|
|
|
|
|
|
|
configs: std::collections::HashMap<std::path::PathBuf, DirConfig>,
|
2021-03-31 21:06:33 -04:00
|
|
|
walk: Intern<crate::config::Walk>,
|
2021-03-29 14:39:48 -04:00
|
|
|
tokenizer: Intern<typos::tokens::Tokenizer>,
|
|
|
|
dict: Intern<crate::dict::Override<'s, 's, crate::dict::BuiltIn>>,
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore: Intern<Vec<regex::Regex>>,
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'s> ConfigEngine<'s> {
|
2021-03-29 14:39:48 -04:00
|
|
|
pub fn new(storage: &'s ConfigStorage) -> Self {
|
|
|
|
Self {
|
|
|
|
storage,
|
|
|
|
overrides: Default::default(),
|
|
|
|
configs: Default::default(),
|
|
|
|
isolated: false,
|
2021-03-31 21:06:33 -04:00
|
|
|
walk: Default::default(),
|
2021-03-29 14:39:48 -04:00
|
|
|
tokenizer: Default::default(),
|
|
|
|
dict: Default::default(),
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore: Default::default(),
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-05 08:34:05 -04:00
|
|
|
pub fn set_overrides(&mut self, overrides: crate::config::Config) -> &mut Self {
|
2021-03-29 14:39:48 -04:00
|
|
|
self.overrides = Some(overrides);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_isolated(&mut self, isolated: bool) -> &mut Self {
|
|
|
|
self.isolated = isolated;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-04-05 22:15:41 -04:00
|
|
|
pub fn walk(&self, cwd: &std::path::Path) -> &crate::config::Walk {
|
2021-05-14 12:26:02 -04:00
|
|
|
debug_assert!(cwd.is_absolute(), "{} is not absolute", cwd.display());
|
2021-03-29 14:39:48 -04:00
|
|
|
let dir = self
|
|
|
|
.configs
|
|
|
|
.get(cwd)
|
|
|
|
.expect("`init_dir` must be called first");
|
2021-03-31 21:06:33 -04:00
|
|
|
self.get_walk(dir)
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2022-06-15 16:40:49 -04:00
|
|
|
pub fn file_types(
|
|
|
|
&self,
|
|
|
|
cwd: &std::path::Path,
|
|
|
|
) -> &std::collections::BTreeMap<kstring::KString, Vec<kstring::KString>> {
|
2021-05-14 12:26:02 -04:00
|
|
|
debug_assert!(cwd.is_absolute(), "{} is not absolute", cwd.display());
|
2021-04-05 22:15:41 -04:00
|
|
|
let dir = self
|
|
|
|
.configs
|
|
|
|
.get(cwd)
|
|
|
|
.expect("`init_dir` must be called first");
|
|
|
|
dir.type_matcher.definitions()
|
|
|
|
}
|
|
|
|
|
2023-03-18 02:25:39 -04:00
|
|
|
pub fn policy(&self, path: &std::path::Path) -> Policy<'_, '_, '_> {
|
2021-05-14 12:26:02 -04:00
|
|
|
debug_assert!(path.is_absolute(), "{} is not absolute", path.display());
|
2021-03-31 21:06:33 -04:00
|
|
|
let dir = self.get_dir(path).expect("`walk()` should be called first");
|
2023-01-13 21:59:49 -05:00
|
|
|
let (file_type, file_config) = dir.get_file_config(path);
|
2021-03-29 14:39:48 -04:00
|
|
|
Policy {
|
2021-04-05 22:03:41 -04:00
|
|
|
check_filenames: file_config.check_filenames,
|
|
|
|
check_files: file_config.check_files,
|
2023-01-13 21:59:49 -05:00
|
|
|
file_type,
|
2021-04-05 22:03:41 -04:00
|
|
|
binary: file_config.binary,
|
|
|
|
tokenizer: self.get_tokenizer(&file_config),
|
|
|
|
dict: self.get_dict(&file_config),
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore: self.get_ignore(&file_config),
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-31 21:06:33 -04:00
|
|
|
fn get_walk(&self, dir: &DirConfig) -> &crate::config::Walk {
|
|
|
|
self.walk.get(dir.walk)
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2021-03-31 21:19:52 -04:00
|
|
|
fn get_tokenizer(&self, file: &FileConfig) -> &typos::tokens::Tokenizer {
|
|
|
|
self.tokenizer.get(file.tokenizer)
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2021-03-31 21:19:52 -04:00
|
|
|
fn get_dict(&self, file: &FileConfig) -> &dyn typos::Dictionary {
|
|
|
|
self.dict.get(file.dict)
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2023-03-18 02:25:39 -04:00
|
|
|
fn get_ignore(&self, file: &FileConfig) -> &[regex::Regex] {
|
|
|
|
self.ignore.get(file.ignore)
|
|
|
|
}
|
|
|
|
|
2021-03-29 14:39:48 -04:00
|
|
|
fn get_dir(&self, path: &std::path::Path) -> Option<&DirConfig> {
|
|
|
|
for path in path.ancestors() {
|
|
|
|
if let Some(dir) = self.configs.get(path) {
|
|
|
|
return Some(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn load_config(
|
|
|
|
&self,
|
|
|
|
cwd: &std::path::Path,
|
|
|
|
) -> Result<crate::config::Config, anyhow::Error> {
|
2021-05-14 12:26:02 -04:00
|
|
|
debug_assert!(cwd.is_absolute(), "{} is not absolute", cwd.display());
|
2021-03-29 14:39:48 -04:00
|
|
|
let mut config = crate::config::Config::default();
|
|
|
|
|
|
|
|
if !self.isolated {
|
2021-05-14 15:06:15 -04:00
|
|
|
for ancestor in cwd.ancestors() {
|
|
|
|
if let Some(derived) = crate::config::Config::from_dir(ancestor)? {
|
|
|
|
config.update(&derived);
|
|
|
|
break;
|
|
|
|
}
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(overrides) = self.overrides.as_ref() {
|
2021-04-05 08:34:05 -04:00
|
|
|
config.update(overrides);
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2021-04-07 21:49:30 -04:00
|
|
|
let mut types = Default::default();
|
2021-08-04 07:55:46 -04:00
|
|
|
std::mem::swap(&mut types, &mut config.type_.patterns);
|
2021-04-07 21:49:30 -04:00
|
|
|
let mut types = types
|
|
|
|
.into_iter()
|
|
|
|
.map(|(type_, type_engine)| {
|
|
|
|
let mut new_engine = config.default.clone();
|
|
|
|
new_engine.update(&type_engine.engine);
|
|
|
|
new_engine.update(&config.overrides);
|
2021-08-04 07:55:46 -04:00
|
|
|
let new_type_engine = crate::config::GlobEngineConfig {
|
2021-04-07 21:49:30 -04:00
|
|
|
extend_glob: type_engine.extend_glob,
|
|
|
|
engine: new_engine,
|
|
|
|
};
|
|
|
|
(type_, new_type_engine)
|
|
|
|
})
|
|
|
|
.collect();
|
2021-08-04 07:55:46 -04:00
|
|
|
std::mem::swap(&mut types, &mut config.type_.patterns);
|
2021-04-07 21:49:30 -04:00
|
|
|
|
|
|
|
config.default.update(&config.overrides);
|
|
|
|
|
2021-03-29 14:39:48 -04:00
|
|
|
Ok(config)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn init_dir(&mut self, cwd: &std::path::Path) -> Result<(), anyhow::Error> {
|
2021-05-14 12:26:02 -04:00
|
|
|
debug_assert!(cwd.is_absolute(), "{} is not absolute", cwd.display());
|
2021-03-29 14:39:48 -04:00
|
|
|
if self.configs.contains_key(cwd) {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let config = self.load_config(cwd)?;
|
2021-04-05 08:34:05 -04:00
|
|
|
let crate::config::Config {
|
|
|
|
files,
|
|
|
|
mut default,
|
2021-04-05 22:03:41 -04:00
|
|
|
type_,
|
2021-04-05 08:34:05 -04:00
|
|
|
overrides,
|
|
|
|
} = config;
|
2021-03-31 21:19:52 -04:00
|
|
|
|
|
|
|
let walk = self.walk.intern(files);
|
|
|
|
|
2022-06-15 16:40:49 -04:00
|
|
|
let mut type_matcher = crate::file_type::TypesBuilder::new();
|
|
|
|
type_matcher.add_defaults();
|
2021-04-06 22:08:01 -04:00
|
|
|
let mut types: std::collections::HashMap<_, _> = Default::default();
|
2021-08-04 07:55:46 -04:00
|
|
|
for (type_name, type_engine) in type_.patterns() {
|
2021-04-06 22:28:40 -04:00
|
|
|
if type_engine.extend_glob.is_empty() {
|
2022-06-15 16:40:49 -04:00
|
|
|
if !type_matcher.contains_name(&type_name) {
|
2021-04-07 21:47:49 -04:00
|
|
|
anyhow::bail!("Unknown type definition `{}`, pass `--type-list` to see valid names or set `extend_glob` to add a new one.", type_name);
|
2021-04-06 22:28:40 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for glob in type_engine.extend_glob.iter() {
|
2022-06-15 16:40:49 -04:00
|
|
|
type_matcher.add(type_name.as_ref(), glob.as_ref());
|
2021-04-06 22:28:40 -04:00
|
|
|
}
|
2021-04-06 22:14:35 -04:00
|
|
|
}
|
|
|
|
|
2021-10-23 10:24:05 -04:00
|
|
|
let mut engine = default.clone();
|
|
|
|
engine.update(&type_engine.engine);
|
|
|
|
engine.update(&overrides);
|
|
|
|
|
|
|
|
let type_config = self.init_file_config(engine);
|
2021-04-06 22:08:01 -04:00
|
|
|
types.insert(type_name, type_config);
|
|
|
|
}
|
2021-04-05 22:03:41 -04:00
|
|
|
default.update(&overrides);
|
|
|
|
let default = self.init_file_config(default);
|
|
|
|
|
|
|
|
let dir = DirConfig {
|
|
|
|
walk,
|
|
|
|
default,
|
|
|
|
types,
|
2021-04-06 22:09:02 -04:00
|
|
|
type_matcher: type_matcher.build()?,
|
2021-04-05 22:03:41 -04:00
|
|
|
};
|
2021-03-31 21:19:52 -04:00
|
|
|
|
|
|
|
self.configs.insert(cwd.to_owned(), dir);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-04-05 22:03:41 -04:00
|
|
|
fn init_file_config(&mut self, engine: crate::config::EngineConfig) -> FileConfig {
|
2021-03-31 21:19:52 -04:00
|
|
|
let binary = engine.binary();
|
|
|
|
let check_filename = engine.check_filename();
|
|
|
|
let check_file = engine.check_file();
|
2021-03-01 21:37:05 -05:00
|
|
|
let crate::config::EngineConfig {
|
2023-12-08 14:07:52 -05:00
|
|
|
tokenizer: mut tokenizer_config,
|
|
|
|
dict: mut dict_config,
|
2023-03-18 02:25:39 -04:00
|
|
|
extend_ignore_re,
|
|
|
|
..
|
2021-03-31 21:19:52 -04:00
|
|
|
} = engine;
|
2023-12-08 14:07:52 -05:00
|
|
|
tokenizer_config.update(&crate::config::TokenizerConfig::from_defaults());
|
|
|
|
dict_config.update(&crate::config::DictConfig::from_defaults());
|
2021-02-12 19:43:12 -05:00
|
|
|
|
2021-06-29 11:40:58 -04:00
|
|
|
if !tokenizer_config.ignore_hex() {
|
|
|
|
log::warn!("`ignore-hex` is deprecated");
|
|
|
|
if !tokenizer_config.identifier_leading_digits() {
|
|
|
|
log::warn!("`identifier-leading-digits` is deprecated");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 19:43:12 -05:00
|
|
|
let tokenizer = typos::tokens::TokenizerBuilder::new()
|
2021-04-29 13:30:56 -04:00
|
|
|
.unicode(tokenizer_config.unicode())
|
2021-02-12 19:43:12 -05:00
|
|
|
.build();
|
|
|
|
|
2021-03-01 21:37:05 -05:00
|
|
|
let dict = crate::dict::BuiltIn::new(dict_config.locale());
|
|
|
|
let mut dict = crate::dict::Override::new(dict);
|
2023-03-18 00:47:25 -04:00
|
|
|
dict.ignored_identifiers(dict_config.extend_ignore_identifiers_re());
|
2021-03-01 21:37:05 -05:00
|
|
|
dict.identifiers(
|
|
|
|
dict_config
|
2021-02-12 19:43:12 -05:00
|
|
|
.extend_identifiers()
|
2021-03-29 14:39:48 -04:00
|
|
|
.map(|(k, v)| (self.storage.get(k), self.storage.get(v))),
|
2021-02-12 19:43:12 -05:00
|
|
|
);
|
2023-10-16 13:37:00 -04:00
|
|
|
dict.ignored_words(dict_config.extend_ignore_words_re());
|
2021-03-01 21:37:05 -05:00
|
|
|
dict.words(
|
|
|
|
dict_config
|
2021-02-12 19:43:12 -05:00
|
|
|
.extend_words()
|
2021-03-29 14:39:48 -04:00
|
|
|
.map(|(k, v)| (self.storage.get(k), self.storage.get(v))),
|
2021-02-12 19:43:12 -05:00
|
|
|
);
|
|
|
|
|
2021-03-29 14:39:48 -04:00
|
|
|
let dict = self.dict.intern(dict);
|
|
|
|
let tokenizer = self.tokenizer.intern(tokenizer);
|
|
|
|
|
2023-03-18 02:25:39 -04:00
|
|
|
let ignore = self.ignore.intern(extend_ignore_re);
|
|
|
|
|
2021-04-06 11:15:14 -04:00
|
|
|
FileConfig {
|
2021-03-01 21:37:05 -05:00
|
|
|
check_filenames: check_filename,
|
|
|
|
check_files: check_file,
|
2021-03-29 21:28:01 -04:00
|
|
|
binary,
|
2021-02-12 19:43:12 -05:00
|
|
|
tokenizer,
|
2021-03-01 21:37:05 -05:00
|
|
|
dict,
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore,
|
2021-04-06 11:15:14 -04:00
|
|
|
}
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Intern<T> {
|
|
|
|
data: Vec<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Intern<T> {
|
2024-04-26 22:14:01 -04:00
|
|
|
pub(crate) fn new() -> Self {
|
2021-03-29 14:39:48 -04:00
|
|
|
Self {
|
|
|
|
data: Default::default(),
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-26 22:14:01 -04:00
|
|
|
pub(crate) fn intern(&mut self, value: T) -> usize {
|
2021-03-29 14:39:48 -04:00
|
|
|
let symbol = self.data.len();
|
|
|
|
self.data.push(value);
|
|
|
|
symbol
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
|
2024-04-26 22:14:01 -04:00
|
|
|
pub(crate) fn get(&self, symbol: usize) -> &T {
|
2021-03-29 14:39:48 -04:00
|
|
|
&self.data[symbol]
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-29 14:39:48 -04:00
|
|
|
impl<T> Default for Intern<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-05 22:03:41 -04:00
|
|
|
#[derive(Clone, Debug)]
|
2021-03-29 14:39:48 -04:00
|
|
|
struct DirConfig {
|
2021-03-31 21:06:33 -04:00
|
|
|
walk: usize,
|
2021-03-31 21:19:52 -04:00
|
|
|
default: FileConfig,
|
2021-04-05 22:03:41 -04:00
|
|
|
types: std::collections::HashMap<kstring::KString, FileConfig>,
|
2022-06-15 16:40:49 -04:00
|
|
|
type_matcher: crate::file_type::Types,
|
2021-04-05 22:03:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl DirConfig {
|
2023-01-13 21:59:49 -05:00
|
|
|
fn get_file_config(&self, path: &std::path::Path) -> (Option<&str>, FileConfig) {
|
2022-06-15 16:40:49 -04:00
|
|
|
let name = self.type_matcher.file_matched(path);
|
2021-04-05 22:03:41 -04:00
|
|
|
|
2023-01-13 21:59:49 -05:00
|
|
|
let config = name
|
|
|
|
.and_then(|name| {
|
|
|
|
log::debug!("{}: `{}` policy", path.display(), name);
|
|
|
|
self.types.get(name).copied()
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
log::debug!(
|
|
|
|
"{}: default policy for `{}` file type",
|
|
|
|
path.display(),
|
|
|
|
name.unwrap_or("<unknown>")
|
|
|
|
);
|
|
|
|
self.default
|
|
|
|
});
|
|
|
|
(name, config)
|
2021-04-05 22:03:41 -04:00
|
|
|
}
|
2021-03-31 21:19:52 -04:00
|
|
|
}
|
|
|
|
|
2021-04-05 22:03:41 -04:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
2021-03-31 21:19:52 -04:00
|
|
|
struct FileConfig {
|
2021-03-29 14:39:48 -04:00
|
|
|
tokenizer: usize,
|
|
|
|
dict: usize,
|
|
|
|
check_filenames: bool,
|
|
|
|
check_files: bool,
|
|
|
|
binary: bool,
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore: usize,
|
2021-03-29 14:39:48 -04:00
|
|
|
}
|
|
|
|
|
2021-02-12 19:43:12 -05:00
|
|
|
#[non_exhaustive]
|
|
|
|
#[derive(derive_setters::Setters)]
|
2023-03-18 02:25:39 -04:00
|
|
|
pub struct Policy<'t, 'd, 'i> {
|
2021-02-12 19:43:12 -05:00
|
|
|
pub check_filenames: bool,
|
|
|
|
pub check_files: bool,
|
2023-01-13 21:59:49 -05:00
|
|
|
pub file_type: Option<&'d str>,
|
2021-02-12 19:43:12 -05:00
|
|
|
pub binary: bool,
|
|
|
|
pub tokenizer: &'t typos::tokens::Tokenizer,
|
2021-03-01 21:37:05 -05:00
|
|
|
pub dict: &'d dyn typos::Dictionary,
|
2023-03-18 02:25:39 -04:00
|
|
|
pub ignore: &'i [regex::Regex],
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
|
2023-03-18 02:25:39 -04:00
|
|
|
impl<'t, 'd, 'i> Policy<'t, 'd, 'i> {
|
2021-02-12 19:43:12 -05:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-16 13:58:00 -04:00
|
|
|
static DEFAULT_TOKENIZER: typos::tokens::Tokenizer = typos::tokens::Tokenizer::new();
|
2021-02-12 19:43:12 -05:00
|
|
|
static DEFAULT_DICT: crate::dict::BuiltIn = crate::dict::BuiltIn::new(crate::config::Locale::En);
|
2023-03-18 02:25:39 -04:00
|
|
|
static DEFAULT_IGNORE: &[regex::Regex] = &[];
|
2021-02-12 19:43:12 -05:00
|
|
|
|
2023-03-18 02:25:39 -04:00
|
|
|
impl<'t, 'd, 'i> Default for Policy<'t, 'd, 'i> {
|
2021-02-12 19:43:12 -05:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
check_filenames: true,
|
|
|
|
check_files: true,
|
2023-01-13 21:59:49 -05:00
|
|
|
file_type: None,
|
2021-02-12 19:43:12 -05:00
|
|
|
binary: false,
|
|
|
|
tokenizer: &DEFAULT_TOKENIZER,
|
2021-03-01 21:37:05 -05:00
|
|
|
dict: &DEFAULT_DICT,
|
2023-03-18 02:25:39 -04:00
|
|
|
ignore: DEFAULT_IGNORE,
|
2021-02-12 19:43:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-07 22:10:27 -04:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
2021-04-09 16:58:12 -04:00
|
|
|
const NEVER_EXIST_TYPE: &str = "THISyTYPEySHOULDyNEVERyEXISTyBUTyIyHATEyYOUyIFyITyDOES";
|
2021-04-07 22:14:57 -04:00
|
|
|
|
2021-04-07 22:10:27 -04:00
|
|
|
#[test]
|
|
|
|
fn test_load_config_applies_overrides() {
|
|
|
|
let storage = ConfigStorage::new();
|
|
|
|
let mut engine = ConfigEngine::new(&storage);
|
|
|
|
engine.set_isolated(true);
|
|
|
|
|
|
|
|
let type_name = kstring::KString::from_static("toml");
|
|
|
|
|
|
|
|
let config = crate::config::Config {
|
|
|
|
default: crate::config::EngineConfig {
|
|
|
|
binary: Some(true),
|
|
|
|
check_filename: Some(true),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-08-04 07:55:46 -04:00
|
|
|
type_: crate::config::TypeEngineConfig {
|
|
|
|
patterns: maplit::hashmap! {
|
|
|
|
type_name.clone() => crate::config::GlobEngineConfig {
|
|
|
|
engine: crate::config::EngineConfig {
|
|
|
|
check_filename: Some(false),
|
|
|
|
check_file: Some(true),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-04-07 22:10:27 -04:00
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
overrides: crate::config::EngineConfig {
|
|
|
|
binary: Some(false),
|
|
|
|
check_file: Some(false),
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
engine.set_overrides(config);
|
|
|
|
|
2021-05-14 12:26:02 -04:00
|
|
|
let cwd = std::path::Path::new(".").canonicalize().unwrap();
|
2021-04-07 22:10:27 -04:00
|
|
|
let loaded = engine.load_config(&cwd).unwrap();
|
|
|
|
assert_eq!(loaded.default.binary, Some(false));
|
|
|
|
assert_eq!(loaded.default.check_filename, Some(true));
|
|
|
|
assert_eq!(loaded.default.check_file, Some(false));
|
|
|
|
assert_eq!(
|
2021-08-04 07:55:46 -04:00
|
|
|
loaded.type_.patterns[type_name.as_str()].engine.binary,
|
|
|
|
Some(false)
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
loaded.type_.patterns[type_name.as_str()]
|
|
|
|
.engine
|
|
|
|
.check_filename,
|
2021-04-07 22:10:27 -04:00
|
|
|
Some(false)
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-08-04 07:55:46 -04:00
|
|
|
loaded.type_.patterns[type_name.as_str()].engine.check_file,
|
2021-04-07 22:10:27 -04:00
|
|
|
Some(false)
|
|
|
|
);
|
|
|
|
}
|
2021-04-07 22:14:57 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_init_fails_on_unknown_type() {
|
|
|
|
let storage = ConfigStorage::new();
|
|
|
|
let mut engine = ConfigEngine::new(&storage);
|
|
|
|
engine.set_isolated(true);
|
|
|
|
|
|
|
|
let type_name = kstring::KString::from_static(NEVER_EXIST_TYPE);
|
|
|
|
|
|
|
|
let config = crate::config::Config {
|
2021-08-04 07:55:46 -04:00
|
|
|
type_: crate::config::TypeEngineConfig {
|
|
|
|
patterns: maplit::hashmap! {
|
|
|
|
type_name => crate::config::GlobEngineConfig {
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-04-07 22:14:57 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
engine.set_overrides(config);
|
|
|
|
|
2021-05-14 12:26:02 -04:00
|
|
|
let cwd = std::path::Path::new(".").canonicalize().unwrap();
|
2021-04-07 22:14:57 -04:00
|
|
|
let result = engine.init_dir(&cwd);
|
|
|
|
assert!(result.is_err());
|
|
|
|
}
|
2021-04-09 16:58:12 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_policy_default() {
|
|
|
|
let storage = ConfigStorage::new();
|
|
|
|
let mut engine = ConfigEngine::new(&storage);
|
|
|
|
engine.set_isolated(true);
|
|
|
|
|
|
|
|
let config = crate::config::Config::default();
|
|
|
|
engine.set_overrides(config);
|
|
|
|
|
2021-05-14 12:26:02 -04:00
|
|
|
let cwd = std::path::Path::new(".").canonicalize().unwrap();
|
2021-04-09 16:58:12 -04:00
|
|
|
engine.init_dir(&cwd).unwrap();
|
|
|
|
let policy = engine.policy(&cwd.join("Cargo.toml"));
|
|
|
|
assert!(!policy.binary);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_policy_fallback() {
|
|
|
|
let storage = ConfigStorage::new();
|
|
|
|
let mut engine = ConfigEngine::new(&storage);
|
|
|
|
engine.set_isolated(true);
|
|
|
|
|
|
|
|
let type_name = kstring::KString::from_static(NEVER_EXIST_TYPE);
|
|
|
|
|
|
|
|
let config = crate::config::Config {
|
|
|
|
default: crate::config::EngineConfig {
|
|
|
|
binary: Some(true),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-08-04 07:55:46 -04:00
|
|
|
type_: crate::config::TypeEngineConfig {
|
|
|
|
patterns: maplit::hashmap! {
|
|
|
|
type_name.clone() => crate::config::GlobEngineConfig {
|
|
|
|
extend_glob: vec![type_name],
|
|
|
|
engine: crate::config::EngineConfig {
|
|
|
|
binary: Some(false),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-04-09 16:58:12 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
engine.set_overrides(config);
|
|
|
|
|
2021-05-14 12:26:02 -04:00
|
|
|
let cwd = std::path::Path::new(".").canonicalize().unwrap();
|
2021-04-09 16:58:12 -04:00
|
|
|
engine.init_dir(&cwd).unwrap();
|
|
|
|
let policy = engine.policy(&cwd.join("Cargo.toml"));
|
|
|
|
assert!(policy.binary);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_policy_type_specific() {
|
|
|
|
let storage = ConfigStorage::new();
|
|
|
|
let mut engine = ConfigEngine::new(&storage);
|
|
|
|
engine.set_isolated(true);
|
|
|
|
|
|
|
|
let type_name = kstring::KString::from_static(NEVER_EXIST_TYPE);
|
|
|
|
|
|
|
|
let config = crate::config::Config {
|
|
|
|
default: crate::config::EngineConfig {
|
|
|
|
binary: Some(true),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-08-04 07:55:46 -04:00
|
|
|
type_: crate::config::TypeEngineConfig {
|
|
|
|
patterns: maplit::hashmap! {
|
|
|
|
type_name.clone() => crate::config::GlobEngineConfig {
|
2021-04-10 14:07:07 -04:00
|
|
|
extend_glob: vec![type_name],
|
2021-04-09 16:58:12 -04:00
|
|
|
engine: crate::config::EngineConfig {
|
|
|
|
binary: Some(false),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-08-04 07:55:46 -04:00
|
|
|
}},
|
2021-04-09 16:58:12 -04:00
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
engine.set_overrides(config);
|
|
|
|
|
2021-05-14 12:26:02 -04:00
|
|
|
let cwd = std::path::Path::new(".").canonicalize().unwrap();
|
2021-04-09 16:58:12 -04:00
|
|
|
engine.init_dir(&cwd).unwrap();
|
|
|
|
let policy = engine.policy(&cwd.join("Cargo.toml"));
|
|
|
|
assert!(policy.binary);
|
|
|
|
let policy = engine.policy(&cwd.join(NEVER_EXIST_TYPE));
|
|
|
|
assert!(!policy.binary);
|
|
|
|
}
|
2021-04-07 22:10:27 -04:00
|
|
|
}
|