roger 1.1.3 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +2 -0
  3. data/.rubocop.yml +47 -0
  4. data/.travis.yml +1 -5
  5. data/CHANGELOG.md +8 -0
  6. data/Gemfile +3 -3
  7. data/Rakefile +10 -4
  8. data/bin/roger +1 -1
  9. data/doc/mockupfile.md +97 -0
  10. data/doc/templating.md +5 -1
  11. data/examples/default_template/Gemfile +1 -1
  12. data/lib/roger/cli.rb +41 -36
  13. data/lib/roger/cli/command.rb +2 -4
  14. data/lib/roger/cli/generate.rb +1 -0
  15. data/lib/roger/cli/release.rb +2 -2
  16. data/lib/roger/cli/serve.rb +11 -11
  17. data/lib/roger/cli/test.rb +6 -5
  18. data/lib/roger/extractor.rb +42 -43
  19. data/lib/roger/generators.rb +27 -19
  20. data/lib/roger/generators/generator.rb +7 -10
  21. data/lib/roger/generators/new.rb +56 -41
  22. data/lib/roger/generators/templates/generator.tt +5 -5
  23. data/lib/roger/helpers/get_callable.rb +15 -14
  24. data/lib/roger/helpers/logging.rb +35 -13
  25. data/lib/roger/mockupfile.rb +13 -23
  26. data/lib/roger/project.rb +41 -34
  27. data/lib/roger/rack/roger.rb +28 -29
  28. data/lib/roger/rack/sleep.rb +4 -5
  29. data/lib/roger/release.rb +95 -72
  30. data/lib/roger/release/cleaner.rb +14 -13
  31. data/lib/roger/release/finalizers.rb +10 -10
  32. data/lib/roger/release/finalizers/dir.rb +17 -19
  33. data/lib/roger/release/finalizers/git_branch.rb +76 -38
  34. data/lib/roger/release/finalizers/rsync.rb +60 -49
  35. data/lib/roger/release/finalizers/zip.rb +32 -29
  36. data/lib/roger/release/injector.rb +43 -37
  37. data/lib/roger/release/processors.rb +24 -22
  38. data/lib/roger/release/processors/mockup.rb +97 -69
  39. data/lib/roger/release/processors/url_relativizer.rb +57 -30
  40. data/lib/roger/release/scm.rb +30 -27
  41. data/lib/roger/release/scm/git.rb +101 -92
  42. data/lib/roger/resolver.rb +86 -61
  43. data/lib/roger/server.rb +52 -27
  44. data/lib/roger/template.rb +102 -74
  45. data/lib/roger/test.rb +16 -13
  46. data/lib/roger/version.rb +3 -2
  47. data/roger.gemspec +9 -5
  48. data/test/helpers/cli.rb +17 -15
  49. data/test/project/Gemfile +2 -2
  50. data/test/project/html/formats/csv.rcsv +0 -0
  51. data/test/project/lib/generators/test.rb +2 -3
  52. data/test/project/lib/tests/fail/fail.rb +5 -6
  53. data/test/project/lib/tests/noop/lib/cli.rb +2 -1
  54. data/test/project/lib/tests/noop/lib/test.rb +5 -5
  55. data/test/project/lib/tests/noop/noop.rb +2 -1
  56. data/test/project/lib/tests/succeed/succeed.rb +5 -6
  57. data/test/unit/cli/cli_base_test.rb +2 -3
  58. data/test/unit/cli/cli_generate_test.rb +9 -10
  59. data/test/unit/cli/cli_serve_test.rb +22 -18
  60. data/test/unit/cli/cli_test_test.rb +13 -15
  61. data/test/unit/cli/cli_version_test.rb +4 -4
  62. data/test/unit/generators_test.rb +8 -10
  63. data/test/unit/helpers/logging_test.rb +64 -0
  64. data/test/unit/rack/roger_test.rb +21 -0
  65. data/test/unit/release/cleaner_test.rb +23 -19
  66. data/test/unit/release/finalizers/git_branch_test.rb +2 -1
  67. data/test/unit/release/finalizers/zip_test.rb +48 -0
  68. data/test/unit/release/mockup_test.rb +48 -0
  69. data/test/unit/release/processors_test.rb +19 -19
  70. data/test/unit/release_test.rb +15 -14
  71. data/test/unit/resolver_test.rb +21 -14
  72. data/test/unit/server_test.rb +31 -0
  73. data/test/unit/template_test.rb +58 -36
  74. data/test/unit/test_test.rb +3 -2
  75. metadata +35 -9
  76. data/test/Mockupfile-syntax.rb +0 -93
