//
// Copyright (c) StellaOps. Licensed under BUSL-1.1.
//
using DotNet.Globbing;
namespace StellaOps.Facet;
///
/// Utility for matching file paths against glob patterns.
///
public sealed class GlobMatcher
{
private readonly List _globs;
///
/// Initializes a new instance of the class.
///
/// Glob patterns to match against.
public GlobMatcher(IEnumerable patterns)
{
ArgumentNullException.ThrowIfNull(patterns);
_globs = patterns
.Select(p => Glob.Parse(NormalizePattern(p)))
.ToList();
}
///
/// Check if a path matches any of the patterns.
///
/// The path to check (Unix-style).
/// True if any pattern matches.
public bool IsMatch(string path)
{
ArgumentNullException.ThrowIfNull(path);
var normalizedPath = NormalizePath(path);
return _globs.Any(g => g.IsMatch(normalizedPath));
}
///
/// Create a matcher for a single facet.
///
/// The facet to create a matcher for.
/// A GlobMatcher for the facet's selectors.
public static GlobMatcher ForFacet(IFacet facet)
{
ArgumentNullException.ThrowIfNull(facet);
return new GlobMatcher(facet.Selectors);
}
private static string NormalizePattern(string pattern)
{
// Ensure patterns use forward slashes
return pattern.Replace('\\', '/');
}
private static string NormalizePath(string path)
{
// Ensure paths use forward slashes and are rooted
var normalized = path.Replace('\\', '/');
if (!normalized.StartsWith('/'))
{
normalized = "/" + normalized;
}
return normalized;
}
}