Add config entry to ignore files

main
trivernis 10 months ago
parent 76b5435d0c
commit 9050b80896
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG Key ID: DFFFCC2C7A02DB45

29
Cargo.lock generated

@ -119,6 +119,16 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bstr"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.83" version = "1.0.83"
@ -311,6 +321,20 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "globset"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata",
"regex-syntax",
"serde",
]
[[package]] [[package]]
name = "handlebars" name = "handlebars"
version = "5.0.0" version = "5.0.0"
@ -488,9 +512,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.6.4" version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]] [[package]]
name = "miette" name = "miette"
@ -796,6 +820,7 @@ dependencies = [
"clap", "clap",
"dirs", "dirs",
"git2", "git2",
"globset",
"handlebars", "handlebars",
"handlebars_switch", "handlebars_switch",
"lazy_static", "lazy_static",

@ -9,6 +9,7 @@ edition = "2021"
clap = { version = "4.4.14", features = ["derive", "env"] } clap = { version = "4.4.14", features = ["derive", "env"] }
dirs = "5.0.1" dirs = "5.0.1"
git2 = "0.18.1" git2 = "0.18.1"
globset = { version = "0.4.14", features = ["serde", "serde1"] }
handlebars = "5.0.0" handlebars = "5.0.0"
handlebars_switch = "0.6.0" handlebars_switch = "0.6.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"

@ -1,12 +1,15 @@
use globset::{Glob, GlobSet, GlobSetBuilder};
use miette::{bail, Context, IntoDiagnostic, Result}; use miette::{bail, Context, IntoDiagnostic, Result};
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
env, env,
fs::{self}, fs::{self},
path::{Path, PathBuf}, path::{Path, PathBuf},
rc::Rc,
}; };
use crate::templating; use crate::templating;
use lazy_static::lazy_static;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SiloRepo { pub struct SiloRepo {
@ -20,7 +23,7 @@ impl SiloRepo {
} }
Ok(Self { Ok(Self {
root: DirEntry::parse(path.to_owned())?, root: DirEntry::parse(Rc::new(ParseContext::default()), path.to_owned())?,
}) })
} }
@ -32,46 +35,81 @@ impl SiloRepo {
} }
} }
pub struct ParseContext {
ignored: GlobSet,
}
impl ParseContext {
pub fn new(ignored: GlobSet) -> Self {
Self { ignored }
}
}
impl Default for ParseContext {
fn default() -> Self {
Self {
ignored: GlobSet::empty(),
}
}
}
lazy_static! {
static ref IGNORED_PATHS: GlobSet = GlobSetBuilder::new()
.add(Glob::new("**/.git").unwrap())
.add(Glob::new("**/dir.{toml,toml.tmpl}").unwrap())
.build()
.unwrap();
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum DirEntry { pub enum DirEntry {
File(FileEntry), File(FileEntry),
Dir(PathBuf, Vec<DirEntry>), Dir(PathBuf, Vec<DirEntry>),
Root(PathBuf, RootDirData, Vec<DirEntry>), Root(PathBuf, RootDirData, Vec<DirEntry>),
Ignored(PathBuf),
} }
impl DirEntry { impl DirEntry {
fn parse(path: PathBuf) -> Result<Self> { fn parse(mut context: Rc<ParseContext>, path: PathBuf) -> Result<Self> {
if path.is_dir() { if path.is_dir() {
log::debug!("Parsing directory {path:?}"); log::debug!("Parsing directory {path:?}");
if path.file_name().unwrap() == ".git" {
log::debug!("Ignoring .git directory");
return Ok(Self::Ignored(path));
}
let mut children = Vec::new();
for read_entry in fs::read_dir(&path).into_diagnostic()? {
let read_entry = read_entry.into_diagnostic()?;
children.push(DirEntry::parse(read_entry.path())?);
}
let meta_file = path.join("dir.toml"); let meta_file = path.join("dir.toml");
let meta_tmpl = path.join("dir.toml.tmpl"); let meta_tmpl = path.join("dir.toml.tmpl");
if meta_file.exists() { let metadata = if meta_file.exists() {
log::debug!("Found metadata file"); log::debug!("Found metadata file");
let metadata = RootDirData::read(&meta_file)?; let metadata = RootDirData::read(&meta_file)?;
context = Rc::new(ParseContext::new(metadata.ignored.clone()));
Ok(Self::Root(path, metadata, children)) Some(metadata)
} else if meta_tmpl.exists() { } else if meta_tmpl.exists() {
log::debug!("Found metadata template"); log::debug!("Found metadata template");
let metadata = RootDirData::read_template(&meta_tmpl)?; let metadata = RootDirData::read_template(&meta_tmpl)?;
context = Rc::new(ParseContext::new(metadata.ignored.clone()));
Ok(Self::Root(path, metadata, children)) Some(metadata)
} else { } else {
log::debug!("Directory is child"); log::debug!("Directory is child");
None
};
let mut children = Vec::new();
for read_entry in fs::read_dir(&path).into_diagnostic()? {
let read_entry = read_entry.into_diagnostic()?;
let entry_path = read_entry.path();
let test_path = entry_path.strip_prefix(&path).into_diagnostic()?;
if !IGNORED_PATHS.is_match(&test_path) && !context.ignored.is_match(&test_path) {
children.push(DirEntry::parse(context.clone(), entry_path)?);
} else {
log::debug!("Entry {entry_path:?} is ignored")
}
}
if let Some(metadata) = metadata {
Ok(Self::Root(path, metadata, children))
} else {
Ok(Self::Dir(path, children)) Ok(Self::Dir(path, children))
} }
} else { } else {
@ -116,10 +154,6 @@ impl DirEntry {
} }
Ok(()) Ok(())
} }
DirEntry::Ignored(p) => {
log::debug!("Ignoring {p:?}");
Ok(())
}
} }
} }
} }
@ -128,17 +162,11 @@ impl DirEntry {
pub enum FileEntry { pub enum FileEntry {
Template(PathBuf), Template(PathBuf),
Plain(PathBuf), Plain(PathBuf),
Ignored(PathBuf),
} }
impl FileEntry { impl FileEntry {
fn parse(path: PathBuf) -> Result<Self> { fn parse(path: PathBuf) -> Result<Self> {
let file_name = path.file_name().unwrap(); if let Some(true) = path.extension().map(|e| e == "tmpl") {
if file_name == "dir.toml" || file_name == "dir.toml.tmpl" {
log::debug!("File is metadata");
Ok(Self::Ignored(path))
} else if let Some(true) = path.extension().map(|e| e == "tmpl") {
log::debug!("File is template"); log::debug!("File is template");
Ok(Self::Template(path)) Ok(Self::Template(path))
} else { } else {
@ -176,9 +204,6 @@ impl FileEntry {
.into_diagnostic() .into_diagnostic()
.with_context(|| format!("copy {path:?} to {dest:?}"))?; .with_context(|| format!("copy {path:?} to {dest:?}"))?;
} }
FileEntry::Ignored(p) => {
log::debug!("Ignoring {p:?}")
}
} }
Ok(()) Ok(())
@ -188,6 +213,8 @@ impl FileEntry {
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
pub struct RootDirData { pub struct RootDirData {
pub path: String, pub path: String,
#[serde(default)]
pub ignored: GlobSet,
} }
impl RootDirData { impl RootDirData {

Loading…
Cancel
Save