fast_ignore 0.17.2 → 0.17.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +0 -13
  4. data/lib/fast_ignore/builders/gitignore.rb +15 -0
  5. data/lib/fast_ignore/builders/shebang.rb +17 -0
  6. data/lib/fast_ignore/builders/shebang_or_gitignore.rb +15 -0
  7. data/lib/fast_ignore/candidate.rb +85 -0
  8. data/lib/fast_ignore/gitconfig_parser.rb +1 -1
  9. data/lib/fast_ignore/gitignore_include_rule_builder.rb +40 -63
  10. data/lib/fast_ignore/gitignore_rule_builder.rb +49 -26
  11. data/lib/fast_ignore/gitignore_rule_group.rb +31 -0
  12. data/lib/fast_ignore/gitignore_rule_scanner.rb +12 -0
  13. data/lib/fast_ignore/matchers/allow_any_dir.rb +39 -0
  14. data/lib/fast_ignore/matchers/allow_path_regexp.rb +45 -0
  15. data/lib/fast_ignore/matchers/ignore_path_regexp.rb +45 -0
  16. data/lib/fast_ignore/matchers/shebang_regexp.rb +46 -0
  17. data/lib/fast_ignore/matchers/unmatchable.rb +31 -0
  18. data/lib/fast_ignore/matchers/within_dir.rb +50 -0
  19. data/lib/fast_ignore/path_expander.rb +11 -0
  20. data/lib/fast_ignore/path_regexp_builder.rb +130 -0
  21. data/lib/fast_ignore/patterns.rb +33 -0
  22. data/lib/fast_ignore/relative_candidate.rb +20 -0
  23. data/lib/fast_ignore/rule_group.rb +42 -0
  24. data/lib/fast_ignore/rule_groups.rb +55 -0
  25. data/lib/fast_ignore/version.rb +1 -1
  26. data/lib/fast_ignore/walkers/base.rb +26 -0
  27. data/lib/fast_ignore/walkers/file_system.rb +46 -0
  28. data/lib/fast_ignore/walkers/gitignore_collecting_file_system.rb +48 -0
  29. data/lib/fast_ignore.rb +54 -84
  30. metadata +23 -11
  31. data/lib/fast_ignore/file_root.rb +0 -35
  32. data/lib/fast_ignore/gitignore_rule_regexp_builder.rb +0 -76
  33. data/lib/fast_ignore/rule.rb +0 -65
  34. data/lib/fast_ignore/rule_builder.rb +0 -37
  35. data/lib/fast_ignore/rule_set.rb +0 -76
  36. data/lib/fast_ignore/rule_sets.rb +0 -109
  37. data/lib/fast_ignore/shebang_rule.rb +0 -80
  38. data/lib/fast_ignore/unmatchable_rule.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56582bce9b3eae6e761585c77846530bb96b287c2d6938dd7213c31b84567560
4
- data.tar.gz: c2aabc49876831524acc8f14bc483aa8ec44ec715941a562bf4a6d5c4ac76b5c
3
+ metadata.gz: c81120885ae42b4893295ecd66b501ed6962d2742adc2bd59433796ca0e41995
4
+ data.tar.gz: 0a15d4651cc7dfc7eeed32b919da373ebee92195385ff0cf22acd92751258b68
5
5
  SHA512:
6
- metadata.gz: bc5e6b69f903bf2bb0beed6001bfa01bfa2f8b7e452eca9270884a38a1924649e336866d94085bd59ff72549d495d3857035227a7b3b0cf22859fd939c1e32ac
7
- data.tar.gz: e286d5802e0a0857552b9c9dbe03999546817478f2960fdbd057709485a862e876e3e9328a12fafc34388ba1aad0893f10ea318e7bdff728fb3ef41facc1568a
6
+ metadata.gz: c38a391c2a05c7439899144c2af1db29281538c855a18be47725b3e92f8fc40ecca2f69f15a26508d5f63d7f45f998cbba73ac41feaa1541356daf20067b4ce9
7
+ data.tar.gz: 0e355b08fbb00c9cca020ac06b0062f73477a59f673f6b465bf71d11c0228889dbeeb487e8e519eeccd09afa84290681f65f75300695332b0a4e44ecbec1b445
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # v0.17.4
2
+ - Deprecated `follow_symlinks:`, it's inaccurately named and awkward.
3
+
4
+ - Plus lots of refactoring that _should_ have no effect on behaviour
5
+ - Some performance regression due to the deprecation logic. we'll improve more than we lost after the deprecations are gone entirely.
6
+
7
+ # v0.17.3
8
+ - Add fuzz tests, fix a couple more edge cases it revealed:
9
+ - `~not_a_user` will be considered literal rather than raising an error, `~a_user` will continue to be expanded to the home directory of `a_user` when used in an `argv_rules:` or `allowed?`
10
+ - an `include_rule:` with a trailing `/` was raising a FrozenError in some circumstances.
11
+
1
12
  # v0.17.2