@@ -1,24 +1,24 @@
1
- require 'rack'
1
+ require "rack"
2
2
  require File.dirname(__FILE__) + "/template"
3
3
  require File.dirname(__FILE__) + "/rack/roger"
4
4
 
5
- require 'webrick'
6
- require 'webrick/https'
5
+ require "webrick"
6
+ require "webrick/https"
7
7
 
8
8
  module Roger
9
+ # The Roger webserver. Initializes a rack server.
9
10
  class Server
10
-
11
11
  attr_reader :server_options
12
12
 
13
13
  attr_reader :project
14
14
 
15
15
  attr_accessor :port, :handler, :host
16
16
 
17
- def initialize(project, options={})
18
- @stack = initialize_rack_builder
19
-
17
+ def initialize(project, options = {})
20
18
  @project = project
21
19
 
20
+ @stack = initialize_rack_builder
21
+
22
22
  @server_options = {}
23
23
 
24
24
  # Defaults
@@ -32,28 +32,28 @@ module Roger
32
32
  # Sets the options, this is a separate method as we want to override certain
33
33
  # things set in the mockupfile from the commandline
34
34
  def set_options(options)
35
- self.port = options[:port] if options.has_key?(:port)
36
- self.handler = options[:handler] if options.has_key?(:handler)
37
- self.host = options[:host] if options.has_key?(:host)
35
+ self.port = options[:port] if options.key?(:port)
36
+ self.handler = options[:handler] if options.key?(:handler)
37
+ self.host = options[:host] if options.key?(:host)
38
38
  end
39
39
 
40
40
  # Use the specified Rack middleware
41
41
  #
42
42
  # @see ::Rack::Builder#use
43
43
  def use(*args, &block)
44
- @stack.use *args, &block
44
+ @stack.use(*args, &block)
45
45
  end
46
46
 
47
47
  # Use the map handler to map endpoints to certain urls
48
48
  #
49
49
  # @see ::Rack::Builder#map
50
50
  def map(*args, &block)
51
- @stack.map *args, &block
51
+ @stack.map(*args, &block)
52
52
  end
53
53
 
54
54
  def run!
55
55
  project.mode = :server
56
- self.handler.run self.application, self.server_options do |server|
56
+ handler.run application, server_options do |server|
57
57
  trap(:INT) do
58
58
  ## Use thins' hard #stop! if available, otherwise just #stop
59
59
  server.respond_to?(:stop!) ? server.stop! : server.stop
@@ -63,21 +63,21 @@ module Roger
63
63
  ensure
64
64
  project.mode = nil
65
65
  end
66
- alias :run :run!
66
+ alias_method :run, :run!
67
67
 
68
68
  def port=(p)
69
- @port = self.server_options[:Port] = p
69
+ @port = server_options[:Port] = p
70
70
  end
71
71
 
72
72
  def host=(h)
73
- @host = self.server_options[:Host] = h
73
+ @host = server_options[:Host] = h
74
74
  end
75
75
 
76
76
  def handler=(h)
77
77
  if h.respond_to?(:run)
78
78
  @handler = h
79
79
  else
80
- @handler = self.get_handler(h)
80
+ @handler = get_handler(h)
81
81
  end
82
82
  end
83
83
 
@@ -87,7 +87,7 @@ module Roger
87
87
  def application
88
88
  return @app if @app
89
89
 
90
- @stack.run Rack::Roger.new(self.project)
90
+ @stack.run Rack::Roger.new(project)
91
91
 
92
92
  @app = @stack
93
93
  end
@@ -96,7 +96,25 @@ module Roger
96
96
  #
97
97
  # @return ::Rack::Builder instance
98
98
  def initialize_rack_builder
99
+ roger_env = Class.new do
100
+ class << self
101
+ attr_accessor :project
102
+ end
103
+
104
+ def initialize(app)
105
+ @app = app
106
+ end
107
+
108
+ def call(env)
109
+ env["roger.project"] = self.class.project
110
+ @app.call(env)
111
+ end
112
+ end
113
+
114
+ roger_env.project = project
115
+
99
116
  builder = ::Rack::Builder.new
