fast_ignore 0.12.0 → 0.15.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +157 -80
- data/lib/fast_ignore.rb +27 -26
- data/lib/fast_ignore/backports.rb +2 -2
- data/lib/fast_ignore/file_root.rb +39 -0
- data/lib/fast_ignore/gitignore_include_rule_builder.rb +102 -0
- data/lib/fast_ignore/gitignore_rule_builder.rb +182 -0
- data/lib/fast_ignore/gitignore_rule_regexp_builder.rb +76 -0
- data/lib/fast_ignore/gitignore_rule_scanner.rb +73 -0
- data/lib/fast_ignore/global_gitignore.rb +50 -0
- data/lib/fast_ignore/rule.rb +28 -12
- data/lib/fast_ignore/rule_builder.rb +18 -80
- data/lib/fast_ignore/rule_set.rb +23 -16
- data/lib/fast_ignore/rule_sets.rb +113 -0
- data/lib/fast_ignore/shebang_rule.rb +34 -14
- data/lib/fast_ignore/unmatchable_rule.rb +41 -0
- data/lib/fast_ignore/version.rb +1 -1
- metadata +19 -31
- data/.gitignore +0 -6
- data/.leftovers.yml +0 -5
- data/.rspec +0 -3
- data/.rubocop.yml +0 -216
- data/.simplecov +0 -10
- data/.spellr.yml +0 -5
- data/.spellr_wordlists/english.txt +0 -62
- data/.spellr_wordlists/ruby.txt +0 -1
- data/.spellr_wordlists/shell.txt +0 -3
- data/.travis.yml +0 -11
- data/Gemfile +0 -9
- data/Rakefile +0 -18
- data/bin/console +0 -8
- data/bin/ls +0 -6
- data/bin/ls_seconds +0 -21
- data/bin/setup +0 -8
- data/bin/time +0 -21
- data/fast_ignore.gemspec +0 -41
- data/lib/fast_ignore/fn_match_to_re.rb +0 -96
- data/lib/fast_ignore/rule_set_builder.rb +0 -126
data/.spellr_wordlists/ruby.txt
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rspec
|
data/.spellr_wordlists/shell.txt
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/gem_tasks'
|
4
|
-
require 'rspec/core/rake_task'
|
5
|
-
require 'rubocop/rake_task'
|
6
|
-
require 'spellr/rake_task'
|
7
|
-
require 'leftovers/rake_task'
|
8
|
-
|
9
|
-
RuboCop::RakeTask.new
|
10
|
-
RSpec::Core::RakeTask.new(:spec)
|
11
|
-
Spellr::RakeTask.generate_task
|
12
|
-
Leftovers::RakeTask.generate_task
|
13
|
-
|
14
|
-
if RUBY_PLATFORM == 'java'
|
15
|
-
task default: :spec
|
16
|
-
else
|
17
|
-
task default: [:spec, :rubocop, :spellr, :leftovers]
|
18
|
-
end
|
data/bin/console
DELETED
data/bin/ls
DELETED
data/bin/ls_seconds
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby --disable-all
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../lib/fast_ignore'
|
5
|
-
|
6
|
-
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
7
|
-
new_a = FastIgnore.new(relative: true, argv_rules: ARGV).to_a
|
8
|
-
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
9
|
-
puts "new #{new_a.count}: #{t2 - t1}"
|
10
|
-
fi = FastIgnore.new(relative: true, argv_rules: ARGV)
|
11
|
-
fi.to_a
|
12
|
-
t3 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
13
|
-
cached_a = fi.to_a
|
14
|
-
t4 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
15
|
-
puts "cached #{cached_a.count}: #{t4 - t3}"
|
16
|
-
t5 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
17
|
-
git_a = `git ls-files`.split("\n")
|
18
|
-
t6 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
19
|
-
puts "git ls-files #{git_a.count}: #{t6 - t5}"
|
20
|
-
|
21
|
-
exit 1 unless new_a.length == cached_a.length && new_a.length == git_a.length
|
data/bin/setup
DELETED
data/bin/time
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
# use mac terminal not vs code terminal
|
5
|
-
# ensure nothing else is watching that dir in the filesystem e.g. webpack
|
6
|
-
|
7
|
-
require 'open3'
|
8
|
-
require 'shellwords'
|
9
|
-
RUNS = 30
|
10
|
-
SCRIPT = "time #{__dir__}/ls #{Shellwords.join(ARGV)}"
|
11
|
-
|
12
|
-
times = Array.new(RUNS).map do
|
13
|
-
run_times = Open3.capture3(SCRIPT)[1]
|
14
|
-
puts run_times.lstrip
|
15
|
-
run_times.scan(/(?:\d+(?:.\d+)?)/)
|
16
|
-
end
|
17
|
-
|
18
|
-
puts format(
|
19
|
-
"\e[1mAverage:\n\e[32m%0.2f real %0.2f user %0.2f sys\e[0m", # rubocop:disable Style/FormatStringToken
|
20
|
-
*times.transpose.map { |n| (n.map(&:to_f).sum / RUNS) }
|
21
|
-
)
|
data/fast_ignore.gemspec
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
lib = File.expand_path('lib', __dir__)
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require 'fast_ignore/version'
|
6
|
-
|
7
|
-
Gem::Specification.new do |spec|
|
8
|
-
spec.name = 'fast_ignore'
|
9
|
-
spec.version = FastIgnore::VERSION
|
10
|
-
spec.authors = ['Dana Sherson']
|
11
|
-
spec.email = ['robot@dana.sh']
|
12
|
-
|
13
|
-
spec.summary = 'Parse gitignore files, quickly'
|
14
|
-
spec.homepage = 'https://github.com/robotdana/fast_ignore'
|
15
|
-
spec.license = 'MIT'
|
16
|
-
|
17
|
-
spec.required_ruby_version = '~> 2.4'
|
18
|
-
|
19
|
-
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
-
spec.metadata['source_code_uri'] = 'https://github.com/robotdana/fast_ignore'
|
22
|
-
spec.metadata['changelog_uri'] = 'https://github.com/robotdana/fast_ignore/blob/master/CHANGELOG.md'
|
23
|
-
end
|
24
|
-
|
25
|
-
# Specify which files should be added to the gem when it is released.
|
26
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
|
-
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
|
-
end
|
30
|
-
spec.require_paths = ['lib']
|
31
|
-
|
32
|
-
spec.add_development_dependency 'bundler', '>= 1.17'
|
33
|
-
spec.add_development_dependency 'leftovers', '>= 0.2.2'
|
34
|
-
spec.add_development_dependency 'pry', '> 0'
|
35
|
-
spec.add_development_dependency 'rake', '>= 12.3.3'
|
36
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
|
-
spec.add_development_dependency 'rubocop', '>= 0.74.0'
|
38
|
-
spec.add_development_dependency 'rubocop-rspec', '~> 1'
|
39
|
-
spec.add_development_dependency 'simplecov', '~> 0.18.5'
|
40
|
-
spec.add_development_dependency 'spellr', '>= 0.8.3'
|
41
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class FastIgnore
|
4
|
-
module FNMatchToRegex
|
5
|
-
# This doesn't look rubyish because i ported it from rust (the only rust i ever wrote that worked)
|
6
|
-
class << self
|
7
|
-
def call(pattern) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
8
|
-
re = '\\A'.dup
|
9
|
-
|
10
|
-
in_character_group = false
|
11
|
-
has_characters_in_group = false
|
12
|
-
escape_next_character = false
|
13
|
-
last_char_opened_character_group = false
|
14
|
-
negated_character_group = false
|
15
|
-
stars = 0
|
16
|
-
|
17
|
-
pattern.each_char do |char| # rubocop:disable Metrics/BlockLength
|
18
|
-
if escape_next_character
|
19
|
-
re << Regexp.escape(char)
|
20
|
-
escape_next_character = false
|
21
|
-
elsif char == '\\' # single char, just needs to be escaped
|
22
|
-
escape_next_character = true
|
23
|
-
elsif in_character_group
|
24
|
-
if char == '/'
|
25
|
-
if negated_character_group
|
26
|
-
has_characters_in_group = true
|
27
|
-
re << char
|
28
|
-
end
|
29
|
-
elsif char == '^'
|
30
|
-
if last_char_opened_character_group
|
31
|
-
re << char
|
32
|
-
negated_character_group = true
|
33
|
-
else
|
34
|
-
re << '\\^'
|
35
|
-
has_characters_in_group = true
|
36
|
-
end
|
37
|
-
# not characters in group
|
38
|
-
elsif char == ']'
|
39
|
-
break unless has_characters_in_group
|
40
|
-
|
41
|
-
re << ']'
|
42
|
-
in_character_group = false
|
43
|
-
has_characters_in_group = false
|
44
|
-
negated_character_group = false
|
45
|
-
last_char_opened_character_group = false
|
46
|
-
elsif char == '-'
|
47
|
-
has_characters_in_group = true
|
48
|
-
re << char
|
49
|
-
else
|
50
|
-
has_characters_in_group = true
|
51
|
-
re << Regexp.escape(char)
|
52
|
-
end
|
53
|
-
last_char_opened_character_group = false
|
54
|
-
elsif char == '*'
|
55
|
-
stars += 1
|
56
|
-
elsif char == '/'
|
57
|
-
re << if stars >= 2
|
58
|
-
'(?:.*/)?'
|
59
|
-
elsif stars.positive?
|
60
|
-
'[^/]*/'
|
61
|
-
else
|
62
|
-
char
|
63
|
-
end
|
64
|
-
stars = 0
|
65
|
-
else
|
66
|
-
if stars.positive?
|
67
|
-
re << '[^/]*'
|
68
|
-
stars = 0
|
69
|
-
end
|
70
|
-
if char == '?'
|
71
|
-
re << '[^/]'
|
72
|
-
elsif char == '['
|
73
|
-
re << '['
|
74
|
-
in_character_group = true
|
75
|
-
last_char_opened_character_group = true
|
76
|
-
else
|
77
|
-
re << Regexp.escape(char)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
if in_character_group
|
83
|
-
return /(?!)/ # impossible to match anything
|
84
|
-
end
|
85
|
-
|
86
|
-
if stars >= 2
|
87
|
-
re << '.*'
|
88
|
-
elsif stars.positive?
|
89
|
-
re << '[^/]*'
|
90
|
-
end
|
91
|
-
re << '\\z'
|
92
|
-
Regexp.new(re, Regexp::IGNORECASE)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class FastIgnore
|
4
|
-
module RuleSetBuilder
|
5
|
-
class << self
|
6
|
-
# :nocov:
|
7
|
-
using ::FastIgnore::Backports::DeletePrefixSuffix if defined?(::FastIgnore::Backports::DeletePrefixSuffix)
|
8
|
-
# :nocov:
|
9
|
-
|
10
|
-
def build( # rubocop:disable Metrics/ParameterLists
|
11
|
-
root:,
|
12
|
-
ignore_rules: nil,
|
13
|
-
ignore_files: nil,
|
14
|
-
gitignore: :auto,
|
15
|
-
include_rules: nil,
|
16
|
-
include_files: nil,
|
17
|
-
argv_rules: nil
|
18
|
-
)
|
19
|
-
prepare [
|
20
|
-
from_array(ignore_rules),
|
21
|
-
*from_files(ignore_files, project_root: root),
|
22
|
-
from_array('.git'),
|
23
|
-
from_gitignore_arg(gitignore, project_root: root),
|
24
|
-
from_array(include_rules, allow: true),
|
25
|
-
*from_files(include_files, allow: true, project_root: root),
|
26
|
-
from_array(argv_rules, allow: true, expand_path: root)
|
27
|
-
]
|
28
|
-
end
|
29
|
-
|
30
|
-
def append_gitignore(rule_sets, project_root:, relative_path:, soft: true)
|
31
|
-
new_gitignore = from_file(relative_path, project_root: project_root, gitignore: true, soft: soft)
|
32
|
-
return unless new_gitignore
|
33
|
-
|
34
|
-
base_gitignore = rule_sets.find(&:gitignore?)
|
35
|
-
if base_gitignore
|
36
|
-
base_gitignore << new_gitignore
|
37
|
-
else
|
38
|
-
rule_sets << new_gitignore
|
39
|
-
prepare(rule_sets)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def prepare(rule_sets)
|
46
|
-
rule_sets.compact!
|
47
|
-
rule_sets.reject!(&:empty?)
|
48
|
-
rule_sets.sort_by!(&:weight)
|
49
|
-
rule_sets
|
50
|
-
end
|
51
|
-
|
52
|
-
def from_file(filename, project_root:, allow: false, file_root: nil, gitignore: false, soft: false) # rubocop:disable Metrics/ParameterLists
|
53
|
-
filename = ::File.expand_path(filename, project_root)
|
54
|
-
return if soft && !::File.exist?(filename)
|
55
|
-
unless file_root || filename.start_with?(project_root)
|
56
|
-
raise FastIgnore::Error, "#{filename} is not within #{project_root}"
|
57
|
-
end
|
58
|
-
|
59
|
-
file_root ||= "#{::File.dirname(filename)}/".delete_prefix(project_root)
|
60
|
-
build_rule_set(::File.readlines(filename), allow, file_root: file_root, gitignore: gitignore)
|
61
|
-
end
|
62
|
-
|
63
|
-
def from_files(files, project_root:, allow: false)
|
64
|
-
Array(files).map do |file|
|
65
|
-
from_file(file, project_root: project_root, allow: allow)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def from_gitignore_arg(gitignore, project_root:)
|
70
|
-
return unless gitignore
|
71
|
-
|
72
|
-
gi = ::FastIgnore::RuleSet.new([], false, true)
|
73
|
-
gi << from_gitignore_file(gitconfig_global_gitignore_path || default_global_gitignore_path)
|
74
|
-
gi << from_gitignore_file(::File.join(project_root, '.git/info/exclude'))
|
75
|
-
gi << from_gitignore_file(::File.join(project_root, '.gitignore'), soft: gitignore == :auto)
|
76
|
-
gi
|
77
|
-
end
|
78
|
-
|
79
|
-
def from_gitignore_file(path, soft: true)
|
80
|
-
return if soft && !::File.exist?(path)
|
81
|
-
|
82
|
-
build_rule_set(::File.readlines(path), false, file_root: '', gitignore: true)
|
83
|
-
end
|
84
|
-
|
85
|
-
def gitconfig_global_gitignore_path
|
86
|
-
config_path = ::File.expand_path('~/.gitconfig')
|
87
|
-
return unless ::File.exist?(config_path)
|
88
|
-
|
89
|
-
ignore_path = ::File.readlines(config_path).find { |l| l.start_with?("\texcludesfile = ") }
|
90
|
-
return unless ignore_path
|
91
|
-
|
92
|
-
ignore_path.delete_prefix!("\texcludesfile = ")
|
93
|
-
ignore_path.strip!
|
94
|
-
::File.expand_path(ignore_path)
|
95
|
-
end
|
96
|
-
|
97
|
-
def default_global_gitignore_path
|
98
|
-
if ENV['XDG_CONFIG_HOME'] && !ENV['XDG_CONFIG_HOME'].empty?
|
99
|
-
::File.expand_path('git/ignore', ENV['XDG_CONFIG_HOME'])
|
100
|
-
else
|
101
|
-
::File.expand_path('~/.config/git/ignore')
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def from_array(rules, allow: false, expand_path: false)
|
106
|
-
return unless rules
|
107
|
-
|
108
|
-
rules = Array(rules)
|
109
|
-
|
110
|
-
return if rules.empty?
|
111
|
-
|
112
|
-
rules = rules.flat_map { |string| string.to_s.lines }
|
113
|
-
|
114
|
-
build_rule_set(rules, allow, expand_path: expand_path)
|
115
|
-
end
|
116
|
-
|
117
|
-
def build_rule_set(rules, allow, expand_path: false, file_root: nil, gitignore: false)
|
118
|
-
rules = rules.flat_map do |rule|
|
119
|
-
::FastIgnore::RuleBuilder.build(rule, allow, expand_path, file_root)
|
120
|
-
end
|
121
|
-
|
122
|
-
::FastIgnore::RuleSet.new(rules, allow, gitignore)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|