Module: Ace::Git::Atoms::PatternFilter
- Defined in:
- lib/ace/git/atoms/pattern_filter.rb
Overview
Pure functions for pattern matching and filtering Migrated from ace-git-diff
Constant Summary collapse
- MAX_CACHE_SIZE =
Maximum cache size to prevent unbounded memory growth in long-running processes
100
Class Method Summary collapse
-
.clear_cache! ⇒ Object
Clear the pattern cache (mainly for testing).
-
.extract_file_path(line) ⇒ String
Extract file path from diff header line.
-
.file_header?(line) ⇒ Boolean
Check if a line is a file header in git diff format.
-
.filter_diff_by_patterns(diff, exclude_patterns) ⇒ String
Filter paths from diff output based on exclude patterns.
-
.glob_to_regex(glob_patterns) ⇒ Array<Regexp>
Convert glob patterns to regex patterns Uses caching for performance when same patterns are used repeatedly.
-
.matches_include?(file_path, include_patterns) ⇒ Boolean
Match a path against include patterns (glob).
-
.should_exclude?(file_path, patterns) ⇒ Boolean
Check if a file path should be excluded based on patterns.
Class Method Details
.clear_cache! ⇒ Object
Clear the pattern cache (mainly for testing)
46 47 48 49 50 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 46 def clear_cache! PatternFilter.instance_variable_get(:@cache_mutex).synchronize do PatternFilter.instance_variable_get(:@pattern_cache).clear end end |
.extract_file_path(line) ⇒ String
Extract file path from diff header line
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 76 def extract_file_path(line) return "" if line.nil? || line.empty? case line when /^diff --git a\/(.+) b\/(.+)$/ Regexp.last_match(2) # Use the 'b/' path (new file path) when /^\+\+\+ b\/(.+)$/ Regexp.last_match(1) when /^--- a\/(.+)$/ Regexp.last_match(1) else "" end end |
.file_header?(line) ⇒ Boolean
Check if a line is a file header in git diff format
66 67 68 69 70 71 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 66 def file_header?(line) return false if line.nil? || line.empty? line.start_with?("diff --git", "+++", "---") || line.match?(/^index [a-f0-9]+\.\.[a-f0-9]+/) end |
.filter_diff_by_patterns(diff, exclude_patterns) ⇒ String
Filter paths from diff output based on exclude patterns
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 95 def filter_diff_by_patterns(diff, exclude_patterns) return "" if diff.nil? || diff.empty? return diff if exclude_patterns.nil? || exclude_patterns.empty? lines = diff.split("\n") filtered_lines = [] skip_until_next_file = false lines.each do |line| # Check if this is a file header if file_header?(line) file_path = extract_file_path(line) if should_exclude?(file_path, exclude_patterns) skip_until_next_file = true else skip_until_next_file = false filtered_lines << line end elsif !skip_until_next_file filtered_lines << line end end filtered_lines.join("\n") end |
.glob_to_regex(glob_patterns) ⇒ Array<Regexp>
Convert glob patterns to regex patterns Uses caching for performance when same patterns are used repeatedly
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 24 def glob_to_regex(glob_patterns) return [] if glob_patterns.nil? || glob_patterns.empty? # Generate cache key from sorted patterns cache_key = glob_patterns.sort.join("|") # Check cache first (thread-safe read) PatternFilter.instance_variable_get(:@cache_mutex).synchronize do cache = PatternFilter.instance_variable_get(:@pattern_cache) return cache[cache_key] if cache.key?(cache_key) # Evict oldest entry if cache is full (FIFO eviction) cache.shift if cache.size >= MAX_CACHE_SIZE # Compile patterns and cache patterns = glob_patterns.map { |pattern| compile_glob_pattern(pattern) } cache[cache_key] = patterns patterns end end |
.matches_include?(file_path, include_patterns) ⇒ Boolean
Match a path against include patterns (glob)
125 126 127 128 129 130 131 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 125 def matches_include?(file_path, include_patterns) return true if include_patterns.nil? || include_patterns.empty? return false if file_path.nil? || file_path.empty? regex_patterns = glob_to_regex(include_patterns) regex_patterns.any? { |pattern| file_path.match?(pattern) } end |
.should_exclude?(file_path, patterns) ⇒ Boolean
Check if a file path should be excluded based on patterns
56 57 58 59 60 61 |
# File 'lib/ace/git/atoms/pattern_filter.rb', line 56 def should_exclude?(file_path, patterns) return false if file_path.nil? || file_path.empty? return false if patterns.nil? || patterns.empty? patterns.any? { |pattern| file_path.match?(pattern) } end |