fast_ignore 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69021259195d30c9d3eb2e4461a779ef70b67d664370c5dff06d79f16ff009cb
4
- data.tar.gz: f3e60391822c26b461316389277f3901801c89e1dfcea59e819976d2b4c4b761
3
+ metadata.gz: f3d94c089fb5c75d6c9d0650d2391d03425c487c81296495f44f35ed1f6d80ac
4
+ data.tar.gz: a9bba05df8121aa49d38b39c7aaaa0e3c7d2b30e4b874d083fe517fa36846b97
5
5
  SHA512:
6
- metadata.gz: c99e8a9d3be9addeca4d18d327e450b9d6c345b6db354beb612e7f7e999af743d4ee4f62df9b1be0dec4a03820f948c52f8cb53d202ff8d3242499bbc453da87
7
- data.tar.gz: 2d17fe903303a913df5d763789517897e7c444c89069b3f81ce28df0136c1c5c6a94fd1c6f8080e17291713a75da4246da67c1c86a90c89a9084137276ba0b4d
6
+ metadata.gz: e8954fbef86b13d7948744b2c803319b261d67b6afe83412f1e099a377b17adae2aa1106a3445e6f5604449130c8dfc815331fe104f205ca09b87f5ff8caa69e
7
+ data.tar.gz: e53891e9d8b056a62ede7399695deb2911d5836ad5b8442b2ef90d7876fb4d794f1665697df6e7eeecf616f828217fce841f96c9bdfd39e73ae6c89594a65d5c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # v0.10.1
2
+ - Add option to follow symlinks (turns out i needed it)
3
+ - performance improvements
4
+
1
5
  # v0.10.0
2
6
  - patterns with middle slashes are anchored to the root (like the gitignore documentation, now that it more clearly explains)
