hx 0.7.4 → 0.8.2
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.
- data/VERSION +1 -1
- data/bin/hx +3 -2
- data/lib/hx.rb +48 -59
- data/lib/hx/backend/couchdb.rb +5 -3
- data/lib/hx/backend/hobix.rb +2 -3
- data/lib/hx/backend/rawfiles.rb +4 -3
- data/lib/hx/{commandline.rb → cli.rb} +2 -2
- data/lib/hx/listing/limit.rb +2 -3
- data/lib/hx/listing/paginate.rb +5 -5
- data/lib/hx/listing/recursiveindex.rb +19 -12
- data/lib/hx/output/liquidtemplate.rb +5 -9
- data/lib/hx/path.rb +208 -0
- data/lib/hx/rack/application.rb +0 -1
- data/loc.sh +3 -0
- data/spec/cache_spec.rb +4 -4
- data/spec/nullinput_spec.rb +2 -2
- data/spec/overlay_spec.rb +4 -4
- data/spec/pathops_spec.rb +6 -6
- data/spec/rack_spec.rb +2 -0
- data/spec/selector_spec.rb +150 -0
- data/spec/site_spec.rb +1 -1
- data/spec/spec_helper.rb +12 -2
- metadata +7 -5
- data/spec/pathfilter_spec.rb +0 -45
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.2
|
data/bin/hx
CHANGED
data/lib/hx.rb
CHANGED
@@ -21,12 +21,12 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'thread'
|
26
25
|
require 'set'
|
27
26
|
require 'pathname'
|
28
27
|
require 'tempfile'
|
29
28
|
require 'yaml'
|
29
|
+
require 'hx/path'
|
30
30
|
|
31
31
|
module Hx
|
32
32
|
|
@@ -38,17 +38,18 @@ end
|
|
38
38
|
class EditingNotSupportedError < RuntimeError
|
39
39
|
end
|
40
40
|
|
41
|
+
# minimal complete definition: each_entry_path + get_entry, or each_entry
|
41
42
|
module Filter
|
42
43
|
def edit_entry(path, prototype=nil)
|
43
44
|
raise EditingNotSupportedError, "Editing not supported for #{path}"
|
44
45
|
end
|
45
46
|
|
46
|
-
def each_entry_path
|
47
|
-
each_entry { |path, entry| yield path }
|
47
|
+
def each_entry_path(selector)
|
48
|
+
each_entry(selector) { |path, entry| yield path }
|
48
49
|
end
|
49
50
|
|
50
|
-
def each_entry
|
51
|
-
each_entry_path do |path|
|
51
|
+
def each_entry(selector)
|
52
|
+
each_entry_path(selector) do |path|
|
52
53
|
begin
|
53
54
|
entry = get_entry(path)
|
54
55
|
rescue NoSuchEntryError
|
@@ -59,8 +60,8 @@ module Filter
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def get_entry(path)
|
62
|
-
each_entry do |entry_path, entry|
|
63
|
-
return entry
|
63
|
+
each_entry(Path.literal(path)) do |entry_path, entry|
|
64
|
+
return entry
|
64
65
|
end
|
65
66
|
raise NoSuchEntryError, path
|
66
67
|
end
|
@@ -69,7 +70,7 @@ end
|
|
69
70
|
class NullInput
|
70
71
|
include Filter
|
71
72
|
|
72
|
-
def each_entry
|
73
|
+
def each_entry(selector)
|
73
74
|
self
|
74
75
|
end
|
75
76
|
end
|
@@ -79,13 +80,25 @@ NULL_INPUT = NullInput.new
|
|
79
80
|
class PathSubset
|
80
81
|
include Filter
|
81
82
|
|
83
|
+
def patterns_to_selector(patterns)
|
84
|
+
patterns.map { |p| Path::parse_pattern(p) }.inject { |a, b| a | b }
|
85
|
+
end
|
86
|
+
private :patterns_to_selector
|
87
|
+
|
82
88
|
def initialize(input, options)
|
83
89
|
@input = input
|
84
|
-
|
90
|
+
only = patterns_to_selector(Array(options[:only] || []))
|
91
|
+
except = patterns_to_selector(Array(options[:except] || []))
|
92
|
+
except = ~except if except
|
93
|
+
if only and except
|
94
|
+
@selector = only & except
|
95
|
+
else
|
96
|
+
@selector = only || except || Path::ALL
|
97
|
+
end
|
85
98
|
end
|
86
99
|
|
87
100
|
def edit_entry(path, prototype=nil)
|
88
|
-
if @
|
101
|
+
if @selector.accept? path
|
89
102
|
@input.edit_entry(path, prototype) { |text| yield text }
|
90
103
|
else
|
91
104
|
raise EditingNotSupportedError, "Editing not supported for #{path}"
|
@@ -93,47 +106,20 @@ class PathSubset
|
|
93
106
|
self
|
94
107
|
end
|
95
108
|
|
96
|
-
def each_entry_path
|
97
|
-
@input.each_entry_path
|
98
|
-
yield path if @path_filter.accept? path
|
99
|
-
end
|
109
|
+
def each_entry_path(selector, &block)
|
110
|
+
@input.each_entry_path(@selector & selector, &block)
|
100
111
|
self
|
101
112
|
end
|
102
113
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
class PathSubset::Predicate
|
110
|
-
def initialize(accept, reject)
|
111
|
-
@accept_re = patterns_to_re(accept)
|
112
|
-
@reject_re = patterns_to_re(reject)
|
113
|
-
end
|
114
|
-
|
115
|
-
def accept?(path)
|
116
|
-
(not @accept_re or path =~ @accept_re) and
|
117
|
-
(not @reject_re or path !~ @reject_re)
|
118
|
-
end
|
119
|
-
|
120
|
-
def patterns_to_re(patterns)
|
121
|
-
return nil if patterns.nil? or patterns.empty?
|
122
|
-
patterns = Array(patterns)
|
123
|
-
Regexp.new("(?:#{patterns.map { |p| pattern_to_re(p) }.join("|")})")
|
114
|
+
def each_entry(selector, &block)
|
115
|
+
@input.each_entry(@selector & selector, &block)
|
116
|
+
self
|
124
117
|
end
|
125
|
-
private :patterns_to_re
|
126
118
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
when "**"; ".*"
|
131
|
-
when "*"; "[^/]*"
|
132
|
-
else Regexp.quote(s)
|
133
|
-
end
|
134
|
-
}}$"
|
119
|
+
def get_entry(path)
|
120
|
+
raise NoSuchEntryError, path unless @selector.accept? path
|
121
|
+
@input.get_entry(path)
|
135
122
|
end
|
136
|
-
private :pattern_to_re
|
137
123
|
end
|
138
124
|
|
139
125
|
class Overlay
|
@@ -143,10 +129,10 @@ class Overlay
|
|
143
129
|
@inputs = inputs
|
144
130
|
end
|
145
131
|
|
146
|
-
def each_entry_path
|
132
|
+
def each_entry_path(selector)
|
147
133
|
seen = Set[]
|
148
134
|
@inputs.each do |input|
|
149
|
-
input.each_entry_path do |path|
|
135
|
+
input.each_entry_path(selector) do |path|
|
150
136
|
yield path unless seen.include? path
|
151
137
|
seen.add path
|
152
138
|
end
|
@@ -197,8 +183,11 @@ class AddPath
|
|
197
183
|
self
|
198
184
|
end
|
199
185
|
|
200
|
-
def each_entry_path
|
201
|
-
@input.each_entry_path
|
186
|
+
def each_entry_path(selector)
|
187
|
+
@input.each_entry_path(Path::ALL) do |path|
|
188
|
+
path = add_circumfix(path)
|
189
|
+
yield path if selector.accept? path
|
190
|
+
end
|
202
191
|
self
|
203
192
|
end
|
204
193
|
|
@@ -218,10 +207,10 @@ class StripPath
|
|
218
207
|
self
|
219
208
|
end
|
220
209
|
|
221
|
-
def each_entry_path
|
222
|
-
@input.each_entry_path do |path|
|
210
|
+
def each_entry_path(selector)
|
211
|
+
@input.each_entry_path(Path::ALL) do |path|
|
223
212
|
path = strip_circumfix(path)
|
224
|
-
yield path if path
|
213
|
+
yield path if path and selector.accept? path
|
225
214
|
end
|
226
215
|
self
|
227
216
|
end
|
@@ -246,14 +235,14 @@ class Cache
|
|
246
235
|
self
|
247
236
|
end
|
248
237
|
|
249
|
-
def each_entry
|
238
|
+
def each_entry(selector)
|
250
239
|
entries = nil
|
251
240
|
@lock.synchronize do
|
252
241
|
if @entries
|
253
242
|
entries = @entries
|
254
243
|
else
|
255
244
|
entries = []
|
256
|
-
@input.each_entry do |path, entry|
|
245
|
+
@input.each_entry(Path::ALL) do |path, entry|
|
257
246
|
@entries_by_path[path] = entry
|
258
247
|
entries << [path, entry]
|
259
248
|
end
|
@@ -261,7 +250,7 @@ class Cache
|
|
261
250
|
end
|
262
251
|
end
|
263
252
|
entries.each do |path, entry|
|
264
|
-
yield path, entry.dup
|
253
|
+
yield path, entry.dup if selector.accept? path
|
265
254
|
end
|
266
255
|
self
|
267
256
|
end
|
@@ -294,9 +283,9 @@ class Sort
|
|
294
283
|
self
|
295
284
|
end
|
296
285
|
|
297
|
-
def each_entry
|
286
|
+
def each_entry(selector)
|
298
287
|
entries = []
|
299
|
-
@input.each_entry do |path, entry|
|
288
|
+
@input.each_entry(selector) do |path, entry|
|
300
289
|
entries << [path, entry]
|
301
290
|
end
|
302
291
|
unless @key_fields.empty?
|
@@ -542,8 +531,8 @@ class Site
|
|
542
531
|
self
|
543
532
|
end
|
544
533
|
|
545
|
-
def each_entry_path
|
546
|
-
@combined_output.each_entry_path { |path| yield path }
|
534
|
+
def each_entry_path(selector)
|
535
|
+
@combined_output.each_entry_path(selector) { |path| yield path }
|
547
536
|
self
|
548
537
|
end
|
549
538
|
|
data/lib/hx/backend/couchdb.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'cgi'
|
26
25
|
require 'net/http'
|
27
26
|
require 'uri'
|
@@ -81,9 +80,12 @@ class CouchDB
|
|
81
80
|
self
|
82
81
|
end
|
83
82
|
|
84
|
-
def each_entry_path
|
83
|
+
def each_entry_path(selector)
|
85
84
|
listing = JSON.parse(get_document('_all_docs'))
|
86
|
-
listing['rows'].each
|
85
|
+
listing['rows'].each do |row|
|
86
|
+
path = row['id']
|
87
|
+
yield path if selector.accept? path
|
88
|
+
end
|
87
89
|
self
|
88
90
|
end
|
89
91
|
|
data/lib/hx/backend/hobix.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'yaml'
|
26
25
|
require 'hx'
|
27
26
|
require 'hx/backend/rawfiles'
|
@@ -73,8 +72,8 @@ class Hobix
|
|
73
72
|
self
|
74
73
|
end
|
75
74
|
|
76
|
-
def each_entry_path
|
77
|
-
@source.each_entry_path { |path| yield path }
|
75
|
+
def each_entry_path(selector)
|
76
|
+
@source.each_entry_path(selector) { |path| yield path }
|
78
77
|
self
|
79
78
|
end
|
80
79
|
|
data/lib/hx/backend/rawfiles.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'pathname'
|
26
25
|
require 'hx'
|
27
26
|
|
@@ -56,9 +55,11 @@ class RawFiles
|
|
56
55
|
self
|
57
56
|
end
|
58
57
|
|
59
|
-
def each_entry_path
|
58
|
+
def each_entry_path(selector)
|
60
59
|
Pathname.glob(@entry_dir + '**/*') do |pathname|
|
61
|
-
|
60
|
+
next unless pathname.file?
|
61
|
+
path = pathname_to_path(pathname)
|
62
|
+
yield path if selector.accept? path
|
62
63
|
end
|
63
64
|
self
|
64
65
|
end
|
@@ -28,7 +28,7 @@ require 'pathname'
|
|
28
28
|
require 'tempfile'
|
29
29
|
|
30
30
|
module Hx
|
31
|
-
module
|
31
|
+
module CLI
|
32
32
|
|
33
33
|
DEFAULT_CONFIG_FILENAME = "config.hx"
|
34
34
|
|
@@ -105,7 +105,7 @@ end
|
|
105
105
|
|
106
106
|
def self.do_gen(site, update_only)
|
107
107
|
output_dir = Hx.get_pathname(site.options, :output_dir)
|
108
|
-
site.each_entry do |path, entry|
|
108
|
+
site.each_entry(Path::ALL) do |path, entry|
|
109
109
|
pathname = output_dir + path
|
110
110
|
content = entry['content']
|
111
111
|
if update_only
|
data/lib/hx/listing/limit.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'hx'
|
26
25
|
|
27
26
|
module Hx
|
@@ -35,8 +34,8 @@ class Limit
|
|
35
34
|
@limit = options[:limit]
|
36
35
|
end
|
37
36
|
|
38
|
-
def each_entry
|
39
|
-
@input.each_entry do |path, entry|
|
37
|
+
def each_entry(selector)
|
38
|
+
@input.each_entry(selector) do |path, entry|
|
40
39
|
if entry['items']
|
41
40
|
trimmed_entry = entry.dup
|
42
41
|
trimmed_entry['items'] = entry['items'][0...@limit]
|
data/lib/hx/listing/paginate.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'hx'
|
26
25
|
|
27
26
|
module Hx
|
@@ -35,14 +34,14 @@ class Paginate
|
|
35
34
|
@page_size = options[:page_size]
|
36
35
|
end
|
37
36
|
|
38
|
-
def each_entry
|
39
|
-
@input.each_entry do |index_path, index_entry|
|
37
|
+
def each_entry(selector)
|
38
|
+
@input.each_entry(Path::ALL) do |index_path, index_entry|
|
40
39
|
items = index_entry['items'] || []
|
41
40
|
if items.empty?
|
42
41
|
index_entry = index_entry.dup
|
43
42
|
index_entry['pages'] = [index_entry]
|
44
43
|
index_entry['page_index'] = 0
|
45
|
-
yield index_path, index_entry
|
44
|
+
yield index_path, index_entry if selector.accept? index_path
|
46
45
|
else
|
47
46
|
pages = []
|
48
47
|
n_pages = (items.size + @page_size - 1) / @page_size
|
@@ -65,7 +64,8 @@ class Paginate
|
|
65
64
|
end
|
66
65
|
pages[-1]['entry'].delete('next_page')
|
67
66
|
pages.each do |page|
|
68
|
-
|
67
|
+
path = page['path']
|
68
|
+
yield path, page['entry'] if selector.accept? path
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'hx'
|
26
25
|
require 'hx/listing/limit'
|
27
26
|
require 'hx/listing/paginate'
|
@@ -47,23 +46,31 @@ class RecursiveIndex
|
|
47
46
|
@input = input
|
48
47
|
end
|
49
48
|
|
50
|
-
def
|
49
|
+
def merge_updated(index, entry)
|
50
|
+
updated = [entry, index].map { |e| e['updated'] }.compact.max
|
51
|
+
index['updated'] = updated if updated
|
52
|
+
end
|
53
|
+
private :merge_updated
|
54
|
+
|
55
|
+
def each_entry(selector)
|
51
56
|
indexes = Hash.new { |h,k| h[k] = {'items' => []} }
|
52
|
-
@input.each_entry do |path, entry|
|
57
|
+
@input.each_entry(Path::ALL) do |path, entry|
|
53
58
|
components = path.split("/")
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
index
|
59
|
+
if components.last == "index"
|
60
|
+
index = indexes[path] = entry.merge(indexes[path])
|
61
|
+
merge_updated(index, entry)
|
62
|
+
else
|
63
|
+
until components.empty?
|
64
|
+
components.pop
|
65
|
+
index_path = (components + ["index"]).join("/")
|
66
|
+
index = indexes[index_path]
|
67
|
+
index['items'] << {'path' => path, 'entry' => entry}
|
68
|
+
merge_updated(index, entry)
|
62
69
|
end
|
63
70
|
end
|
64
71
|
end
|
65
72
|
indexes.each do |path, entry|
|
66
|
-
yield path, entry
|
73
|
+
yield path, entry if selector.accept? path
|
67
74
|
end
|
68
75
|
self
|
69
76
|
end
|
@@ -21,7 +21,6 @@
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
require 'rubygems'
|
25
24
|
require 'time'
|
26
25
|
require 'liquid'
|
27
26
|
require 'redcloth'
|
@@ -72,7 +71,7 @@ class LiquidTemplate
|
|
72
71
|
# same template directory for things to work right
|
73
72
|
Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_dir)
|
74
73
|
Liquid::Template.register_filter(TextFilters)
|
75
|
-
template_file = template_dir + options[:template]
|
74
|
+
template_file = template_dir + "#{options[:template]}.liquid"
|
76
75
|
@template = Liquid::Template.parse(template_file.read)
|
77
76
|
@extension = options[:extension]
|
78
77
|
@mime_type = options[:mime_type]
|
@@ -80,13 +79,10 @@ class LiquidTemplate
|
|
80
79
|
@strip_extension_re = /\.#{Regexp.quote(@extension)}$/ if @extension
|
81
80
|
end
|
82
81
|
|
83
|
-
def each_entry_path
|
84
|
-
@input.each_entry_path do |path|
|
85
|
-
unless @extension.nil?
|
86
|
-
|
87
|
-
else
|
88
|
-
yield path
|
89
|
-
end
|
82
|
+
def each_entry_path(selector)
|
83
|
+
@input.each_entry_path(Path::ALL) do |path|
|
84
|
+
path = "#{path}.#{@extension}" unless @extension.nil?
|
85
|
+
yield path if selector.accept? path
|
90
86
|
end
|
91
87
|
self
|
92
88
|
end
|
data/lib/hx/path.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# hx/path - path selectors
|
2
|
+
#
|
3
|
+
# Copyright (c) 2009-2010 MenTaLguY <mental@rydia.net>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Hx
|
25
|
+
module Path
|
26
|
+
|
27
|
+
module Selector
|
28
|
+
def prefix ; "" ; end
|
29
|
+
def suffix ; "" ; end
|
30
|
+
def regexp ; nil ; end
|
31
|
+
def remaining_suffix(prefix_consumed) ; suffix ; end
|
32
|
+
|
33
|
+
def accept?(path)
|
34
|
+
raise NotImplementedError, "#{self.class}#accept? not implemented"
|
35
|
+
end
|
36
|
+
|
37
|
+
def |(other)
|
38
|
+
Disjunction.new(self, other)
|
39
|
+
end
|
40
|
+
|
41
|
+
def &(other)
|
42
|
+
Conjunction.new(self, other)
|
43
|
+
end
|
44
|
+
|
45
|
+
def ~()
|
46
|
+
Negation.new(self)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class All
|
51
|
+
include Selector
|
52
|
+
|
53
|
+
REGEXP = Regexp.new("^.*$")
|
54
|
+
|
55
|
+
def regexp ; REGEXP ; end
|
56
|
+
def accept?(path) ; true ; end
|
57
|
+
end
|
58
|
+
|
59
|
+
ALL = All.new
|
60
|
+
|
61
|
+
class Literal
|
62
|
+
include Selector
|
63
|
+
|
64
|
+
attr_reader :value
|
65
|
+
alias prefix value
|
66
|
+
|
67
|
+
def initialize(value)
|
68
|
+
@value = value
|
69
|
+
@regexp = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def remaining_suffix(prefix_consumed)
|
73
|
+
@value[prefix_consumed..-1]
|
74
|
+
end
|
75
|
+
|
76
|
+
def regexp
|
77
|
+
@regexp ||= Regexp.new("^#{Regexp.quote(@value)}$")
|
78
|
+
end
|
79
|
+
|
80
|
+
def accept?(path)
|
81
|
+
@value == path
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.parse_pattern(pattern_string)
|
86
|
+
tokens = []
|
87
|
+
pattern_string.scan(/(\*\*?|[^*]+)/) do |token,|
|
88
|
+
tokens << case token
|
89
|
+
when "**"; :doublestar
|
90
|
+
when "*"; :star
|
91
|
+
else; token
|
92
|
+
end
|
93
|
+
end
|
94
|
+
prefix = tokens.first
|
95
|
+
if tokens.size == 1 and String === prefix
|
96
|
+
Literal.new(prefix)
|
97
|
+
else
|
98
|
+
prefix = "" unless String === prefix
|
99
|
+
suffix = tokens.last
|
100
|
+
suffix = "" unless String === suffix
|
101
|
+
regexp = Regexp.new("^#{tokens.map { |token|
|
102
|
+
case token
|
103
|
+
when :doublestar; '.*'
|
104
|
+
when :star; '[^/]*'
|
105
|
+
else; Regexp.quote(token)
|
106
|
+
end
|
107
|
+
}}$")
|
108
|
+
Pattern.new(regexp, prefix, suffix)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.literal(literal_string)
|
113
|
+
Literal.new(literal_string)
|
114
|
+
end
|
115
|
+
|
116
|
+
class Pattern
|
117
|
+
include Selector
|
118
|
+
|
119
|
+
attr_reader :prefix
|
120
|
+
attr_reader :suffix
|
121
|
+
attr_reader :regexp
|
122
|
+
|
123
|
+
def initialize(regexp, prefix, suffix)
|
124
|
+
@regexp = regexp
|
125
|
+
@prefix = prefix
|
126
|
+
@suffix = suffix
|
127
|
+
end
|
128
|
+
|
129
|
+
def accept?(path)
|
130
|
+
!!(@regexp.match(path))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
module Connective
|
135
|
+
include Selector
|
136
|
+
|
137
|
+
attr_reader :prefix
|
138
|
+
attr_reader :suffix
|
139
|
+
|
140
|
+
def initialize(*selectors)
|
141
|
+
@selectors = selectors
|
142
|
+
prefixes = selectors.map { |s| s.prefix }
|
143
|
+
prefix_length = (prefixes.first || "").length
|
144
|
+
prefixes.each_cons(2) do |a, b|
|
145
|
+
prefix_length.downto(0) do |length|
|
146
|
+
prefix_length = length
|
147
|
+
break if a[0...length] == b[0...length]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
@prefix = prefixes.first[0...prefix_length]
|
151
|
+
suffixes = selectors.map { |s| s.remaining_suffix(prefix_length) }
|
152
|
+
suffix_length = (suffixes.first || "").length
|
153
|
+
suffixes.each_cons(2) do |a, b|
|
154
|
+
suffix_length.downto(0) do |length|
|
155
|
+
suffix_length = length
|
156
|
+
break if a[-length..-1] == b[-length..-1]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
@suffix = suffixes.first[-suffix_length..-1]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class Conjunction
|
164
|
+
include Connective
|
165
|
+
|
166
|
+
def accept?(path)
|
167
|
+
@selectors.all? { |s| s.accept? path }
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class Disjunction
|
172
|
+
include Connective
|
173
|
+
|
174
|
+
attr_reader :regexp
|
175
|
+
|
176
|
+
def initialize(*selectors)
|
177
|
+
super
|
178
|
+
regexps = @selectors.map { |s| s.regexp }
|
179
|
+
if regexps.all?
|
180
|
+
@regexp = Regexp.union(*regexps)
|
181
|
+
else
|
182
|
+
@regexp = nil
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def accept?(path)
|
187
|
+
if @regexp
|
188
|
+
!!@regexp.match(path)
|
189
|
+
else
|
190
|
+
@selectors.any? { |s| s.accept? path }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class Negation
|
196
|
+
include Selector
|
197
|
+
|
198
|
+
def initialize(selector)
|
199
|
+
@selector = selector
|
200
|
+
end
|
201
|
+
|
202
|
+
def accept?(path)
|
203
|
+
not @selector.accept?(path)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
data/lib/hx/rack/application.rb
CHANGED
data/loc.sh
ADDED
data/spec/cache_spec.rb
CHANGED
@@ -12,20 +12,20 @@ describe Hx::Cache do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should return itself from each_entry" do
|
15
|
-
@cache.each_entry {}.should == @cache
|
15
|
+
@cache.each_entry(Hx::Path::ALL) {}.should == @cache
|
16
16
|
end
|
17
17
|
|
18
18
|
it "enumerates the same entries from the source" do
|
19
|
-
@cache.each_entry do |path, entry|
|
19
|
+
@cache.each_entry(Hx::Path::ALL) do |path, entry|
|
20
20
|
entry.should == @source.get_entry(path)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
it "only reads the source once" do
|
25
|
-
@cache.each_entry {}
|
25
|
+
@cache.each_entry(Hx::Path::ALL) {}
|
26
26
|
def @source.each_entry
|
27
27
|
raise RuntimeError, "should not be called"
|
28
28
|
end
|
29
|
-
@cache.each_entry {}
|
29
|
+
@cache.each_entry(Hx::Path::ALL) {}
|
30
30
|
end
|
31
31
|
end
|
data/spec/nullinput_spec.rb
CHANGED
@@ -8,11 +8,11 @@ describe Hx::NullInput do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should return itself from each_entry" do
|
11
|
-
@null_source.each_entry {}.should == @null_source
|
11
|
+
@null_source.each_entry(Hx::Path::ALL) {}.should == @null_source
|
12
12
|
end
|
13
13
|
|
14
14
|
it "enumerates no entry paths" do
|
15
|
-
@null_source.each_entry do |path, entry|
|
15
|
+
@null_source.each_entry(Hx::Path::ALL) do |path, entry|
|
16
16
|
raise RuntimeError("No entries")
|
17
17
|
end
|
18
18
|
end
|
data/spec/overlay_spec.rb
CHANGED
@@ -14,25 +14,25 @@ describe Hx::Overlay do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should return itself from each_entry" do
|
17
|
-
@overlay.each_entry {}.should == @overlay
|
17
|
+
@overlay.each_entry(Hx::Path::ALL) {}.should == @overlay
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should expose the union of paths" do
|
21
21
|
actual_paths = []
|
22
|
-
@overlay.each_entry do |path, entry|
|
22
|
+
@overlay.each_entry(Hx::Path::ALL) do |path, entry|
|
23
23
|
actual_paths << path
|
24
24
|
end
|
25
25
|
actual_paths.sort.should == %w(foo bar baz).sort
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should give earlier sources precedence" do
|
29
|
-
@overlay.each_entry do |path, entry|
|
29
|
+
@overlay.each_entry(Hx::Path::ALL) do |path, entry|
|
30
30
|
entry.should == @a.get_entry('bar') if path == 'bar'
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should expose entries from all sources" do
|
35
|
-
@overlay.each_entry do |path, entry|
|
35
|
+
@overlay.each_entry(Hx::Path::ALL) do |path, entry|
|
36
36
|
entry.should == @a.get_entry('foo') if path == 'foo'
|
37
37
|
entry.should == @b.get_entry('baz') if path == 'baz'
|
38
38
|
end
|
data/spec/pathops_spec.rb
CHANGED
@@ -14,12 +14,12 @@ describe Hx::AddPath do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should return itself from each_entry" do
|
17
|
-
@add.each_entry {}.should == @add
|
17
|
+
@add.each_entry(Hx::Path::ALL) {}.should == @add
|
18
18
|
end
|
19
19
|
|
20
20
|
it "yields augmented paths from each_entry" do
|
21
21
|
paths = Set[]
|
22
|
-
@add.each_entry do |path, entry|
|
22
|
+
@add.each_entry(Hx::Path::ALL) do |path, entry|
|
23
23
|
paths.add path
|
24
24
|
end
|
25
25
|
paths.should == @after_paths
|
@@ -36,12 +36,12 @@ describe Hx::StripPath do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should return itself from each_entry" do
|
39
|
-
@strip.each_entry {}.should == @strip
|
39
|
+
@strip.each_entry(Hx::Path::ALL) {}.should == @strip
|
40
40
|
end
|
41
41
|
|
42
42
|
it "yields stripped paths from each_entry" do
|
43
43
|
paths = Set[]
|
44
|
-
@strip.each_entry do |path, entry|
|
44
|
+
@strip.each_entry(Hx::Path::ALL) do |path, entry|
|
45
45
|
paths.add path
|
46
46
|
end
|
47
47
|
paths.should == @after_paths
|
@@ -59,12 +59,12 @@ describe Hx::PathSubset do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it "returns itself from each_entry" do
|
62
|
-
@subset.each_entry {}.should == @subset
|
62
|
+
@subset.each_entry(Hx::Path::ALL) {}.should == @subset
|
63
63
|
end
|
64
64
|
|
65
65
|
it "enumerates paths according to the subset filter" do
|
66
66
|
actual_paths = Set[]
|
67
|
-
@subset.each_entry do |path, entry|
|
67
|
+
@subset.each_entry(Hx::Path::ALL) do |path, entry|
|
68
68
|
actual_paths.add path
|
69
69
|
end
|
70
70
|
actual_paths.should == Set['foo/bar', 'foo/baz']
|
data/spec/rack_spec.rb
CHANGED
@@ -3,11 +3,13 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
3
3
|
require 'hx'
|
4
4
|
require 'hx/rack'
|
5
5
|
require 'rack/mock'
|
6
|
+
require 'rack/lint'
|
6
7
|
|
7
8
|
describe Hx::Rack::Application do
|
8
9
|
before(:each) do
|
9
10
|
@input = FakeInput.new
|
10
11
|
@app = Hx::Rack::Application.new(@input, {})
|
12
|
+
@app = Rack::Lint.new(@app)
|
11
13
|
@service = Rack::MockRequest.new(@app)
|
12
14
|
end
|
13
15
|
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'hx/path'
|
4
|
+
|
5
|
+
describe Hx::Path::Pattern do
|
6
|
+
it "should include Hx::Path::Selector" do
|
7
|
+
Hx::Path::Pattern.should < Hx::Path::Selector
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse pattern strings" do
|
11
|
+
cases = [ { :pattern => "foo/**/bar",
|
12
|
+
:prefix => "foo/",
|
13
|
+
:suffix => "/bar" },
|
14
|
+
{ :pattern => "foo/*/bar",
|
15
|
+
:prefix => "foo/",
|
16
|
+
:suffix => "/bar" },
|
17
|
+
{ :pattern => "[blah",
|
18
|
+
:prefix => "[blah",
|
19
|
+
:suffix => "" },
|
20
|
+
{ :pattern => "hoge*",
|
21
|
+
:prefix => "hoge",
|
22
|
+
:suffix => "" },
|
23
|
+
{ :pattern => "*hoge",
|
24
|
+
:prefix => "",
|
25
|
+
:suffix => "hoge" } ]
|
26
|
+
for test_case in cases
|
27
|
+
pattern = Hx::Path.parse_pattern(test_case[:pattern])
|
28
|
+
pattern.prefix.should == test_case[:prefix]
|
29
|
+
pattern.suffix.should == test_case[:suffix]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should accept or reject paths" do
|
34
|
+
pattern = Hx::Path.parse_pattern("foo/bar")
|
35
|
+
pattern.should accept("foo/bar")
|
36
|
+
pattern.should_not accept("foo/baz")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should provide an equivalent regexp" do
|
40
|
+
pattern = Hx::Path.parse_pattern("foo/bar")
|
41
|
+
pattern.regexp.should_not be_nil
|
42
|
+
pattern.regexp.match("foo/bar").should_not be_nil
|
43
|
+
pattern.regexp.match("foo/bar/baz").should be_nil
|
44
|
+
|
45
|
+
pattern = Hx::Path.parse_pattern("foo/*/baz")
|
46
|
+
pattern.regexp.should_not be_nil
|
47
|
+
pattern.regexp.match("foo/baz").should be_nil
|
48
|
+
pattern.regexp.match("foo/bar/baz").should_not be_nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
PATHFILTER_PREFIX_CASES = [
|
53
|
+
{ :patterns => ["foo/bar", "fudge/bear"],
|
54
|
+
:prefix => "f",
|
55
|
+
:suffix => "ar" },
|
56
|
+
{ :patterns => ["foo/*/bar", "fudge/*/bear"],
|
57
|
+
:prefix => "f",
|
58
|
+
:suffix => "ar" },
|
59
|
+
{ :patterns => ["foo/bar", "fudge/*/bear"],
|
60
|
+
:prefix => "f",
|
61
|
+
:suffix => "ar" },
|
62
|
+
{ :patterns => ["bar*", "*bear"],
|
63
|
+
:prefix => "",
|
64
|
+
:suffix => "" },
|
65
|
+
{ :patterns => ["foobarbaz", "foobar*barbaz"],
|
66
|
+
:prefix => "foobar",
|
67
|
+
:suffix => "baz" },
|
68
|
+
{ :patterns => ["foobarbaz*", "foobar*barbaz"],
|
69
|
+
:prefix => "foobar",
|
70
|
+
:suffix => "" },
|
71
|
+
{ :patterns => ["*foobarbaz", "foobar*barbaz"],
|
72
|
+
:prefix => "",
|
73
|
+
:suffix => "barbaz" }
|
74
|
+
]
|
75
|
+
|
76
|
+
describe "Hx::Path::Selector disjunctions" do
|
77
|
+
it "should be possible" do
|
78
|
+
filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
|
79
|
+
filter = filters.inject { |a, b| a | b }
|
80
|
+
filter.should be_a_kind_of(Hx::Path::Selector)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should accept and reject the right paths" do
|
84
|
+
filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
|
85
|
+
filter = filters.inject { |a, b| a | b }
|
86
|
+
filter.should accept("foo/bar")
|
87
|
+
filter.should accept("abcdefg")
|
88
|
+
filter.should_not accept("hoge")
|
89
|
+
end
|
90
|
+
|
91
|
+
for test_case_outer in PATHFILTER_PREFIX_CASES
|
92
|
+
Proc.new do |test_case|
|
93
|
+
it "should produce optimal prefixes and suffixes" do
|
94
|
+
filters = test_case[:patterns].map { |p| Hx::Path.parse_pattern(p) }
|
95
|
+
filter = filters.inject { |a, b| a | b }
|
96
|
+
filter.prefix.should == test_case[:prefix]
|
97
|
+
filter.suffix.should == test_case[:suffix]
|
98
|
+
end
|
99
|
+
end.call(test_case_outer)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "negated Hx::Path::Selectors" do
|
104
|
+
before :each do
|
105
|
+
@pattern = ~Hx::Path.parse_pattern("foo*bar")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should be possible" do
|
109
|
+
@pattern.should be_a_kind_of(Hx::Path::Selector)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should reject what they match" do
|
113
|
+
@pattern.should_not accept("foobar")
|
114
|
+
@pattern.should accept("hoge")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should have empty prefix and suffix" do
|
118
|
+
@pattern.prefix.should == ""
|
119
|
+
@pattern.suffix.should == ""
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "Hx::Path::Selector conjunctions" do
|
124
|
+
it "should be possible" do
|
125
|
+
filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
|
126
|
+
filter = filters.inject { |a, b| a & b }
|
127
|
+
filter.should be_a_kind_of(Hx::Path::Selector)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should accept only paths matching both filters" do
|
131
|
+
filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
|
132
|
+
filter = filters.inject { |a, b| a & b }
|
133
|
+
filter.should accept("foobar")
|
134
|
+
filter.should accept("fooxbar")
|
135
|
+
filter.should_not accept("lemur")
|
136
|
+
filter.should_not accept("foobear")
|
137
|
+
filter.should_not accept("rebar")
|
138
|
+
end
|
139
|
+
|
140
|
+
for test_case_outer in PATHFILTER_PREFIX_CASES
|
141
|
+
Proc.new do |test_case|
|
142
|
+
it "should produce optimal prefixes and suffixes" do
|
143
|
+
filters = test_case[:patterns].map { |p| Hx::Path.parse_pattern(p) }
|
144
|
+
filter = filters.inject { |a, b| a & b }
|
145
|
+
filter.prefix.should == test_case[:prefix]
|
146
|
+
filter.suffix.should == test_case[:suffix]
|
147
|
+
end
|
148
|
+
end.call(test_case_outer)
|
149
|
+
end
|
150
|
+
end
|
data/spec/site_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -4,6 +4,10 @@ require 'hx'
|
|
4
4
|
require 'ostruct'
|
5
5
|
require 'spec'
|
6
6
|
require 'spec/autorun'
|
7
|
+
begin
|
8
|
+
require 'rubygems'
|
9
|
+
rescue LoadError
|
10
|
+
end
|
7
11
|
|
8
12
|
class FakeInput
|
9
13
|
include Hx::Filter
|
@@ -18,8 +22,8 @@ class FakeInput
|
|
18
22
|
@entries[path] = entry
|
19
23
|
end
|
20
24
|
|
21
|
-
def each_entry_path
|
22
|
-
@entries.each_key { |path| yield path }
|
25
|
+
def each_entry_path(selector)
|
26
|
+
@entries.each_key { |path| yield path if selector.accept? path }
|
23
27
|
self
|
24
28
|
end
|
25
29
|
|
@@ -32,6 +36,12 @@ class FakeInput
|
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
39
|
+
Spec::Matchers.define :accept do |value|
|
40
|
+
match do |acceptor|
|
41
|
+
acceptor.accept?(value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
35
45
|
Spec::Runner.configure do |config|
|
36
46
|
|
37
47
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MenTaLguY
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-04-25 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,21 +48,23 @@ files:
|
|
48
48
|
- lib/hx/backend/couchdb.rb
|
49
49
|
- lib/hx/backend/hobix.rb
|
50
50
|
- lib/hx/backend/rawfiles.rb
|
51
|
-
- lib/hx/
|
51
|
+
- lib/hx/cli.rb
|
52
52
|
- lib/hx/listing/limit.rb
|
53
53
|
- lib/hx/listing/paginate.rb
|
54
54
|
- lib/hx/listing/recursiveindex.rb
|
55
55
|
- lib/hx/output/liquidtemplate.rb
|
56
|
+
- lib/hx/path.rb
|
56
57
|
- lib/hx/rack.rb
|
57
58
|
- lib/hx/rack/application.rb
|
59
|
+
- loc.sh
|
58
60
|
- spec/cache_spec.rb
|
59
61
|
- spec/hx_dummy.rb
|
60
62
|
- spec/hx_dummy2.rb
|
61
63
|
- spec/nullinput_spec.rb
|
62
64
|
- spec/overlay_spec.rb
|
63
|
-
- spec/pathfilter_spec.rb
|
64
65
|
- spec/pathops_spec.rb
|
65
66
|
- spec/rack_spec.rb
|
67
|
+
- spec/selector_spec.rb
|
66
68
|
- spec/site_spec.rb
|
67
69
|
- spec/spec.opts
|
68
70
|
- spec/spec_helper.rb
|
@@ -98,10 +100,10 @@ test_files:
|
|
98
100
|
- spec/spec_helper.rb
|
99
101
|
- spec/cache_spec.rb
|
100
102
|
- spec/hx_dummy.rb
|
101
|
-
- spec/pathfilter_spec.rb
|
102
103
|
- spec/nullinput_spec.rb
|
103
104
|
- spec/site_spec.rb
|
104
105
|
- spec/hx_dummy2.rb
|
105
106
|
- spec/rack_spec.rb
|
106
107
|
- spec/overlay_spec.rb
|
107
108
|
- spec/pathops_spec.rb
|
109
|
+
- spec/selector_spec.rb
|
data/spec/pathfilter_spec.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
require 'hx'
|
4
|
-
|
5
|
-
describe Hx::PathSubset::Predicate do
|
6
|
-
it "accepts anything when the accept and reject patterns are nil" do
|
7
|
-
filter = Hx::PathSubset::Predicate.new(nil, nil)
|
8
|
-
filter.accept?("blah").should be_true
|
9
|
-
end
|
10
|
-
|
11
|
-
it "accepts only paths matching the accept pattern when it is specified" do
|
12
|
-
filter = Hx::PathSubset::Predicate.new("foo", nil)
|
13
|
-
filter.accept?("foo").should be_true
|
14
|
-
filter.accept?("bar").should be_false
|
15
|
-
end
|
16
|
-
|
17
|
-
it "accepts only paths not matching reject, when only that is specified" do
|
18
|
-
filter = Hx::PathSubset::Predicate.new(nil, "foo")
|
19
|
-
filter.accept?("foo").should be_false
|
20
|
-
filter.accept?("bar").should be_true
|
21
|
-
end
|
22
|
-
|
23
|
-
it "matches the difference of accept and reject when both are specified" do
|
24
|
-
filter = Hx::PathSubset::Predicate.new("foo/*", "foo/bar")
|
25
|
-
filter.accept?("foo/bar").should be_false
|
26
|
-
filter.accept?("foo/baz").should be_true
|
27
|
-
filter.accept?("bar").should be_false
|
28
|
-
end
|
29
|
-
|
30
|
-
it "shouldn't match across slashes with single star" do
|
31
|
-
filter = Hx::PathSubset::Predicate.new("foo/*", nil)
|
32
|
-
filter.accept?("bar").should be_false
|
33
|
-
filter.accept?("foo").should be_false
|
34
|
-
filter.accept?("foo/bar").should be_true
|
35
|
-
filter.accept?("foo/bar/baz").should be_false
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should match across slashes with double star" do
|
39
|
-
filter = Hx::PathSubset::Predicate.new("foo/**", nil)
|
40
|
-
filter.accept?("bar").should be_false
|
41
|
-
filter.accept?("foo").should be_false
|
42
|
-
filter.accept?("foo/bar").should be_true
|
43
|
-
filter.accept?("foo/bar/baz").should be_true
|
44
|
-
end
|
45
|
-
end
|