Documentation
¶
Overview ¶
Package pathrules implements gitignore-like path matching with reusable include/exclude policies.
The package is intentionally generic and can be used for ignore workflows, allow-list workflows, compression selection, conversion selection, and other path-based pipelines.
Basic flow:
- parse rules from text (`ParseRules`)
- optionally load rules from file (`LoadRulesFile`)
- customize parsing (`ParseOptions`): plain/negated actions, comment and negation prefixes, negation disabling, trailing-space handling
- optionally enable brace alternation patterns like "*.{md,txt}" (`MatcherOptions.EnableBraceExpansion`, disabled by default)
- optionally enable backslash escaping of pattern metacharacters like "\*" (`MatcherOptions.EnableEscaping`, disabled by default, independent of EnableBraceExpansion)
- optionally build extension-based include rules (`ParseExtensions`)
- compile matcher (`NewMatcher`)
- ask for decision (`Decide` / `Included` / `Excluded`)
For hierarchical rule files, use `Provider`:
- create provider with root directory and rules file name
- evaluate paths relative to that root
- provider caches compiled directory matchers
- for one-directory batches use `DecideInDir` / `IncludedInDir`
- optional symlink/junction escape hardening: `EnableSymlinkEscapeCheck` (disabled by default)
Index ¶
- Variables
- type Action
- type DirEntry
- type MatchResult
- type Matcher
- type MatcherOptions
- type ParseOptions
- type Provider
- func (p *Provider) Decide(relPath string, isDir bool) (MatchResult, error)
- func (p *Provider) DecideInDir(relDir string, entries []DirEntry) ([]MatchResult, error)
- func (p *Provider) Excluded(relPath string, isDir bool) (bool, error)
- func (p *Provider) ExcludedInDir(relDir string, entries []DirEntry) ([]bool, error)
- func (p *Provider) Included(relPath string, isDir bool) (bool, error)
- func (p *Provider) IncludedInDir(relDir string, entries []DirEntry) ([]bool, error)
- type ProviderOptions
- type Rule
- func LoadRulesFile(path string, opts ParseOptions) ([]Rule, error)
- func LoadRulesFiles(opts ParseOptions, paths ...string) ([]Rule, error)
- func MergeRules(ruleSets ...[]Rule) []Rule
- func ParseExtensions(exts []string) []Rule
- func ParseRules(r io.Reader, opts ParseOptions) ([]Rule, error)
- func ParseRulesString(src string, opts ParseOptions) ([]Rule, error)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidRule indicates malformed or unsupported rule input. ErrInvalidRule = errors.New("invalid rule") // ErrInvalidPattern indicates malformed or unsupported rule pattern. ErrInvalidPattern = errors.New("invalid pattern") // ErrInvalidParseOptions indicates conflicting or unsupported ParseOptions values. ErrInvalidParseOptions = errors.New("invalid parse options") // ErrInvalidRulesFileName indicates invalid provider rules file name. ErrInvalidRulesFileName = errors.New("invalid rules file name") // ErrInvalidEntryName indicates invalid directory entry input for batch APIs. ErrInvalidEntryName = errors.New("invalid entry name") // ErrNilProvider indicates a nil Provider receiver. ErrNilProvider = errors.New("provider is nil") // ErrPathOutsideRoot indicates path traversal or non-relative input path. ErrPathOutsideRoot = errors.New("path is outside provider root") // ErrRulesPathOutsideRoot indicates resolved rules file path escaped provider root. ErrRulesPathOutsideRoot = errors.New("rules file path is outside provider root") )
Sentinel errors for pathrules operations.
Functions ¶
This section is empty.
Types ¶
type DirEntry ¶
type DirEntry struct {
// Name is one entry name relative to target directory (without path separators).
Name string `json:"name" yaml:"name"`
// IsDir reports whether entry path is a directory.
IsDir bool `json:"is_dir,omitempty" yaml:"is_dir,omitempty"`
}
DirEntry is one directory entry input for Provider batch APIs.
type MatchResult ¶
type MatchResult struct {
// Included reports final include decision.
Included bool `json:"included" yaml:"included"`
// Matched reports whether at least one rule matched.
Matched bool `json:"matched" yaml:"matched"`
// RuleIndex is the matched rule index in matcher input order, -1 when no match.
RuleIndex int `json:"rule_index" yaml:"rule_index"`
}
MatchResult is a deterministic decision produced by matcher.
type Matcher ¶
type Matcher struct {
// contains filtered or unexported fields
}
Matcher evaluates path decisions against compiled ordered rules.
func NewMatcher ¶
func NewMatcher(rules []Rule, opts MatcherOptions) (*Matcher, error)
NewMatcher compiles ordered rules into matcher.
func (*Matcher) Decide ¶
func (m *Matcher) Decide(path string, isDir bool) MatchResult
Decide returns deterministic include/exclude decision for one path.
Decision policy:
- last matched rule wins
- if no rule matched, default action is used
type MatcherOptions ¶
type MatcherOptions struct {
// CaseInsensitive enables ASCII case-insensitive matching.
CaseInsensitive bool `json:"case_insensitive,omitempty" yaml:"case_insensitive,omitempty"`
// DefaultAction is applied when no rule matched.
DefaultAction Action `json:"default_action,omitempty" yaml:"default_action,omitempty"`
// EnableBraceExpansion enables gitignore-like brace alternation "{a,b,c}" in patterns,
// expanded into a cartesian product of alternatives at compile time.
// Disabled by default, so "{" and "}" stay literal for existing rule sets.
//
// When enabled, "{" always starts an alternation group and must form a complete,
// non-nested group with at least two comma-separated alternatives (not all empty);
// anything else is ErrInvalidPattern. A literal "{" then requires EnableEscaping.
EnableBraceExpansion bool `json:"enable_brace_expansion,omitempty" yaml:"enable_brace_expansion,omitempty"`
// EnableEscaping enables backslash-escaping of pattern metacharacters:
// "\*", "\?", "\[", "\]", "\{", "\}", "\,", "\\",
// and generically, "\X" for any other character X.
// Independent of EnableBraceExpansion: useful on its own to match a literal "*" or "?" in a filename.
//
// Disabled by default, so a pattern's backslashes keep being normalized to "/"
// (Windows-style path input), same as when this option does not exist.
// When enabled, that normalization stops: use "/" for path separators and "\X" for a literal X.
EnableEscaping bool `json:"enable_escaping,omitempty" yaml:"enable_escaping,omitempty"`
}
MatcherOptions controls matcher behavior.
type ParseOptions ¶ added in v0.2.0
type ParseOptions struct {
// CommentPrefix is the line-comment prefix. Empty defaults to "#".
// The comment-prefix check always runs before the negation-prefix check,
// so a line matching both is treated as a comment;
// do not configure one prefix as a strict prefix of the other (e.g. "#" and "#!").
CommentPrefix string `json:"comment_prefix,omitempty" yaml:"comment_prefix,omitempty"`
// NegationPrefix is the negation token. Empty defaults to "!".
// Only consulted when DisableNegation is false. See CommentPrefix caveat above.
NegationPrefix string `json:"negation_prefix,omitempty" yaml:"negation_prefix,omitempty"`
// PlainAction is applied to a plain (non-negated) pattern line.
// Zero value defaults to ActionExclude.
PlainAction Action `json:"plain_action,omitempty" yaml:"plain_action,omitempty"`
// NegatedAction is applied to a negated pattern line.
// Zero value defaults to ActionInclude. Unused when DisableNegation is true.
NegatedAction Action `json:"negated_action,omitempty" yaml:"negated_action,omitempty"`
// DisableNegation disables negation-prefix handling entirely:
// every line uses PlainAction, and a leading NegationPrefix token
// (escaped or not) is left in the pattern verbatim.
DisableNegation bool `json:"disable_negation,omitempty" yaml:"disable_negation,omitempty"`
// KeepTrailingSpaces skips trailing-space trimming; only trailing "\r" is stripped.
// Default false preserves current trimming behavior.
KeepTrailingSpaces bool `json:"keep_trailing_spaces,omitempty" yaml:"keep_trailing_spaces,omitempty"`
}
ParseOptions controls ParseRules line-parsing semantics.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider loads rules files along path hierarchy and evaluates final decisions.
func NewProvider ¶
func NewProvider(rootDir string, opts ProviderOptions) (*Provider, error)
NewProvider creates a recursive rules provider rooted at rootDir.
func (*Provider) Decide ¶
func (p *Provider) Decide(relPath string, isDir bool) (MatchResult, error)
Decide returns final include/exclude decision for a path relative to provider root.
Decision order:
- BaseRules matcher.
- Rules files from root to deepest containing directory.
Last matched rule wins.
func (*Provider) DecideInDir ¶
func (p *Provider) DecideInDir(relDir string, entries []DirEntry) ([]MatchResult, error)
DecideInDir returns decisions for multiple entries from one directory.
The same directory matcher chain is loaded once and reused for every entry.
func (*Provider) ExcludedInDir ¶
ExcludedInDir reports exclude decisions for multiple entries from one directory.
type ProviderOptions ¶
type ProviderOptions struct {
// RulesFileName is the rules file loaded in each directory in the path chain.
// Empty value defaults to ".pathrules".
RulesFileName string `json:"rules_file_name,omitempty" yaml:"rules_file_name,omitempty"`
// BaseRules are in-memory rules evaluated before directory-loaded rules.
BaseRules []Rule `json:"base_rules,omitempty" yaml:"base_rules,omitempty"`
// ParseOptions controls how each directory's rules file is parsed.
ParseOptions ParseOptions `json:"parse_options" yaml:"parse_options"`
// MatcherOptions controls rule matching behavior for all compiled matchers.
MatcherOptions MatcherOptions `json:"matcher_options" yaml:"matcher_options"`
// EnableSymlinkEscapeCheck enables resolved-path validation to block
// symlink/junction escapes outside provider root.
// Default is false for lower cold-path overhead.
EnableSymlinkEscapeCheck bool `json:"enable_symlink_escape_check,omitempty" yaml:"enable_symlink_escape_check,omitempty"`
}
ProviderOptions configures recursive rules provider behavior.
type Rule ¶
type Rule struct {
// Pattern is a gitignore-like pattern.
Pattern string `json:"pattern" yaml:"pattern"`
// Action is a decision action applied when the rule matches.
Action Action `json:"action" yaml:"action"`
}
Rule is one user-visible path rule.
func LoadRulesFile ¶
func LoadRulesFile(path string, opts ParseOptions) ([]Rule, error)
LoadRulesFile reads and parses rules from a file according to opts.
func LoadRulesFiles ¶
func LoadRulesFiles(opts ParseOptions, paths ...string) ([]Rule, error)
LoadRulesFiles reads and merges rules from files in the given order, using opts for every file.
Returned rules preserve file order and rule order inside each file.
func MergeRules ¶
MergeRules merges rule slices preserving input order.
func ParseExtensions ¶ added in v0.1.2
ParseExtensions converts extension list to include rules.
Accepted extension forms:
- "txt"
- ".txt"
- "*.txt"
Empty values are skipped. Returned patterns are normalized to lower-case "*.ext" form and preserve input order.
func ParseRules ¶
func ParseRules(r io.Reader, opts ParseOptions) ([]Rule, error)
ParseRules parses gitignore-like rules from reader according to opts.
Semantics (defaults, i.e. opts == ParseOptions{}):
- blank lines are ignored
- lines starting with the comment prefix ("#" by default) are ignored
- lines starting with the negation prefix ("!" by default) create an include rule and have the prefix stripped; other lines create an exclude rule
- "\" + comment prefix and "\" + negation prefix escape a literal leading comment/negation token
See ParseOptions for reconfiguring prefixes and actions.
func ParseRulesString ¶
func ParseRulesString(src string, opts ParseOptions) ([]Rule, error)
ParseRulesString parses rules from string input according to opts.