File: gitignorespec_spec.rb

package info (click to toggle)
ruby-pathspec 1.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 224 kB
  • sloc: ruby: 861; sh: 21; makefile: 8
file content (303 lines) | stat: -rw-r--r-- 12,204 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
require 'spec_helper'
require 'pathspec/gitignorespec'

describe PathSpec::GitIgnoreSpec do
  # Original specification by http://git-scm.com/docs/gitignore

  # A blank line matches no files, so it can serve as a separator for
  # readability.
  describe 'does nothing for newlines' do
    subject { PathSpec::GitIgnoreSpec.new "\n" }
    it { is_expected.to_not match('foo.tmp') }
    it { is_expected.to_not match(' ') }
    it { is_expected.to_not be_inclusive }
  end

  describe 'does nothing for blank strings' do
    subject { PathSpec::GitIgnoreSpec.new '' }
    it { is_expected.to_not match 'foo.tmp' }
    it { is_expected.to_not match ' ' }
    it { is_expected.to_not be_inclusive }
  end

  # A line starting with # serves as a comment. Put a backslash ("\") in front
  # of the first hash for patterns that begin with a hash.
  describe 'does nothing for comments' do
    subject { PathSpec::GitIgnoreSpec.new '# this is a gitignore style comment' }
    it { is_expected.to_not match('foo.tmp') }
    it { is_expected.to_not match(' ') }
    it { is_expected.to_not be_inclusive }
  end

  describe 'ignores comment char with a slash' do
    subject { PathSpec::GitIgnoreSpec.new '\#averystrangefile' }
    it { is_expected.to match('#averystrangefile') }
    it { is_expected.to_not match('foobar') }
    it { is_expected.to be_inclusive }
  end

  describe 'escapes characters with slashes' do
    subject { PathSpec::GitIgnoreSpec.new 'twinkletwinkle\*' }
    it { is_expected.to match('twinkletwinkle*') }
    it { is_expected.to_not match('twinkletwinkletwinkle') }
    it { is_expected.to be_inclusive }
  end

  # Trailing spaces are ignored unless they are quoted with backlash ("\").
  describe 'ignores trailing spaces' do
    subject { PathSpec::GitIgnoreSpec.new 'foo        ' }
    it { is_expected.to match('foo') }
    it { is_expected.to_not match('foo        ') }
    it { is_expected.to be_inclusive }
  end

  # This is not handled properly yet
  describe 'does not ignore escaped trailing spaces'

  # An optional prefix "!" which negates the pattern; any matching file excluded
  # by a previous pattern will become included again. It is not possible to
  # re-include a file if a parent directory of that file is excluded. Git
  # doesn't list excluded directories for performance reasons, so any patterns
  # on contained files have no effect, no matter where they are defined. Put a
  # backslash ("\") in front of the first "!" for patterns that begin with a
  # literal "!", for example, "\!important!.txt".
  describe 'is exclusive of !' do
    subject { PathSpec::GitIgnoreSpec.new '!important.txt' }
    it { is_expected.to match('important.txt') }
    it { is_expected.to_not be_inclusive }
    it { is_expected.to_not match('!important.txt') }
  end

  # If the pattern ends with a slash, it is removed for the purpose of the
  # following description, but it would only find a match with a directory. In
  # other words, foo/ will match a directory foo and paths underneath it, but
  # will not match a regular file or a symbolic link foo (this is consistent
  # with the way how pathspec works in general in Git).
  describe 'trailing slashes match directories and their contents but not regular files or symlinks' do
    subject { PathSpec::GitIgnoreSpec.new 'foo/' }
    it { is_expected.to match('foo/') }
    it { is_expected.to match('foo/bar') }
    it { is_expected.to match('baz/foo/bar') }
    it { is_expected.to_not match('foo') }
    it { is_expected.to be_inclusive }
  end

  # If the pattern does not contain a slash '/', Git treats it as a shell glob
  # pattern and checks for a match against the pathname relative to the location
  # of the .gitignore file (relative to the toplevel of the work tree if not
  # from a .gitignore file).
  describe 'handles basic globbing' do
    subject { PathSpec::GitIgnoreSpec.new '*.tmp' }
    it { is_expected.to match('foo.tmp') }
    it { is_expected.to match('foo/bar.tmp') }
    it { is_expected.to match('foo/bar.tmp/baz') }
    it { is_expected.to_not match('foo.rb') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles inner globs' do
    subject { PathSpec::GitIgnoreSpec.new 'foo-*-bar' }
    it { is_expected.to match('foo--bar') }
    it { is_expected.to match('foo-hello-bar') }
    it { is_expected.to match('a/foo-hello-bar') }
    it { is_expected.to match('foo-hello-bar/b') }
    it { is_expected.to match('a/foo-hello-bar/b') }
    it { is_expected.to_not match('foo.tmp') }
  end

  describe 'handles postfix globs' do
    subject { PathSpec::GitIgnoreSpec.new '~temp-*' }
    it { is_expected.to match('~temp-') }
    it { is_expected.to match('~temp-foo') }
    it { is_expected.to match('foo/~temp-bar') }
    it { is_expected.to match('foo/~temp-bar/baz') }
    it { is_expected.to_not match('~temp') }
  end

  describe 'handles multiple globs' do
    subject { PathSpec::GitIgnoreSpec.new '*.middle.*' }
    it { is_expected.to match('hello.middle.rb') }
    it { is_expected.to_not match('foo.rb') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles dir globs' do
    subject { PathSpec::GitIgnoreSpec.new 'dir/*' }
    it { is_expected.to match('dir/foo') }
    it { is_expected.to_not match('foo/') }
    it { is_expected.to be_inclusive }
  end

  # Otherwise, Git treats the pattern as a shell glob suitable for consumption
  # by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not
  # match a / in the pathname. For example, "Documentation/*.html" matches
  # "Documentation/git.html" but not "Documentation/ppc/ppc.html" or
  # "tools/perf/Documentation/perf.html".
  describe 'handles dir globs' do
    subject { PathSpec::GitIgnoreSpec.new 'dir/*' }
    it { is_expected.to match('dir/foo') }
    it { is_expected.to_not match('foo/') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles globs inside of dirs' do
    subject { PathSpec::GitIgnoreSpec.new 'Documentation/*.html' }
    it { is_expected.to match('Documentation/git.html') }
    it { is_expected.to_not match('Documentation/ppc/ppc.html') }
    it { is_expected.to_not match('tools/perf/Documentation/perf.html') } # TODO: Or is it? Git 2 weirdness?
    it { is_expected.to be_inclusive }
  end

  describe 'handles wildcards' do
    subject { PathSpec::GitIgnoreSpec.new 'jokeris????' }
    it { is_expected.to match('jokeriswild') }
    it { is_expected.to_not match('jokerisfat') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles brackets' do
    subject { PathSpec::GitIgnoreSpec.new '*[eu][xl]*' }
    it { is_expected.to match('youknowregex') }
    it { is_expected.to match('youknowregularexpressions') }
    it { is_expected.to_not match('youknownothing') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles unmatched brackets' do
    subject { PathSpec::GitIgnoreSpec.new '*[*[*' }
    it { is_expected.to match('bracket[oh[wow') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles brackets with carats' do
    subject { PathSpec::GitIgnoreSpec.new '*[^]' }
    it { is_expected.to match('myfavorite^') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles brackets for brackets' do
    subject { PathSpec::GitIgnoreSpec.new '*[]]' }
    it { is_expected.to match('yodawg[]]') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles brackets with escaped characters' do
    # subject { GitIgnoreSpec.new 'back[\\]slash' }
    # it { is_expected.to match('back\\slash') }
    # it { is_expected.to_not match('back\\\\slash') }
    # it { is_expected.to be_inclusive }
  end

  describe 'handles negated brackets' do
    subject { PathSpec::GitIgnoreSpec.new 'ab[!cd]ef' }
    it { is_expected.to_not match('abcef') }
    it { is_expected.to match('abzef') }
    it { is_expected.to be_inclusive }
  end

  # A leading slash matches the beginning of the pathname. For example, "/*.c"
  # matches "cat-file.c" but not "mozilla-sha1/sha1.c".
  describe 'handles leading / as relative to base directory' do
    subject { PathSpec::GitIgnoreSpec.new '/*.c' }
    it { is_expected.to match('cat-file.c') }
    it { is_expected.to_not match('mozilla-sha1/sha1.c') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles simple single paths' do
    subject { PathSpec::GitIgnoreSpec.new 'spam' }
    it { is_expected.to match('spam') }
    it { is_expected.to match('spam/') }
    it { is_expected.to match('foo/spam') }
    it { is_expected.to match('spam/foo') }
    it { is_expected.to match('foo/spam/bar') }
    it { is_expected.to_not match('foo') }
  end

  # Two consecutive asterisks ("**") in patterns matched against full pathname
  # may have special meaning:

  # A leading "**" followed by a slash means match in all directories. For
  # example, "**/foo" matches file or directory "foo" anywhere, the same as
  # pattern "foo". "**/foo/bar" matches file or directory "bar" anywhere that is
  # directly under directory "foo".
  describe 'handles prefixed ** as searching any location' do
    subject { PathSpec::GitIgnoreSpec.new '**/foo' }
    it { is_expected.to match('foo') }
    it { is_expected.to match('bar/foo') }
    it { is_expected.to match('baz/bar/foo') }
    it { is_expected.to_not match('baz/bar/foo.rb') }
    it { is_expected.to be_inclusive }
  end

  describe 'handles prefixed ** with a directory as searching a file under a directory in any location' do
    subject { PathSpec::GitIgnoreSpec.new '**/foo/bar' }
    it { is_expected.to_not match('foo') }
    it { is_expected.to match('foo/bar') }
    it { is_expected.to match('baz/foo/bar') }
    it { is_expected.to match('baz/foo/bar/sub') }
    it { is_expected.to_not match('baz/foo/bar.rb') }
    it { is_expected.to_not match('baz/bananafoo/bar') }
    it { is_expected.to be_inclusive }
  end

  # A trailing "/**" matches everything inside. For example, "abc/**" matches
  # all files inside directory "abc", relative to the location of the .gitignore
  # file, with infinite depth.
  describe 'handles leading /** as all files inside a directory' do
    subject { PathSpec::GitIgnoreSpec.new 'abc/**' }
    it { is_expected.to match('abc/') }
    it { is_expected.to match('abc/def') }
    it { is_expected.to_not match('123/abc/def') }
    it { is_expected.to_not match('123/456/abc/') }
    it { is_expected.to be_inclusive }
  end

  # A slash followed by two consecutive asterisks then a slash matches zero or
  # more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b"
  # and so on.
  describe 'handles /** in the middle of a path' do
    subject { PathSpec::GitIgnoreSpec.new 'a/**/b' }
    it { is_expected.to match('a/b') }
    it { is_expected.to match('a/x/b') }
    it { is_expected.to match('a/x/y/b') }
    it { is_expected.to_not match('123/a/b') }
    it { is_expected.to_not match('123/a/x/b') }
    it { is_expected.to be_inclusive }
  end

  describe 'matches all paths when given **' do
    subject { PathSpec::GitIgnoreSpec.new '**' }

    it { is_expected.to match('a/b') }
    it { is_expected.to match('a/x/b') }
    it { is_expected.to match('a/x/y/b') }
    it { is_expected.to match('123/a/b') }
    it { is_expected.to match('123/a/x/b') }
  end

  # Other consecutive asterisks are considered invalid.
  describe 'considers other consecutive asterisks invalid' do
    subject { PathSpec::GitIgnoreSpec.new 'a/***/b' }
    it { is_expected.to_not match('a/b') }
    it { is_expected.to_not match('a/x/b') }
    it { is_expected.to_not match('a/x/y/b') }
    it { is_expected.to_not match('123/a/b') }
    it { is_expected.to_not match('123/a/x/b') }
    it { is_expected.to_not be_inclusive }
  end

  describe 'does not match single absolute paths' do
    subject { PathSpec::GitIgnoreSpec.new '/' }
    it { is_expected.to_not match('foo.tmp') }
    it { is_expected.to_not match(' ') }
    it { is_expected.to_not match('a/b') }
  end

  describe 'nested paths are relative to the file' do
    subject { PathSpec::GitIgnoreSpec.new 'foo/spam' }
    it { is_expected.to match('foo/spam') }
    it { is_expected.to match('foo/spam/bar') }
    it { is_expected.to_not match('bar/foo/spam') }
  end
end