fast_ignore 0.15.2 → 0.16.0
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 +4 -0
- data/README.md +1 -1
- data/lib/fast_ignore/gitconfig_parser.rb +207 -0
- data/lib/fast_ignore/global_gitignore.rb +3 -3
- data/lib/fast_ignore/version.rb +1 -1
- data/lib/fast_ignore.rb +14 -12
- metadata +28 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88d6249cc842976d1b5c0e984816cfc260cc3edcbe4774ea4580e934bedcf925
|
4
|
+
data.tar.gz: 3ab13efc019bee9b5cadcb45f485021132f07787bce73d66bb9ef63b76bc51ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 853124ae1ddf1fc599e8a422580ee84ff705907a70c7ece17db72502a4468ca0d5479f918c175f91dc1915c7cccb5ad4cd7eaa956adf2d7b0a5e2fa024821c3d
|
7
|
+
data.tar.gz: b90c827caa6c24c3491237ec5fb538b828b2daea879a4d94d6bc3ac4368807c7040bc0d6ea6405b8e9712483d00fddfb6d43e1a970786f374144a4d6165f59ee
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# v0.16.0
|
2
|
+
- Entirely rewrite the way that git config files are read. previously it was just a regexp. now we actually parse git config files according to the same rules as git.
|
3
|
+
- Add ruby 3 to the test matrix
|
4
|
+
|
1
5
|
# v0.15.2
|
2
6
|
- Updated methods with multiple `_` arguments to have different names to make sorbet happy
|
3
7
|
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ FastIgnore.new(relative: true).sort == `git ls-files`.split("\n").sort
|
|
15
15
|
## Features
|
16
16
|
|
17
17
|
- Fast (faster than using `` `git ls-files`.split("\n") `` for small repos (because it avoids the overhead of ``` `` ```))
|
18
|
-
- Supports ruby 2.4-3.0.
|
18
|
+
- Supports ruby 2.4-3.0.x & jruby
|
19
19
|
- supports all [gitignore rule patterns](https://git-scm.com/docs/gitignore#_pattern_format)
|
20
20
|
- doesn't require git to be installed
|
21
21
|
- supports a gitignore-esque "include" patterns. ([`include_rules:`](#include_rules)/[`include_files:`](#include_files))
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
class FastIgnore
|
5
|
+
class GitconfigParseError < FastIgnore::Error; end
|
6
|
+
|
7
|
+
class GitconfigParser # rubocop:disable Metrics/ClassLength
|
8
|
+
def self.parse(file, root: Dir.pwd, nesting: 1)
|
9
|
+
new(file, root: root, nesting: nesting).parse
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(path, root: Dir.pwd, nesting: 1)
|
13
|
+
@path = path
|
14
|
+
@root = root
|
15
|
+
@nesting = nesting
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse
|
19
|
+
raise ::FastIgnore::GitconfigParseError if nesting >= 10
|
20
|
+
|
21
|
+
read_file(path)
|
22
|
+
return unless value
|
23
|
+
|
24
|
+
value
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :nesting
|
30
|
+
attr_reader :path
|
31
|
+
attr_reader :root
|
32
|
+
attr_accessor :value
|
33
|
+
attr_accessor :within_quotes
|
34
|
+
attr_accessor :section
|
35
|
+
|
36
|
+
def read_file(path) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
37
|
+
return unless ::File.readable?(path)
|
38
|
+
|
39
|
+
file = StringScanner.new(::File.read(path))
|
40
|
+
|
41
|
+
until file.eos?
|
42
|
+
if file.skip(/(\s+|[#;].*\n)/)
|
43
|
+
# skip
|
44
|
+
elsif file.skip(/\[core\]/i)
|
45
|
+
self.section = :core
|
46
|
+
elsif file.skip(/\[include\]/i)
|
47
|
+
self.section = :include
|
48
|
+
elsif file.skip(/\[(?i:includeif) +"/)
|
49
|
+
self.section = include_if(file) ? :include : :not_include
|
50
|
+
elsif file.skip(/\[[\w.]+( "([^\0\\"]|\\(\\{2})*"|\\{2}*)+")?\]/)
|
51
|
+
self.section = :other
|
52
|
+
elsif section == :core && file.skip(/excludesfile\s*=(\s|\\\n)*/i)
|
53
|
+
self.value = scan_value(file)
|
54
|
+
elsif section == :include && file.skip(/path\s*=(\s|\\\n)*/)
|
55
|
+
include_path = scan_value(file)
|
56
|
+
|
57
|
+
value = ::FastIgnore::GitconfigParser.parse(
|
58
|
+
::File.expand_path(include_path, ::File.dirname(path)),
|
59
|
+
root: root,
|
60
|
+
nesting: nesting + 1
|
61
|
+
)
|
62
|
+
self.value = value if value
|
63
|
+
self.section = :include
|
64
|
+
elsif file.skip(/[a-zA-Z0-9]\w*\s*([#;].*)?\n/)
|
65
|
+
nil
|
66
|
+
elsif file.skip(/[a-zA-Z0-9]\w*\s*=(\s|\\\n)*/)
|
67
|
+
skip_value(file)
|
68
|
+
else
|
69
|
+
raise ::FastIgnore::GitconfigParseError
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def scan_condition_value(file)
|
75
|
+
if file.scan(/([^\0\\\n"]|\\(\\{2})*"|\\{2}*)+(?="\])/)
|
76
|
+
value = file.matched
|
77
|
+
file.skip(/"\]/)
|
78
|
+
value
|
79
|
+
else
|
80
|
+
raise ::FastIgnore::GitconfigParseError
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def skip_condition_value(file)
|
85
|
+
raise ::FastIgnore::GitconfigParseError unless file.skip(/([^\0\\\n"]|\\(\\{2})*"|\\{2}*)+"\]/)
|
86
|
+
end
|
87
|
+
|
88
|
+
def include_if(file)
|
89
|
+
if file.skip(/onbranch:/)
|
90
|
+
on_branch?(scan_condition_value(file))
|
91
|
+
elsif file.skip(/gitdir:/)
|
92
|
+
gitdir?(scan_condition_value(file), path: path)
|
93
|
+
elsif file.skip(%r{gitdir/i:})
|
94
|
+
gitdir?(scan_condition_value(file), case_insensitive: true, path: path)
|
95
|
+
else
|
96
|
+
skip_condition_value(file)
|
97
|
+
false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_branch?(branch_pattern)
|
102
|
+
branch_pattern += '**' if branch_pattern.end_with?('/')
|
103
|
+
current_branch = ::File.readable?("#{root}/.git/HEAD") && ::File.read("#{root}/.git/HEAD").sub!(
|
104
|
+
%r{\Aref: refs/heads/}, ''
|
105
|
+
)
|
106
|
+
return unless current_branch
|
107
|
+
|
108
|
+
# goddamit git what does 'a pattern with standard globbing wildcards' mean
|
109
|
+
::File.fnmatch(branch_pattern, current_branch, ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH)
|
110
|
+
end
|
111
|
+
|
112
|
+
def gitdir?(gitdir, path:, case_insensitive: false)
|
113
|
+
gitdir += '**' if gitdir.end_with?('/')
|
114
|
+
gitdir.sub!(%r{\A~/}, ENV['HOME'] + '/')
|
115
|
+
gitdir.sub!(/\A\./, path + '/')
|
116
|
+
gitdir = "**/#{gitdir}" unless gitdir.start_with?('/')
|
117
|
+
options = ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH
|
118
|
+
options |= ::File::FNM_CASEFOLD if case_insensitive
|
119
|
+
::File.fnmatch(gitdir, ::File.join(root, '.git'), options)
|
120
|
+
end
|
121
|
+
|
122
|
+
def scan_value(file) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
123
|
+
value = +''
|
124
|
+
until file.eos?
|
125
|
+
if file.skip(/\\\n/)
|
126
|
+
# continue
|
127
|
+
elsif file.skip(/\\\\/)
|
128
|
+
value << '\\'
|
129
|
+
elsif file.skip(/\\n/)
|
130
|
+
value << "\n"
|
131
|
+
elsif file.skip(/\\t/)
|
132
|
+
value << "\t"
|
133
|
+
elsif file.skip(/\\b/)
|
134
|
+
value.chop!
|
135
|
+
elsif file.skip(/\\"/)
|
136
|
+
value << '"'
|
137
|
+
elsif file.skip(/\\/)
|
138
|
+
raise ::FastIgnore::GitconfigParseError
|
139
|
+
elsif within_quotes
|
140
|
+
if file.skip(/"/)
|
141
|
+
self.within_quotes = false
|
142
|
+
elsif file.scan(/[^"\\\n]+/)
|
143
|
+
value << file.matched
|
144
|
+
elsif file.skip(/\n/)
|
145
|
+
raise ::FastIgnore::GitconfigParseError
|
146
|
+
# :nocov:
|
147
|
+
else
|
148
|
+
raise "Unmatched #{file.rest}"
|
149
|
+
# :nocov:
|
150
|
+
end
|
151
|
+
elsif file.skip(/"/)
|
152
|
+
self.within_quotes = true
|
153
|
+
elsif file.scan(/[^;#"\s\\]+/)
|
154
|
+
value << file.matched
|
155
|
+
elsif file.skip(/\s*[;#\n]/)
|
156
|
+
break
|
157
|
+
elsif file.scan(/\s+/) # rubocop:disable Lint/DuplicateBranch
|
158
|
+
value << file.matched
|
159
|
+
# :nocov:
|
160
|
+
else
|
161
|
+
raise "Unmatched #{file.rest}"
|
162
|
+
# :nocov:
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
raise ::FastIgnore::GitconfigParseError if within_quotes
|
167
|
+
|
168
|
+
value
|
169
|
+
end
|
170
|
+
|
171
|
+
def skip_value(file) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
172
|
+
until file.eos?
|
173
|
+
if file.skip(/\\(?:\n|\\|n|t|b|")/)
|
174
|
+
nil
|
175
|
+
elsif file.skip(/\\/)
|
176
|
+
raise ::FastIgnore::GitconfigParseError
|
177
|
+
elsif within_quotes
|
178
|
+
if file.skip(/"/)
|
179
|
+
self.within_quotes = false
|
180
|
+
elsif file.skip(/[^"\\\n]+/)
|
181
|
+
nil
|
182
|
+
elsif file.scan(/\n/)
|
183
|
+
raise ::FastIgnore::GitconfigParseError
|
184
|
+
# :nocov:
|
185
|
+
else
|
186
|
+
raise "Unmatched #{file.rest}"
|
187
|
+
# :nocov:
|
188
|
+
end
|
189
|
+
elsif file.skip(/"/)
|
190
|
+
self.within_quotes = true
|
191
|
+
elsif file.skip(/[^;#"\s\\]+/) # rubocop:disable Lint/DuplicateBranch
|
192
|
+
nil
|
193
|
+
elsif file.skip(/\s*[;#\n]/)
|
194
|
+
break
|
195
|
+
elsif file.skip(/\s+/) # rubocop:disable Lint/DuplicateBranch
|
196
|
+
nil
|
197
|
+
# :nocov:
|
198
|
+
else
|
199
|
+
raise "Unmatched #{file.rest}"
|
200
|
+
# :nocov:
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
raise ::FastIgnore::GitconfigParseError if within_quotes
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -15,13 +15,13 @@ class FastIgnore
|
|
15
15
|
|
16
16
|
def gitconfig_gitignore_path(config_path)
|
17
17
|
return unless config_path
|
18
|
-
return unless ::File.
|
18
|
+
return unless ::File.readable?(config_path)
|
19
19
|
|
20
|
-
ignore_path = ::
|
20
|
+
ignore_path = ::FastIgnore::GitconfigParser.parse(config_path)
|
21
21
|
return unless ignore_path
|
22
22
|
|
23
23
|
ignore_path.strip!
|
24
|
-
return
|
24
|
+
return '' if ignore_path.empty? # don't expand path in this case
|
25
25
|
|
26
26
|
::File.expand_path(ignore_path)
|
27
27
|
end
|
data/lib/fast_ignore/version.rb
CHANGED
data/lib/fast_ignore.rb
CHANGED
@@ -4,22 +4,24 @@ require_relative './fast_ignore/backports'
|
|
4
4
|
|
5
5
|
require 'set'
|
6
6
|
require 'strscan'
|
7
|
-
require_relative './fast_ignore/rule_sets'
|
8
|
-
require_relative './fast_ignore/rule_set'
|
9
|
-
require_relative './fast_ignore/global_gitignore'
|
10
|
-
require_relative './fast_ignore/rule_builder'
|
11
|
-
require_relative './fast_ignore/gitignore_rule_builder'
|
12
|
-
require_relative './fast_ignore/gitignore_include_rule_builder'
|
13
|
-
require_relative './fast_ignore/gitignore_rule_regexp_builder'
|
14
|
-
require_relative './fast_ignore/gitignore_rule_scanner'
|
15
|
-
require_relative './fast_ignore/file_root'
|
16
|
-
require_relative './fast_ignore/rule'
|
17
|
-
require_relative './fast_ignore/unmatchable_rule'
|
18
|
-
require_relative './fast_ignore/shebang_rule'
|
19
7
|
|
20
8
|
class FastIgnore
|
21
9
|
class Error < StandardError; end
|
22
10
|
|
11
|
+
require_relative './fast_ignore/rule_sets'
|
12
|
+
require_relative './fast_ignore/rule_set'
|
13
|
+
require_relative './fast_ignore/global_gitignore'
|
14
|
+
require_relative './fast_ignore/rule_builder'
|
15
|
+
require_relative './fast_ignore/gitignore_rule_builder'
|
16
|
+
require_relative './fast_ignore/gitignore_include_rule_builder'
|
17
|
+
require_relative './fast_ignore/gitignore_rule_regexp_builder'
|
18
|
+
require_relative './fast_ignore/gitignore_rule_scanner'
|
19
|
+
require_relative './fast_ignore/file_root'
|
20
|
+
require_relative './fast_ignore/rule'
|
21
|
+
require_relative './fast_ignore/unmatchable_rule'
|
22
|
+
require_relative './fast_ignore/shebang_rule'
|
23
|
+
require_relative './fast_ignore/gitconfig_parser'
|
24
|
+
|
23
25
|
include ::Enumerable
|
24
26
|
|
25
27
|
# :nocov:
|
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.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dana Sherson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,9 @@ dependencies:
|
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 0.93.1
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '1.12'
|
90
93
|
type: :development
|
91
94
|
prerelease: false
|
92
95
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -94,6 +97,9 @@ dependencies:
|
|
94
97
|
- - ">="
|
95
98
|
- !ruby/object:Gem::Version
|
96
99
|
version: 0.93.1
|
100
|
+
- - "<"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.12'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: rubocop-rspec
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +128,20 @@ dependencies:
|
|
122
128
|
- - "~>"
|
123
129
|
- !ruby/object:Gem::Version
|
124
130
|
version: 0.18.5
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: simplecov-console
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
125
145
|
- !ruby/object:Gem::Dependency
|
126
146
|
name: spellr
|
127
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,7 +156,7 @@ dependencies:
|
|
136
156
|
- - ">="
|
137
157
|
- !ruby/object:Gem::Version
|
138
158
|
version: 0.8.3
|
139
|
-
description:
|
159
|
+
description:
|
140
160
|
email:
|
141
161
|
- robot@dana.sh
|
142
162
|
executables: []
|
@@ -149,6 +169,7 @@ files:
|
|
149
169
|
- lib/fast_ignore.rb
|
150
170
|
- lib/fast_ignore/backports.rb
|
151
171
|
- lib/fast_ignore/file_root.rb
|
172
|
+
- lib/fast_ignore/gitconfig_parser.rb
|
152
173
|
- lib/fast_ignore/gitignore_include_rule_builder.rb
|
153
174
|
- lib/fast_ignore/gitignore_rule_builder.rb
|
154
175
|
- lib/fast_ignore/gitignore_rule_regexp_builder.rb
|
@@ -168,7 +189,7 @@ metadata:
|
|
168
189
|
homepage_uri: https://github.com/robotdana/fast_ignore
|
169
190
|
source_code_uri: https://github.com/robotdana/fast_ignore
|
170
191
|
changelog_uri: https://github.com/robotdana/fast_ignore/blob/main/CHANGELOG.md
|
171
|
-
post_install_message:
|
192
|
+
post_install_message:
|
172
193
|
rdoc_options: []
|
173
194
|
require_paths:
|
174
195
|
- lib
|
@@ -183,8 +204,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
204
|
- !ruby/object:Gem::Version
|
184
205
|
version: '0'
|
185
206
|
requirements: []
|
186
|
-
rubygems_version: 3.
|
187
|
-
signing_key:
|
207
|
+
rubygems_version: 3.2.15
|
208
|
+
signing_key:
|
188
209
|
specification_version: 4
|
189
210
|
summary: Parse gitignore files, quickly
|
190
211
|
test_files: []
|