///|
/// Creates a portable attribute source. `base_dir` is repository-relative and
/// is empty for root, global, system, and `$GIT_DIR/info/attributes` files.
pub fn AttributeSource::new(
source : String,
content : String,
base_dir? : String = "",
) -> AttributeSource {
{ source, base_dir, content, }
}
///|
/// Parses multiple sources in ascending precedence order.
///
/// Pass system and global files first, followed by root and progressively
/// deeper `.gitattributes` files. Pass `$GIT_DIR/info/attributes` last when it
/// is available. Later matching assignments override earlier ones per
/// attribute, matching Git's precedence model.
pub fn parse_sources(sources : ArrayView[AttributeSource]) -> RuleSet {
let rules : Array[Rule] = []
let macros : Array[MacroDefinition] = []
let diagnostics : Array[Diagnostic] = []
for source in sources {
let parsed = parse(
source.content,
source=source.source,
base_dir=source.base_dir,
)
rules.append(parsed.rules)
macros.append(parsed.macros)
diagnostics.append(parsed.diagnostics)
}
{ rules, macros, diagnostics, }
}
///|
/// Returns all matching rules in evaluation order for inspection and tooling.
pub fn RuleSet::matching_rules(self : RuleSet, path : String) -> Array[Rule] {
self.rules.filter(rule => {
match_pattern(rule.pattern, path, base_dir=rule.base_dir)
})
}