hx 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.2
1
+ 0.8.3
data/lib/hx/cli.rb CHANGED
@@ -42,6 +42,7 @@ Usage: hx [--config CONFIG_FILE] [upgen]
42
42
  hx [--config CONFIG_FILE] regen
43
43
  hx [--config CONFIG_FILE] post[up] SOURCE:PATH
44
44
  hx [--config CONFIG_FILE] edit[up] SOURCE:PATH
45
+ hx [--config CONFIG_FILE] list SOURCE:PATTERN
45
46
 
46
47
  EOS
47
48
 
@@ -128,31 +129,47 @@ def self.cmd_postup(site, entry_spec)
128
129
  cmd_upgen(site)
129
130
  end
130
131
 
131
- def self.parse_entry_spec(entry_spec)
132
+ def self._parse_entry_spec(site, entry_spec)
132
133
  source_name, path = entry_spec.split(':', 2)
134
+ source = site.sources[source_name]
135
+ raise ArgumentError, "No such source #{source_name}" unless source
136
+ return source, path
137
+ end
138
+
139
+ def self.parse_entry_spec(site, entry_spec)
140
+ source, path = _parse_entry_spec(site, entry_spec)
133
141
  raise "Invalid entry specification #{entry_spec}" unless path
134
- return source_name, path
142
+ return source, path
143
+ end
144
+
145
+ def self.parse_entry_pattern(site, entry_pattern)
146
+ source, pattern = _parse_entry_spec(site, entry_pattern)
147
+ pattern = "**" unless pattern
148
+ selector = Hx::Path.parse_pattern(pattern)
149
+ return source, selector
135
150
  end
136
151
 
137
152
  def self.cmd_edit(site, entry_spec)
138
- source_name, path = parse_entry_spec(entry_spec)
139
- do_edit(site, source_name, path, nil)
153
+ source, path = parse_entry_spec(site, entry_spec)
154
+ do_edit(site, source, path, nil)
140
155
  end
141
156
 
142
157
  def self.cmd_post(site, entry_spec)
143
- source_name, path = parse_entry_spec(entry_spec)
158
+ source, path = parse_entry_spec(site, entry_spec)
144
159
  prototype = {
145
160
  'title' => Hx.make_default_title(site.options, path),
146
161
  'author' => Hx.get_default_author(site.options),
147
162
  'content' => ""
148
163
  }
149
- do_edit(site, source_name, path, prototype)
164
+ do_edit(site, source, path, prototype)
150
165
  end
151
166
 
152
- def self.do_edit(site, source_name, path, prototype)
153
- source = site.sources[source_name]
154
- raise ArgumentError, "No such source #{source_name}" unless source
167
+ def self.cmd_list(site, entry_spec)
168
+ source, selector = parse_entry_pattern(site, entry_spec)
169
+ source.each_entry_path(selector) { |path| puts path }
170
+ end
155
171
 
172
+ def self.do_edit(site, source, path, prototype)
156
173
  catch(:unchanged) do
157
174
  begin
158
175
  tempfile = Tempfile.new('hx-entry')
@@ -74,7 +74,7 @@ class LiquidTemplate
74
74
  template_file = template_dir + "#{options[:template]}.liquid"
75
75
  @template = Liquid::Template.parse(template_file.read)
76
76
  @extension = options[:extension]
77
- @mime_type = options[:mime_type]
77
+ @content_type = options[:content_type]
78
78
  @strip_extension_re = nil
79
79
  @strip_extension_re = /\.#{Regexp.quote(@extension)}$/ if @extension
80
80
  end
@@ -99,7 +99,7 @@ class LiquidTemplate
99
99
  'entry' => entry
100
100
  )
101
101
  end
102
- output_entry['mime_type'] = @mime_type if @mime_type
102
+ output_entry['content_type'] = @content_type if @content_type
103
103
  if entry.has_key? 'updated'
104
104
  output_entry['created'] = output_entry['updated'] = entry['updated']
105
105
  end
data/lib/hx/path.rb CHANGED
@@ -25,11 +25,6 @@ module Hx
25
25
  module Path
26
26
 
27
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
28
  def accept?(path)
34
29
  raise NotImplementedError, "#{self.class}#accept? not implemented"
35
30
  end
@@ -49,37 +44,25 @@ end
49
44
 
50
45
  class All
51
46
  include Selector
52
-
53
- REGEXP = Regexp.new("^.*$")
54
-
55
- def regexp ; REGEXP ; end
56
47
  def accept?(path) ; true ; end
57
48
  end
58
49
 
59
50
  ALL = All.new
60
51
 
61
- class Literal
52
+ class Pattern
62
53
  include Selector
63
54
 
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)}$")
55
+ def initialize(tokens)
56
+ @regexp = Regexp.new("^#{tokens.map { |token|
57
+ case token
58
+ when :doublestar; '.*'
59
+ when :star; '[^/]*'
60
+ else; Regexp.quote(token)
61
+ end
62
+ }}$")
78
63
  end
79
64
 
80
- def accept?(path)
81
- @value == path
82
- end
65
+ def accept?(path) ; !!(path =~ @regexp) ; end
83
66
  end
84
67
 
85
68
  def self.parse_pattern(pattern_string)
@@ -91,78 +74,35 @@ def self.parse_pattern(pattern_string)
91
74
  else; token
92
75
  end
93
76
  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
77
+ Pattern.new(tokens)
110
78
  end
111
79
 
112
80
  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
81
+ Pattern.new([literal_string])
132
82
  end
133
83
 
134
84
  module Connective
135
85
  include Selector
136
86
 
137
- attr_reader :prefix
138
- attr_reader :suffix
139
-
140
87
  def initialize(*selectors)
141
88
  @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
89
  end
