pathspec 0.1.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +11 -3
- data/README.md +31 -6
- data/bin/pathspec-rb +93 -0
- data/lib/pathspec.rb +16 -25
- data/lib/pathspec/gitignorespec.rb +247 -261
- data/lib/pathspec/regexspec.rb +14 -10
- data/lib/pathspec/spec.rb +16 -9
- data/spec/files/gitignore_readme +2 -0
- data/spec/files/gitignore_ruby +51 -0
- data/spec/files/gitignore_simple +1 -0
- data/spec/files/regex_simple +1 -0
- data/spec/spec_helper.rb +1 -4
- data/spec/unit/pathspec/gitignorespec_spec.rb +32 -34
- data/spec/unit/pathspec/spec_spec.rb +5 -5
- data/spec/unit/pathspec_spec.rb +138 -86
- metadata +70 -4
data/lib/pathspec/regexspec.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
require 'pathspec/spec'
|
2
2
|
|
3
|
-
class
|
4
|
-
|
5
|
-
|
3
|
+
class PathSpec
|
4
|
+
# Simple regex-based spec
|
5
|
+
class RegexSpec < Spec
|
6
|
+
def initialize(pattern)
|
7
|
+
@pattern = pattern.dup
|
8
|
+
@regex = Regexp.compile pattern
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
super
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
def inclusive?
|
14
|
+
true
|
15
|
+
end
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
def match(path)
|
18
|
+
@regex.match(path) if @regex
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
data/lib/pathspec/spec.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
|
-
class
|
2
|
-
|
1
|
+
class PathSpec
|
2
|
+
# Abstract spec
|
3
|
+
class Spec
|
4
|
+
attr_reader :regex
|
5
|
+
attr_reader :pattern
|
3
6
|
|
4
|
-
|
5
|
-
end
|
7
|
+
def initialize(*_); end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
def match(files)
|
10
|
+
raise 'Unimplemented'
|
11
|
+
end
|
12
|
+
|
13
|
+
def inclusive?
|
14
|
+
true
|
15
|
+
end
|
10
16
|
|
11
|
-
|
12
|
-
|
17
|
+
def to_s
|
18
|
+
@pattern
|
19
|
+
end
|
13
20
|
end
|
14
21
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Source: https://github.com/github/gitignore/blob/master/Ruby.gitignore
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
/.config
|
5
|
+
/coverage/
|
6
|
+
/InstalledFiles
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/spec/examples.txt
|
10
|
+
/test/tmp/
|
11
|
+
/test/version_tmp/
|
12
|
+
/tmp/
|
13
|
+
|
14
|
+
# Used by dotenv library to load environment variables.
|
15
|
+
# .env
|
16
|
+
|
17
|
+
## Specific to RubyMotion:
|
18
|
+
.dat*
|
19
|
+
.repl_history
|
20
|
+
build/
|
21
|
+
*.bridgesupport
|
22
|
+
build-iPhoneOS/
|
23
|
+
build-iPhoneSimulator/
|
24
|
+
|
25
|
+
## Specific to RubyMotion (use of CocoaPods):
|
26
|
+
#
|
27
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
28
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
29
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
30
|
+
#
|
31
|
+
# vendor/Pods/
|
32
|
+
|
33
|
+
## Documentation cache and generated files:
|
34
|
+
/.yardoc/
|
35
|
+
/_yardoc/
|
36
|
+
/doc/
|
37
|
+
/rdoc/
|
38
|
+
|
39
|
+
## Environment normalization:
|
40
|
+
/.bundle/
|
41
|
+
/vendor/bundle
|
42
|
+
/lib/bundler/man/
|
43
|
+
|
44
|
+
# for a library or gem, you might want to ignore these files since the code is
|
45
|
+
# intended to run in multiple environments; otherwise, check them in:
|
46
|
+
# Gemfile.lock
|
47
|
+
# .ruby-version
|
48
|
+
# .ruby-gemset
|
49
|
+
|
50
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
51
|
+
.rvmrc
|
@@ -0,0 +1 @@
|
|
1
|
+
*.md
|
@@ -0,0 +1 @@
|
|
1
|
+
.*\.md
|
data/spec/spec_helper.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'pathspec/gitignorespec'
|
3
3
|
|
4
|
-
describe GitIgnoreSpec do
|
4
|
+
describe PathSpec::GitIgnoreSpec do
|
5
5
|
# Original specification by http://git-scm.com/docs/gitignore
|
6
6
|
|
7
7
|
# A blank line matches no files, so it can serve as a separator for
|
8
8
|
# readability.
|
9
9
|
describe 'does nothing for newlines' do
|
10
|
-
subject { GitIgnoreSpec.new "\n" }
|
10
|
+
subject { PathSpec::GitIgnoreSpec.new "\n" }
|
11
11
|
it { is_expected.to_not match('foo.tmp') }
|
12
12
|
it { is_expected.to_not match(' ') }
|
13
13
|
it { is_expected.to_not be_inclusive }
|
14
14
|
end
|
15
15
|
|
16
16
|
describe 'does nothing for blank strings' do
|
17
|
-
subject { GitIgnoreSpec.new '' }
|
17
|
+
subject { PathSpec::GitIgnoreSpec.new '' }
|
18
18
|
it { is_expected.to_not match 'foo.tmp' }
|
19
19
|
it { is_expected.to_not match ' ' }
|
20
20
|
it { is_expected.to_not be_inclusive }
|
@@ -23,21 +23,21 @@ describe GitIgnoreSpec do
|
|
23
23
|
# A line starting with # serves as a comment. Put a backslash ("\") in front
|
24
24
|
# of the first hash for patterns that begin with a hash.
|
25
25
|
describe 'does nothing for comments' do
|
26
|
-
subject { GitIgnoreSpec.new '# this is a gitignore style comment' }
|
26
|
+
subject { PathSpec::GitIgnoreSpec.new '# this is a gitignore style comment' }
|
27
27
|
it { is_expected.to_not match('foo.tmp') }
|
28
28
|
it { is_expected.to_not match(' ') }
|
29
29
|
it { is_expected.to_not be_inclusive }
|
30
30
|
end
|
31
31
|
|
32
32
|
describe 'ignores comment char with a slash' do
|
33
|
-
subject { GitIgnoreSpec.new '\#averystrangefile' }
|
33
|
+
subject { PathSpec::GitIgnoreSpec.new '\#averystrangefile' }
|
34
34
|
it { is_expected.to match('#averystrangefile') }
|
35
35
|
it { is_expected.to_not match('foobar') }
|
36
36
|
it { is_expected.to be_inclusive }
|
37
37
|
end
|
38
38
|
|
39
39
|
describe 'escapes characters with slashes' do
|
40
|
-
subject { GitIgnoreSpec.new 'twinkletwinkle\*' }
|
40
|
+
subject { PathSpec::GitIgnoreSpec.new 'twinkletwinkle\*' }
|
41
41
|
it { is_expected.to match('twinkletwinkle*') }
|
42
42
|
it { is_expected.to_not match('twinkletwinkletwinkle') }
|
43
43
|
it { is_expected.to be_inclusive }
|
@@ -45,7 +45,7 @@ describe GitIgnoreSpec do
|
|
45
45
|
|
46
46
|
# Trailing spaces are ignored unless they are quoted with backlash ("\").
|
47
47
|
describe 'ignores trailing spaces' do
|
48
|
-
subject { GitIgnoreSpec.new 'foo ' }
|
48
|
+
subject { PathSpec::GitIgnoreSpec.new 'foo ' }
|
49
49
|
it { is_expected.to match('foo') }
|
50
50
|
it { is_expected.to_not match('foo ') }
|
51
51
|
it { is_expected.to be_inclusive }
|
@@ -62,7 +62,7 @@ describe GitIgnoreSpec do
|
|
62
62
|
# backslash ("\") in front of the first "!" for patterns that begin with a
|
63
63
|
# literal "!", for example, "\!important!.txt".
|
64
64
|
describe 'is exclusive of !' do
|
65
|
-
subject { GitIgnoreSpec.new '!important.txt' }
|
65
|
+
subject { PathSpec::GitIgnoreSpec.new '!important.txt' }
|
66
66
|
it { is_expected.to match('important.txt') }
|
67
67
|
it { is_expected.to_not be_inclusive }
|
68
68
|
it { is_expected.to_not match('!important.txt') }
|
@@ -74,7 +74,7 @@ describe GitIgnoreSpec do
|
|
74
74
|
# will not match a regular file or a symbolic link foo (this is consistent
|
75
75
|
# with the way how pathspec works in general in Git).
|
76
76
|
describe 'trailing slashes match directories and their contents but not regular files or symlinks' do
|
77
|
-
subject { GitIgnoreSpec.new 'foo/' }
|
77
|
+
subject { PathSpec::GitIgnoreSpec.new 'foo/' }
|
78
78
|
it { is_expected.to match('foo/') }
|
79
79
|
it { is_expected.to match('foo/bar') }
|
80
80
|
it { is_expected.to match('baz/foo/bar') }
|
@@ -87,7 +87,7 @@ describe GitIgnoreSpec do
|
|
87
87
|
# of the .gitignore file (relative to the toplevel of the work tree if not
|
88
88
|
# from a .gitignore file).
|
89
89
|
describe 'handles basic globbing' do
|
90
|
-
subject { GitIgnoreSpec.new '*.tmp' }
|
90
|
+
subject { PathSpec::GitIgnoreSpec.new '*.tmp' }
|
91
91
|
it { is_expected.to match('foo.tmp') }
|
92
92
|
it { is_expected.to match('foo/bar.tmp') }
|
93
93
|
it { is_expected.to match('foo/bar.tmp/baz') }
|
@@ -96,7 +96,7 @@ describe GitIgnoreSpec do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
describe 'handles inner globs' do
|
99
|
-
subject { GitIgnoreSpec.new 'foo-*-bar' }
|
99
|
+
subject { PathSpec::GitIgnoreSpec.new 'foo-*-bar' }
|
100
100
|
it { is_expected.to match('foo--bar') }
|
101
101
|
it { is_expected.to match('foo-hello-bar') }
|
102
102
|
it { is_expected.to match('a/foo-hello-bar') }
|
@@ -106,7 +106,7 @@ describe GitIgnoreSpec do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
describe 'handles postfix globs' do
|
109
|
-
subject { GitIgnoreSpec.new '~temp-*' }
|
109
|
+
subject { PathSpec::GitIgnoreSpec.new '~temp-*' }
|
110
110
|
it { is_expected.to match('~temp-') }
|
111
111
|
it { is_expected.to match('~temp-foo') }
|
112
112
|
it { is_expected.to match('foo/~temp-bar') }
|
@@ -115,14 +115,14 @@ describe GitIgnoreSpec do
|
|
115
115
|
end
|
116
116
|
|
117
117
|
describe 'handles multiple globs' do
|
118
|
-
subject { GitIgnoreSpec.new '*.middle.*' }
|
118
|
+
subject { PathSpec::GitIgnoreSpec.new '*.middle.*' }
|
119
119
|
it { is_expected.to match('hello.middle.rb') }
|
120
120
|
it { is_expected.to_not match('foo.rb') }
|
121
121
|
it { is_expected.to be_inclusive }
|
122
122
|
end
|
123
123
|
|
124
124
|
describe 'handles dir globs' do
|
125
|
-
subject { GitIgnoreSpec.new 'dir/*' }
|
125
|
+
subject { PathSpec::GitIgnoreSpec.new 'dir/*' }
|
126
126
|
it { is_expected.to match('dir/foo') }
|
127
127
|
it { is_expected.to_not match('foo/') }
|
128
128
|
it { is_expected.to be_inclusive }
|
@@ -134,14 +134,14 @@ describe GitIgnoreSpec do
|
|
134
134
|
# "Documentation/git.html" but not "Documentation/ppc/ppc.html" or
|
135
135
|
# "tools/perf/Documentation/perf.html".
|
136
136
|
describe 'handles dir globs' do
|
137
|
-
subject { GitIgnoreSpec.new 'dir/*' }
|
137
|
+
subject { PathSpec::GitIgnoreSpec.new 'dir/*' }
|
138
138
|
it { is_expected.to match('dir/foo') }
|
139
139
|
it { is_expected.to_not match('foo/') }
|
140
140
|
it { is_expected.to be_inclusive }
|
141
141
|
end
|
142
142
|
|
143
143
|
describe 'handles globs inside of dirs' do
|
144
|
-
subject { GitIgnoreSpec.new 'Documentation/*.html' }
|
144
|
+
subject { PathSpec::GitIgnoreSpec.new 'Documentation/*.html' }
|
145
145
|
it { is_expected.to match('Documentation/git.html') }
|
146
146
|
it { is_expected.to_not match('Documentation/ppc/ppc.html') }
|
147
147
|
it { is_expected.to_not match('tools/perf/Documentation/perf.html') } # TODO: Or is it? Git 2 weirdness?
|
@@ -149,14 +149,14 @@ describe GitIgnoreSpec do
|
|
149
149
|
end
|
150
150
|
|
151
151
|
describe 'handles wildcards' do
|
152
|
-
subject { GitIgnoreSpec.new 'jokeris????' }
|
152
|
+
subject { PathSpec::GitIgnoreSpec.new 'jokeris????' }
|
153
153
|
it { is_expected.to match('jokeriswild') }
|
154
154
|
it { is_expected.to_not match('jokerisfat') }
|
155
155
|
it { is_expected.to be_inclusive }
|
156
156
|
end
|
157
157
|
|
158
158
|
describe 'handles brackets' do
|
159
|
-
subject { GitIgnoreSpec.new '*[eu][xl]*' }
|
159
|
+
subject { PathSpec::GitIgnoreSpec.new '*[eu][xl]*' }
|
160
160
|
it { is_expected.to match('youknowregex') }
|
161
161
|
it { is_expected.to match('youknowregularexpressions') }
|
162
162
|
it { is_expected.to_not match('youknownothing') }
|
@@ -164,19 +164,19 @@ describe GitIgnoreSpec do
|
|
164
164
|
end
|
165
165
|
|
166
166
|
describe 'handles unmatched brackets' do
|
167
|
-
subject { GitIgnoreSpec.new '*[*[*' }
|
167
|
+
subject { PathSpec::GitIgnoreSpec.new '*[*[*' }
|
168
168
|
it { is_expected.to match('bracket[oh[wow') }
|
169
169
|
it { is_expected.to be_inclusive }
|
170
170
|
end
|
171
171
|
|
172
172
|
describe 'handles brackets with carats' do
|
173
|
-
subject { GitIgnoreSpec.new '*[^]' }
|
173
|
+
subject { PathSpec::GitIgnoreSpec.new '*[^]' }
|
174
174
|
it { is_expected.to match('myfavorite^') }
|
175
175
|
it { is_expected.to be_inclusive }
|
176
176
|
end
|
177
177
|
|
178
178
|
describe 'handles brackets for brackets' do
|
179
|
-
subject { GitIgnoreSpec.new '*[]]' }
|
179
|
+
subject { PathSpec::GitIgnoreSpec.new '*[]]' }
|
180
180
|
it { is_expected.to match('yodawg[]]') }
|
181
181
|
it { is_expected.to be_inclusive }
|
182
182
|
end
|
@@ -189,7 +189,7 @@ describe GitIgnoreSpec do
|
|
189
189
|
end
|
190
190
|
|
191
191
|
describe 'handles negated brackets' do
|
192
|
-
subject { GitIgnoreSpec.new 'ab[!cd]ef' }
|
192
|
+
subject { PathSpec::GitIgnoreSpec.new 'ab[!cd]ef' }
|
193
193
|
it { is_expected.to_not match('abcef') }
|
194
194
|
it { is_expected.to match('abzef') }
|
195
195
|
it { is_expected.to be_inclusive }
|
@@ -198,14 +198,14 @@ describe GitIgnoreSpec do
|
|
198
198
|
# A leading slash matches the beginning of the pathname. For example, "/*.c"
|
199
199
|
# matches "cat-file.c" but not "mozilla-sha1/sha1.c".
|
200
200
|
describe 'handles leading / as relative to base directory' do
|
201
|
-
subject { GitIgnoreSpec.new '/*.c' }
|
201
|
+
subject { PathSpec::GitIgnoreSpec.new '/*.c' }
|
202
202
|
it { is_expected.to match('cat-file.c') }
|
203
203
|
it { is_expected.to_not match('mozilla-sha1/sha1.c') }
|
204
204
|
it { is_expected.to be_inclusive }
|
205
205
|
end
|
206
206
|
|
207
207
|
describe 'handles simple single paths' do
|
208
|
-
subject { GitIgnoreSpec.new 'spam' }
|
208
|
+
subject { PathSpec::GitIgnoreSpec.new 'spam' }
|
209
209
|
it { is_expected.to match('spam') }
|
210
210
|
it { is_expected.to match('spam/') }
|
211
211
|
it { is_expected.to match('foo/spam') }
|
@@ -222,7 +222,7 @@ describe GitIgnoreSpec do
|
|
222
222
|
# pattern "foo". "**/foo/bar" matches file or directory "bar" anywhere that is
|
223
223
|
# directly under directory "foo".
|
224
224
|
describe 'handles prefixed ** as searching any location' do
|
225
|
-
subject { GitIgnoreSpec.new '**/foo' }
|
225
|
+
subject { PathSpec::GitIgnoreSpec.new '**/foo' }
|
226
226
|
it { is_expected.to match('foo') }
|
227
227
|
it { is_expected.to match('bar/foo') }
|
228
228
|
it { is_expected.to match('baz/bar/foo') }
|
@@ -231,7 +231,7 @@ describe GitIgnoreSpec do
|
|
231
231
|
end
|
232
232
|
|
233
233
|
describe 'handles prefixed ** with a directory as searching a file under a directory in any location' do
|
234
|
-
subject { GitIgnoreSpec.new '**/foo/bar' }
|
234
|
+
subject { PathSpec::GitIgnoreSpec.new '**/foo/bar' }
|
235
235
|
it { is_expected.to_not match('foo') }
|
236
236
|
it { is_expected.to match('foo/bar') }
|
237
237
|
it { is_expected.to match('baz/foo/bar') }
|
@@ -245,7 +245,7 @@ describe GitIgnoreSpec do
|
|
245
245
|
# all files inside directory "abc", relative to the location of the .gitignore
|
246
246
|
# file, with infinite depth.
|
247
247
|
describe 'handles leading /** as all files inside a directory' do
|
248
|
-
subject { GitIgnoreSpec.new 'abc/**' }
|
248
|
+
subject { PathSpec::GitIgnoreSpec.new 'abc/**' }
|
249
249
|
it { is_expected.to match('abc/') }
|
250
250
|
it { is_expected.to match('abc/def') }
|
251
251
|
it { is_expected.to_not match('123/abc/def') }
|
@@ -257,7 +257,7 @@ describe GitIgnoreSpec do
|
|
257
257
|
# more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b"
|
258
258
|
# and so on.
|
259
259
|
describe 'handles /** in the middle of a path' do
|
260
|
-
subject { GitIgnoreSpec.new 'a/**/b' }
|
260
|
+
subject { PathSpec::GitIgnoreSpec.new 'a/**/b' }
|
261
261
|
it { is_expected.to match('a/b') }
|
262
262
|
it { is_expected.to match('a/x/b') }
|
263
263
|
it { is_expected.to match('a/x/y/b') }
|
@@ -267,7 +267,7 @@ describe GitIgnoreSpec do
|
|
267
267
|
end
|
268
268
|
|
269
269
|
describe 'matches all paths when given **' do
|
270
|
-
subject { GitIgnoreSpec.new '**' }
|
270
|
+
subject { PathSpec::GitIgnoreSpec.new '**' }
|
271
271
|
|
272
272
|
it { is_expected.to match('a/b') }
|
273
273
|
it { is_expected.to match('a/x/b') }
|
@@ -278,7 +278,7 @@ describe GitIgnoreSpec do
|
|
278
278
|
|
279
279
|
# Other consecutive asterisks are considered invalid.
|
280
280
|
describe 'considers other consecutive asterisks invalid' do
|
281
|
-
subject { GitIgnoreSpec.new 'a/***/b' }
|
281
|
+
subject { PathSpec::GitIgnoreSpec.new 'a/***/b' }
|
282
282
|
it { is_expected.to_not match('a/b') }
|
283
283
|
it { is_expected.to_not match('a/x/b') }
|
284
284
|
it { is_expected.to_not match('a/x/y/b') }
|
@@ -288,18 +288,16 @@ describe GitIgnoreSpec do
|
|
288
288
|
end
|
289
289
|
|
290
290
|
describe 'does not match single absolute paths' do
|
291
|
-
subject { GitIgnoreSpec.new
|
291
|
+
subject { PathSpec::GitIgnoreSpec.new '/' }
|
292
292
|
it { is_expected.to_not match('foo.tmp') }
|
293
293
|
it { is_expected.to_not match(' ') }
|
294
294
|
it { is_expected.to_not match('a/b') }
|
295
295
|
end
|
296
296
|
|
297
297
|
describe 'nested paths are relative to the file' do
|
298
|
-
subject { GitIgnoreSpec.new 'foo/spam' }
|
298
|
+
subject { PathSpec::GitIgnoreSpec.new 'foo/spam' }
|
299
299
|
it { is_expected.to match('foo/spam') }
|
300
300
|
it { is_expected.to match('foo/spam/bar') }
|
301
301
|
it { is_expected.to_not match('bar/foo/spam') }
|
302
302
|
end
|
303
|
-
|
304
|
-
|
305
303
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'pathspec/spec'
|
3
3
|
|
4
|
-
describe Spec do
|
5
|
-
subject { Spec.new }
|
4
|
+
describe PathSpec::Spec do
|
5
|
+
subject { PathSpec::Spec.new }
|
6
6
|
|
7
|
-
it
|
8
|
-
expect { subject.match
|
7
|
+
it 'does not allow matching' do
|
8
|
+
expect { subject.match 'anything' }.to raise_error(/Unimplemented/)
|
9
9
|
end
|
10
10
|
|
11
|
-
it { is_expected.to be_inclusive
|
11
|
+
it { is_expected.to be_inclusive }
|
12
12
|
end
|
data/spec/unit/pathspec_spec.rb
CHANGED
@@ -4,30 +4,47 @@ require 'pathspec'
|
|
4
4
|
require 'fakefs/spec_helpers'
|
5
5
|
|
6
6
|
describe PathSpec do
|
7
|
-
shared_examples
|
8
|
-
it { is_expected.
|
9
|
-
it { is_expected.
|
10
|
-
it { is_expected.to match('
|
7
|
+
shared_examples 'standard gitignore negation' do
|
8
|
+
it { is_expected.not_to match('important.txt') }
|
9
|
+
it { is_expected.not_to match('abc/important.txt') }
|
10
|
+
it { is_expected.to match('bar/baz/') }
|
11
|
+
it { is_expected.to match('foo/file') }
|
12
|
+
it { is_expected.not_to match('foo/important.txt') }
|
13
|
+
it { is_expected.to match('foo/subdir/file') }
|
11
14
|
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
# Specs that should be kept up to date with the README
|
17
|
+
context 'README.md' do
|
18
|
+
subject { PathSpec.from_filename 'spec/files/gitignore_readme' }
|
19
|
+
|
20
|
+
it { is_expected.to match('abc/def.rb') }
|
21
|
+
it { is_expected.not_to match('abc/important.txt') }
|
22
|
+
it do
|
23
|
+
expect(subject.match_paths(['/abc/123', '/abc/important.txt', '/abc/'])).to contain_exactly(
|
24
|
+
'/abc/123',
|
25
|
+
'/abc/')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'initialization' do
|
30
|
+
context 'from multilines' do
|
31
|
+
context '#new' do
|
32
|
+
subject {
|
33
|
+
PathSpec.new <<-IGNORELINES
|
17
34
|
!important.txt
|
18
35
|
foo/**
|
19
36
|
/bar/baz
|
20
37
|
IGNORELINES
|
21
38
|
}
|
22
39
|
|
23
|
-
it_behaves_like
|
40
|
+
it_behaves_like 'standard gitignore negation'
|
24
41
|
end
|
25
42
|
end
|
26
43
|
|
27
|
-
context
|
28
|
-
let(:str) {
|
44
|
+
context 'from a string with no newlines' do
|
45
|
+
let(:str) { 'foo/**' }
|
29
46
|
|
30
|
-
context
|
47
|
+
context '#new' do
|
31
48
|
subject { PathSpec.new str }
|
32
49
|
|
33
50
|
it { is_expected.to match('foo/important.txt') }
|
@@ -35,67 +52,67 @@ IGNORELINES
|
|
35
52
|
end
|
36
53
|
end
|
37
54
|
|
38
|
-
context
|
39
|
-
it
|
40
|
-
expect { PathSpec.new Object.new }.to raise_error
|
55
|
+
context 'from a non-string/non-enumerable' do
|
56
|
+
it 'throws an exception' do
|
57
|
+
expect { PathSpec.new Object.new }.to raise_error(/Cannot make Pathspec/)
|
41
58
|
end
|
42
59
|
end
|
43
60
|
|
44
|
-
context
|
45
|
-
let(:arr) { [
|
61
|
+
context 'from array of gitignore strings' do
|
62
|
+
let(:arr) { ['!important.txt', 'foo/**', '/bar/baz'] }
|
46
63
|
|
47
|
-
context
|
64
|
+
context '#new' do
|
48
65
|
subject { PathSpec.new arr }
|
49
66
|
|
50
|
-
it_behaves_like
|
67
|
+
it_behaves_like 'standard gitignore negation'
|
51
68
|
end
|
52
69
|
|
53
|
-
context
|
70
|
+
context '#from_lines' do
|
54
71
|
subject {
|
55
72
|
PathSpec.from_lines(arr)
|
56
73
|
}
|
57
74
|
|
58
|
-
it_behaves_like
|
75
|
+
it_behaves_like 'standard gitignore negation'
|
59
76
|
end
|
60
77
|
|
61
|
-
context
|
78
|
+
context '#add array' do
|
62
79
|
subject {
|
63
80
|
ps = PathSpec.new []
|
64
81
|
ps.add arr
|
65
82
|
}
|
66
83
|
|
67
|
-
it_behaves_like
|
84
|
+
it_behaves_like 'standard gitignore negation'
|
68
85
|
end
|
69
86
|
end
|
70
87
|
|
71
|
-
context
|
88
|
+
context 'from linedelimited gitignore string' do
|
72
89
|
let(:line) { "!important.txt\nfoo/**\n/bar/baz\n" }
|
73
90
|
|
74
|
-
context
|
91
|
+
context '#new' do
|
75
92
|
subject { PathSpec.new line }
|
76
93
|
|
77
|
-
it_behaves_like
|
94
|
+
it_behaves_like 'standard gitignore negation'
|
78
95
|
end
|
79
96
|
|
80
|
-
context
|
97
|
+
context '#from_lines' do
|
81
98
|
subject {
|
82
99
|
PathSpec.from_lines(line)
|
83
100
|
}
|
84
101
|
|
85
|
-
it_behaves_like
|
102
|
+
it_behaves_like 'standard gitignore negation'
|
86
103
|
end
|
87
104
|
|
88
|
-
context
|
105
|
+
context '#add' do
|
89
106
|
subject {
|
90
107
|
ps = PathSpec.new
|
91
108
|
ps.add line
|
92
109
|
}
|
93
110
|
|
94
|
-
it_behaves_like
|
111
|
+
it_behaves_like 'standard gitignore negation'
|
95
112
|
end
|
96
113
|
end
|
97
114
|
|
98
|
-
context
|
115
|
+
context 'from a gitignore file' do
|
99
116
|
include FakeFS::SpecHelpers
|
100
117
|
|
101
118
|
let(:filename) { '.gitignore' }
|
@@ -107,24 +124,24 @@ IGNORELINES
|
|
107
124
|
}
|
108
125
|
end
|
109
126
|
|
110
|
-
context
|
127
|
+
context '#new' do
|
111
128
|
subject {
|
112
129
|
PathSpec.new File.open(filename, 'r')
|
113
130
|
}
|
114
131
|
|
115
|
-
it_behaves_like
|
132
|
+
it_behaves_like 'standard gitignore negation'
|
116
133
|
end
|
117
134
|
|
118
|
-
context
|
135
|
+
context '#from_filename' do
|
119
136
|
subject {
|
120
137
|
PathSpec.from_filename(filename)
|
121
138
|
}
|
122
139
|
|
123
|
-
it_behaves_like
|
140
|
+
it_behaves_like 'standard gitignore negation'
|
124
141
|
end
|
125
142
|
end
|
126
143
|
|
127
|
-
context
|
144
|
+
context 'from multiple gitignore files' do
|
128
145
|
include FakeFS::SpecHelpers
|
129
146
|
|
130
147
|
let(:filenames) { ['.gitignore', '.otherignore'] }
|
@@ -141,26 +158,26 @@ IGNORELINES
|
|
141
158
|
}
|
142
159
|
end
|
143
160
|
|
144
|
-
context
|
161
|
+
context '#new' do
|
145
162
|
subject {
|
146
163
|
arr = filenames.collect { |f| File.open(f, 'r') }
|
147
164
|
PathSpec.new arr
|
148
165
|
}
|
149
166
|
|
150
|
-
it_behaves_like
|
167
|
+
it_behaves_like 'standard gitignore negation'
|
151
168
|
|
152
169
|
it { is_expected.to_not match('banana') }
|
153
170
|
it { is_expected.to match('banananananana') }
|
154
171
|
end
|
155
172
|
|
156
|
-
context
|
173
|
+
context '#add' do
|
157
174
|
subject {
|
158
175
|
arr = filenames.collect { |f| File.open(f, 'r') }
|
159
176
|
ps = PathSpec.new
|
160
177
|
ps.add arr
|
161
178
|
}
|
162
179
|
|
163
|
-
it_behaves_like
|
180
|
+
it_behaves_like 'standard gitignore negation'
|
164
181
|
|
165
182
|
it { is_expected.to_not match('banana') }
|
166
183
|
it { is_expected.to match('banananananana') }
|
@@ -168,12 +185,13 @@ IGNORELINES
|
|
168
185
|
end
|
169
186
|
end
|
170
187
|
|
171
|
-
context
|
188
|
+
context '#match_tree' do
|
172
189
|
include FakeFS::SpecHelpers
|
173
190
|
|
174
|
-
context
|
191
|
+
context 'unix' do
|
175
192
|
let(:root) {'/tmp/project'}
|
176
|
-
let(:gitignore) {
|
193
|
+
let(:gitignore) {
|
194
|
+
<<-GITIGNORE
|
177
195
|
!**/important.txt
|
178
196
|
abc/**
|
179
197
|
GITIGNORE
|
@@ -194,12 +212,13 @@ IGNORELINES
|
|
194
212
|
it { is_expected.to include "#{root}/abc".to_s }
|
195
213
|
it { is_expected.to include "#{root}/abc/1".to_s }
|
196
214
|
it { is_expected.not_to include "#{root}/abc/important.txt".to_s }
|
197
|
-
it { is_expected.not_to include
|
215
|
+
it { is_expected.not_to include root.to_s.to_s }
|
198
216
|
end
|
199
217
|
|
200
|
-
context
|
218
|
+
context 'windows' do
|
201
219
|
let(:root) {'C:/project'}
|
202
|
-
let(:gitignore) {
|
220
|
+
let(:gitignore) {
|
221
|
+
<<-GITIGNORE
|
203
222
|
!**/important.txt
|
204
223
|
abc/**
|
205
224
|
GITIGNORE
|
@@ -220,53 +239,59 @@ IGNORELINES
|
|
220
239
|
it { is_expected.to include "#{root}/abc".to_s }
|
221
240
|
it { is_expected.to include "#{root}/abc/1".to_s }
|
222
241
|
it { is_expected.not_to include "#{root}/abc/important.txt".to_s }
|
223
|
-
it { is_expected.not_to include
|
242
|
+
it { is_expected.not_to include root.to_s.to_s }
|
224
243
|
end
|
225
244
|
end
|
226
245
|
|
227
|
-
context
|
228
|
-
let(:gitignore) {
|
246
|
+
context '#match_paths' do
|
247
|
+
let(:gitignore) {
|
248
|
+
<<-GITIGNORE
|
229
249
|
!**/important.txt
|
230
250
|
/abc/**
|
231
251
|
GITIGNORE
|
232
252
|
}
|
233
253
|
|
234
|
-
context
|
254
|
+
context 'with no root arg' do
|
235
255
|
subject { PathSpec.new(gitignore).match_paths(['/abc/important.txt', '/abc/', '/abc/1']) }
|
236
256
|
|
237
|
-
it { is_expected.to include
|
238
|
-
it { is_expected.to include
|
239
|
-
it { is_expected.not_to include
|
257
|
+
it { is_expected.to include '/abc/' }
|
258
|
+
it { is_expected.to include '/abc/1' }
|
259
|
+
it { is_expected.not_to include '/abc/important.txt' }
|
240
260
|
end
|
241
261
|
|
242
262
|
context 'relative to non-root dir' do
|
243
|
-
subject {
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
it { is_expected.
|
263
|
+
subject {
|
264
|
+
PathSpec.new(gitignore).match_paths([
|
265
|
+
'/def/abc/important.txt',
|
266
|
+
'/def/abc/',
|
267
|
+
'/def/abc/1'
|
268
|
+
], '/def') }
|
269
|
+
|
270
|
+
it { is_expected.to include '/def/abc/' }
|
271
|
+
it { is_expected.to include '/def/abc/1' }
|
272
|
+
it { is_expected.not_to include '/def/abc/important.txt' }
|
251
273
|
end
|
252
274
|
|
253
275
|
context 'relative to windows drive letter' do
|
254
|
-
subject {
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
it { is_expected.
|
276
|
+
subject {
|
277
|
+
PathSpec.new(gitignore).match_paths([
|
278
|
+
'C:/def/abc/important.txt',
|
279
|
+
'C:/def/abc/',
|
280
|
+
'C:/def/abc/1'
|
281
|
+
], 'C:/def/') }
|
282
|
+
|
283
|
+
it { is_expected.to include 'C:/def/abc/' }
|
284
|
+
it { is_expected.to include 'C:/def/abc/1' }
|
285
|
+
it { is_expected.not_to include 'C:/def/abc/important.txt' }
|
262
286
|
end
|
263
287
|
end
|
264
288
|
|
265
289
|
# Example to exclude everything except a specific directory foo/bar (note
|
266
290
|
# the /* - without the slash, the wildcard would also exclude everything
|
267
291
|
# within foo/bar): (from git-scm.com)
|
268
|
-
context
|
269
|
-
let(:gitignore) {
|
292
|
+
context 'very specific gitignore' do
|
293
|
+
let(:gitignore) {
|
294
|
+
<<-GITIGNORE
|
270
295
|
# exclude everything except directory foo/bar
|
271
296
|
/*
|
272
297
|
!/foo
|
@@ -277,13 +302,14 @@ GITIGNORE
|
|
277
302
|
|
278
303
|
subject { PathSpec.new(gitignore) }
|
279
304
|
|
280
|
-
it { is_expected.not_to match(
|
281
|
-
it { is_expected.to match(
|
282
|
-
it { is_expected.to match(
|
305
|
+
it { is_expected.not_to match('foo/bar') }
|
306
|
+
it { is_expected.to match('anything') }
|
307
|
+
it { is_expected.to match('foo/otherthing') }
|
283
308
|
end
|
284
309
|
|
285
|
-
context
|
286
|
-
let(:gitignore) {
|
310
|
+
context '#empty' do
|
311
|
+
let(:gitignore) {
|
312
|
+
<<-GITIGNORE
|
287
313
|
# A comment
|
288
314
|
GITIGNORE
|
289
315
|
}
|
@@ -295,39 +321,65 @@ GITIGNORE
|
|
295
321
|
end
|
296
322
|
end
|
297
323
|
|
298
|
-
context
|
299
|
-
let(:regexfile) {
|
324
|
+
context 'regex file' do
|
325
|
+
let(:regexfile) {
|
326
|
+
<<-REGEX
|
300
327
|
ab*a
|
301
328
|
REGEX
|
302
329
|
}
|
303
330
|
|
304
331
|
subject { PathSpec.new regexfile, :regex}
|
305
332
|
|
306
|
-
it
|
333
|
+
it 'matches the regex' do
|
307
334
|
expect(subject.match('anna')).to be false
|
308
335
|
expect(subject.match('abba')).to be true
|
309
336
|
end
|
310
337
|
|
311
|
-
context
|
312
|
-
it
|
338
|
+
context '#from_filename' do
|
339
|
+
it 'forwards the type argument' do
|
313
340
|
io = double
|
314
341
|
|
315
342
|
expect(File).to receive(:open).and_yield(io)
|
316
343
|
expect(PathSpec).to receive(:from_lines).with(io, :regex)
|
317
344
|
|
318
|
-
PathSpec.from_filename
|
345
|
+
PathSpec.from_filename '/some/file', :regex
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'reads a simple regex file' do
|
349
|
+
spec = PathSpec.from_filename 'spec/files/regex_simple', :regex
|
350
|
+
|
351
|
+
expect(spec.match('artifact.md')).to be true
|
352
|
+
expect(spec.match('code.rb')).to be false
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'reads a simple gitignore file' do
|
356
|
+
spec = PathSpec.from_filename 'spec/files/gitignore_simple', :git
|
357
|
+
|
358
|
+
expect(spec.match('artifact.md')).to be true
|
359
|
+
expect(spec.match('code.rb')).to be false
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'reads an example ruby gitignore file' do
|
363
|
+
spec = PathSpec.from_filename 'spec/files/gitignore_ruby', :git
|
364
|
+
|
365
|
+
expect(spec.match('coverage/')).to be true
|
366
|
+
expect(spec.match('coverage/index.html')).to be true
|
367
|
+
expect(spec.match('pathspec-0.0.1.gem')).to be true
|
368
|
+
expect(spec.match('lib/pathspec')).to be false
|
369
|
+
expect(spec.match('Gemfile')).to be false
|
319
370
|
end
|
320
371
|
end
|
321
372
|
end
|
322
373
|
|
323
|
-
context
|
324
|
-
let(:file) {
|
374
|
+
context 'unsuppored spec type' do
|
375
|
+
let(:file) {
|
376
|
+
<<-REGEX
|
325
377
|
This is some kind of nonsense.
|
326
378
|
REGEX
|
327
379
|
}
|
328
380
|
|
329
|
-
it
|
330
|
-
expect { PathSpec.new file, :foo}.to raise_error
|
381
|
+
it 'does not allow an unknown spec type' do
|
382
|
+
expect { PathSpec.new file, :foo}.to raise_error(/Unknown/)
|
331
383
|
end
|
332
384
|
end
|
333
385
|
end
|