fast_ignore 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.spellr_wordlists/english.txt +6 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +3 -0
- data/README.md +11 -9
- data/Rakefile +5 -1
- data/bin/ls_seconds +21 -0
- data/lib/fast_ignore.rb +31 -4
- data/lib/fast_ignore/backports.rb +2 -6
- data/lib/fast_ignore/rule_set.rb +20 -2
- data/lib/fast_ignore/rule_set_builder.rb +54 -12
- data/lib/fast_ignore/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45d98b9329a3cf9935ad9bda95f89ffcea7776c19acde46b4f758cf03bad654b
|
4
|
+
data.tar.gz: ec33228d9d25f5e82a8deed045c5dc2f1885e7fcf05779e079ab4a1460f981f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d03cc0337b2b5bb4b7f90adaeedf645e6fcc01a299c873cbdec743f2d13a7a6820c2269a4193d1723907e3f7de00ec4aa76d90a52efba9c022462edb5e129fe
|
7
|
+
data.tar.gz: 9771665b209531cd704c8603b9791755e054f5a3f72214ef43d23dfb403263f5c00f5ebe9be27b94a63503c85e35dc3d6c4293822cf93bd8ef4dc60b6b2b7715
|
@@ -11,18 +11,21 @@ enumerables
|
|
11
11
|
env
|
12
12
|
errno
|
13
13
|
esque
|
14
|
+
excludesfile
|
14
15
|
extensionless
|
15
16
|
fancyignore
|
16
17
|
filesystem
|
17
18
|
fnmatch
|
18
19
|
frotz
|
19
20
|
gemfile
|
21
|
+
gitconfig
|
20
22
|
github
|
21
23
|
gitignore
|
22
24
|
gitkeep
|
23
25
|
hashbang
|
24
26
|
includefile
|
25
27
|
janky
|
28
|
+
jruby
|
26
29
|
klass
|
27
30
|
llo
|
28
31
|
memoize
|
@@ -43,6 +46,7 @@ rvm
|
|
43
46
|
sherson
|
44
47
|
simplecov
|
45
48
|
stdin
|
49
|
+
subdir
|
46
50
|
substring
|
47
51
|
sudo
|
48
52
|
symlinks
|
@@ -53,4 +57,6 @@ unrecursive
|
|
53
57
|
upcase
|
54
58
|
usr
|
55
59
|
webpack
|
60
|
+
xconfig
|
61
|
+
xdg
|
56
62
|
zsh
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# v0.12.0
|
2
|
+
- Reads all relevant gitignore files (nested .gitignore files, global .gitignore referred to in .gitconfig, and .git/info/exclude)
|
3
|
+
|
1
4
|
# v0.11.0
|
2
5
|
- major performance improvement (use regexp rather than fnmatch)
|
3
6
|
- optionally pass directory: and content: into allowed? if these are already loaded.
|
data/README.md
CHANGED
@@ -14,12 +14,13 @@ FastIgnore.new(relative: true).sort == `git ls-files`.split("\n").sort
|
|
14
14
|
## Features
|
15
15
|
|
16
16
|
- Fast (faster than using `` `git ls-files`.split("\n") `` for small repos (because it avoids the overhead of ``` `` ```))
|
17
|
-
- Supports ruby 2.4 - 2.7
|
17
|
+
- Supports ruby 2.4 - 2.7 & jruby
|
18
18
|
- supports all gitignore rule patterns
|
19
19
|
- doesn't require git to be installed
|
20
20
|
- supports a gitignore-esque "include" patterns. (`include_rules:`/`include_files:`)
|
21
21
|
- supports an expansion of include patterns, matching expanded paths (`argv_rules:`)
|
22
22
|
- supports matching by shebang rather than filename for extensionless files: `#!:`
|
23
|
+
- in addition to .gitignore, reads .git/info/excludes and the ignore file mentioned in your ~/.gitconfig
|
23
24
|
|
24
25
|
## Installation
|
25
26
|
|
@@ -98,10 +99,12 @@ FastIgnore.new(follow_symlinks: true).to_a
|
|
98
99
|
|
99
100
|
By default, root is PWD (the current working directory)
|
100
101
|
This directory is used for:
|
101
|
-
-
|
102
|
-
-
|
102
|
+
- the location of .git/core/exclude
|
103
|
+
- the outermost directory that project .gitignore files are looked for
|
104
|
+
- the root directory for array rules starting with `/` or ending with `/**`
|
103
105
|
- and the path that relative is relative to
|
104
|
-
- which files get checked
|
106
|
+
- the ancestor of which files get checked
|
107
|
+
- the ancestor of all include_files and ignore_files
|
105
108
|
|
106
109
|
To use a different directory:
|
107
110
|
```ruby
|
@@ -111,7 +114,8 @@ FastIgnore.new(root: '../relative/path/to/root').to_a
|
|
111
114
|
|
112
115
|
### `gitignore:`
|
113
116
|
|
114
|
-
By default, the .gitignore file in root directory is loaded.
|
117
|
+
By default, the .gitignore file in the root directory is loaded, plus any .gitignore files in subdirectories, the global ignore file, and .git/info/exclude.
|
118
|
+
|
115
119
|
To not do this use
|
116
120
|
```ruby
|
117
121
|
FastIgnore.new(gitignore: false).to_a
|
@@ -124,7 +128,7 @@ FastIgnore.new(gitignore: true).to_a
|
|
124
128
|
|
125
129
|
If the gitignore file is somewhere else
|
126
130
|
```ruby
|
127
|
-
FastIgnore.new(ignore_file: '/absolute/path/to/.gitignore'
|
131
|
+
FastIgnore.new(ignore_file: '/absolute/path/to/.gitignore').to_a
|
128
132
|
```
|
129
133
|
Note that the location of the .gitignore file will affect rules beginning with `/` or ending in `/**`
|
130
134
|
|
@@ -133,7 +137,7 @@ You can specify other gitignore-style files to ignore as well.
|
|
133
137
|
Missing files will raise an `Errno::ENOENT` error.
|
134
138
|
|
135
139
|
```ruby
|
136
|
-
FastIgnore.new(ignore_files: '/
|
140
|
+
FastIgnore.new(ignore_files: 'relative/path/to/my/ignore/file').to_a
|
137
141
|
FastIgnore.new(ignore_files: ['/absolute/path/to/my/ignore/file', '/and/another']).to_a
|
138
142
|
```
|
139
143
|
|
@@ -235,8 +239,6 @@ This is not required, and if FastIgnore does have to go to the filesystem for th
|
|
235
239
|
|
236
240
|
|
237
241
|
## Known issues
|
238
|
-
- Doesn't take into account project excludes in `.git/info/exclude`
|
239
|
-
- Doesn't take into account globally ignored files in `git config core.excludesFile`.
|
240
242
|
- Doesn't know what to do if you change the current working directory inside the `FastIgnore#each` block.
|
241
243
|
So don't do that.
|
242
244
|
|
data/Rakefile
CHANGED
@@ -11,4 +11,8 @@ RSpec::Core::RakeTask.new(:spec)
|
|
11
11
|
Spellr::RakeTask.generate_task
|
12
12
|
Leftovers::RakeTask.generate_task
|
13
13
|
|
14
|
-
|
14
|
+
if RUBY_PLATFORM == 'java'
|
15
|
+
task default: :spec
|
16
|
+
else
|
17
|
+
task default: [:spec, :rubocop, :spellr, :leftovers]
|
18
|
+
end
|
data/bin/ls_seconds
ADDED
@@ -0,0 +1,21 @@
|
|
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/lib/fast_ignore.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative './fast_ignore/backports'
|
4
4
|
|
5
|
+
require 'set'
|
5
6
|
require_relative './fast_ignore/rule_set_builder'
|
6
7
|
require_relative './fast_ignore/rule_builder'
|
7
8
|
require_relative './fast_ignore/rule_set'
|
@@ -19,11 +20,13 @@ class FastIgnore
|
|
19
20
|
using ::FastIgnore::Backports::DirEachChild if defined?(::FastIgnore::Backports::DirEachChild)
|
20
21
|
# :nocov:
|
21
22
|
|
22
|
-
def initialize(relative: false, root: nil, follow_symlinks: false, **rule_set_builder_args)
|
23
|
+
def initialize(relative: false, root: nil, gitignore: :auto, follow_symlinks: false, **rule_set_builder_args)
|
23
24
|
@relative = relative
|
24
25
|
@follow_symlinks = follow_symlinks
|
26
|
+
@gitignore_enabled = gitignore
|
27
|
+
@loaded_gitignore_files = Set[''] if gitignore
|
25
28
|
@root = "#{::File.expand_path(root.to_s, Dir.pwd)}/"
|
26
|
-
@rule_sets = ::FastIgnore::RuleSetBuilder.build(root: @root, **rule_set_builder_args)
|
29
|
+
@rule_sets = ::FastIgnore::RuleSetBuilder.build(root: @root, gitignore: gitignore, **rule_set_builder_args)
|
27
30
|
|
28
31
|
freeze
|
29
32
|
end
|
@@ -43,6 +46,8 @@ class FastIgnore
|
|
43
46
|
return false if directory.nil? ? directory?(full_path) : directory
|
44
47
|
|
45
48
|
relative_path = full_path.delete_prefix(@root)
|
49
|
+
load_gitignore_recursive(relative_path) if @gitignore_enabled
|
50
|
+
|
46
51
|
filename = ::File.basename(relative_path)
|
47
52
|
|
48
53
|
@rule_sets.all? { |r| r.allowed_recursive?(relative_path, false, full_path, filename, content) }
|
@@ -61,8 +66,30 @@ class FastIgnore
|
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
64
|
-
def
|
65
|
-
|
69
|
+
def load_gitignore_recursive(path)
|
70
|
+
paths = []
|
71
|
+
while (path = ::File.dirname(path)) != '.'
|
72
|
+
paths << path
|
73
|
+
end
|
74
|
+
|
75
|
+
paths.reverse_each(&method(:load_gitignore))
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_gitignore(parent_path, soft: true)
|
79
|
+
return if @loaded_gitignore_files.include?(parent_path)
|
80
|
+
|
81
|
+
::FastIgnore::RuleSetBuilder.append_gitignore(
|
82
|
+
@rule_sets, project_root: @root, relative_path: parent_path + '.gitignore', soft: soft
|
83
|
+
)
|
84
|
+
@loaded_gitignore_files << parent_path
|
85
|
+
end
|
86
|
+
|
87
|
+
def each_recursive(parent_full_path, parent_relative_path, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
88
|
+
children = ::Dir.children(parent_full_path)
|
89
|
+
|
90
|
+
load_gitignore(parent_relative_path, soft: false) if @gitignore_enabled && children.include?('.gitignore')
|
91
|
+
|
92
|
+
children.each do |filename|
|
66
93
|
begin
|
67
94
|
full_path = parent_full_path + filename
|
68
95
|
relative_path = parent_relative_path + filename
|
@@ -6,12 +6,8 @@ class FastIgnore
|
|
6
6
|
unless ruby_major.to_i > 2 || ruby_major.to_i == 2 && ruby_minor.to_i > 5
|
7
7
|
module DirEachChild
|
8
8
|
refine ::Dir.singleton_class do
|
9
|
-
def
|
10
|
-
Dir.entries(path).
|
11
|
-
next if entry == '.' || entry == '..'
|
12
|
-
|
13
|
-
block.call entry
|
14
|
-
end
|
9
|
+
def children(path)
|
10
|
+
Dir.entries(path) - ['.', '..']
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
data/lib/fast_ignore/rule_set.rb
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
class FastIgnore
|
4
4
|
class RuleSet
|
5
|
-
|
5
|
+
attr_reader :gitignore
|
6
|
+
alias_method :gitignore?, :gitignore
|
7
|
+
undef :gitignore
|
8
|
+
|
9
|
+
def initialize(rules, allow, gitignore)
|
6
10
|
@dir_rules = squash_rules(rules.reject(&:file_only?)).freeze
|
7
11
|
@file_rules = squash_rules(rules.reject(&:dir_only?)).freeze
|
8
12
|
@any_not_anchored = rules.any?(&:unanchored?)
|
@@ -10,8 +14,18 @@ class FastIgnore
|
|
10
14
|
|
11
15
|
@allowed_recursive = { '.' => true }
|
12
16
|
@allow = allow
|
17
|
+
@gitignore = gitignore
|
18
|
+
|
19
|
+
freeze unless gitignore?
|
20
|
+
end
|
13
21
|
|
14
|
-
|
22
|
+
def <<(other)
|
23
|
+
return unless other
|
24
|
+
|
25
|
+
@any_not_anchored ||= other.any_not_anchored
|
26
|
+
@has_shebang_rules ||= other.has_shebang_rules
|
27
|
+
@dir_rules += other.dir_rules
|
28
|
+
@file_rules += other.file_rules
|
15
29
|
end
|
16
30
|
|
17
31
|
def allowed_recursive?(relative_path, dir, full_path, filename, content = nil)
|
@@ -47,5 +61,9 @@ class FastIgnore
|
|
47
61
|
def empty?
|
48
62
|
@dir_rules.empty? && @file_rules.empty?
|
49
63
|
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
attr_reader :dir_rules, :file_rules, :any_not_anchored, :has_shebang_rules
|
50
68
|
end
|
51
69
|
end
|
@@ -27,6 +27,19 @@ class FastIgnore
|
|
27
27
|
]
|
28
28
|
end
|
29
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
|
+
|
30
43
|
private
|
31
44
|
|
32
45
|
def prepare(rule_sets)
|
@@ -36,12 +49,15 @@ class FastIgnore
|
|
36
49
|
rule_sets
|
37
50
|
end
|
38
51
|
|
39
|
-
def from_file(filename, project_root:, allow: false)
|
52
|
+
def from_file(filename, project_root:, allow: false, file_root: nil, gitignore: false, soft: false) # rubocop:disable Metrics/ParameterLists
|
40
53
|
filename = ::File.expand_path(filename, project_root)
|
41
|
-
|
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
|
42
58
|
|
43
|
-
file_root
|
44
|
-
build_rule_set(::File.readlines(filename), allow, file_root: file_root)
|
59
|
+
file_root ||= "#{::File.dirname(filename)}/".delete_prefix(project_root)
|
60
|
+
build_rule_set(::File.readlines(filename), allow, file_root: file_root, gitignore: gitignore)
|
45
61
|
end
|
46
62
|
|
47
63
|
def from_files(files, project_root:, allow: false)
|
@@ -51,12 +67,38 @@ class FastIgnore
|
|
51
67
|
end
|
52
68
|
|
53
69
|
def from_gitignore_arg(gitignore, project_root:)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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')
|
60
102
|
end
|
61
103
|
end
|
62
104
|
|
@@ -72,12 +114,12 @@ class FastIgnore
|
|
72
114
|
build_rule_set(rules, allow, expand_path: expand_path)
|
73
115
|
end
|
74
116
|
|
75
|
-
def build_rule_set(rules, allow, expand_path: false, file_root: nil)
|
117
|
+
def build_rule_set(rules, allow, expand_path: false, file_root: nil, gitignore: false)
|
76
118
|
rules = rules.flat_map do |rule|
|
77
119
|
::FastIgnore::RuleBuilder.build(rule, allow, expand_path, file_root)
|
78
120
|
end
|
79
121
|
|
80
|
-
::FastIgnore::RuleSet.new(rules, allow)
|
122
|
+
::FastIgnore::RuleSet.new(rules, allow, gitignore)
|
81
123
|
end
|
82
124
|
end
|
83
125
|
end
|
data/lib/fast_ignore/version.rb
CHANGED
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.12.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-05-
|
11
|
+
date: 2020-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- Rakefile
|
161
161
|
- bin/console
|
162
162
|
- bin/ls
|
163
|
+
- bin/ls_seconds
|
163
164
|
- bin/setup
|
164
165
|
- bin/time
|
165
166
|
- fast_ignore.gemspec
|