117
+ builder.use roger_env
100
118
  builder.use ::Rack::ShowExceptions
101
119
  builder.use ::Rack::Lint
102
120
  builder.use ::Rack::ConditionalGet
@@ -108,23 +126,30 @@ module Roger
108
126
  # Get the actual handler for use in the server
109
127
  # Will always return a handler, it will try to use the fallbacks
110
128
  def get_handler(preferred_handler_name = nil)
111
- servers = %w[puma mongrel thin webrick]
129
+ servers = %w(puma mongrel thin webrick)
112
130
  servers.unshift(preferred_handler_name) if preferred_handler_name
113
131
 
132
+ handler, server_name = detect_valid_handler(servers)
133
+
134
+ if preferred_handler_name && server_name != preferred_handler_name
135
+ puts "Handler '#{preferred_handler_name}' not found, using fallback ('#{handler.inspect}')."
136
+ end
137
+ handler
138
+ end
139
+
140
+ # See what handlers work
141
+ def detect_valid_handler(servers)
114
142
  handler = nil
115
- while((server_name = servers.shift) && handler === nil) do
143
+ while (server_name = servers.shift) && handler.nil?
116
144
  begin
117
145
  handler = ::Rack::Handler.get(server_name)
146
+ return [handler, server_name]
118
147
  rescue LoadError
148
+ handler = nil
119
149
  rescue NameError
150
+ handler = nil
120
151
  end
121
152
  end
122
-
123
- if preferred_handler_name && server_name != preferred_handler_name
124
- puts "Handler '#{preferred_handler_name}' not found, using fallback ('#{handler.inspect}')."
125
- end
126
- handler
127
153
  end
128
-
129
154
  end
130
- end
155
+ end
@@ -1,56 +1,53 @@
1
- require 'tilt'
2
- require 'mime/types'
3
- require 'yaml'
4
- require 'ostruct'
1
+ require "tilt"
2
+ require "mime/types"
3
+ require "yaml"
4
+ require "ostruct"
5
5
 
6
6
  # We're enforcing Encoding to UTF-8
7
7
  Encoding.default_external = "UTF-8"
8
8
 
9
9
  module Roger
10
-
10
+ # Roger template processing class
11
11
  class Template
12
-
13
12
  # The source
14
13
  attr_accessor :source
15
-
14
+
16
15
  # Store the frontmatter
17
16
  attr_accessor :data
18
-
17
+
19
18
  # The actual Tilt template
20
19
  attr_accessor :template
21
-
20
+
22
21
  # The path to the source file for this template
23
22
  attr_accessor :source_path
24
-
23
+
25
24
  class << self
26
25
  def open(path, options = {})
27
- raise "Unknown file #{path}" unless File.exist?(path)
28
- self.new(File.read(path), options.update(:source_path => path))
29
- end
26
+ fail "Unknown file #{path}" unless File.exist?(path)
27
+ new(File.read(path), options.update(source_path: path))
28
+ end
30
29
  end
31
-
32
-
33
- # @option options [String,Pathname] :source_path The path to the source of the template being processed
30
+
31
+ # @option options [String,Pathname] :source_path The path to
32
+ # the source of the template being processed
34
33
  # @option options [String,Pathname] :layouts_path The path to where all layouts reside
35
- # @option options [String,Pathname] :partials_path The path to where all partials reside
34
+ # @option options [String,Pathname] :partials_path The path to where all partials reside
36
35
  def initialize(source, options = {})
37
36
  @options = options
38
37
 
39
38
  self.source_path = options[:source_path]
40
39
  self.data, self.source = extract_front_matter(source)
41
- self.template = Tilt.new(self.source_path.to_s){ self.source }
42
-
43
- if self.data[:layout] && layout_template_path = self.find_template(self.data[:layout], :layouts_path)
44
- @layout_template = Tilt.new(layout_template_path.to_s)
45
- end
40
+ self.template = Tilt.new(source_path.to_s) { self.source }
41
+
42
+ initialize_layout
46
43
  end
47
-
44
+
48
45
  def render(env = {})
49
46
  context = TemplateContext.new(self, env)
50
-
47
+
51
48
  if @layout_template