2
13
  - Remove unnecessary backport code that was leftover when support for 2.4 was dropped
3
14
  - Tiny performance improvements from rubocop-performance's suggestions
data/README.md CHANGED
@@ -166,19 +166,6 @@ When `relative: true`: FastIgnore#each will yield paths relative to the [`root:`
166
166
  FastIgnore.new(relative: true).to_a
167
167
  ```
168
168
 
169
- ### `follow_symlinks: true`
170
-
171
- **Default: false**
172
-
173
- When `follow_symlinks: false`: FastIgnore#each will match git's behaviour and not follow symbolic links.
174
- When `follow_symlinks: true`: FastIgnore#each will check if a symlink points to a directory, and files in linked directories must also match rules using the symlink path as the directory location, not the real directory location.
175
-
176
- **This doesn't use the real path for matching or yield or return it.**
177
-
178
- ```ruby
179
- FastIgnore.new(follow_symlinks: true).to_a
180
- ```
181
-
182
169
  ### `root:`
183
170
 
184
171
  **Default: Dir.pwd ($PWD, the current working directory)**
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Builders
5
+ module Gitignore
6
+ def self.build(rule, allow, expand_path_with: nil)
7
+ if allow
8
+ ::FastIgnore::GitignoreIncludeRuleBuilder.new(rule, expand_path_with: expand_path_with).build
9
+ else
10
+ ::FastIgnore::GitignoreRuleBuilder.new(rule, expand_path_with: expand_path_with).build
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Builders
5
+ module Shebang
6
+ def self.build(shebang, allow)
7
+ shebang.strip!
8
+ pattern = /\A#!.*\b#{::Regexp.escape(shebang)}\b/i
9
+ rule = ::FastIgnore::Matchers::ShebangRegexp.new(pattern, allow)
10
+ return rule unless allow
11
+
12
+ # also allow all directories in case they include a file with the matching shebang file
13
+ [::FastIgnore::Matchers::AllowAnyDir, rule]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Builders
5
+ module ShebangOrGitignore
6
+ def self.build(rule, allow, expand_path_with: nil)
7
+ if rule.delete_prefix!('#!:')
8
+ ::FastIgnore::Builders::Shebang.build(rule, allow)
9
+ else
10
+ ::FastIgnore::Builders::Gitignore.build(rule, allow, expand_path_with: expand_path_with)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,85 @@
1
+ # frozen-string-literal: true
2
+
3
+ class FastIgnore
4
+ class Candidate
5
+ class << self
6
+ def root
7
+ @root ||= new('/', nil, true, true, nil)
8
+ end
9
+ end
10
+
11
+ def initialize(full_path, filename, directory, exists, content)
12
+ @full_path = full_path
13
+ @filename = filename
14
+ (@directory = directory) unless directory.nil?
15
+ (@exists = exists) unless exists.nil?
16
+ (@first_line = content.slice(/.*/)) if content # we only care about the first line
17
+ end
18
+
19
+ def parent
20
+ @parent ||= ::FastIgnore::Candidate.new(::File.dirname(@full_path), nil, true, true, nil)
21
+ end
22
+
23
+ # use \0 because it can't be in paths
24
+ def key
25
+ @key ||= :"#{
26
+ "\0" if defined?(@directory) && @directory
27
+ }#{
28
+ @full_path
29
+ }\0#{
30
+ @first_line if defined?(@first_line)
31
+ }"
32
+ end
33
+
34
+ def relative_to(dir)
35
+ return unless @full_path.start_with?(dir)
36
+
37
+ ::FastIgnore::RelativeCandidate.new(@full_path.delete_prefix(dir), self)
38
+ end
39
+
40
+ def directory?
41
+ return @directory if defined?(@directory)
42
+
43
+ @directory = ::File.lstat(@full_path).directory?
44
+ rescue ::Errno::ENOENT, ::Errno::EACCES, ::Errno::ENAMETOOLONG
45
+ @exists ||= false
46
+ @directory = false
47
+ end
48
+
49
+ def exists?
50
+ return @exists if defined?(@exists)
51
+
52
+ @exists = ::File.exist?(@full_path)
53
+ rescue ::Errno::EACCES, ::Errno::ELOOP, ::Errno::ENAMETOOLONG
54
+ # :nocov: can't quite get this set up in a test
55
+ @exists = false
56
+ # :nocov:
57
+ end
58
+
59
+ def filename
60
+ @filename ||= ::File.basename(@full_path)
61
+ end
62
+
63
+ # how long can a shebang be?
64
+ # https://www.in-ulm.de/~mascheck/various/shebang/
65
+ def first_line # rubocop:disable Metrics/MethodLength
66
+ @first_line ||= begin
67
+ file = ::File.new(@full_path)
68
+ first_line = file.sysread(64)
69
+ if first_line.start_with?('#!')
70
+ first_line += file.readline unless first_line.include?("\n")
71
+ file.close
72
+ first_line
73
+ else
74
+ file.close
75
+ ''
76
+ end
77
+ rescue ::EOFError, ::SystemCallError
78
+ # :nocov:
79
+ file&.close
80
+ # :nocov:
81
+ ''
82
+ end
83
+ end
84
+ end
85
+ end
@@ -55,7 +55,7 @@ class FastIgnore
55
55
  include_path = scan_value(file)
56
56
 
57
57
  value = ::FastIgnore::GitconfigParser.parse(
58
- ::File.expand_path(include_path, ::File.dirname(path)),
58
+ PathExpander.expand_path(include_path, ::File.dirname(path)),
59
59
  root: root,
60
60
  nesting: nesting + 1
61
61
  )
@@ -2,22 +2,10 @@
2
2
 
3
3
  class FastIgnore
4
4
  class GitignoreIncludeRuleBuilder < GitignoreRuleBuilder
5
- def initialize(rule, file_path, expand_path_from = nil)
6
- super(rule, file_path)
5
+ def initialize(rule, expand_path_with: nil)
6
+ super
7
7
 
8
- @parent_segments = []
9
8
  @negation = true
10
- @expand_path_from = expand_path_from
11
- end
12
-
13
- def expand_rule_path
14
- anchored! unless @s.match?(/\*/) # rubocop:disable Performance/StringInclude # it's StringScanner#match?
15
- return unless @s.match?(%r{(?:[~/]|\.{1,2}/|.*/\.\./)})
16
-
17
- dir_only! if @s.match?(%r{.*/\s*\z})
18
- @s.string.replace(::File.expand_path(@s.rest))
19
- @s.string.delete_prefix!(@expand_path_from)
20
- @s.pos = 0
21
9
  end
22
10
 
23
11
  def negated!
@@ -25,74 +13,63 @@ class FastIgnore
25
13
  end
26
14
 
27
15
  def unmatchable_rule!
28
- throw :abort_build, ::FastIgnore::UnmatchableRule
29
- end
30
-
31
- def nothing_emitted?
32
- @re.empty? && @parent_segments.empty?
33
- end
34
-
35
- def emit_dir
36
- anchored!
37
-
38
- @parent_segments << @re
39
- @re = ::FastIgnore::GitignoreRuleRegexpBuilder.new
16
+ throw :abort_build, ::FastIgnore::Matchers::Unmatchable
40
17
  end
41
18
 
42
19
  def emit_end
43
- @dir_only || @re.append_end_dir_or_anchor
20
+ if @dir_only
21
+ @child_re = @re.dup
22
+ @re.append_end_anchor
23
+ else
24
+ @re.append_dir_or_end_anchor
25
+ end
26
+
44
27
  break!
45
28
  end
46
29
 
47
- def parent_dir_re # rubocop:disable Metrics/MethodLength
48
- segment_joins_count = @parent_segments.length
49
- parent_prefix = if @file_path
50
- segment_joins_count += @file_path.escaped_segments_length
30
+ def build_parent_dir_rules
31
+ return unless @negation
51
32
 
52
- if @anchored
53
- "\\A#{@file_path.escaped_segments_joined}"
54
- else
55
- "\\A#{@file_path.escaped_segments_joined}(?:.*/)?"
33
+ if @anchored
34
+ parent_pattern = @s.string.dup
35
+ if parent_pattern.sub!(%r{/[^/]+/?\s*\z}, '/')
36
+ ::FastIgnore::GitignoreIncludeRuleBuilder.new(parent_pattern).build_as_parent
56
37
  end
57
38
  else
58
- prefix
39
+ [::FastIgnore::Matchers::AllowAnyDir]
59
40
  end
41
+ end
60
42
 
61
- out = parent_prefix.dup
62
- unless @parent_segments.empty?
63
- out << '(?:'
64
- out << @parent_segments.join('/(?:')
65
- out << '/'
43
+ def build_child_file_rule # rubocop:disable Metrics/MethodLength
44
+ if @child_re.end_with?('/')
45
+ @child_re.append_many_non_dir.append_dir if @dir_only
46
+ else
47
+ @child_re.append_dir
66
48
  end
67
- out << (')?' * segment_joins_count)
68
- out
69
- end
70
49
 
71
- def build_parent_dir_rule
72
- # Regexp::IGNORECASE = 1
73
- ::FastIgnore::Rule.new(::Regexp.new(parent_dir_re, 1), true, anchored_or_file_path, true)
74
- end
50
+ @child_re.prepend(prefix)
75
51
 
76
- def build_child_file_rule
77
- # Regexp::IGNORECASE = 1
78
- ::FastIgnore::Rule.new(@re.append_dir.to_regexp, @negation, anchored_or_file_path, false)
52
+ if @negation
53
+ ::FastIgnore::Matchers::AllowPathRegexp.new(@child_re.to_regexp, @anchored, false)
54
+ else
55
+ ::FastIgnore::Matchers::IgnorePathRegexp.new(@child_re.to_regexp, @anchored, false)
56
+ end
79
57
  end
80
58
 
81
- def build_rule
82
- joined_re = ::FastIgnore::GitignoreRuleRegexpBuilder.new
83
- joined_re.append(@parent_segments.join('/'))
84
- joined_re.append_dir unless @parent_segments.empty?
85
- joined_re.append(@re)
86
- @re = joined_re
59
+ def build_as_parent
60
+ anchored!
61
+ dir_only!
87
62
 
88
- rules = [super, build_parent_dir_rule]
89
- (rules << build_child_file_rule) if @dir_only
90
- rules
63
+ catch :abort_build do
64
+ process_rule
65
+ build_rule(child_file_rule: false)
66
+ end
91
67
  end
92
68
 
93
- def process_rule
94
- expand_rule_path if @expand_path_from
95
- super
69
+ def build_rule(child_file_rule: true)
70
+ @child_re ||= @re.dup # in case emit_end wasn't called
71
+
72
+ [super(), *build_parent_dir_rules, (build_child_file_rule if child_file_rule)].compact
96
73
  end
97
74
  end
98
75
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  class FastIgnore
4
4
  class GitignoreRuleBuilder # rubocop:disable Metrics/ClassLength
5
- def initialize(rule, file_path)
6
- @re = ::FastIgnore::GitignoreRuleRegexpBuilder.new
5
+ def initialize(rule, expand_path_with: nil)
6
+ @re = ::FastIgnore::PathRegexpBuilder.new
7
7
  @s = ::FastIgnore::GitignoreRuleScanner.new(rule)
8
8
 
9
- @file_path = file_path
9
+ @expand_path_with = expand_path_with
10
10
  @negation = false
11
11
  @anchored = false
12
12
  @dir_only = false
@@ -49,6 +49,11 @@ class FastIgnore
49
49
  @re.append_dir
50
50
  end
51
51
 
52
+ def emit_any_dir
53
+ anchored!
54
+ @re.append_any_dir
55
+ end
56
+
52
57
  def emit_end
53
58
  @re.append_end_anchor
54
59
  break!
@@ -60,11 +65,22 @@ class FastIgnore
60
65
  @re.append_escaped(@s.next_character) || unmatchable_rule!
61
66
  end
62
67
 
63
- def process_star_end_after_slash
64
- return true unless @s.star_end?
65
-
66
- @re.append_many_non_dir
67
- emit_end
68
+ def process_star_end_after_slash # rubocop:disable Metrics/MethodLength
69
+ if @s.star_end?
70
+ @re.append_many_non_dir
71
+ emit_end
72
+ elsif @s.two_star_end?
73
+ break!
74
+ elsif @s.star_slash_end?
75
+ @re.append_many_non_dir
76
+ dir_only!
77
+ emit_end
78
+ elsif @s.two_star_slash_end?
79
+ dir_only!
80
+ break!
81
+ else
82
+ true
83
+ end
68
84
  end
69
85
 
70
86
  def process_slash
@@ -76,7 +92,7 @@ class FastIgnore
76
92
  process_star_end_after_slash
77
93
  end
78
94
 
79
- def process_two_stars # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
95
+ def process_two_stars # rubocop:disable Metrics/MethodLength
80
96
  return unless @s.two_stars?
81
97
  return break! if @s.end?
82
98
 
@@ -90,8 +106,7 @@ class FastIgnore
90
106
  if nothing_emitted?
91
107
  never_anchored!
92
108
  else
93
- @re.append_any_dir
94
- anchored!
109
+ emit_any_dir
95
110
  end
96
111
  process_star_end_after_slash
97
112
  end
@@ -141,6 +156,7 @@ class FastIgnore
141
156
  end
142
157
 
143
158
  def process_rule # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
159
+ expand_rule_path! if @expand_path_with
144
160
  anchored! if @s.slash?
145
161
 
146
162
  catch :break do
@@ -159,28 +175,24 @@ class FastIgnore
159
175
  end
160
176
  end
161
177
 
162
- def prefix # rubocop:disable Metrics/MethodLength
163
- out = ::FastIgnore::GitignoreRuleRegexpBuilder.new
164
- if @file_path
165
- out.append_start_anchor.append(@file_path.escaped)
166
- out.append_any_dir unless @anchored
178
+ def prefix
179
+ out = ::FastIgnore::PathRegexpBuilder.new
180
+
181
+ if @anchored
182
+ out.append_start_anchor
167
183
  else
168
- if @anchored
169
- out.append_start_anchor
170
- else
171
- out.append_start_dir_or_anchor
172
- end
184
+ out.append_dir_or_start_anchor
173
185
  end
174
186
  out
175
187
  end
176
188
 
177
189
  def build_rule
178
190
  @re.prepend(prefix)
179
- ::FastIgnore::Rule.new(@re.to_regexp, @negation, anchored_or_file_path, @dir_only)
180
- end
181
-
182
- def anchored_or_file_path
183
- @anchored || @file_path
191
+ if @negation
192
+ ::FastIgnore::Matchers::AllowPathRegexp.new(@re.to_regexp, @anchored, @dir_only)
193
+ else
194
+ ::FastIgnore::Matchers::IgnorePathRegexp.new(@re.to_regexp, @anchored, @dir_only)
195
+ end
184
196
  end
185
197
 
186
198
  def build
@@ -194,5 +206,16 @@ class FastIgnore
194
206
  build_rule
195
207
  end
196
208
  end
209
+
210
+ def expand_rule_path!
211
+ anchored! unless @s.match?(/\*/) # rubocop:disable Performance/StringInclude # it's StringScanner#match?
212
+ return unless @s.match?(%r{(?:[~/]|\.{1,2}/|.*/\.\./)})
213
+
214
+ dir_only! if @s.match?(%r{.*/\s*\z})
215
+
216
+ @s.string.replace(PathExpander.expand_path(@s.rest, @expand_path_with))
217
+ @s.string.delete_prefix!(@expand_path_with)
218
+ @s.pos = 0
219
+ end
197
220
  end
198
221
  end
@@ -0,0 +1,31 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'set'
4
+
5
+ class FastIgnore
6
+ class GitignoreRuleGroup < ::FastIgnore::RuleGroup
7
+ def initialize(root)
8
+ @root = root
9
+ @loaded_paths = Set[root]
10
+
11
+ super([
12
+ ::FastIgnore::Patterns.new('.git', root: '/'),
13
+ ::FastIgnore::Patterns.new(from_file: ::FastIgnore::GlobalGitignore.path(root: root), root: root),
14
+ ::FastIgnore::Patterns.new(from_file: "#{root}.git/info/exclude", root: root),
15
+ ::FastIgnore::Patterns.new(from_file: "#{root}.gitignore", root: root)
16
+ ], false)
17
+ end
18
+
19
+ def add_gitignore(dir)
20
+ return if @loaded_paths.include?(dir)
21
+
22
+ @loaded_paths << dir
23
+ matcher = ::FastIgnore::Patterns.new(from_file: "#{dir}.gitignore").build_matchers(allow: false)
24
+ @matchers += matcher unless !matcher || matcher.empty?
25
+ end
26
+
27
+ def add_gitignore_to_root(path)
28
+ add_gitignore(path) until @loaded_paths.include?(path = "#{::File.dirname(path)}/")
29
+ end
30
+ end
31
+ end
@@ -42,6 +42,18 @@ class FastIgnore
42
42
  skip(/\*\s*\z/)
43
43
  end
44
44
 
45
+ def two_star_end?
46
+ skip(/\*{2,}\s*\z/)
47
+ end
48
+
49
+ def star_slash_end?
50
+ skip(%r{\*/\s*\z})
51
+ end
52
+
53
+ def two_star_slash_end?
54
+ skip(%r{\*{2,}/\s*\z})
55
+ end
56
+
45
57
  def question_mark?
46
58
  skip(/\?/)
47
59
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Matchers
5
+ module AllowAnyDir
6
+ class << self
7
+ def squash_id
8
+ :allow_any_dir
9
+ end
10
+
11
+ def dir_only?
12
+ true
13
+ end
14
+
15
+ def file_only?
16
+ false
17
+ end
18
+
19
+ def squash(_)
20
+ self
21
+ end
22
+
23
+ def weight
24
+ 0
25
+ end
26
+
27
+ # :nocov:
28
+ def inspect
29
+ '#<AllowAnyDir>'
30
+ end
31
+ # :nocov:
32
+
33
+ def match?(_)
34
+ :allow
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Matchers
5
+ class AllowPathRegexp
6
+ attr_reader :dir_only
7
+ alias_method :dir_only?, :dir_only
8
+ undef :dir_only
9
+
10
+ attr_reader :squash_id
11
+ attr_reader :rule
12
+
13
+ def initialize(rule, squashable, dir_only)
14
+ @rule = rule
15
+ @dir_only = dir_only
16
+ @squashable = squashable
17
+ @squash_id = squashable ? :allow : object_id
18
+
19
+ freeze
20
+ end
21
+
22
+ def squash(list)
23
+ self.class.new(::Regexp.union(list.map(&:rule)), @squashable, @dir_only)
24
+ end
25
+
26
+ def file_only?
27
+ false
28
+ end
29
+
30
+ def weight
31
+ 1
32
+ end
33
+
34
+ # :nocov:
35
+ def inspect
36
+ "#<AllowPathRegexp #{'dir_only ' if @dir_only}#{@rule.inspect}>"
37
+ end
38
+ # :nocov:
39
+
40
+ def match?(candidate)
41
+ :allow if @rule.match?(candidate.relative_path)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module Matchers
5
+ class IgnorePathRegexp
6
+ attr_reader :dir_only
7
+ alias_method :dir_only?, :dir_only
8
+ undef :dir_only
9
+
10
+ attr_reader :squash_id
11
+ attr_reader :rule
12
+
13
+ def initialize(rule, anchored, dir_only)
14
+ @rule = rule
15
+ @dir_only = dir_only
16
+ @anchored = anchored
17
+ @squash_id = anchored ? :ignore : object_id
18
+
19
+ freeze
20
+ end
21
+
22
+ def squash(list)
23
+ self.class.new(::Regexp.union(list.map(&:rule)), @anchored, @dir_only)
24
+ end
25
+
26
+ def file_only?
27
+ false
28
+ end
29
+
30
+ def weight
31
+ 1
32
+ end
33
+
34
+ # :nocov:
35
+ def inspect
36
+ "#<IgnorePathRegexp #{'dir_only ' if @dir_only}#{@rule.inspect}>"
37
+ end
38
+ # :nocov:
39
+
40
+ def match?(candidate)
41
+ :ignore if @rule.match?(candidate.relative_path)
42
+ end
43
+ end
44
+ end
45
+ end