roger 1.6.4 → 1.7.0
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 +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +12 -0
- data/Gemfile +4 -3
- data/Rakefile +1 -0
- data/doc/cli.md +12 -1
- data/doc/templating.md +9 -0
- data/lib/roger/cli/serve.rb +12 -8
- data/lib/roger/cli.rb +78 -5
- data/lib/roger/helpers/registration.rb +33 -0
- data/lib/roger/project.rb +14 -8
- data/lib/roger/rack/roger.rb +1 -1
- data/lib/roger/release/finalizers/dir.rb +10 -7
- data/lib/roger/release/finalizers/git_branch.rb +18 -32
- data/lib/roger/release/finalizers/rsync.rb +24 -23
- data/lib/roger/release/finalizers/zip.rb +16 -16
- data/lib/roger/release/finalizers.rb +3 -19
- data/lib/roger/release/processors/mockup.rb +17 -28
- data/lib/roger/release/processors/url_relativizer.rb +11 -13
- data/lib/roger/release/processors.rb +50 -22
- data/lib/roger/release/scm/git.rb +15 -15
- data/lib/roger/release.rb +12 -37
- data/lib/roger/renderer.rb +16 -8
- data/lib/roger/server.rb +59 -3
- data/lib/roger/template/helpers/partial.rb +6 -1
- data/lib/roger/version.rb +1 -1
- data/roger.gemspec +1 -1
- data/test/helpers/generators.rb +25 -0
- data/test/project/layouts/bracket.html.erb +1 -0
- data/test/project/partials/test/locals.html.erb +1 -0
- data/test/project/partials/test/max_depth.html.erb +1 -1
- data/test/project/partials/test/parent_template.html.erb +1 -0
- data/test/unit/cli/cli_base_test.rb +67 -0
- data/test/unit/cli/cli_generate_test.rb +0 -20
- data/test/unit/cli/cli_serve_test.rb +19 -4
- data/test/unit/generators_test.rb +5 -28
- data/test/unit/rack/roger_test.rb +19 -3
- data/test/unit/release/finalizers/rsync_test.rb +11 -9
- data/test/unit/release/processors/mockup_test.rb +12 -0
- data/test/unit/release_test.rb +27 -4
- data/test/unit/renderer/renderer_base_test.rb +24 -0
- data/test/unit/renderer/renderer_layout_test.rb +26 -2
- data/test/unit/renderer/renderer_partial_test.rb +12 -2
- data/test/unit/server_test.rb +32 -0
- data/test/unit/test_helper.rb +2 -7
- metadata +13 -4
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + "/../../renderer"
|
|
3
3
|
module Roger::Release::Processors
|
4
4
|
# The Mockup processor that will process all templates
|
5
5
|
class Mockup < Base
|
6
|
-
|
6
|
+
self.name = :mockup
|
7
7
|
|
8
8
|
MIME_TYPES_TO_EXTENSION = {
|
9
9
|
"text/html" => "html",
|
@@ -15,31 +15,31 @@ module Roger::Release::Processors
|
|
15
15
|
"application/json" => "json"
|
16
16
|
}
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def default_options
|
19
|
+
{
|
20
20
|
env: {},
|
21
21
|
match: ["**/*.{html,md,html.erb}"],
|
22
22
|
skip: [/\Astylesheets/, /\Ajavascripts/]
|
23
23
|
}
|
24
|
-
|
25
|
-
@options.update(options) if options
|
26
24
|
end
|
27
25
|
|
28
|
-
def
|
29
|
-
|
26
|
+
def project
|
27
|
+
release.project
|
28
|
+
end
|
30
29
|
|
31
|
-
|
30
|
+
def perform
|
31
|
+
@options[:env].update("roger.project" => project, "MOCKUP_PROJECT" => project)
|
32
32
|
|
33
|
-
log_call
|
33
|
+
log_call
|
34
34
|
|
35
|
-
release.get_files(options[:match], options[:skip]).each do |file_path|
|
35
|
+
release.get_files(@options[:match], @options[:skip]).each do |file_path|
|
36
36
|
release.log(self, " Extract: #{file_path}", true)
|
37
37
|
|
38
38
|
# Avoid rendering partials which can also be included
|
39
39
|
# in the roger.base_path
|
40
40
|
next if File.basename(file_path).start_with? "_"
|
41
41
|
|
42
|
-
|
42
|
+
run_on_file!(file_path, @options[:env])
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -62,7 +62,7 @@ module Roger::Release::Processors
|
|
62
62
|
partials_path: project.partial_path,
|
63
63
|
layouts_path: project.layouts_path
|
64
64
|
)
|
65
|
-
renderer.render(file_path)
|
65
|
+
renderer.render(file_path, project.options[:renderer] || {})
|
66
66
|
end
|
67
67
|
|
68
68
|
# Determines the output path for a mockup path with a certain template
|
@@ -92,25 +92,14 @@ module Roger::Release::Processors
|
|
92
92
|
|
93
93
|
protected
|
94
94
|
|
95
|
-
def
|
96
|
-
updated_options = {}
|
97
|
-
updated_options.update(@options)
|
98
|
-
|
99
|
-
updated_options.update(options) if options
|
100
|
-
|
101
|
-
updated_options[:env].update("roger.project" => project, "MOCKUP_PROJECT" => project)
|
102
|
-
|
103
|
-
updated_options
|
104
|
-
end
|
105
|
-
|
106
|
-
def log_call(release, options)
|
95
|
+
def log_call
|
107
96
|
release.log(self, "Processing mockup files")
|
108
97
|
|
109
|
-
release.log(self, " Matching: #{options[:match].inspect}", true)
|
110
|
-
release.log(self, " Skiping : #{options[:skip].inspect}", true)
|
111
|
-
release.log(self, " Env : #{options[:env].inspect}", true)
|
98
|
+
release.log(self, " Matching: #{@options[:match].inspect}", true)
|
99
|
+
release.log(self, " Skiping : #{@options[:skip].inspect}", true)
|
100
|
+
release.log(self, " Env : #{@options[:env].inspect}", true)
|
112
101
|
release.log(self, " Files :", true)
|
113
102
|
end
|
114
103
|
end
|
115
104
|
end
|
116
|
-
Roger::Release::Processors.register(
|
105
|
+
Roger::Release::Processors.register(Roger::Release::Processors::Mockup)
|
@@ -6,20 +6,18 @@ module Roger::Release::Processors
|
|
6
6
|
# The relativizer can be used to rewrite absolute paths in attributes to relative paths
|
7
7
|
# during release.
|
8
8
|
class UrlRelativizer < Base
|
9
|
-
|
10
|
-
|
9
|
+
self.name = :url_relativizer
|
10
|
+
|
11
|
+
def default_options
|
12
|
+
{
|
11
13
|
url_attributes: %w(src href action),
|
12
14
|
match: ["**/*.html"],
|
13
15
|
skip: []
|
14
16
|
}
|
15
|
-
|
16
|
-
@options.update(options) if options
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
log_call(release, options)
|
19
|
+
def perform
|
20
|
+
log_call
|
23
21
|
|
24
22
|
@resolver = Roger::Resolver.new(release.build_path)
|
25
23
|
|
@@ -32,10 +30,10 @@ module Roger::Release::Processors
|
|
32
30
|
|
33
31
|
protected
|
34
32
|
|
35
|
-
def log_call
|
36
|
-
log_message = "Relativizing all URLS in #{options[:match].inspect}"
|
37
|
-
log_message << "files in attributes #{options[:url_attributes].inspect},"
|
38
|
-
log_message << "skipping #{options[:skip].any? ? options[:skip].inspect : 'none'
|
33
|
+
def log_call
|
34
|
+
log_message = "Relativizing all URLS in #{@options[:match].inspect}"
|
35
|
+
log_message << "files in attributes #{@options[:url_attributes].inspect},"
|
36
|
+
log_message << "skipping #{@options[:skip].any? ? @options[:skip].inspect : 'none'}"
|
39
37
|
release.log(self, log_message)
|
40
38
|
end
|
41
39
|
|
@@ -73,4 +71,4 @@ module Roger::Release::Processors
|
|
73
71
|
end
|
74
72
|
end
|
75
73
|
|
76
|
-
Roger::Release::Processors.register(
|
74
|
+
Roger::Release::Processors.register(Roger::Release::Processors::UrlRelativizer)
|
@@ -1,30 +1,58 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module Processors
|
5
|
-
# Abstract Processor class
|
6
|
-
class Base
|
7
|
-
def initialize(options = {})
|
8
|
-
@options = {}
|
9
|
-
@options.update(options) if options
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(_release, _options = {})
|
13
|
-
fail ArgumentError, "Implement in subclass"
|
14
|
-
end
|
15
|
-
end
|
1
|
+
# Processors can perform any action on a release
|
2
|
+
module Roger::Release::Processors
|
3
|
+
extend Roger::Helpers::Registration
|
16
4
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
# Abstract Processor class
|
6
|
+
class Base
|
7
|
+
attr_reader :options, :release
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_writer :name
|
22
11
|
|
23
|
-
|
24
|
-
|
12
|
+
# Name of this processor
|
13
|
+
def name
|
14
|
+
@name || fail(ArgumentError, "Implement in subclass")
|
25
15
|
end
|
26
16
|
end
|
17
|
+
|
18
|
+
# Default options for this processor
|
19
|
+
def default_options
|
20
|
+
{}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Name of this processor.
|
24
|
+
# - Can be set by setting the :name config in the release block
|
25
|
+
# - Can be overwritten in implementation if needed
|
26
|
+
def name
|
27
|
+
options && options[:name] || self.class.name
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(release, options = {})
|
31
|
+
@release = release
|
32
|
+
@options = {}.update(default_options)
|
33
|
+
@options.update(options) if options
|
34
|
+
@options.update(my_project_options)
|
35
|
+
|
36
|
+
# Stop immideatly if we've been disabled
|
37
|
+
return if @options[:disable]
|
38
|
+
|
39
|
+
perform
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
# The options passed through the project. This can contain
|
45
|
+
# command line options
|
46
|
+
def my_project_options
|
47
|
+
project_options = release.project.options
|
48
|
+
project_options[:release] && project_options[:release][name] || {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def perform
|
52
|
+
fail ArgumentError, "Implement in subclass"
|
53
|
+
end
|
27
54
|
end
|
28
55
|
end
|
56
|
+
|
29
57
|
require File.dirname(__FILE__) + "/processors/mockup"
|
30
58
|
require File.dirname(__FILE__) + "/processors/url_relativizer"
|
@@ -6,6 +6,20 @@ module Roger
|
|
6
6
|
module Scm
|
7
7
|
# The GIT SCM implementation for Roger release
|
8
8
|
class Git < Base
|
9
|
+
# Find the .git dir in path and all it's parents
|
10
|
+
def self.find_git_dir(path)
|
11
|
+
path = Pathname.new(path).realpath
|
12
|
+
while path.parent != path && !(path + ".git").directory?
|
13
|
+
path = path.parent
|
14
|
+
end
|
15
|
+
|
16
|
+
path += ".git"
|
17
|
+
|
18
|
+
fail "Could not find suitable .git dir in #{path}" unless path.directory?
|
19
|
+
|
20
|
+
path
|
21
|
+
end
|
22
|
+
|
9
23
|
# @option config [String] :ref Ref to use for current tag
|
10
24
|
# @option config [String, Pathname] :path Path to working dir
|
11
25
|
def initialize(config = {})
|
@@ -51,7 +65,7 @@ module Roger
|
|
51
65
|
end
|
52
66
|
|
53
67
|
def git_dir
|
54
|
-
@git_dir ||= find_git_dir(@config[:path])
|
68
|
+
@git_dir ||= self.class.find_git_dir(@config[:path])
|
55
69
|
end
|
56
70
|
|
57
71
|
# Safely escaped git dir
|
@@ -96,20 +110,6 @@ module Roger
|
|
96
110
|
rescue RuntimeError
|
97
111
|
nil
|
98
112
|
end
|
99
|
-
|
100
|
-
# Find the git dir
|
101
|
-
def find_git_dir(path)
|
102
|
-
path = Pathname.new(path).realpath
|
103
|
-
while path.parent != path && !(path + ".git").directory?
|
104
|
-
path = path.parent
|
105
|
-
end
|
106
|
-
|
107
|
-
path += ".git"
|
108
|
-
|
109
|
-
fail "Could not find suitable .git dir in #{path}" unless path.directory?
|
110
|
-
|
111
|
-
path
|
112
|
-
end
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
data/lib/roger/release.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helpers/get_callable"
|
2
2
|
require File.dirname(__FILE__) + "/helpers/get_files"
|
3
3
|
require File.dirname(__FILE__) + "/helpers/logging"
|
4
|
+
require File.dirname(__FILE__) + "/helpers/registration"
|
4
5
|
|
5
6
|
require "shellwords"
|
6
7
|
|
@@ -12,18 +13,10 @@ module Roger
|
|
12
13
|
|
13
14
|
attr_reader :config, :project
|
14
15
|
|
15
|
-
attr_reader :
|
16
|
+
attr_reader :stack
|
16
17
|
|
17
18
|
class << self
|
18
19
|
include Roger::Helpers::GetCallable
|
19
|
-
|
20
|
-
def default_stack
|
21
|
-
[]
|
22
|
-
end
|
23
|
-
|
24
|
-
def default_finalizers
|
25
|
-
[[get_callable(:dir, Roger::Release::Finalizers.map), {}]]
|
26
|
-
end
|
27
20
|
end
|
28
21
|
|
29
22
|
# @option config [:git, :fixed] :scm The SCM to use (default = :git)
|
@@ -39,7 +32,7 @@ module Roger
|
|
39
32
|
real_project_path = project.path.realpath
|
40
33
|
defaults = {
|
41
34
|
scm: :git,
|
42
|
-
source_path:
|
35
|
+
source_path: project.html_path.realpath,
|
43
36
|
target_path: real_project_path + "releases",
|
44
37
|
build_path: real_project_path + "build",
|
45
38
|
cp: ["cp", "-RL"],
|
@@ -51,7 +44,6 @@ module Roger
|
|
51
44
|
|
52
45
|
@project = project
|
53
46
|
@stack = []
|
54
|
-
@finalizers = []
|
55
47
|
end
|
56
48
|
|
57
49
|
# Accessor for target_path
|
@@ -121,7 +113,7 @@ module Roger
|
|
121
113
|
# @examples
|
122
114
|
# release.finalize :zip
|
123
115
|
def finalize(finalizer, options = {})
|
124
|
-
@
|
116
|
+
@stack << [self.class.get_callable(finalizer, Roger::Release::Finalizers.map), options]
|
125
117
|
end
|
126
118
|
|
127
119
|
# Files to clean up in the build directory just before finalization happens
|
@@ -180,9 +172,6 @@ module Roger
|
|
180
172
|
# Run stack
|
181
173
|
run_stack!
|
182
174
|
|
183
|
-
# Run finalizers
|
184
|
-
run_finalizers!
|
185
|
-
|
186
175
|
# Cleanup
|
187
176
|
cleanup! if config[:cleanup_build]
|
188
177
|
ensure
|
@@ -262,16 +251,17 @@ module Roger
|
|
262
251
|
def validate_stack!
|
263
252
|
return if config[:blank]
|
264
253
|
|
265
|
-
mockup_options = {}
|
266
|
-
relativizer_options = {}
|
267
|
-
|
268
254
|
unless find_in_stack(Roger::Release::Processors::Mockup)
|
269
|
-
@stack.unshift([Roger::Release::Processors::Mockup.new,
|
255
|
+
@stack.unshift([Roger::Release::Processors::Mockup.new, {}])
|
270
256
|
end
|
271
257
|
|
272
|
-
# rubocop:disable Style/GuardClause
|
273
258
|
unless find_in_stack(Roger::Release::Processors::UrlRelativizer)
|
274
|
-
@stack.push([Roger::Release::Processors::UrlRelativizer.new,
|
259
|
+
@stack.push([Roger::Release::Processors::UrlRelativizer.new, {}])
|
260
|
+
end
|
261
|
+
|
262
|
+
# rubocop:disable Style/GuardClause
|
263
|
+
unless find_in_stack(Roger::Release::Finalizers::Dir)
|
264
|
+
@stack.push([Roger::Release::Finalizers::Dir.new, {}])
|
275
265
|
end
|
276
266
|
end
|
277
267
|
|
@@ -295,8 +285,6 @@ module Roger
|
|
295
285
|
end
|
296
286
|
|
297
287
|
def run_stack!
|
298
|
-
@stack = self.class.default_stack.dup if @stack.empty?
|
299
|
-
|
300
288
|
# call all objects in @stack
|
301
289
|
@stack.each do |task|
|
302
290
|
if task.is_a?(Array)
|
@@ -307,19 +295,6 @@ module Roger
|
|
307
295
|
end
|
308
296
|
end
|
309
297
|
|
310
|
-
# Will run all finalizers, if no finalizers are set it will take the
|
311
|
-
# default finalizers.
|
312
|
-
#
|
313
|
-
# If config[:blank] is true, it will not use the default finalizers
|
314
|
-
def run_finalizers!
|
315
|
-
@finalizers = self.class.default_finalizers.dup if @finalizers.empty? && !config[:blank]
|
316
|
-
|
317
|
-
# call all objects in @finalizes
|
318
|
-
@finalizers.each do |finalizer|
|
319
|
-
finalizer[0].call(self, finalizer[1])
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
298
|
def cleanup!
|
324
299
|
log(self, "Cleaning up build path #{build_path}")
|
325
300
|
rm_rf(build_path)
|
@@ -330,5 +305,5 @@ end
|
|
330
305
|
require File.dirname(__FILE__) + "/release/scm"
|
331
306
|
require File.dirname(__FILE__) + "/release/injector"
|
332
307
|
require File.dirname(__FILE__) + "/release/cleaner"
|
333
|
-
require File.dirname(__FILE__) + "/release/finalizers"
|
334
308
|
require File.dirname(__FILE__) + "/release/processors"
|
309
|
+
require File.dirname(__FILE__) + "/release/finalizers"
|
data/lib/roger/renderer.rb
CHANGED
@@ -111,8 +111,9 @@ module Roger
|
|
111
111
|
#
|
112
112
|
# If you just want to render an arbitrary file, use #render_file instead
|
113
113
|
#
|
114
|
-
# @option options [Hash] :locals
|
115
|
-
# @option options [String] :source
|
114
|
+
# @option options [Hash] :locals Locals to use during rendering
|
115
|
+
# @option options [String] :source The source for the template
|
116
|
+
# @option options [String, nil] :layout The default layout to use
|
116
117
|
def render(path, options = {}, &block)
|
117
118
|
template, layout = template_and_layout_for_render(path, options)
|
118
119
|
|
@@ -196,16 +197,23 @@ module Roger
|
|
196
197
|
template_type = current_template ? :partial : :template
|
197
198
|
template = template(path, options[:source], template_type)
|
198
199
|
|
199
|
-
|
200
|
-
if !current_template && template.data[:layout]
|
201
|
-
layout = template(template.data[:layout], nil, :layout)
|
202
|
-
else
|
203
|
-
layout = BlankTemplate.new
|
204
|
-
end
|
200
|
+
layout = layout_for_template(template, options)
|
205
201
|
|
206
202
|
[template, layout]
|
207
203
|
end
|
208
204
|
|
205
|
+
# Gets the layout for a specific template
|
206
|
+
def layout_for_template(template, options)
|
207
|
+
layout_name = template.data.key?(:layout) ? template.data[:layout] : options[:layout]
|
208
|
+
|
209
|
+
# Only attempt to load layout when:
|
210
|
+
# - Template is the toplevel template
|
211
|
+
# - A layout_name is available
|
212
|
+
return BlankTemplate.new if current_template || !layout_name
|
213
|
+
|
214
|
+
template(layout_name, nil, :layout)
|
215
|
+
end
|
216
|
+
|
209
217
|
# Will check the template nesting if we haven't already
|
210
218
|
# rendered this path before. If it has we'll throw an argumenteerror
|
211
219
|
def prevent_recursion!(template)
|
data/lib/roger/server.rb
CHANGED
@@ -7,12 +7,26 @@ require "webrick/https"
|
|
7
7
|
|
8
8
|
module Roger
|
9
9
|
# The Roger webserver. Initializes a rack server.
|
10
|
+
#
|
11
|
+
# @option options :port [Integer] The specified port you'd want to use
|
12
|
+
# @option options :auto_port [Boolean] Wether or not you want Roger
|
13
|
+
# to find a suitable port if the specified port is in use.
|
14
|
+
# @option options :handler [String] The preferred handler to use
|
10
15
|
class Server
|
11
16
|
attr_reader :server_options
|
12
17
|
|
18
|
+
# @attr_reader [Roger::Project] project The project used in this server
|
13
19
|
attr_reader :project
|
14
20
|
|
15
|
-
|
21
|
+
# @attr_reader [nil, Integer] used_port The actual port used to start
|
22
|
+
# the webserver. Only set if the server is running.
|
23
|
+
attr_reader :used_port
|
24
|
+
|
25
|
+
# @attr_reader [nil, Class] used_handler The actual used handler.
|
26
|
+
# Only set if the server is running.
|
27
|
+
attr_reader :used_handler
|
28
|
+
|
29
|
+
attr_accessor :port, :handler, :host, :auto_port
|
16
30
|
|
17
31
|
def initialize(project, options = {})
|
18
32
|
@project = project
|
@@ -25,6 +39,10 @@ module Roger
|
|
25
39
|
self.port = 9000
|
26
40
|
self.handler = nil
|
27
41
|
self.host = "0.0.0.0"
|
42
|
+
self.auto_port = true
|
43
|
+
|
44
|
+
@used_port = nil
|
45
|
+
@used_handler = nil
|
28
46
|
|
29
47
|
set_options(options)
|
30
48
|
end
|
@@ -32,9 +50,10 @@ module Roger
|
|
32
50
|
# Sets the options, this is a separate method as we want to override certain
|
33
51
|
# things set in the rogerfile from the commandline
|
34
52
|
def set_options(options)
|
35
|
-
self.port = options[:port] if options.key?(:port)
|
53
|
+
self.port = options[:port].to_i if options.key?(:port)
|
36
54
|
self.handler = options[:handler] if options.key?(:handler)
|
37
55
|
self.host = options[:host] if options.key?(:host)
|
56
|
+
self.auto_port = options[:auto_port] if options.key?(:auto_port)
|
38
57
|
end
|
39
58
|
|
40
59
|
# Use the specified Rack middleware
|
@@ -53,18 +72,38 @@ module Roger
|
|
53
72
|
|
54
73
|
def run!
|
55
74
|
project.mode = :server
|
56
|
-
|
75
|
+
|
76
|
+
options = server_options_for_handler
|
77
|
+
@used_port = options[:Port]
|
78
|
+
@used_handler = handler
|
79
|
+
|
80
|
+
handler.run application, options do |server|
|
57
81
|
trap(:INT) do
|
58
82
|
## Use thins' hard #stop! if available, otherwise just #stop
|
59
83
|
server.respond_to?(:stop!) ? server.stop! : server.stop
|
60
84
|
puts "Roger, out!"
|
61
85
|
end
|
86
|
+
|
87
|
+
yield server if block_given?
|
62
88
|
end
|
63
89
|
ensure
|
64
90
|
project.mode = nil
|
91
|
+
@used_port = nil
|
92
|
+
@used_handler = nil
|
65
93
|
end
|
66
94
|
alias_method :run, :run!
|
67
95
|
|
96
|
+
def server_options_for_handler
|
97
|
+
# Search for available port
|
98
|
+
options = server_options.dup
|
99
|
+
if auto_port && !port_free?(options[:Host], options[:Port])
|
100
|
+
options[:Port] = free_port_for_host_above(options[:Host], options[:Port])
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return the options
|
104
|
+
options
|
105
|
+
end
|
106
|
+
|
68
107
|
def port=(p)
|
69
108
|
@port = server_options[:Port] = p
|
70
109
|
end
|
@@ -83,6 +122,23 @@ module Roger
|
|
83
122
|
|
84
123
|
protected
|
85
124
|
|
125
|
+
# Get the first free port for host above port
|
126
|
+
# Will only ever test 100 ports.
|
127
|
+
def free_port_for_host_above(host, port)
|
128
|
+
test_port = port
|
129
|
+
test_port += 1 until port_free?(host, test_port) || port + 100 <= test_port
|
130
|
+
test_port
|
131
|
+
end
|
132
|
+
|
133
|
+
# See if a certain port is free on a certain host
|
134
|
+
def port_free?(host, port)
|
135
|
+
Addrinfo.tcp(host, port).listen.close
|
136
|
+
|
137
|
+
true
|
138
|
+
rescue SocketError, Errno::EADDRINUSE
|
139
|
+
false
|
140
|
+
end
|
141
|
+
|
86
142
|
# Build the final application that get's run by the Rack Handler
|
87
143
|
def application
|
88
144
|
return @app if @app
|
@@ -3,7 +3,12 @@ module Roger
|
|
3
3
|
module Helpers
|
4
4
|
# The partial helper
|
5
5
|
module Partial
|
6
|
-
def partial(name,
|
6
|
+
def partial(name, locals = {}, &block)
|
7
|
+
if locals[:locals]
|
8
|
+
options = locals
|
9
|
+
else
|
10
|
+
options = { locals: locals }
|
11
|
+
end
|
7
12
|
if block_given?
|
8
13
|
partial_with_block(name, options, &block)
|
9
14
|
else
|
data/lib/roger/version.rb
CHANGED
data/roger.gemspec
CHANGED
@@ -41,6 +41,6 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.add_development_dependency("test-unit", "~> 3.0.0")
|
42
42
|
s.add_development_dependency("mocha", "~> 1.1.0")
|
43
43
|
s.add_development_dependency("simplecov", "~> 0.10.0")
|
44
|
-
s.add_development_dependency("puma", "~>
|
44
|
+
s.add_development_dependency("puma", "~> 3.6.0")
|
45
45
|
s.add_development_dependency("rubocop", "~> 0.31.0")
|
46
46
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Generator scope
|
2
|
+
module Generators
|
3
|
+
# Simple Mock generator
|
4
|
+
class MockedGenerator < Roger::Generators::Base
|
5
|
+
desc "@mocked description"
|
6
|
+
argument :path, type: :string, required: false, desc: "Path to generate project into"
|
7
|
+
argument :another_arg, type: :string, required: false, desc: "Mocked or what?!"
|
8
|
+
|
9
|
+
def test
|
10
|
+
# Somewhat ugly way of checking
|
11
|
+
fail NotImplementedError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Roger::Generators.register :mocked, MockedGenerator
|
16
|
+
|
17
|
+
# Simple Mocku generator that has a project
|
18
|
+
class MockedWithProjectGenerator < Roger::Generators::Base
|
19
|
+
desc "Returns a project"
|
20
|
+
def test
|
21
|
+
# Somewhat ugly way of checking
|
22
|
+
fail StandardError if @project
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
[<%= yield %>]
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= locals[:variable] %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if depth < max_depth %>
|
2
|
-
<%= partial 'test/max_depth',
|
2
|
+
<%= partial 'test/max_depth', { depth: locals[:depth] + 1, max_depth: locals[:max_depth] } %>
|
3
3
|
<% else %>
|
4
4
|
Stop! Hammertime!
|
5
5
|
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= renderer.parent_template.source_path %>
|