fast_ignore 0.5.2 → 0.6.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/.rubocop.yml +4 -0
- data/CHANGELOG.md +8 -0
- data/README.md +32 -2
- data/bin/ls +1 -1
- data/bin/ls-disable-gems +6 -0
- data/lib/fast_ignore/backports.rb +16 -0
- data/lib/fast_ignore/rule_parser.rb +13 -20
- data/lib/fast_ignore/rule_set.rb +6 -18
- data/lib/fast_ignore/rule_set_builder.rb +69 -18
- data/lib/fast_ignore/version.rb +1 -1
- data/lib/fast_ignore.rb +34 -34
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85adcabd5164bc3c1cf44af50ff5565b8ce00d6c69f8145eab0634fbaef551fb
|
4
|
+
data.tar.gz: de0192432d8423e5fee408aa7d3a052bc008d96b5cacadf7d2d6b66da3527030
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8507d8f07c51e0cb2b00a0ea619683bc41ca85b0a89d7e4787f5b0aa9157d255ec261a4ffab130982c89f1c85b4a0dd5f7030bb18de20186362eaf894b816b65
|
7
|
+
data.tar.gz: 661628a1913544cc67d1833ddb84218db6b85de165ba11fb39dd1f62c014638b9fd72d8f3efe0bc8ce2f1379acf43a63a2bedf016e9ff5927d400e8c4932a57c
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# v0.6.0
|
2
|
+
- nicer argv handling
|
3
|
+
- add `argv_rules:` option, which resolves paths and considers everything that doesn't start with a `*` to start with a `/`
|
4
|
+
- combine the different includes methods and files using AND
|
5
|
+
- slightly more realistic version comparison just in case someone releases ruby 2.10
|
6
|
+
- can be run with --disable-gems
|
7
|
+
- `.allowed?` now more exactly matches `.each`, it returns false for directories and unreadable files.
|
8
|
+
|
1
9
|
# v0.5.2
|
2
10
|
- performance improvements
|
3
11
|
|
data/README.md
CHANGED
@@ -66,6 +66,11 @@ FastIgnore.new(gitignore: '/absolute/path/to/.gitignore').to_a
|
|
66
66
|
```
|
67
67
|
Note that the location of the .gitignore file will affect rules beginning with `/` or ending in `/**`
|
68
68
|
|
69
|
+
To raise if the gitignore file is not found use:
|
70
|
+
```ruby
|
71
|
+
FastIgnore.new(gitignore: true)
|
72
|
+
```
|
73
|
+
|
69
74
|
To check if a single file is allowed, use
|
70
75
|
```ruby
|
71
76
|
FastIgnore.new.allowed?('relative/path')
|
@@ -78,7 +83,7 @@ FastIgnore.new.allowed?('~/home/path')
|
|
78
83
|
|
79
84
|
Building on the gitignore format, FastIgnore also accepts a list of allowed or included files.
|
80
85
|
|
81
|
-
```
|
86
|
+
```gitignore
|
82
87
|
# a line like this means any files named foo will be included
|
83
88
|
# as well as any files within directories named foo
|
84
89
|
foo
|
@@ -98,7 +103,32 @@ FastIgnore.new(include_files: '/absolute/path/to/my/include/file', gitignore: fa
|
|
98
103
|
FastIgnore.new(include_rules: %w{my*rule /and/another !rule}, gitignore: false)
|
99
104
|
```
|
100
105
|
|
101
|
-
|
106
|
+
There is an additional argument meant for dealing with humans and `ARGV` values.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
FastIgnore.new(argv_rules: ['./a/pasted/path', '/or/a/path/from/stdin', 'an/argument', '*.txt'])
|
110
|
+
```
|
111
|
+
|
112
|
+
It resolves absolute paths, and paths beginning with `~`, `../` and `./` (with and without `!`)
|
113
|
+
It assumes all rules are anchored unless they begin with `*` or `!*`.
|
114
|
+
|
115
|
+
Note: it will *not* resolve e.g. `/../` in the middle of a rule that doesn't begin with any of `~`,`../`,`./`,`/`.
|
116
|
+
|
117
|
+
## Combinations
|
118
|
+
|
119
|
+
In the simplest case a file must be allowed by each ignore file, each include file, and each array of rules. That is, they are combined using AND.
|
120
|
+
|
121
|
+
To combine files using `OR`, that is, a file may be included by either file it doesn't have to be referred to in both:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
FastIgnore.new(include_files: StringIO.new([File.read('/my/path'), File.read('/another/path')]).join("\n"))
|
125
|
+
```
|
126
|
+
|
127
|
+
To use the additional ARGV handling rules mentioned above for files
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
FastIgnore.new(include_rules: ["my/rule", File.read('/my/path')])
|
131
|
+
```
|
102
132
|
|
103
133
|
## Known issues
|
104
134
|
- Doesn't take into account project excludes in `.git/info/exclude`
|
data/bin/ls
CHANGED
data/bin/ls-disable-gems
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FastIgnore
|
4
|
+
module Backports
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def ruby_version_less_than?(major, minor)
|
8
|
+
ruby_major, ruby_minor = RUBY_VERSION.split('.', 2)
|
9
|
+
|
10
|
+
return true if major > ruby_major.to_i
|
11
|
+
return true if minor > ruby_minor.to_i
|
12
|
+
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'rule'
|
4
|
+
require_relative 'backports'
|
4
5
|
|
5
6
|
class FastIgnore
|
6
7
|
class RuleParser
|
7
|
-
|
8
|
-
require_relative 'backports/match'
|
9
|
-
using ::FastIgnore::Backports::Match
|
10
|
-
end
|
11
|
-
|
12
|
-
unless ::RUBY_VERSION >= '2.5'
|
8
|
+
if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
|
13
9
|
require_relative 'backports/delete_prefix_suffix'
|
14
10
|
using ::FastIgnore::Backports::DeletePrefixSuffix
|
11
|
+
|
12
|
+
if ::FastIgnore::Backports.ruby_version_less_than?(2, 4)
|
13
|
+
require_relative 'backports/match'
|
14
|
+
using ::FastIgnore::Backports::Match
|
15
|
+
end
|
15
16
|
end
|
16
17
|
|
17
18
|
# rule or nil
|
@@ -19,11 +20,11 @@ class FastIgnore
|
|
19
20
|
def new_rule(rule, root:, rule_set:, allow: false, expand_path: false) # rubocop:disable Metrics/MethodLength
|
20
21
|
rule = strip(rule)
|
21
22
|
rule, dir_only = extract_dir_only(rule)
|
22
|
-
rule = expand_path(rule, root) if expand_path
|
23
23
|
|
24
24
|
return if skip?(rule)
|
25
25
|
|
26
26
|
rule, negation = extract_negation(rule, allow)
|
27
|
+
rule = expand_path(rule, root) if expand_path
|
27
28
|
|
28
29
|
anchored, prefix = prefix(rule)
|
29
30
|
|
@@ -79,23 +80,15 @@ class FastIgnore
|
|
79
80
|
end
|
80
81
|
|
81
82
|
def expand_path(rule, root)
|
82
|
-
if rule.match?(%r{^(?:[~/]|\.{1,2}/)})
|
83
|
-
::File.expand_path(rule).delete_prefix(root)
|
84
|
-
else
|
85
|
-
rule
|
86
|
-
end
|
87
|
-
end
|
83
|
+
rule = ::File.expand_path(rule).delete_prefix(root) if rule.match?(%r{^(?:[~/]|\.{1,2}/)})
|
88
84
|
|
89
|
-
|
90
|
-
empty?(rule) || comment?(rule)
|
91
|
-
end
|
85
|
+
rule = "/#{rule}" unless rule.start_with?('*') || rule.start_with?('/')
|
92
86
|
|
93
|
-
|
94
|
-
rule.empty?
|
87
|
+
rule
|
95
88
|
end
|
96
89
|
|
97
|
-
def
|
98
|
-
rule.start_with?('#')
|
90
|
+
def skip?(rule)
|
91
|
+
rule.empty? || rule.start_with?('#')
|
99
92
|
end
|
100
93
|
end
|
101
94
|
end
|
data/lib/fast_ignore/rule_set.rb
CHANGED
@@ -12,8 +12,8 @@ class FastIgnore
|
|
12
12
|
@project_root = project_root
|
13
13
|
|
14
14
|
@any_not_anchored = false
|
15
|
-
@empty = true
|
16
15
|
@allow = allow
|
16
|
+
@default = true unless allow
|
17
17
|
end
|
18
18
|
|
19
19
|
def allowed_recursive?(path, dir)
|
@@ -30,35 +30,23 @@ class FastIgnore
|
|
30
30
|
return rule.negation? if ::File.fnmatch?(rule.rule, path, 14)
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def parse_rules(rule_line, root: @root, expand_path: false)
|
37
|
-
::FastIgnore::RuleParser.new_rule(rule_line, rule_set: self, allow: @allow, root: root, expand_path: expand_path)
|
33
|
+
(not @allow) || (@any_not_anchored if dir)
|
38
34
|
end
|
39
35
|
|
40
36
|
def append_rules(anchored, rules)
|
41
37
|
rules.each do |rule|
|
42
|
-
@empty = false
|
43
38
|
@rules << rule
|
44
39
|
@non_dir_only_rules << rule unless rule.dir_only?
|
45
40
|
@any_not_anchored ||= !anchored
|
46
41
|
end
|
47
42
|
end
|
48
43
|
|
49
|
-
def
|
50
|
-
@
|
44
|
+
def length
|
45
|
+
@rules.length
|
51
46
|
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
def default?(dir)
|
56
|
-
return true unless @allow
|
57
|
-
return true if @empty
|
58
|
-
return false unless dir
|
59
|
-
return true if @any_not_anchored
|
60
|
-
|
61
|
-
false
|
48
|
+
def empty?
|
49
|
+
@rules.empty?
|
62
50
|
end
|
63
51
|
end
|
64
52
|
end
|
@@ -1,37 +1,88 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'rule_set'
|
4
|
+
require_relative 'rule_parser'
|
4
5
|
|
5
6
|
class FastIgnore
|
6
7
|
class RuleSetBuilder
|
7
|
-
|
8
|
+
def self.from_args( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
9
|
+
root: Dir.pwd,
|
10
|
+
ignore_rules: nil,
|
11
|
+
ignore_files: nil,
|
12
|
+
gitignore: :auto,
|
13
|
+
include_rules: nil,
|
14
|
+
include_files: nil,
|
15
|
+
argv_rules: nil
|
16
|
+
)
|
17
|
+
rule_sets = [
|
18
|
+
from_array(ignore_rules, root: root),
|
19
|
+
*from_files(ignore_files, project_root: root),
|
20
|
+
from_array('.git', root: root),
|
21
|
+
from_gitignore_arg(gitignore, root: root),
|
22
|
+
from_array(include_rules, root: root, allow: true),
|
23
|
+
*from_files(include_files, allow: true, project_root: root),
|
24
|
+
from_array(argv_rules, root: root, allow: true, expand_path: true)
|
25
|
+
]
|
8
26
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
27
|
+
rule_sets.compact!
|
28
|
+
rule_sets.reject!(&:empty?)
|
29
|
+
rule_sets.sort_by!(&:length)
|
30
|
+
rule_sets
|
13
31
|
end
|
14
32
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
33
|
+
def self.from_file(filename, allow: false, project_root: Dir.pwd)
|
34
|
+
filename = ::File.expand_path(filename)
|
35
|
+
root = ::File.dirname(filename)
|
36
|
+
rule_set = ::FastIgnore::RuleSet.new(project_root: project_root, allow: allow)
|
37
|
+
|
38
|
+
::IO.foreach(filename) do |rule_string|
|
39
|
+
parse_rules(rule_string, allow: allow, rule_set: rule_set, root: root)
|
20
40
|
end
|
21
41
|
|
22
|
-
|
42
|
+
rule_set
|
23
43
|
end
|
24
44
|
|
25
|
-
def
|
26
|
-
files.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
45
|
+
def self.from_files(files, allow: false, project_root: Dir.pwd)
|
46
|
+
Array(files).map do |file|
|
47
|
+
from_file(file, allow: allow, project_root: project_root)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.from_gitignore_arg(gitignore, root: Dir.pwd) # rubocop:disable Metrics/MethodLength
|
52
|
+
default_path = ::File.join(root, '.gitignore')
|
53
|
+
case gitignore
|
54
|
+
when :auto
|
55
|
+
from_file(default_path, project_root: root) if ::File.exist?(default_path)
|
56
|
+
when true
|
57
|
+
from_file(default_path, project_root: root)
|
58
|
+
when false
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
from_file(gitignore, project_root: root)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.from_array(rules, allow: false, expand_path: false, root: Dir.pwd)
|
66
|
+
rules = Array(rules)
|
67
|
+
return if rules.empty?
|
68
|
+
|
69
|
+
rule_set = ::FastIgnore::RuleSet.new(project_root: root, allow: allow)
|
70
|
+
|
71
|
+
rules.each_with_object(rule_set) do |rule_string, set|
|
72
|
+
rule_string.each_line do |rule_line|
|
73
|
+
parse_rules(rule_line, rule_set: set, allow: allow, root: root, expand_path: expand_path)
|
31
74
|
end
|
32
75
|
end
|
76
|
+
end
|
33
77
|
|
34
|
-
|
78
|
+
def self.parse_rules(rule_line, rule_set:, allow: false, root: Dir.pwd, expand_path: false)
|
79
|
+
::FastIgnore::RuleParser.new_rule(
|
80
|
+
rule_line,
|
81
|
+
rule_set: rule_set,
|
82
|
+
allow: allow,
|
83
|
+
root: root,
|
84
|
+
expand_path: expand_path
|
85
|
+
)
|
35
86
|
end
|
36
87
|
end
|
37
88
|
end
|
data/lib/fast_ignore/version.rb
CHANGED
data/lib/fast_ignore.rb
CHANGED
@@ -1,69 +1,63 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './fast_ignore/rule_set_builder'
|
4
|
+
require_relative './fast_ignore/backports'
|
4
5
|
|
5
6
|
class FastIgnore
|
6
7
|
include ::Enumerable
|
7
8
|
|
8
|
-
|
9
|
+
if ::FastIgnore::Backports.ruby_version_less_than?(2, 5)
|
9
10
|
require_relative 'fast_ignore/backports/delete_prefix_suffix'
|
10
11
|
using ::FastIgnore::Backports::DeletePrefixSuffix
|
11
|
-
end
|
12
12
|
|
13
|
-
unless ::RUBY_VERSION >= '2.5'
|
14
13
|
require_relative 'fast_ignore/backports/dir_each_child'
|
15
14
|
using ::FastIgnore::Backports::DirEachChild
|
16
15
|
end
|
17
16
|
|
18
|
-
def initialize( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
17
|
+
def initialize( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
19
18
|
relative: false,
|
20
19
|
root: ::Dir.pwd,
|
21
20
|
ignore_rules: nil,
|
22
21
|
ignore_files: nil,
|
23
|
-
gitignore:
|
22
|
+
gitignore: :auto,
|
24
23
|
include_rules: nil,
|
25
|
-
include_files: nil
|
24
|
+
include_files: nil,
|
25
|
+
argv_rules: nil
|
26
26
|
)
|
27
27
|
@root = root.delete_suffix('/')
|
28
28
|
@root_trailing_slash = "#{@root}/"
|
29
|
-
ignore = ::FastIgnore::RuleSetBuilder.new(root: @root)
|
30
|
-
only = ::FastIgnore::RuleSetBuilder.new(allow: true, root: @root)
|
31
|
-
only.add_files(Array(include_files))
|
32
|
-
only.add_rules(Array(include_rules), expand_path: true)
|
33
|
-
@only = only.rule_set
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
@rule_sets = ::FastIgnore::RuleSetBuilder.from_args(
|
31
|
+
root: @root,
|
32
|
+
ignore_rules: ignore_rules,
|
33
|
+
ignore_files: ignore_files,
|
34
|
+
gitignore: gitignore,
|
35
|
+
include_rules: include_rules,
|
36
|
+
include_files: include_files,
|
37
|
+
argv_rules: argv_rules
|
38
|
+
)
|
39
|
+
|
40
40
|
@relative = relative
|
41
41
|
end
|
42
42
|
|
43
43
|
def each(&block)
|
44
44
|
if block_given?
|
45
|
-
|
45
|
+
each_allowed(&block)
|
46
46
|
else
|
47
|
-
enum_for(:
|
47
|
+
enum_for(:each_allowed)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
def allowed?(path)
|
52
52
|
path = ::File.expand_path(path)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
def all_allowed
|
58
|
-
find_children(@root_trailing_slash) do |path, dir|
|
59
|
-
next false unless @ignore.allowed_unrecursive?(path, dir)
|
60
|
-
next false unless @only.allowed_unrecursive?(path, dir)
|
61
|
-
next true if dir
|
53
|
+
stat = ::File.stat(path)
|
54
|
+
dir = stat.directory?
|
55
|
+
return false unless stat.readable?
|
56
|
+
return false if dir
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
58
|
+
@rule_sets.all? { |r| r.allowed_recursive?(path, dir) }
|
59
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
60
|
+
false
|
67
61
|
end
|
68
62
|
|
69
63
|
private
|
@@ -72,15 +66,21 @@ class FastIgnore
|
|
72
66
|
@relative ? path.delete_prefix(@root_trailing_slash) : path
|
73
67
|
end
|
74
68
|
|
75
|
-
def
|
69
|
+
def each_allowed(path = @root_trailing_slash, &block) # rubocop:disable Metrics/MethodLength
|
76
70
|
Dir.each_child(path) do |child|
|
77
71
|
begin
|
78
72
|
child = path + child
|
79
73
|
stat = ::File.stat(child)
|
80
74
|
next unless stat.readable?
|
81
75
|
|
82
|
-
|
83
|
-
|
76
|
+
dir = stat.directory?
|
77
|
+
next unless @rule_sets.all? { |r| r.allowed_unrecursive?(child, dir) }
|
78
|
+
|
79
|
+
if dir
|
80
|
+
each_allowed("#{child}/", &block)
|
81
|
+
else
|
82
|
+
yield prepare_path(child)
|
83
|
+
end
|
84
84
|
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
85
85
|
nil
|
86
86
|
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.
|
4
|
+
version: 0.6.0
|
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-02-
|
11
|
+
date: 2020-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -112,9 +112,11 @@ files:
|
|
112
112
|
- Rakefile
|
113
113
|
- bin/console
|
114
114
|
- bin/ls
|
115
|
+
- bin/ls-disable-gems
|
115
116
|
- bin/setup
|
116
117
|
- fast_ignore.gemspec
|
117
118
|
- lib/fast_ignore.rb
|
119
|
+
- lib/fast_ignore/backports.rb
|
118
120
|
- lib/fast_ignore/backports/delete_prefix_suffix.rb
|
119
121
|
- lib/fast_ignore/backports/dir_each_child.rb
|
120
122
|
- lib/fast_ignore/backports/match.rb
|