fast_ignore 0.11.0 → 0.12.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/.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
|