3
7
  - new shebang pattern (#!:), the previous version was extremely janky.
@@ -6,7 +10,6 @@
6
10
  - documentation improvements
7
11
  - root can be given as a path relative to PWD
8
12
  - includes with 'a/**/d' now matches a/b/c/d properly
9
- -
10
13
 
11
14
  # v0.9.0
12
15
  - speed improvements, which may break things (Specifically, only using relative paths internally, is about 30% faster (depending on root depth))
data/README.md CHANGED
@@ -50,12 +50,20 @@ FastIgnore.new.each.with_index { |file, index| puts "#{file}#{index}" }
50
50
  ```
51
51
 
52
52
  ### `relative: true`
53
- By default, FastIgnore will return full paths. To return paths relative to the current working directory, use:
53
+ By default, FastIgnore will return full paths. To return paths relative to the current working directory, or the supplied [`root:`](#root), use:
54
54
 
55
55
  ```ruby
56
56
  FastIgnore.new(relative: true).to_a
57
57
  ```
58
58
 
59
+ ### `follow_symlinks: true`
60
+ By default, FastIgnore will match git's behaviour and not follow symbolic links.
61
+ To make it follow symlinks, use:
62
+
63
+ ```ruby
64
+ FastIgnore.new(follow_symlinks: true).to_a
65
+ ```
66
+
59
67
  ### `root:`
60
68
 
61
69
  By default, root is PWD (the current working directory)
@@ -200,11 +208,10 @@ This does unfortunately lose the file path as the root for `/` and `/**` rules.
200
208
  ## Known issues
201
209
  - Doesn't take into account project excludes in `.git/info/exclude`
202
210
  - Doesn't take into account globally ignored files in `git config core.excludesFile`.
203
- - Doesn't follow this rule in the gitignore documentation because I don't understand what it means that isn't covered by other rules:
204
-
205
- > [If the pattern does not contain a slash /, Git treats it as a shell glob pattern and checks for a match against the pathname relative to the location of the `.gitignore` file (relative to the toplevel of the work tree if not from a `.gitignore` file)](https://www.git-scm.com/docs/gitignore#_pattern_format)
211
+ - Doesn't know what to do if you change the current working directory inside the `FastIgnore#each` block.
212
+ So don't do that.
206
213
 
207
- if someone can explain it with examples [make an issue please](https://github.com/robotdana/fast_ignore/issues/new)
214
+ (It does handle changing the current working directory between `FastIgnore#allowed?` calls.)
208
215
 
209
216
  ## Development
210
217
 
data/bin/ls CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby --disable-all
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative '../lib/fast_ignore'
data/bin/time ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'open3'
5
+ RUNS = 30
6
+ SCRIPT = "time #{__dir__}/ls"
7
+ Dir.chdir ARGV[0] do
8
+ times = Array.new(RUNS).map do
9
+ run_times = Open3.capture3(SCRIPT)[1]
10
+ puts run_times.lstrip
11
+ run_times.scan(/(?:\d+(?:.\d+)?)/)
12
+ end
13
+
14
+ puts format(
15
+ "\e[1mAverage:\n\e[32m%0.2f real %0.2f user %0.2f sys\e[0m", # rubocop:disable Style/FormatStringToken
16
+ *times.transpose.map { |n| (n.map(&:to_f).sum / RUNS) }
17
+ )
18
+ end
data/fast_ignore.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ['lib']
31
31
 
32
32
  spec.add_development_dependency 'bundler', '>= 1.17'
33
- spec.add_development_dependency 'leftovers', '>= 0.2.1'
33
+ spec.add_development_dependency 'leftovers', '>= 0.2.2'
34
34
  spec.add_development_dependency 'pry', '> 0'
35
35
  spec.add_development_dependency 'rake', '>= 12.3.3'
36
36
  spec.add_development_dependency 'rspec', '~> 3.0'
data/lib/fast_ignore.rb CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  require_relative './fast_ignore/backports'
4
4
 
5
- require_relative './fast_ignore/rule_parser'
6
5
  require_relative './fast_ignore/rule_set_builder'
6
+ require_relative './fast_ignore/rule_builder'
7
7
  require_relative './fast_ignore/rule_set'
8
8
  require_relative './fast_ignore/rule'
9
9
 
@@ -22,70 +22,61 @@ class FastIgnore
22
22
  end
23
23
  # :nocov:
24
24
 
25
- def initialize( # rubocop:disable Metrics/MethodLength
26
- relative: false,
27
- root: nil,
28
- include_shebangs: nil,
29
- **rule_set_builder_args
30
- )
31
- # :nocov:
32
- if include_shebangs && !Array(include_shebangs).empty?
33
-
34
- warn <<~WARNING
35
- Removed FastIgnore `include_shebangs:` argument.
36
- It will be ignored. Please replace with the include_rules: in the shebang format
37
- https://github.com/robotdana/fast_ignore#shebang-rules
38
- WARNING
39
- end
40
- # :nocov:
41
-
42
- root = root ? File.expand_path(root, ::Dir.pwd) : ::Dir.pwd
43
- @root = "#{root}/"
44
-
45
- @rule_sets = ::FastIgnore::RuleSetBuilder.from_args(root: @root, **rule_set_builder_args)
25
+ def initialize(relative: false, root: nil, follow_symlinks: false, **rule_set_builder_args)
46
26
  @relative = relative
27
+ @follow_symlinks = follow_symlinks
28
+ dir_pwd = Dir.pwd
29
+ @root = "#{::File.expand_path(root.to_s, dir_pwd)}/"
30
+ @rule_sets = ::FastIgnore::RuleSetBuilder.build(root: @root, **rule_set_builder_args)
47
31
 
48
32
  freeze
49
33
  end
50
34
 
51
35
  def each(&block)
52
- if block_given?
53
- each_allowed(&block)
36
+ return enum_for(:each) unless block_given?
37
+
38
+ dir_pwd = Dir.pwd
39
+ root_from_pwd = @root.start_with?(dir_pwd) ? ".#{@root.delete_prefix(dir_pwd)}" : @root
40
+
41
+ each_recursive(root_from_pwd, '', &block)
42
+ end
43
+
44
+ def directory?(path)
45
+ if @follow_symlinks
46
+ ::File.stat(path).directory?
54
47
  else
55
- enum_for(:each_allowed)
48
+ ::File.lstat(path).directory?
56
49
  end
57
50
  end
58
51
 
59
52
  def allowed?(path)
60
53
  full_path = ::File.expand_path(path, @root)
61
54
  return false unless full_path.start_with?(@root)
62
-
63
- dir = ::File.lstat(full_path).directory?
64
- return false if dir
55
+ return false if directory?(full_path)
65
56
 
66
57
  relative_path = full_path.delete_prefix(@root)
67
58
  filename = ::File.basename(relative_path)
68
59
 
69
- @rule_sets.all? { |r| r.allowed_recursive?(relative_path, dir, filename) }
60
+ @rule_sets.all? { |r| r.allowed_recursive?(relative_path, false, filename) }
70
61
  rescue ::Errno::ENOENT, ::Errno::EACCES, ::Errno::ENOTDIR, ::Errno::ELOOP, ::Errno::ENAMETOOLONG
71
62
  false
72
63
  end
73
64
 
74
65
  private
75
66
 
76
- def each_allowed(full_path = @root, relative_path = '', &block) # rubocop:disable Metrics/MethodLength
77
- ::Dir.each_child(full_path) do |filename|
67
+ def each_recursive(parent_full_path, parent_relative_path, &block) # rubocop:disable Metrics/MethodLength
68
+ ::Dir.each_child(parent_full_path) do |filename|
78
69
  begin
79
- full_child = full_path + filename
80
- relative_child = relative_path + filename
81
- dir = ::File.lstat(full_child).directory?
70
+ full_path = parent_full_path + filename
71
+ relative_path = parent_relative_path + filename
72
+ dir = directory?(full_path)
82
73
 
83
- next unless @rule_sets.all? { |r| r.allowed_unrecursive?(relative_child, dir, filename) }
74
+ next unless @rule_sets.all? { |r| r.allowed_unrecursive?(relative_path, dir, filename) }
84
75
 
85
76
  if dir
86
- each_allowed("#{full_child}/", "#{relative_child}/", &block)
77
+ each_recursive(full_path + '/', relative_path + '/', &block)
87
78
  else
88
- yield(@relative ? relative_child : full_child)
79
+ yield(@relative ? relative_path : @root + relative_path)
89
80
  end
90
81
  rescue ::Errno::ENOENT, ::Errno::EACCES, ::Errno::ENOTDIR, ::Errno::ELOOP, ::Errno::ENAMETOOLONG
91
82
  nil
@@ -10,18 +10,20 @@ class FastIgnore
10
10
 
11
11
  attr_reader :negation
12
12
  alias_method :negation?, :negation
13
+
13
14
  attr_reader :dir_only
14
15
  alias_method :dir_only?, :dir_only
15
- attr_reader :file_only
16
- alias_method :file_only?, :file_only
17
16
 
18
17
  attr_reader :shebang
19
- attr_reader :rule
18
+ alias_method :file_only?, :shebang
19
+
20
+ attr_reader :unanchored
21
+ alias_method :unanchored?, :unanchored
20
22
 
21
- def initialize(rule, dir_only, file_only, negation, shebang = nil)
23
+ def initialize(rule, unanchored, dir_only, negation, shebang = nil)
22
24
  @rule = rule
25
+ @unanchored = unanchored
23
26
  @dir_only = dir_only
24
- @file_only = file_only
25
27
  @negation = negation
26
28
  @shebang = shebang
27
29
 
@@ -31,9 +33,9 @@ class FastIgnore
31
33
  # :nocov:
32
34
  def inspect
33
35
  if shebang
34
- "#<Rule #{'allow ' if negation?}#!:#{shebang.to_s[15..-4]}>"
36
+ "#<Rule #{'allow ' if @negation}#!:#{@shebang.to_s[15..-4]}>"
35
37
  else
36
- "#<Rule #{'!' if negation?}#{rule}#{'/' if dir_only?}>"
38
+ "#<Rule #{'!' if @negation}#{@rule}#{'/' if @dir_only}>"
37
39
  end
38
40
  end
39
41
  # :nocov:
@@ -42,6 +44,7 @@ class FastIgnore
42
44
  if @shebang
43
45
  match_shebang?(path, filename)
44
46
  else
47
+ # 14 = FNMATCH_OPTIONS
45
48
  ::File.fnmatch?(@rule, path, 14)
46
49
  end
47
50
  end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastIgnore
4
+ module RuleBuilder
5
+ # rule or nil
6
+ class << self
7
+ # :nocov:
8
+ if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
9
+ require_relative 'backports/delete_prefix_suffix'
10
+ using ::FastIgnore::Backports::DeletePrefixSuffix
11
+ end
12
+ # :nocov:
13
+
14
+ def build(rule, allow, expand_path, file_root)
15
+ strip(rule)
16
+
17
+ return shebang_rules(rule, allow) if remove_shebang(rule)
18
+ return [] if skip?(rule)
19
+
20
+ gitignore_rules(rule, allow, expand_path, file_root)
21
+ end
22
+
23
+ private
24
+
25
+ def strip(rule)
26
+ rule.chomp!
27
+ rule.rstrip! unless rule.end_with?('\\ ')
28
+ end
29
+
30
+ def remove_shebang(rule)
31
+ return unless rule.delete_prefix!('#!:')
32
+
33
+ rule.strip!
34
+
35
+ true
36
+ end
37
+
38
+ def shebang_rules(rule, allow)
39
+ rules = [::FastIgnore::Rule.new(nil, true, false, allow, /\A#!.*\b#{Regexp.escape(rule)}\b/.freeze)]
40
+ return rules unless allow
41
+
42
+ rules << ::FastIgnore::Rule.new('**/*', true, true, true)
43
+ rules
44
+ end
45
+
46
+ def skip?(rule)
47
+ rule.empty? || rule.start_with?('#')
48
+ end
49
+
50
+ def gitignore_rules(rule, allow, expand_path, file_root)
51
+ dir_only = extract_dir_only(rule)
52
+ negation = extract_negation(rule, allow)
53
+
54
+ expand_rule_path(rule, expand_path) if expand_path
55
+ unanchored = unanchored?(rule)
56
+ rule.delete_prefix!('/')
57
+
58
+ rule.prepend("#{file_root}#{'**/' if unanchored}") if file_root || unanchored
59
+
60
+ build_gitignore_rules(rule, unanchored, allow, dir_only, negation)
61
+ end
62
+
63
+ def extract_dir_only(rule)
64
+ rule.delete_suffix!('/')
65
+ end
66
+
67
+ def extract_negation(rule, allow)
68
+ return allow unless rule.delete_prefix!('!')
69
+
70
+ not allow
71
+ end
72
+
73
+ EXPAND_PATH_RE = %r{^(?:[~/]|\.{1,2}/)}.freeze
74
+ def expand_rule_path(rule, root)
75
+ rule.replace(::File.expand_path(rule)) if rule.match?(EXPAND_PATH_RE)
76
+ rule.delete_prefix!(root)
77
+ rule.prepend('/') unless rule.start_with?('*') || rule.start_with?('/')
78
+ end
79
+
80
+ def unanchored?(rule)
81
+ not rule.include?('/') # we've already removed the trailing '/' with extract_dir_only
82
+ end
83
+
84
+ def build_gitignore_rules(rule, unanchored, allow, dir_only, negation)
85
+ rules = [::FastIgnore::Rule.new(rule.freeze, unanchored, dir_only, negation)]
86
+ return rules unless allow
87
+
88
+ rules << ::FastIgnore::Rule.new("#{rule}/**/*", unanchored, false, negation)
89
+ rules + ancestor_rules(rule, unanchored)
90
+ end
91
+
92
+ def ancestor_rules(parent, unanchored)
93
+ ancestor_rules = []
94
+
95
+ while (parent = ::File.dirname(parent)) != '.'
96
+ rule = ::File.basename(parent) == '**' ? "#{parent}/*" : parent.freeze
97
+ ancestor_rules << ::FastIgnore::Rule.new(rule, unanchored, true, true)
98
+ end
99
+
100
+ ancestor_rules
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,12 +2,15 @@
2
2
 
3
3
  class FastIgnore
4
4
  class RuleSet
5
- def initialize(allow: false)
6
- @dir_rules = []
7
- @file_rules = []
5
+ def initialize(rules, allow)
6
+ @dir_rules = rules.reject(&:file_only?).freeze
7
+ @file_rules = rules.reject(&:dir_only?).freeze
8
+ @any_not_anchored = rules.any?(&:unanchored?)
9
+ @has_shebang_rules = rules.any?(&:shebang)
8
10
  @allowed_recursive = { '.' => true }
9
- @any_not_anchored = false
10
11
  @allow = allow
12
+
13
+ freeze
11
14
  end
12
15
 
13
16
  def freeze
@@ -26,21 +29,10 @@ class FastIgnore
26
29
 
27
30
  def allowed_unrecursive?(path, dir, filename)
28
31
  (dir ? @dir_rules : @file_rules).reverse_each do |rule|
29
- # 14 = Rule::FNMATCH_OPTIONS
30
-
31
32
  return rule.negation? if rule.match?(path, filename)
32
33
  end
33
34
 
34
- (not @allow) || (@any_not_anchored if dir)
35
- end
36
-
37
- def append_rules(anchored, rules)
38
- rules.each do |rule|
39
- (@dir_rules << rule) unless rule.file_only?
40
- (@file_rules << rule) unless rule.dir_only?
41
- @any_not_anchored ||= !anchored
42
- @has_shebang_rules ||= rule.shebang
43
- end
35
+ (not @allow) || (dir && @any_not_anchored)
44
36
  end
45
37
 
46
38
  def weight
@@ -1,92 +1,87 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FastIgnore
4
- class RuleSetBuilder
5
- # :nocov:
6
- if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
7
- require_relative 'backports/delete_prefix_suffix'
8
- using ::FastIgnore::Backports::DeletePrefixSuffix
9
- end
10
- # :nocov:
4
+ module RuleSetBuilder
5
+ class << self
6
+ # :nocov:
7
+ if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
8
+ require_relative 'backports/delete_prefix_suffix'
9
+ using ::FastIgnore::Backports::DeletePrefixSuffix
10
+ end
11
+ # :nocov:
11
12
 
12
- def self.from_args( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
13
- root:,
14
- ignore_rules: nil,
15
- ignore_files: nil,
16
- gitignore: :auto,
17
- include_rules: nil,
18
- include_files: nil,
19
- argv_rules: nil
20
- )
21
- rule_sets = [
22
- from_array(ignore_rules),
23
- *from_files(ignore_files, project_root: root),
24
- from_array('.git'),
25
- from_gitignore_arg(gitignore, project_root: root),
26
- from_array(include_rules, allow: true),
27
- *from_files(include_files, allow: true, project_root: root),
28
- from_array(argv_rules, allow: true, expand_path: root)
29
- ]
13
+ def build( # rubocop:disable Metrics/ParameterLists
14
+ root:,
15
+ ignore_rules: nil,
16
+ ignore_files: nil,
17
+ gitignore: :auto,
18
+ include_rules: nil,
19
+ include_files: nil,
20
+ argv_rules: nil
21
+ )
22
+ prepare [
23
+ from_array(ignore_rules),
24
+ *from_files(ignore_files, project_root: root),
25
+ from_array('.git'),
26
+ from_gitignore_arg(gitignore, project_root: root),
27
+ from_array(include_rules, allow: true),
28
+ *from_files(include_files, allow: true, project_root: root),
29
+ from_array(argv_rules, allow: true, expand_path: root)
30
+ ]
31
+ end
30
32
 
31
- rule_sets.compact!
32
- rule_sets.reject!(&:empty?)
33
- rule_sets.sort_by!(&:weight)
34
- rule_sets
35
- end
33
+ private
36
34
 
37
- def self.from_file(filename, project_root:, allow: false)
38
- filename = ::File.expand_path(filename, project_root)
39
- raise FastIgnore::Error, "#{filename} is not within #{project_root}" unless filename.start_with?(project_root)
35
+ def prepare(rule_sets)
36
+ rule_sets.compact!
37
+ rule_sets.reject!(&:empty?)
38
+ rule_sets.sort_by!(&:weight)
39
+ rule_sets
40
+ end
40
41
 
41
- file_root = "#{::File.dirname(filename)}/".delete_prefix(project_root)
42
- rule_set = ::FastIgnore::RuleSet.new(allow: allow)
42
+ def from_file(filename, project_root:, allow: false)
43
+ filename = ::File.expand_path(filename, project_root)
44
+ raise FastIgnore::Error, "#{filename} is not within #{project_root}" unless filename.start_with?(project_root)
43
45
 
44
- ::IO.foreach(filename) do |rule_string|
45
- parse_rules(rule_string, allow: allow, rule_set: rule_set, file_root: file_root)
46
+ file_root = "#{::File.dirname(filename)}/".delete_prefix(project_root)
47
+ build_rule_set(::File.readlines(filename), allow, file_root: file_root)
46
48
  end
47
49
 
48
- rule_set.freeze
49
- end
50
-
51
- def self.from_files(files, project_root:, allow: false)
52
- Array(files).map do |file|
53
- from_file(file, allow: allow, project_root: project_root)
50
+ def from_files(files, project_root:, allow: false)
51
+ Array(files).map do |file|
52
+ from_file(file, project_root: project_root, allow: allow)
53
+ end
54
54
  end
55
- end
56
55
 
57
- def self.from_gitignore_arg(gitignore, project_root:)
58
- default_path = ::File.join(project_root, '.gitignore')
59
- case gitignore
60
- when :auto
61
- from_file(default_path, project_root: project_root) if ::File.exist?(default_path)
62
- when true
63
- from_file(default_path, project_root: project_root)
56
+ def from_gitignore_arg(gitignore, project_root:)
57
+ default_path = ::File.join(project_root, '.gitignore')
58
+ case gitignore
59
+ when :auto
60
+ from_file(default_path, project_root: project_root) if ::File.exist?(default_path)
61
+ when true
62
+ from_file(default_path, project_root: project_root)
63
+ end
64
64
  end
65
- end
66
65
 
67
- def self.from_array(rules, allow: false, expand_path: false)
68
- rules = Array(rules)
69
- return if rules.empty?
66
+ def from_array(rules, allow: false, expand_path: false)
67
+ return unless rules
70
68
 
71
- rule_set = ::FastIgnore::RuleSet.new(allow: allow)
69
+ rules = Array(rules)
72
70
 
73
- rules.each do |rule_string|
74
- rule_string.to_s.each_line do |rule_line|
75
- parse_rules(rule_line, rule_set: rule_set, allow: allow, expand_path: expand_path)
76
- end
71
+ return if rules.empty?
72
+
73
+ rules = rules.flat_map { |string| string.to_s.lines }
74
+
75
+ build_rule_set(rules, allow, expand_path: expand_path)
77
76
  end
78
77
 
79
- rule_set.freeze
80
- end
78
+ def build_rule_set(rules, allow, expand_path: false, file_root: nil)
79
+ rules = rules.flat_map do |rule|
80
+ ::FastIgnore::RuleBuilder.build(rule, allow, expand_path, file_root)
81
+ end
81
82
 
82
- def self.parse_rules(rule_line, rule_set:, allow: false, expand_path: false, file_root: nil)
83
- ::FastIgnore::RuleParser.new_rule(
84
- rule_line,
85
- rule_set: rule_set,
86
- allow: allow,
87
- expand_path: expand_path,
88
- file_root: file_root
89
- )
83
+ ::FastIgnore::RuleSet.new(rules, allow).freeze
84
+ end
90
85
  end
91
86
  end
92
87
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FastIgnore
4
- VERSION = '0.10.0'
4
+ VERSION = '0.10.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_ignore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dana Sherson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-21 00:00:00.000000000 Z
11
+ date: 2020-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.1
33
+ version: 0.2.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.1
40
+ version: 0.2.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -160,15 +160,15 @@ files:
160
160
  - Rakefile
161
161
  - bin/console
162
162
  - bin/ls
163
- - bin/ls-disable-gems
164
163
  - bin/setup
164
+ - bin/time
165
165
  - fast_ignore.gemspec
166
166
  - lib/fast_ignore.rb
167
167
  - lib/fast_ignore/backports.rb
168
168
  - lib/fast_ignore/backports/delete_prefix_suffix.rb
169
169
  - lib/fast_ignore/backports/dir_each_child.rb
170
170
  - lib/fast_ignore/rule.rb
171
- - lib/fast_ignore/rule_parser.rb
171
+ - lib/fast_ignore/rule_builder.rb
172
172
  - lib/fast_ignore/rule_set.rb
173
173
  - lib/fast_ignore/rule_set_builder.rb
174
174
  - lib/fast_ignore/version.rb
data/bin/ls-disable-gems DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby --disable-gems
2
- # frozen_string_literal: true
3
-
4
- require_relative '../lib/fast_ignore'
5
-
6
- puts FastIgnore.new(relative: true, argv_rules: ARGV).to_a
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class FastIgnore
4
- class RuleParser
5
- # :nocov:
6
- if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
7
- require_relative 'backports/delete_prefix_suffix'
8
- using ::FastIgnore::Backports::DeletePrefixSuffix
9
- end
10
- # :nocov:
11
-
12
- # rule or nil
13
- class << self
14
- def new_rule(rule, rule_set:, allow: false, expand_path: false, file_root: nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
15
- rule = rule.dup
16
- strip(rule)
17
-
18
- return rule_set.append_rules(false, shebang_rules(rule, allow)) if extract_shebang(rule)
19
-
20
- return if skip?(rule)
21
-
22
- dir_only = extract_dir_only(rule)
23
- negation = extract_negation(rule, allow)
24
-
25
- expand_rule_path(rule, expand_path) if expand_path
26
- anchored = anchored?(rule)
27
- rule.delete_prefix!('/')
28
-
29
- rule.prepend("#{file_root}#{'**/' unless anchored}") if file_root || (not anchored)
30
-
31
- rule.freeze
32
-
33
- rule_set.append_rules(
34
- anchored,
35
- rules(rule, allow, dir_only, negation)
36
- )
37
- end
38
-
39
- private
40
-
41
- def shebang_rules(rule, allow)
42
- rules = [::FastIgnore::Rule.new(nil, false, true, allow, /\A#!.*\b#{Regexp.escape(rule)}\b/)]
43
- return rules unless allow
44
-
45
- rules << ::FastIgnore::Rule.new('**/*', true, false, true)
46
- rules
47
- end
48
-
49
- def rules(rule, allow, dir_only, negation)
50
- rules = [::FastIgnore::Rule.new(rule, dir_only, false, negation)]
51
- return rules unless allow
52
-
53
- rules << ::FastIgnore::Rule.new("#{rule}/**/*", false, false, negation)
54
- rules + ancestor_rules(rule)
55
- end
56
-
57
- def ancestor_rules(parent)
58
- ancestor_rules = []
59
-
60
- while (parent = ::File.dirname(parent)) != '.'
61
- rule = ::File.basename(parent) == '**' ? "#{parent}/*" : parent.freeze
62
- ancestor_rules << ::FastIgnore::Rule.new(rule, true, false, true)
63
- end
64
-
65
- ancestor_rules
66
- end
67
-
68
- def extract_negation(rule, allow)
69
- return allow unless rule.delete_prefix!('!')
70
-
71
- not allow
72
- end
73
-
74
- def extract_dir_only(rule)
75
- rule.delete_suffix!('/')
76
- end
77
-
78
- def strip(rule)
79
- rule.chomp!
80
- rule.rstrip! unless rule.end_with?('\\ ')
81
- end
82
-
83
- def anchored?(rule)
84
- rule.include?('/') # we've already removed the trailing '/' with extract_dir_only
85
- end
86
-
87
- EXPAND_PATH_RE = %r{^(?:[~/]|\.{1,2}/)}.freeze
88
- def expand_rule_path(rule, root)
89
- rule.replace(::File.expand_path(rule)) if rule.match?(EXPAND_PATH_RE)
90
- rule.delete_prefix!(root)
91
- rule.prepend('/') unless rule.start_with?('*') || rule.start_with?('/')
92
- end
93
-
94
- def extract_shebang(rule)
95
- rule.delete_prefix!('#!:') && (rule.strip! || true)
96
- end
97
-
98
- def skip?(rule)
99
- rule.empty? || rule.start_with?('#')
100
- end
101
- end
102
- end
103
- end