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.
@@ -1 +0,0 @@
1
- rspec
@@ -1,3 +0,0 @@
1
- env
2
- euo
3
- usr
@@ -1,11 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- before_install: gem install bundler
6
- rvm:
7
- - 2.4
8
- - 2.5
9
- - 2.6
10
- - 2.7
11
- - jruby
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- # Specify your gem's dependencies in fast_ignore.gemspec
8
-
9
- gemspec
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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'fast_ignore'
6
-
7
- require 'pry'
8
- Pry.start
data/bin/ls DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby --disable-all
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,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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
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
- )
@@ -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