161
90
  end
162
91
 
163
92
  class Conjunction
164
93
  include Connective
165
94
 
95
+ def self.new(*selectors)
96
+ if selectors.any? { |s| All === s }
97
+ selectors.reject! { |s| All === s }
98
+ case selectors.size
99
+ when 0; return ALL
100
+ when 1; return selectors.first
101
+ end
102
+ end
103
+ super(*selectors)
104
+ end
105
+
166
106
  def accept?(path)
167
107
  @selectors.all? { |s| s.accept? path }
168
108
  end
@@ -171,24 +111,8 @@ end
171
111
  class Disjunction
172
112
  include Connective
173
113
 
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
114
  def accept?(path)
187
- if @regexp
188
- !!@regexp.match(path)
189
- else
190
- @selectors.any? { |s| s.accept? path }
191
- end
115
+ @selectors.any? { |s| s.accept? path }
192
116
  end
193
117
  end
194
118
 
@@ -78,13 +78,13 @@ class Application
78
78
  end
79
79
 
80
80
  if entry
81
- mime_type = entry['mime_type']
82
- unless mime_type
81
+ content_type = entry['content_type']
82
+ unless content_type
83
83
  effective_path =~ /(\.[^.]+)$/
84
- mime_type = ::Rack::Mime.mime_type($1 || '')
84
+ content_type = ::Rack::Mime.mime_type($1 || '')
85
85
  end
86
86
  content = entry['content'].to_s
87
- [200, {'Content-Type' => mime_type}, [content]]
87
+ [200, {'Content-Type' => content_type}, [content]]
88
88
  else
89
89
  message = "#{env['SCRIPT_NAME']}#{path} not found"
90
90
  [404, {'Content-Type' => "text/plain"}, [message]]
data/spec/rack_spec.rb CHANGED
@@ -30,22 +30,22 @@ describe Hx::Rack::Application do
30
30
  it "should infer content type from file extension by default" do
31
31
  cases = { "html" => "text/html",
32
32
  "jpeg" => "image/jpeg" }
33
- for extension, mime_type in cases
33
+ for extension, content_type in cases
34
34
  path = "blah.#{extension}"
35
35
  @input.add_entry(path, "")
36
36
  response = @service.get("/#{path}", :lint => true, :fatal => true)
37
37
  response.status.to_i.should == 200
38
- response['Content-Type'].should == mime_type
38
+ response['Content-Type'].should == content_type
39
39
  end
40
40
  end
41
41
 
42
42
  it "should allow entries to specify their mime type" do
43
43
  path = "blah.html"
44
- mime_type = "junk/garbage"
45
- @input.add_entry(path, "", 'mime_type' => mime_type)
44
+ content_type = "junk/garbage"
45
+ @input.add_entry(path, "", 'content_type' => content_type)
46
46
  response = @service.get("/#{path}", :lint => true, :fatal => true)
47
47
  response.status.to_i.should == 200
48
- response['Content-Type'].should == mime_type
48
+ response['Content-Type'].should == content_type
49
49
  end
50
50
 
51
51
  it "should redirect for directories with indices" do
@@ -7,72 +7,27 @@ describe Hx::Path::Pattern do
7
7
  Hx::Path::Pattern.should < Hx::Path::Selector
8
8
  end
9
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")
10
+ it "should accept or reject literal paths" do
11
+ pattern = Hx::Path.literal("foo/bar")
35
12
  pattern.should accept("foo/bar")
36
13
  pattern.should_not accept("foo/baz")
37
14
  end
38
15
 
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
16
+ it "should match single path components with stars" do
17
+ pattern = Hx::Path.parse_pattern("foo/*")
18
+ pattern.should_not accept("baz/eek")
19
+ pattern.should accept("foo/bar")
20
+ pattern.should_not accept("foo/bar/baz")
21
+ end
44
22
 
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
23
+ it "should match multiple path components with double stars" do
24
+ pattern = Hx::Path.parse_pattern("foo/**")
25
+ pattern.should_not accept("baz/eek")
26
+ pattern.should accept("foo/bar")
27
+ pattern.should accept("foo/bar/baz")
49
28
  end
50
29
  end
51
30
 
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
31
  describe "Hx::Path::Selector disjunctions" do
77
32
  it "should be possible" do
78
33
  filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
@@ -87,17 +42,6 @@ describe "Hx::Path::Selector disjunctions" do
87
42
  filter.should accept("abcdefg")
88
43
  filter.should_not accept("hoge")
89
44
  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
45
  end
102
46
 
103
47
  describe "negated Hx::Path::Selectors" do
@@ -113,11 +57,6 @@ describe "negated Hx::Path::Selectors" do
113
57
  @pattern.should_not accept("foobar")
114
58
  @pattern.should accept("hoge")
115
59
  end
116
-
117
- it "should have empty prefix and suffix" do
118
- @pattern.prefix.should == ""
119
- @pattern.suffix.should == ""
120
- end
121
60
  end
122
61
 
123
62
  describe "Hx::Path::Selector conjunctions" do
@@ -137,14 +76,10 @@ describe "Hx::Path::Selector conjunctions" do
137
76
  filter.should_not accept("rebar")
138
77
  end
139
78
 
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)
79
+ it "should optimize use of ALL" do
80
+ filter = Hx::Path.parse_pattern("foo")
81
+ (filter & Hx::Path::ALL).should equal(filter)
82
+ (Hx::Path::ALL & filter).should equal(filter)
83
+ (Hx::Path::ALL & Hx::Path::ALL).should equal(Hx::Path::ALL)
149
84
  end
150
85
  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.8.2
4
+ version: 0.8.3
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-04-25 00:00:00 -04:00
12
+ date: 2010-05-29 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency