fast_ignore 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|