Commit
Message
Changed Files (7)
-
modified CHANGELOG.md
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e8871b..1153c10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [unreleased] + +### 🚀 Features + +- Add in/exclude to git ui refs to generate + +### 🐛 Bug Fixes + +- Enable use of $ABBAYE_BUILDING_VERSION in script builder outputs ## [0.7.0] - 2026-06-08 ### 🚀 Features -
modified Cargo.lock
diff --git a/Cargo.lock b/Cargo.lock index 8e37a59..0ede3ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,6 +33,7 @@ dependencies = [ "toml 1.1.2+spec-1.1.0", "tracing", "tracing-subscriber", + "walkdir", ] [[package]] -
modified Cargo.toml
diff --git a/Cargo.toml b/Cargo.toml index 45b2658..c88b1b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,15 @@ [package] name = "abbaye" +authors = ["Ololduck <ololduck@vit.am>"] version = "0.7.0" edition = "2024" rust-version = "1.85.1" description = "A release page generator for software projects" -documentation = "http://vit.am/~ololduck/abbaye/latest/" -repository = "https://git.sr.ht/~ololduck/abbaye" +homepage = "https://vit.am/~ololduck/abbaye/latest/" +documentation = "https://vit.am/~ololduck/abbaye/latest/" +repository = "https://vit.am/~ololduck/abbaye/repository.git" +keywords = ["SSG", "Static Site Generator", "release tool"] +categories = ["command-line-utilities", "template-engine"] license = "AGPL-3.0-or-later" include = ["CHANGELOG.md", "README.md", "src/**/*"] publish = false @@ -36,6 +40,7 @@ tokio = { version = "1.52.3", features = ["full"] } toml = { version = "1.1.2", features = ["serde"] } tracing = { version = "0.1.44", features = ["log"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } +walkdir = "2" [dependencies.gix] version = "0.84" @@ -53,3 +58,6 @@ strip = true lto = true panic = "abort" codegen-units = 1 + +[package.metadata.aur] +optdepends = ["git"] -
modified abbaye.toml
diff --git a/abbaye.toml b/abbaye.toml index afbbd03..5a65183 100644 --- a/abbaye.toml +++ b/abbaye.toml @@ -40,3 +40,12 @@ outputs = ["target/abbaye.schema.json"] id = "archive source" type = "archive" # creates a compressed tarball of the source code (can be of anything, really) output = "target/abbaye-source.tar.gz" + +[[builders]] +id = "AUR package" +type = "script" +script = [ + "cargo aur", + "sed -i \"s%source=.*$%source=(\"https://vit.am/~ololduck/abbaye/abbaye-$pkgver-x86-64.tar.gz\")%\" target/cargo-aur/PKGBUILD" +] +outputs = ["target/cargo-aur/abbaye-$ABBAYE_BUILDING_VERSION-x86_64.tar.gz"] -
modified src/builders/script.rs
diff --git a/src/builders/script.rs b/src/builders/script.rs index 645c144..a71ecab 100644 --- a/src/builders/script.rs +++ b/src/builders/script.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use std::process::Stdio; use crate::builders::{ArtifactPath, Builder, LogEvent, LogSender}; +use crate::utils::expand_variables; use miette::{IntoDiagnostic, Result, miette}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -104,30 +105,76 @@ impl Builder for ScriptBuilder { // Collect every declared output path as an artifact. let mut artifacts = Vec::new(); for output in &config.outputs { - let (path, name) = match output { - ScriptBuilderOutput::Path(p) => { - let name = p - .file_name() - .ok_or_else(|| miette!("output path has no file name: {}", p.display()))? - .to_string_lossy() - .into_owned(); - (p, name) + let vars = vec![("ABBAYE_BUILDING_VERSION", version)]; + + let (pattern, name_override) = match output { + ScriptBuilderOutput::Path(p) => (expand_variables(p, vars), None), + ScriptBuilderOutput::PathWithName { path: p, name } => { + (expand_variables(p, vars), Some(name.clone())) } - ScriptBuilderOutput::PathWithName { path: p, name } => (p, name.clone()), }; - if !path.exists() { - return Err(miette!( - "declared script output does not exist: {}", - path.display() - )); + + let pattern_str = pattern.to_string_lossy().to_string(); + + // Check if pattern contains glob characters + if pattern_str.contains(['*', '?', '[']) { + // Compile the glob pattern + let glob = globset::Glob::new(&pattern_str) + .into_diagnostic()? + .compile_matcher(); + + let mut matched = false; + + // Walk the directory to find matching paths + let parent = pattern + .parent() + .unwrap_or_else(|| std::path::Path::new(".")); + for entry in walkdir::WalkDir::new(parent) + .into_iter() + .filter_map(|e| e.ok()) + { + let path = entry.path(); + if glob.is_match(path) { + matched = true; + let name = name_override.clone().unwrap_or_else(|| { + path.file_name() + .unwrap_or_default() + .to_string_lossy() + .into_owned() + }); + artifacts.push(ArtifactPath { + path: path.to_path_buf(), + name, + hash: None, + }); + } + } + + if !matched { + return Err(miette!("no files matched output pattern: {}", pattern_str)); + } + } else { + // Regular path (non-glob) + if !pattern.exists() { + return Err(miette!( + "declared script output does not exist: {}", + pattern.display() + )); + } + let name = name_override.unwrap_or_else(|| { + pattern + .file_name() + .unwrap_or_default() + .to_string_lossy() + .into_owned() + }); + artifacts.push(ArtifactPath { + path: pattern.clone(), + name, + hash: None, + }); } - artifacts.push(ArtifactPath { - path: path.clone(), - name, - hash: None, - }); } - Ok(artifacts) } } -
modified src/main.rs
diff --git a/src/main.rs b/src/main.rs index 0596f16..817630b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -179,6 +179,8 @@ mod updater; /// Extracts current version information from different sources (ex: git tags, cargo metadata, etc.). pub mod version_extractors; +pub mod utils; + /// Build the full website for every git tag, sorted from the lowest semver /// version to the highest. /// -
added src/utils.rs
diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..ab2b7a3 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +/// Expands shell-style variables in a path string. +/// +/// This function takes a path containing variables in `$VAR` or `${VAR}` syntax +/// and substitutes them with values from the provided iterator of key-value pairs. +/// Any variables not found in the provided mappings are left unchanged. +/// +/// # Generic Parameters +/// +/// * `P` - A type that can be converted to a `Path` +/// * `I` - An iterator-like type that produces `(S, S)` tuples +/// * `S` - A type that can be read as `&str` +/// +/// # Arguments +/// +/// * `path` - The path string or `Path` object containing variables +/// * `vars` - An iterator of `(key, value)` pairs for variable substitution +/// +/// # Returns +/// +/// A `PathBuf` with all variables substituted with their corresponding values. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// +/// let mut vars = HashMap::new(); +/// vars.insert("USER", "john"); +/// vars.insert("PROJECT", "rust"); +/// +/// let expanded = expand_variables("/home/$USER/$PROJECT", vars); +/// assert_eq!(expanded.to_string_lossy(), "/home/john/rust"); +/// ``` +/// +/// With a vector: +/// +/// ``` +/// let vars = vec![("USER", "john"), ("PROJECT", "rust")]; +/// let expanded = expand_variables("/home/$USER/${PROJECT}", vars); +/// assert_eq!(expanded.to_string_lossy(), "/home/john/rust"); +/// ``` +pub fn expand_variables<P, I, S>(path: P, vars: I) -> PathBuf +where + P: AsRef<Path>, + I: IntoIterator<Item = (S, S)>, + S: AsRef<str>, +{ + let mut path_str = path.as_ref().to_string_lossy().to_string(); + + // Convert iterator into a HashMap for efficient lookup + let var_map: HashMap<String, String> = vars + .into_iter() + .map(|(k, v)| (k.as_ref().to_string(), v.as_ref().to_string())) + .collect(); + + // Replace each variable + for (key, value) in var_map { + path_str = path_str.replace(&format!("${{{}}}", key), &value); + path_str = path_str.replace(&format!("${}", key), &value); + } + + PathBuf::from(path_str) +}