52
- content_for_layout = self.template.render(context, {}) # yields
53
-
49
+ content_for_layout = template.render(context, {}) # yields
50
+
54
51
  @layout_template.render(context, {}) do |content_for|
55
52
  if content_for
56
53
  context._content_for_blocks[content_for]
@@ -59,26 +56,28 @@ module Roger
59
56
  end
60
57
  end
61
58
  else
62
- self.template.render(context, {})
59
+ template.render(context, {})
63
60
  end
64
61
  end
65
-
62
+
66
63
  def find_template(name, path_type)
67
- raise(ArgumentError, "path_type must be one of :partials_path or :layouts_path") unless [:partials_path, :layouts_path].include?(path_type)
64
+ unless [:partials_path, :layouts_path].include?(path_type)
65
+ fail(ArgumentError, "path_type must be one of :partials_path or :layouts_path")
66
+ end
68
67
 
69
68
  return nil unless @options[path_type]
70
69
 
71
- @resolvers ||= {}
70
+ @resolvers ||= {}
72
71
  @resolvers[path_type] ||= Resolver.new(@options[path_type])
73
-
74
- @resolvers[path_type].find_template(name, :preferred_extension => self.target_extension)
72
+
73
+ @resolvers[path_type].find_template(name, preferred_extension: target_extension)
75
74
  end
76
75
 
77
76
  # Try to infer the final extension of the output file.
78
77
  def target_extension
79
78
  return @target_extension if @target_extension
80
79
 
81
- if type = MIME::Types[self.target_mime_type].first
80
+ if type = MIME::Types[target_mime_type].first
82
81
  # Dirty little hack to enforce the use of .html instead of .htm
83
82
  if type.sub_type == "html"
84
83
  @target_extension = "html"
@@ -86,49 +85,68 @@ module Roger
86
85
  @target_extension = type.extensions.first
87
86
  end
88
87
  else
89
- @target_extension = File.extname(self.source_path.to_s).sub(/^\./, "")
88
+ @target_extension = File.extname(source_path.to_s).sub(/^\./, "")
90
89
  end
91
90
  end
92
91
 
93
92
  def source_extension
94
- parts = File.basename(File.basename(self.source_path.to_s)).split(".")
93
+ parts = File.basename(File.basename(source_path.to_s)).split(".")
95
94
  if parts.size > 2
96
95
  parts[-2..-1].join(".")
97
96
  else
98
- File.extname(self.source_path.to_s).sub(/^\./, "")
97
+ File.extname(source_path.to_s).sub(/^\./, "")
99
98
  end
100
99
  end
101
100
 
102
101
  # Try to figure out the mime type based on the Tilt class and if that doesn't
103
102
  # work we try to infer the type by looking at extensions (needed for .erb)
104
103
  def target_mime_type
105
- mime = self.template.class.default_mime_type
106
- return mime if mime
107
-
108
- path = File.basename(self.source_path.to_s)
109
- mime = MIME::Types.type_for(path).first
110
- return mime.to_s if mime
104
+ mime =
105
+ mime_type_from_template ||
106
+ mime_type_from_filename ||
107
+ mime_type_from_sub_extension
111
108
 
112
- parts = File.basename(path).split(".")
113
- if parts.size > 2
114
- mime = MIME::Types.type_for(parts[0..-2].join(".")).first
115
- return mime.to_s if mime
116
- else
117
- nil
118
- end
109
+ mime.to_s if mime
119
110
  end
120
-
111
+
121
112
  protected
122
113
 
114
+ def initialize_layout
115
+ return unless data[:layout]
116
+ layout_template_path = find_template(data[:layout], :layouts_path)
117
+
118
+ @layout_template = Tilt.new(layout_template_path.to_s) if layout_template_path
119
+ end
120
+
121
+ def mime_type_from_template
122
+ template.class.default_mime_type
123
+ end
124
+
125
+ def mime_type_from_filename
126
+ path = File.basename(source_path.to_s)
127
+ MIME::Types.type_for(path).first
128
+ end
129
+
130
+ # Will get mime_type from source_path extension
131
+ # but it will only look at the second extension so
132
+ # .html.erb will look at .html
133
+ def mime_type_from_sub_extension
134
+ parts = File.basename(source_path.to_s).split(".")
135
+ MIME::Types.type_for(parts[0..-2].join(".")).first if parts.size > 2
136
+ end
137
+
123
138
  # Get the front matter portion of the file and extract it.
