pathspec 0.1.2 → 0.2.1
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 +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
|