### Quick Example: Discover Repository and Walk File Tree Source: https://github.com/xenoatom/xenoatom.glob/blob/main/readme.md This example demonstrates how to use XenoAtom.Glob to discover a repository and walk its working tree while honoring ignore rules. It uses RepositoryDiscovery.Discover and FileTreeWalker.Enumerate with FileTreeWalkOptions. The example prints the relative path of each entry. ```csharp using XenoAtom.Glob.Git; using XenoAtom.Glob.IO; var repository = RepositoryDiscovery.Discover(@"C:\code\my-repo"); var walker = new FileTreeWalker(); // Walk the working tree while honoring the repository ignore rules. foreach (var entry in walker.Enumerate(repository.WorkingTreeRoot, new FileTreeWalkOptions { RepositoryContext = repository, })) { Console.WriteLine(entry.RelativePath); } ``` -------------------------------- ### Glob Matching Examples Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Demonstrates various glob patterns including single-segment wildcards, double-star matching across segments, and escaped literals. ```csharp GlobPattern.Parse("src/*.cs").IsMatch("src/app.cs"); // true GlobPattern.Parse("src/*.cs").IsMatch("src/lib/app.cs"); // false GlobPattern.Parse("src/**/app.cs").IsMatch("src/app.cs"); // true GlobPattern.Parse("src/**/app.cs").IsMatch("src/lib/app.cs"); // true GlobPattern.Parse(@"data/\*.txt").IsMatch("data/*.txt"); // true ``` -------------------------------- ### Path Input Rules Examples Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Shows how to parse a glob pattern and match paths with both forward and backslashes, and how to evaluate ignore rules with and without the isDirectory flag. ```csharp var pattern = GlobPattern.Parse("src/**/file.cs"); pattern.IsMatch("src/nested/file.cs"); // true pattern.IsMatch(@"src\nested\file.cs"); // true var matcher = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore("build/\n")); matcher.Evaluate("build", isDirectory: true).IsIgnored; // true matcher.Evaluate("build").IsIgnored; // false ``` -------------------------------- ### Discover Git repository with RepositoryDiscovery Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Use RepositoryDiscovery.Discover to get repository information from a path inside a working tree. The returned object exposes WorkingTreeRoot, GitDirectory, InfoExcludePath, and GlobalExcludePath. Supports normal .git directories, gitfiles, and exclude files. ```csharp using XenoAtom.Glob.Git; var repository = RepositoryDiscovery.Discover(@"C:\code\my-repo\src"); Console.WriteLine(repository.WorkingTreeRoot); Console.WriteLine(repository.GitDirectory); Console.WriteLine(repository.InfoExcludePath); Console.WriteLine(repository.GlobalExcludePath); ``` -------------------------------- ### Parse Git ignore rules and evaluate paths Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Parses a Git-compatible ignore rule set and evaluates sample paths. The last matching rule wins; negated rules start with '!'. A directory ignored by an ancestor rule blocks deeper children unless the directory itself is made reachable again. ```csharp using XenoAtom.Glob.Ignore; var ruleSet = IgnoreRuleSet.ParseGitIgnore(""" *.tmp build/ !build/keep.tmp src/generated/* !src/generated/include.txt """); var matcher = new IgnoreMatcher(ruleSet); matcher.Evaluate("file.tmp").IsIgnored; // true matcher.Evaluate("build/output.bin").IsIgnored; // true matcher.Evaluate("build/keep.tmp").IsIgnored; // true matcher.Evaluate("src/generated/code.cs").IsIgnored; // true matcher.Evaluate("src/generated/include.txt").IsIgnored; // false ``` -------------------------------- ### Build and test commands Source: https://github.com/xenoatom/xenoatom.glob/blob/main/AGENTS.md Run from the project root. Builds the solution in Release configuration and runs all tests. All tests must pass before submitting. ```sh cd src dotnet build -c Release dotnet test -c Release ``` -------------------------------- ### Common .gitignore rule forms Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Demonstrates typical .gitignore patterns: *.log, bin/, foo/*, foo/**, !foo/keep.txt, /root-only.txt, and docs/**/*.bak. Each pattern's meaning is explained in the surrounding list. ```csharp var matcher = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore(""" *.log bin/ foo/* foo/** !foo/keep.txt /root-only.txt docs/**/*.bak """)); ``` -------------------------------- ### Enumerate files with FileTreeWalker Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Use FileTreeWalker.Enumerate with a RepositoryContext to walk the working tree, optionally including directories. The walker traverses lazily, prunes ignored directories, and returns normalized relative paths with metadata. ```csharp using XenoAtom.Glob.Git; using XenoAtom.Glob.IO; var repository = RepositoryDiscovery.Discover(@"C:\code\my-repo"); var walker = new FileTreeWalker(); foreach (var entry in walker.Enumerate(repository.WorkingTreeRoot, new FileTreeWalkOptions { RepositoryContext = repository, IncludeDirectories = true, })) { Console.WriteLine($"{entry.RelativePath} | dir={entry.IsDirectory}"); } ``` -------------------------------- ### Layering multiple rule sets with baseDirectory Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Shows how to combine multiple IgnoreRuleSet instances; later rule sets have higher precedence. Use baseDirectory when a rule set comes from a nested directory such as src/.gitignore. ```csharp var rootRules = IgnoreRuleSet.ParseGitIgnore("*.tmp"); var nestedRules = IgnoreRuleSet.ParseGitIgnore("!keep.tmp", baseDirectory: "src"); var matcher = new IgnoreMatcher(rootRules, nestedRules); matcher.Evaluate("src/keep.tmp").IsIgnored; // false matcher.Evaluate("other/keep.tmp").IsIgnored; // true ``` -------------------------------- ### Glob Matching with GlobPattern Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Parses a glob pattern with character classes and wildcards, then matches several paths to demonstrate case sensitivity and segment matching. ```csharp using XenoAtom.Glob; var pattern = GlobPattern.Parse("src/**/[Tt]est?.cs"); pattern.IsMatch("src/unit/Test1.cs"); // true pattern.IsMatch("src/unit/test2.cs"); // true pattern.IsMatch("src/unit/test20.cs"); // false ``` -------------------------------- ### Add extra ignore rule sets during traversal Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Parse additional .gitignore rules with IgnoreRuleSet.ParseGitIgnore and pass them via AdditionalRuleSets. Later rule sets have higher precedence than earlier ones. ```csharp var extraRules = IgnoreRuleSet.ParseGitIgnore(""" *.cache artifacts/ """); var entries = walker.Enumerate(rootPath, new FileTreeWalkOptions { RepositoryContext = repository, AdditionalRuleSets = [extraRules], }); ``` -------------------------------- ### Explicit dialect selection with IgnoreRuleSet.Parse Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Uses IgnoreRuleSet.Parse with IgnoreDialect.IgnoreFile for explicit dialect selection. Currently .ignore parsing uses the same semantics as the Git-compatible parser. ```csharp var ignoreRules = IgnoreRuleSet.Parse(""" *.cache artifacts/ """, IgnoreDialect.IgnoreFile); ``` -------------------------------- ### IgnoreMatcher Constructor Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Creates an IgnoreMatcher from one or more IgnoreRuleSet instances. Later rule sets have higher precedence. ```APIDOC ## IgnoreMatcher Constructor ### Description Creates an IgnoreMatcher from one or more IgnoreRuleSet instances. Later rule sets have higher precedence. ### Parameters - **ruleSets** (params IgnoreRuleSet[]) - Required - One or more rule sets to combine. ### Example ```csharp var rootRules = IgnoreRuleSet.ParseGitIgnore("*.tmp"); var nestedRules = IgnoreRuleSet.ParseGitIgnore("!keep.tmp", baseDirectory: "src"); var matcher = new IgnoreMatcher(rootRules, nestedRules); ``` ``` -------------------------------- ### Directory blocking vs wildcard re-inclusion Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Shows that ignoring a directory (build/) blocks re-inclusion of children even with a negated rule, while ignoring its contents (build/*) allows re-inclusion. This is standard Git behavior and a common surprise. ```csharp var blocked = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore(""" build/ !build/keep.tmp """)); blocked.Evaluate("build/keep.tmp").IsIgnored; // true var reachable = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore(""" build/* !build/keep.tmp """)); reachable.Evaluate("build/keep.tmp").IsIgnored; // false ``` -------------------------------- ### IgnoreRuleSet.ParseGitIgnore Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Parses Git-compatible ignore content into an IgnoreRuleSet. This is the primary entry point for creating ignore rules from .gitignore-style text. ```APIDOC ## IgnoreRuleSet.ParseGitIgnore ### Description Parses Git-compatible ignore content into an IgnoreRuleSet. This is the primary entry point for creating ignore rules from .gitignore-style text. ### Method ParseGitIgnore ### Parameters - **content** (string) - Required - The Git-compatible ignore content to parse. ### Returns - **IgnoreRuleSet** - The parsed rule set. ### Example ```csharp var ruleSet = IgnoreRuleSet.ParseGitIgnore(""" *.tmp build/ !build/keep.tmp src/generated/* !src/generated/include.txt """); ``` ``` -------------------------------- ### IgnoreMatcher.Evaluate Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Evaluates a path against the ignore rules and returns an evaluation result indicating whether the path is ignored. This is the core method for checking if a path should be ignored. ```APIDOC ## IgnoreMatcher.Evaluate ### Description Evaluates a path against the ignore rules and returns an evaluation result indicating whether the path is ignored. This is the core method for checking if a path should be ignored. ### Method Evaluate ### Parameters - **path** (string) - Required - The path to evaluate. ### Returns - **IgnoreEvaluation** - An object with an `IsIgnored` property indicating whether the path is ignored. ### Example ```csharp var matcher = new IgnoreMatcher(ruleSet); matcher.Evaluate("file.tmp").IsIgnored; // true ``` ``` -------------------------------- ### Path separators in ignore matching Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Shows that ignore rule syntax uses '/', but candidate paths can use either '/' or '\'. Both evaluate to ignored for the same rule. ```csharp var matcher = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore("src/generated/\n")); matcher.Evaluate("src/generated/file.cs").IsIgnored; // true matcher.Evaluate(@"src\generated\file.cs").IsIgnored; // true ``` -------------------------------- ### IgnoreRuleSet.Parse Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Parses ignore content with an explicit dialect selection. Currently supports the IgnoreFile dialect which uses the same semantics as the Git-compatible parser. ```APIDOC ## IgnoreRuleSet.Parse ### Description Parses ignore content with an explicit dialect selection. Currently supports the IgnoreFile dialect which uses the same semantics as the Git-compatible parser. ### Parameters - **content** (string) - Required - The ignore content to parse. - **dialect** (IgnoreDialect) - Required - The dialect to use for parsing. ### Returns - **IgnoreRuleSet** - The parsed rule set. ### Example ```csharp var ignoreRules = IgnoreRuleSet.Parse(""" *.cache artifacts/ """, IgnoreDialect.IgnoreFile); ``` ``` -------------------------------- ### Reusing an evaluator on hot paths Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Uses IgnoreMatcher.CreateEvaluator() to keep pooled scratch buffers across calls and avoid rebuilding temporary state when evaluating many paths repeatedly. ```csharp var matcher = new IgnoreMatcher(IgnoreRuleSet.ParseGitIgnore(""" *.tmp vendor/ """)); using var evaluator = matcher.CreateEvaluator(); foreach (var path in paths) { if (evaluator.Evaluate(path).IsIgnored) { // skip } } ``` -------------------------------- ### IgnoreMatcher.CreateEvaluator Source: https://github.com/xenoatom/xenoatom.glob/blob/main/doc/readme.md Creates an evaluator for hot paths that reuses pooled scratch buffers across calls, avoiding rebuilding temporary state each time. ```APIDOC ## IgnoreMatcher.CreateEvaluator ### Description Creates an evaluator for hot paths that reuses pooled scratch buffers across calls, avoiding rebuilding temporary state each time. ### Returns - **IgnoreEvaluator** - An evaluator that can be used to evaluate paths efficiently. ### Example ```csharp using var evaluator = matcher.CreateEvaluator(); foreach (var path in paths) { if (evaluator.Evaluate(path).IsIgnored) { // skip } } ``` ```