124
139
  def extract_front_matter(source)
125
140
  fm_regex = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
126
-
141
+
127
142
  if match = source.match(fm_regex)
128
143
  source = source.sub(fm_regex, "")
129
144
 
130
145
  begin
131
- data = (YAML.load(match[1]) || {}).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
146
+ data = (YAML.load(match[1]) || {}).inject({}) do |memo, (k, v)|
147
+ memo[k.to_sym] = v
148
+ memo
149
+ end
132
150
  rescue *YAML_ERRORS => e
133
151
  puts "YAML Exception: #{e.message}"
134
152
  return false
@@ -141,20 +159,21 @@ module Roger
141
159
  rescue
142
160
  [{}, source]
143
161
  end
144
-
145
162
  end
146
-
163
+
164
+ # The context that is passed to all templates
147
165
  class TemplateContext
148
166
  attr_accessor :_content_for_blocks
149
167
 
150
- def initialize(template, env={})
168
+ def initialize(template, env = {})
151
169
  @_content_for_blocks = {}
152
- @_template, @_env = template, env
170
+ @_template = template
171
+ @_env = env
153
172
 
154
173
  # Block counter to make sure erbtemp binding is always unique
155
174
  @block_counter = 0
156
175
  end
157
-
176
+
158
177
  # The current Roger::Template in use
159
178
  def template
160
179
  @_template
@@ -162,9 +181,9 @@ module Roger
162
181
 
163
182
  # Access to the front-matter of the document (if any)
164
183
  def document
165
- @_data ||= OpenStruct.new(self.template.data)
184
+ @_data ||= OpenStruct.new(template.data)
166
185
  end
167
-
186
+
168
187
  # The current environment variables.
169
188
  def env
170
189
  @_env
@@ -186,40 +205,49 @@ module Roger
186
205
  @_content_for_blocks[block_name] = capture(&block)
187
206
  end
188
207
 
208
+ # rubocop:disable Lint/Eval
189
209
  def capture(&block)
190
- raise ArgumentError, "content_for works only with ERB Templates" if !self.template.template.kind_of?(Tilt::ERBTemplate)
210
+ unless template.template.is_a?(Tilt::ERBTemplate)
211
+ fail ArgumentError, "content_for works only with ERB Templates"
212
+ end
191
213
 
192
214
  @block_counter += 1
193
215
  counter = @block_counter
194
216
 
195
217
  eval "@_erbout_tmp#{counter} = _erbout", block.binding
196
218
  eval "_erbout = \"\"", block.binding
197
- t = Tilt::ERBTemplate.new(){ "<%= yield %>" }
219
+ t = Tilt::ERBTemplate.new { "<%= yield %>" }
198
220
  t.render(&block)
199
221
  ensure
200
222
  eval "_erbout = @_erbout_tmp#{counter}", block.binding
201
223
  end
202
-
203
- def partial(name, options = {}, &block)
204
- if template_path = self.template.find_template(name, :partials_path)
205
- partial_template = Tilt.new(template_path.to_s)
206
- if block_given?
207
- block_content = capture(&block)
208
- else
209
- block_content = ""
210
- end
211
- out = partial_template.render(self, options[:locals] || {}){ block_content }
212
224
 
225
+ def partial(name, options = {}, &block)
226
+ template_path = template.find_template(name, :partials_path)
227
+ if template_path
228
+ out = render_partial(template_path, options, &block)
213
229
  if block_given?
214
230
  eval "_erbout.concat(#{out.dump})", block.binding
215
231
  else
216
232
  out
217
233
  end
218
234
  else
219
- raise ArgumentError, "No such partial #{name}, referenced from #{self.template.source_path}"
235
+ fail ArgumentError, "No such partial #{name}, referenced from #{template.source_path}"
236
+ end
237
+ end
238
+ # rubocop:enable Lint/Eval
239
+
240
+ protected
241
+
242
+ # Capture a block and render the partial
243
+ def render_partial(template_path, options, &block)
244
+ partial_template = Tilt.new(template_path.to_s)
245
+ if block_given?
246
+ block_content = capture(&block)
247
+ else
248
+ block_content = ""
220
249
  end
250
+ partial_template.render(self, options[:locals] || {}) { block_content }
221
251
  end
222
-
223
252
  end
224
-
225
253
  end