fast_ignore 0.10.1 → 0.13.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 +19 -0
- data/README.md +178 -71
- data/lib/fast_ignore.rb +43 -27
- data/lib/fast_ignore/backports.rb +56 -6
- data/lib/fast_ignore/fn_match_to_re.rb +96 -0
- data/lib/fast_ignore/rule.rb +20 -42
- data/lib/fast_ignore/rule_builder.rb +13 -14
- data/lib/fast_ignore/rule_set.rb +38 -14
- data/lib/fast_ignore/rule_set_builder.rb +73 -19
- data/lib/fast_ignore/shebang_rule.rb +62 -0
- data/lib/fast_ignore/version.rb +1 -1
- metadata +6 -23
- data/.gitignore +0 -6
- data/.leftovers.yml +0 -5
- data/.rspec +0 -3
- data/.rubocop.yml +0 -216
- data/.simplecov +0 -10
- data/.spellr.yml +0 -5
- data/.spellr_wordlists/english.txt +0 -50
- data/.spellr_wordlists/ruby.txt +0 -1
- data/.spellr_wordlists/shell.txt +0 -3
- data/.travis.yml +0 -9
- data/Gemfile +0 -9
- data/Rakefile +0 -14
- data/bin/console +0 -8
- data/bin/ls +0 -6
- data/bin/setup +0 -8
- data/bin/time +0 -18
- data/fast_ignore.gemspec +0 -41
- data/lib/fast_ignore/backports/delete_prefix_suffix.rb +0 -56
- data/lib/fast_ignore/backports/dir_each_child.rb +0 -18
@@ -2,15 +2,65 @@
|
|
2
2
|
|
3
3
|
class FastIgnore
|
4
4
|
module Backports
|
5
|
-
|
5
|
+
ruby_major, ruby_minor = RUBY_VERSION.split('.', 2)
|
6
|
+
unless ruby_major.to_i > 2 || ruby_major.to_i == 2 && ruby_minor.to_i > 5
|
7
|
+
module DirEachChild
|
8
|
+
refine ::Dir.singleton_class do
|
9
|
+
def children(path)
|
10
|
+
Dir.entries(path) - ['.', '..']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
6
14
|
|
7
|
-
|
8
|
-
|
15
|
+
module DeletePrefixSuffix
|
16
|
+
refine ::String do
|
17
|
+
# delete_prefix!(prefix) -> self or nil
|
18
|
+
# Deletes leading prefix from str, returning nil if no change was made.
|
19
|
+
#
|
20
|
+
# "hello".delete_prefix!("hel") #=> "lo"
|
21
|
+
# "hello".delete_prefix!("llo") #=> nil
|
22
|
+
def delete_prefix!(str)
|
23
|
+
return unless start_with?(str)
|
9
24
|
|
10
|
-
|
11
|
-
|
25
|
+
slice!(0..(str.length - 1))
|
26
|
+
self
|
27
|
+
end
|
12
28
|
|
13
|
-
|
29
|
+
# delete_suffix!(suffix) -> self or nil
|
30
|
+
# Deletes trailing suffix from str, returning nil if no change was made.
|
31
|
+
#
|
32
|
+
# "hello".delete_suffix!("llo") #=> "he"
|
33
|
+
# "hello".delete_suffix!("hel") #=> nil
|
34
|
+
def delete_suffix!(str)
|
35
|
+
return unless end_with?(str)
|
36
|
+
|
37
|
+
slice!(-str.length..-1)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# delete_prefix(prefix) -> new_str click to toggle source
|
42
|
+
# Returns a copy of str with leading prefix deleted.
|
43
|
+
#
|
44
|
+
# "hello".delete_prefix("hel") #=> "lo"
|
45
|
+
# "hello".delete_prefix("llo") #=> "hello"
|
46
|
+
def delete_prefix(str)
|
47
|
+
s = dup
|
48
|
+
s.delete_prefix!(str)
|
49
|
+
s
|
50
|
+
end
|
51
|
+
|
52
|
+
# delete_suffix(suffix) -> new_str
|
53
|
+
# Returns a copy of str with trailing suffix deleted.
|
54
|
+
#
|
55
|
+
# "hello".delete_suffix("llo") #=> "he"
|
56
|
+
# "hello".delete_suffix("hel") #=> "hello"
|
57
|
+
def delete_suffix(str) # leftovers:allowed
|
58
|
+
s = dup
|
59
|
+
s.delete_suffix!(str)
|
60
|
+
s
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
14
64
|
end
|
15
65
|
end
|
16
66
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FastIgnore
|
4
|
+
module FNMatchToRegex
|
5
|
+
# This doesn't look rubyish because i ported it from rust (the only rust i ever wrote that worked)
|
6
|
+
class << self
|
7
|
+
def call(pattern) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
8
|
+
re = '\\A'.dup
|
9
|
+
|
10
|
+
in_character_group = false
|
11
|
+
has_characters_in_group = false
|
12
|
+
escape_next_character = false
|
13
|
+
last_char_opened_character_group = false
|
14
|
+
negated_character_group = false
|
15
|
+
stars = 0
|
16
|
+
|
17
|
+
pattern.each_char do |char| # rubocop:disable Metrics/BlockLength
|
18
|
+
if escape_next_character
|
19
|
+
re << Regexp.escape(char)
|
20
|
+
escape_next_character = false
|
21
|
+
elsif char == '\\' # single char, just needs to be escaped
|
22
|
+
escape_next_character = true
|
23
|
+
elsif in_character_group
|
24
|
+
if char == '/'
|
25
|
+
if negated_character_group
|
26
|
+
has_characters_in_group = true
|
27
|
+
re << char
|
28
|
+
end
|
29
|
+
elsif char == '^'
|
30
|
+
if last_char_opened_character_group
|
31
|
+
re << char
|
32
|
+
negated_character_group = true
|
33
|
+
else
|
34
|
+
re << '\\^'
|
35
|
+
has_characters_in_group = true
|
36
|
+
end
|
37
|
+
# not characters in group
|
38
|
+
elsif char == ']'
|
39
|
+
break unless has_characters_in_group
|
40
|
+
|
41
|
+
re << ']'
|
42
|
+
in_character_group = false
|
43
|
+
has_characters_in_group = false
|
44
|
+
negated_character_group = false
|
45
|
+
last_char_opened_character_group = false
|
46
|
+
elsif char == '-'
|
47
|
+
has_characters_in_group = true
|
48
|
+
re << char
|
49
|
+
else
|
50
|
+
has_characters_in_group = true
|
51
|
+
re << Regexp.escape(char)
|
52
|
+
end
|
53
|
+
last_char_opened_character_group = false
|
54
|
+
elsif char == '*'
|
55
|
+
stars += 1
|
56
|
+
elsif char == '/'
|
57
|
+
re << if stars >= 2
|
58
|
+
'(?:.*/)?'
|
59
|
+
elsif stars.positive?
|
60
|
+
'[^/]*/'
|
61
|
+
else
|
62
|
+
char
|
63
|
+
end
|
64
|
+
stars = 0
|
65
|
+
else
|
66
|
+
if stars.positive?
|
67
|
+
re << '[^/]*'
|
68
|
+
stars = 0
|
69
|
+
end
|
70
|
+
if char == '?'
|
71
|
+
re << '[^/]'
|
72
|
+
elsif char == '['
|
73
|
+
re << '['
|
74
|
+
in_character_group = true
|
75
|
+
last_char_opened_character_group = true
|
76
|
+
else
|
77
|
+
re << Regexp.escape(char)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if in_character_group
|
83
|
+
return /(?!)/ # impossible to match anything
|
84
|
+
end
|
85
|
+
|
86
|
+
if stars >= 2
|
87
|
+
re << '.*'
|
88
|
+
elsif stars.positive?
|
89
|
+
re << '[^/]*'
|
90
|
+
end
|
91
|
+
re << '\\z'
|
92
|
+
Regexp.new(re, Regexp::IGNORECASE)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/fast_ignore/rule.rb
CHANGED
@@ -2,70 +2,48 @@
|
|
2
2
|
|
3
3
|
class FastIgnore
|
4
4
|
class Rule
|
5
|
-
# FNMATCH_OPTIONS = (
|
6
|
-
# ::File::FNM_DOTMATCH |
|
7
|
-
# ::File::FNM_PATHNAME |
|
8
|
-
# ::File::FNM_CASEFOLD
|
9
|
-
# ).freeze # = 14
|
10
|
-
|
11
5
|
attr_reader :negation
|
12
6
|
alias_method :negation?, :negation
|
7
|
+
undef :negation
|
13
8
|
|
14
9
|
attr_reader :dir_only
|
15
10
|
alias_method :dir_only?, :dir_only
|
16
|
-
|
17
|
-
attr_reader :shebang
|
18
|
-
alias_method :file_only?, :shebang
|
11
|
+
undef :dir_only
|
19
12
|
|
20
13
|
attr_reader :unanchored
|
21
14
|
alias_method :unanchored?, :unanchored
|
15
|
+
undef :unanchored
|
16
|
+
|
17
|
+
attr_reader :type
|
18
|
+
attr_reader :rule
|
22
19
|
|
23
|
-
def initialize(rule,
|
24
|
-
@rule = rule
|
20
|
+
def initialize(rule, negation, unanchored = nil, dir_only = nil)
|
21
|
+
@rule = rule.is_a?(Regexp) ? rule : ::FastIgnore::FNMatchToRegex.call(rule)
|
25
22
|
@unanchored = unanchored
|
26
23
|
@dir_only = dir_only
|
27
24
|
@negation = negation
|
28
|
-
|
25
|
+
|
26
|
+
@type = negation ? 1 : 0
|
29
27
|
|
30
28
|
freeze
|
31
29
|
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
if shebang
|
36
|
-
"#<Rule #{'allow ' if @negation}#!:#{@shebang.to_s[15..-4]}>"
|
37
|
-
else
|
38
|
-
"#<Rule #{'!' if @negation}#{@rule}#{'/' if @dir_only}>"
|
39
|
-
end
|
31
|
+
def file_only?
|
32
|
+
false
|
40
33
|
end
|
41
|
-
# :nocov:
|
42
34
|
|
43
|
-
def
|
44
|
-
|
45
|
-
match_shebang?(path, filename)
|
46
|
-
else
|
47
|
-
# 14 = FNMATCH_OPTIONS
|
48
|
-
::File.fnmatch?(@rule, path, 14)
|
49
|
-
end
|
35
|
+
def shebang
|
36
|
+
nil
|
50
37
|
end
|
51
38
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
first_line(path)&.match?(@shebang)
|
39
|
+
# :nocov:
|
40
|
+
def inspect
|
41
|
+
"#<Rule #{'!' if @negation}#{@rule}#{'/' if @dir_only}>"
|
56
42
|
end
|
43
|
+
# :nocov:
|
57
44
|
|
58
|
-
def
|
59
|
-
|
60
|
-
first_line = file.sysread(25)
|
61
|
-
first_line += file.sysread(50) until first_line.include?("\n")
|
62
|
-
file.close
|
63
|
-
first_line
|
64
|
-
rescue ::EOFError, ::SystemCallError
|
65
|
-
# :nocov:
|
66
|
-
file&.close
|
67
|
-
# :nocov:
|
68
|
-
first_line
|
45
|
+
def match?(relative_path, _, _, _)
|
46
|
+
@rule.match?(relative_path)
|
69
47
|
end
|
70
48
|
end
|
71
49
|
end
|
@@ -2,19 +2,15 @@
|
|
2
2
|
|
3
3
|
class FastIgnore
|
4
4
|
module RuleBuilder
|
5
|
-
# rule or nil
|
6
5
|
class << self
|
7
6
|
# :nocov:
|
8
|
-
|
9
|
-
require_relative 'backports/delete_prefix_suffix'
|
10
|
-
using ::FastIgnore::Backports::DeletePrefixSuffix
|
11
|
-
end
|
7
|
+
using ::FastIgnore::Backports::DeletePrefixSuffix if defined?(::FastIgnore::Backports::DeletePrefixSuffix)
|
12
8
|
# :nocov:
|
13
9
|
|
14
10
|
def build(rule, allow, expand_path, file_root)
|
15
|
-
strip(rule)
|
16
|
-
|
17
11
|
return shebang_rules(rule, allow) if remove_shebang(rule)
|
12
|
+
|
13
|
+
strip(rule)
|
18
14
|
return [] if skip?(rule)
|
19
15
|
|
20
16
|
gitignore_rules(rule, allow, expand_path, file_root)
|
@@ -36,7 +32,7 @@ class FastIgnore
|
|
36
32
|
end
|
37
33
|
|
38
34
|
def shebang_rules(rule, allow)
|
39
|
-
rules = [::FastIgnore::
|
35
|
+
rules = [::FastIgnore::ShebangRule.new(/\A#!.*\b#{Regexp.escape(rule)}\b/i.freeze, allow)]
|
40
36
|
return rules unless allow
|
41
37
|
|
42
38
|
rules << ::FastIgnore::Rule.new('**/*', true, true, true)
|
@@ -51,8 +47,11 @@ class FastIgnore
|
|
51
47
|
dir_only = extract_dir_only(rule)
|
52
48
|
negation = extract_negation(rule, allow)
|
53
49
|
|
54
|
-
|
55
|
-
|
50
|
+
unanchored = if expand_path
|
51
|
+
expand_rule_path(rule, expand_path)
|
52
|
+
else
|
53
|
+
unanchored?(rule)
|
54
|
+
end
|
56
55
|
rule.delete_prefix!('/')
|
57
56
|
|
58
57
|
rule.prepend("#{file_root}#{'**/' if unanchored}") if file_root || unanchored
|
@@ -74,7 +73,7 @@ class FastIgnore
|
|
74
73
|
def expand_rule_path(rule, root)
|
75
74
|
rule.replace(::File.expand_path(rule)) if rule.match?(EXPAND_PATH_RE)
|
76
75
|
rule.delete_prefix!(root)
|
77
|
-
rule.
|
76
|
+
rule.start_with?('*')
|
78
77
|
end
|
79
78
|
|
80
79
|
def unanchored?(rule)
|
@@ -82,10 +81,10 @@ class FastIgnore
|
|
82
81
|
end
|
83
82
|
|
84
83
|
def build_gitignore_rules(rule, unanchored, allow, dir_only, negation)
|
85
|
-
rules = [::FastIgnore::Rule.new(rule
|
84
|
+
rules = [::FastIgnore::Rule.new(rule, negation, unanchored, dir_only)]
|
86
85
|
return rules unless allow
|
87
86
|
|
88
|
-
rules << ::FastIgnore::Rule.new("#{rule}/**/*", unanchored, false
|
87
|
+
rules << ::FastIgnore::Rule.new("#{rule}/**/*", negation, unanchored, false)
|
89
88
|
rules + ancestor_rules(rule, unanchored)
|
90
89
|
end
|
91
90
|
|
@@ -94,7 +93,7 @@ class FastIgnore
|
|
94
93
|
|
95
94
|
while (parent = ::File.dirname(parent)) != '.'
|
96
95
|
rule = ::File.basename(parent) == '**' ? "#{parent}/*" : parent.freeze
|
97
|
-
ancestor_rules << ::FastIgnore::Rule.new(rule,
|
96
|
+
ancestor_rules << ::FastIgnore::Rule.new(rule, true, unanchored, true)
|
98
97
|
end
|
99
98
|
|
100
99
|
ancestor_rules
|
data/lib/fast_ignore/rule_set.rb
CHANGED
@@ -2,39 +2,59 @@
|
|
2
2
|
|
3
3
|
class FastIgnore
|
4
4
|
class RuleSet
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
attr_reader :gitignore
|
6
|
+
alias_method :gitignore?, :gitignore
|
7
|
+
undef :gitignore
|
8
|
+
|
9
|
+
def initialize(rules, allow, gitignore)
|
10
|
+
@dir_rules = squash_rules(rules.reject(&:file_only?)).freeze
|
11
|
+
@file_rules = squash_rules(rules.reject(&:dir_only?)).freeze
|
8
12
|
@any_not_anchored = rules.any?(&:unanchored?)
|
9
13
|
@has_shebang_rules = rules.any?(&:shebang)
|
14
|
+
|
10
15
|
@allowed_recursive = { '.' => true }
|
11
16
|
@allow = allow
|
17
|
+
@gitignore = gitignore
|
12
18
|
|
13
|
-
freeze
|
19
|
+
freeze unless gitignore?
|
14
20
|
end
|
15
21
|
|
16
|
-
def
|
17
|
-
|
18
|
-
@file_rules.freeze
|
22
|
+
def <<(other)
|
23
|
+
return unless other
|
19
24
|
|
20
|
-
|
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
|
21
29
|
end
|
22
30
|
|
23
|
-
def allowed_recursive?(
|
24
|
-
@allowed_recursive.fetch(
|
25
|
-
@allowed_recursive[
|
26
|
-
allowed_recursive?(::File.dirname(
|
31
|
+
def allowed_recursive?(relative_path, dir, full_path, filename, content = nil)
|
32
|
+
@allowed_recursive.fetch(relative_path) do
|
33
|
+
@allowed_recursive[relative_path] =
|
34
|
+
allowed_recursive?(::File.dirname(relative_path), true, nil, nil, nil) &&
|
35
|
+
allowed_unrecursive?(relative_path, dir, full_path, filename, content)
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
30
|
-
def allowed_unrecursive?(
|
39
|
+
def allowed_unrecursive?(relative_path, dir, full_path, filename, content)
|
31
40
|
(dir ? @dir_rules : @file_rules).reverse_each do |rule|
|
32
|
-
return rule.negation? if rule.match?(
|
41
|
+
return rule.negation? if rule.match?(relative_path, full_path, filename, content)
|
33
42
|
end
|
34
43
|
|
35
44
|
(not @allow) || (dir && @any_not_anchored)
|
36
45
|
end
|
37
46
|
|
47
|
+
def squash_rules(rules)
|
48
|
+
out = rules.chunk_while { |a, b| a.type == b.type }.map do |chunk|
|
49
|
+
first = chunk.first
|
50
|
+
next first if chunk.length == 1
|
51
|
+
|
52
|
+
first.class.new(Regexp.union(chunk.map(&:rule)), first.negation?)
|
53
|
+
end
|
54
|
+
|
55
|
+
out
|
56
|
+
end
|
57
|
+
|
38
58
|
def weight
|
39
59
|
@dir_rules.length + (@has_shebang_rules ? 10 : 0)
|
40
60
|
end
|
@@ -42,5 +62,9 @@ class FastIgnore
|
|
42
62
|
def empty?
|
43
63
|
@dir_rules.empty? && @file_rules.empty?
|
44
64
|
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
attr_reader :dir_rules, :file_rules, :any_not_anchored, :has_shebang_rules
|
45
69
|
end
|
46
70
|
end
|
@@ -1,20 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class FastIgnore
|
4
|
-
module RuleSetBuilder
|
4
|
+
module RuleSetBuilder # rubocop:disable Metrics/ModuleLength
|
5
5
|
class << self
|
6
6
|
# :nocov:
|
7
|
-
|
8
|
-
require_relative 'backports/delete_prefix_suffix'
|
9
|
-
using ::FastIgnore::Backports::DeletePrefixSuffix
|
10
|
-
end
|
7
|
+
using ::FastIgnore::Backports::DeletePrefixSuffix if defined?(::FastIgnore::Backports::DeletePrefixSuffix)
|
11
8
|
# :nocov:
|
12
9
|
|
13
10
|
def build( # rubocop:disable Metrics/ParameterLists
|
14
11
|
root:,
|
15
12
|
ignore_rules: nil,
|
16
13
|
ignore_files: nil,
|
17
|
-
gitignore:
|
14
|
+
gitignore: true,
|
18
15
|
include_rules: nil,
|
19
16
|
include_files: nil,
|
20
17
|
argv_rules: nil
|
@@ -22,7 +19,7 @@ class FastIgnore
|
|
22
19
|
prepare [
|
23
20
|
from_array(ignore_rules),
|
24
21
|
*from_files(ignore_files, project_root: root),
|
25
|
-
from_array('.git'),
|
22
|
+
(from_array('.git') if gitignore),
|
26
23
|
from_gitignore_arg(gitignore, project_root: root),
|
27
24
|
from_array(include_rules, allow: true),
|
28
25
|
*from_files(include_files, allow: true, project_root: root),
|
@@ -30,6 +27,19 @@ class FastIgnore
|
|
30
27
|
]
|
31
28
|
end
|
32
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
|
+
|
33
43
|
private
|
34
44
|
|
35
45
|
def prepare(rule_sets)
|
@@ -39,12 +49,15 @@ class FastIgnore
|
|
39
49
|
rule_sets
|
40
50
|
end
|
41
51
|
|
42
|
-
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
|
43
53
|
filename = ::File.expand_path(filename, project_root)
|
44
|
-
|
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
|
45
58
|
|
46
|
-
file_root
|
47
|
-
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)
|
48
61
|
end
|
49
62
|
|
50
63
|
def from_files(files, project_root:, allow: false)
|
@@ -54,12 +67,53 @@ class FastIgnore
|
|
54
67
|
end
|
55
68
|
|
56
69
|
def from_gitignore_arg(gitignore, project_root:)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
70
|
+
return unless gitignore
|
71
|
+
|
72
|
+
gi = ::FastIgnore::RuleSet.new([], false, true)
|
73
|
+
gi << from_root_gitignore_file(global_gitignore_path(root: project_root))
|
74
|
+
gi << from_root_gitignore_file(::File.join(project_root, '.git/info/exclude'))
|
75
|
+
gi << from_root_gitignore_file(::File.join(project_root, '.gitignore'))
|
76
|
+
gi
|
77
|
+
end
|
78
|
+
|
79
|
+
def from_root_gitignore_file(path)
|
80
|
+
return unless ::File.exist?(path)
|
81
|
+
|
82
|
+
build_rule_set(::File.readlines(path), false, file_root: '', gitignore: true)
|
83
|
+
end
|
84
|
+
|
85
|
+
def global_gitignore_path(root:)
|
86
|
+
gitconfig_gitignore_path(::File.expand_path('.git/config', root)) ||
|
87
|
+
gitconfig_gitignore_path(::File.expand_path('~/.gitconfig')) ||
|
88
|
+
gitconfig_gitignore_path(xdg_config_path) ||
|
89
|
+
gitconfig_gitignore_path('/etc/gitconfig') ||
|
90
|
+
default_global_gitignore_path
|
91
|
+
end
|
92
|
+
|
93
|
+
def gitconfig_gitignore_path(config_path)
|
94
|
+
return unless config_path
|
95
|
+
return unless ::File.exist?(config_path)
|
96
|
+
|
97
|
+
ignore_path = ::File.readlines(config_path).find { |l| l.sub!(/\A\s*excludesfile\s*=/, '') }
|
98
|
+
return unless ignore_path
|
99
|
+
|
100
|
+
ignore_path.strip!
|
101
|
+
return ignore_path if ignore_path.empty? # don't expand path in this case
|
102
|
+
|
103
|
+
::File.expand_path(ignore_path)
|
104
|
+
end
|
105
|
+
|
106
|
+
def xdg_config_path
|
107
|
+
return unless ENV['XDG_CONFIG_HOME'] && !ENV['XDG_CONFIG_HOME'].empty?
|
108
|
+
|
109
|
+
::File.expand_path('git/config', ENV['XDG_CONFIG_HOME'])
|
110
|
+
end
|
111
|
+
|
112
|
+
def default_global_gitignore_path
|
113
|
+
if ENV['XDG_CONFIG_HOME'] && !ENV['XDG_CONFIG_HOME'].empty?
|
114
|
+
::File.expand_path('git/ignore', ENV['XDG_CONFIG_HOME'])
|
115
|
+
else
|
116
|
+
::File.expand_path('~/.config/git/ignore')
|
63
117
|
end
|
64
118
|
end
|
65
119
|
|
@@ -75,12 +129,12 @@ class FastIgnore
|
|
75
129
|
build_rule_set(rules, allow, expand_path: expand_path)
|
76
130
|
end
|
77
131
|
|
78
|
-
def build_rule_set(rules, allow, expand_path: false, file_root: nil)
|
132
|
+
def build_rule_set(rules, allow, expand_path: false, file_root: nil, gitignore: false)
|
79
133
|
rules = rules.flat_map do |rule|
|
80
134
|
::FastIgnore::RuleBuilder.build(rule, allow, expand_path, file_root)
|
81
135
|
end
|
82
136
|
|
83
|
-
::FastIgnore::RuleSet.new(rules, allow)
|
137
|
+
::FastIgnore::RuleSet.new(rules, allow, gitignore)
|
84
138
|
end
|
85
139
|
end
|
86
140
|
end
|