http_router 0.3.10 → 0.3.11
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +5 -9
- data/benchmarks/rec2.rb +3 -0
- data/http_router.gemspec +2 -1
- data/lib/http_router.rb +0 -2
- data/lib/http_router/node.rb +11 -15
- data/lib/http_router/root.rb +23 -19
- data/lib/http_router/route.rb +10 -10
- data/lib/http_router/version.rb +1 -1
- data/spec/misc_spec.rb +1 -1
- metadata +27 -14
- data/Tumbler +0 -4
- data/ext/gem_rake.rb +0 -126
data/README.rdoc
CHANGED
@@ -14,7 +14,7 @@ This is very new code. Lots of stuff probably doesn't work right. I will likely
|
|
14
14
|
* Regex support for variables.
|
15
15
|
* Request condition support.
|
16
16
|
* Partial matches.
|
17
|
-
* Supports interstitial variables (e.g. /my-:variable-brings.all.the.boys/yard)
|
17
|
+
* Supports interstitial variables (e.g. /my-:variable-brings.all.the.boys/yard) and unnamed variable /one/:/two
|
18
18
|
* Very fast and small code base (~1,000 loc).
|
19
19
|
* Sinatra compatibility.
|
20
20
|
|
data/Rakefile
CHANGED
@@ -1,18 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'bundler'
|
2
3
|
require 'spec'
|
4
|
+
require 'code_stats'
|
3
5
|
require 'spec/rake/spectask'
|
6
|
+
|
4
7
|
Spec::Rake::SpecTask.new(:spec) do |t|
|
5
8
|
t.spec_opts ||= []
|
6
9
|
t.spec_opts << "--options" << "spec/spec.opts"
|
7
10
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
8
11
|
end
|
9
12
|
|
10
|
-
begin
|
11
|
-
require 'code_stats'
|
12
|
-
CodeStats::Tasks.new
|
13
|
-
rescue LoadError
|
14
|
-
end
|
15
|
-
|
16
13
|
require 'rake/rdoctask'
|
17
14
|
desc "Generate documentation"
|
18
15
|
Rake::RDocTask.new do |rd|
|
@@ -21,6 +18,5 @@ Rake::RDocTask.new do |rd|
|
|
21
18
|
rd.rdoc_dir = 'rdoc'
|
22
19
|
end
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
Bundler::GemHelper.install_tasks
|
21
|
+
Bundler::GemHelper.install_tasks
|
22
|
+
CodeStats::Tasks.new(:reporting_depth => 3)
|
data/benchmarks/rec2.rb
CHANGED
data/http_router.gemspec
CHANGED
@@ -23,10 +23,11 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_runtime_dependency 'rack', '>=1.0'
|
24
24
|
s.add_runtime_dependency 'url_mount', '>=0.2.1'
|
25
25
|
s.add_development_dependency 'rspec'
|
26
|
+
s.add_development_dependency 'code_stats'
|
26
27
|
s.add_development_dependency 'rake'
|
27
28
|
s.add_development_dependency 'sinatra'
|
28
29
|
s.add_development_dependency 'rbench'
|
29
|
-
s.add_development_dependency '
|
30
|
+
s.add_development_dependency 'bundler', ">= 1.0.0.rc4"
|
30
31
|
|
31
32
|
if s.respond_to? :specification_version then
|
32
33
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/lib/http_router.rb
CHANGED
data/lib/http_router/node.rb
CHANGED
@@ -133,10 +133,10 @@ class HttpRouter
|
|
133
133
|
current_nodes
|
134
134
|
end
|
135
135
|
|
136
|
-
def find_on_parts(request, parts, params
|
136
|
+
def find_on_parts(request, parts, params)
|
137
137
|
if parts and !parts.empty?
|
138
138
|
if parts.size == 1 and parts.first == ''
|
139
|
-
potential_match = find_on_parts(request, [], params
|
139
|
+
potential_match = find_on_parts(request, [], params)
|
140
140
|
if potential_match and (router.ignore_trailing_slash? or potential_match.value && potential_match.value.route.trailing_slash_ignore?)
|
141
141
|
parts.shift
|
142
142
|
return potential_match
|
@@ -149,10 +149,10 @@ class HttpRouter
|
|
149
149
|
if tester.respond_to?(:matches?) and match = tester.matches?(parts)
|
150
150
|
dupped_parts = parts.dup
|
151
151
|
params.push((val = tester.consume(match, dupped_parts) and val.is_a?(Array)) ? val.map{|v| Rack::Utils.uri_unescape(v)} : Rack::Utils.uri_unescape(val))
|
152
|
-
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params
|
152
|
+
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
|
153
153
|
elsif tester.respond_to?(:match) and match = tester.match(parts.whole_path) and match.begin(0) == 0
|
154
154
|
dupped_parts = router.split(parts.whole_path[match[0].size, parts.whole_path.size])
|
155
|
-
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params
|
155
|
+
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
|
156
156
|
else
|
157
157
|
nil
|
158
158
|
end
|
@@ -161,14 +161,14 @@ class HttpRouter
|
|
161
161
|
end
|
162
162
|
if match = @lookup && @lookup[parts.first]
|
163
163
|
parts.shift
|
164
|
-
return match.find_on_parts(request, parts, params
|
164
|
+
return match.find_on_parts(request, parts, params)
|
165
165
|
elsif @catchall
|
166
166
|
params.push((val = @catchall.variable.consume(nil, parts) and val.is_a?(Array)) ? val.map{|v| Rack::Utils.uri_unescape(v)} : Rack::Utils.uri_unescape(val))
|
167
|
-
return @catchall.find_on_parts(request, parts, params
|
167
|
+
return @catchall.find_on_parts(request, parts, params)
|
168
168
|
end
|
169
169
|
end
|
170
170
|
if request_node
|
171
|
-
request_node.find_on_request_methods(request
|
171
|
+
request_node.find_on_request_methods(request)
|
172
172
|
elsif arbitrary_node
|
173
173
|
arbitrary_node.find_on_arbitrary(request)
|
174
174
|
elsif @value
|
@@ -203,7 +203,7 @@ class HttpRouter
|
|
203
203
|
RequestMethods = [:request_method, :host, :port, :scheme, :user_agent, :ip, :fullpath, :query_string]
|
204
204
|
attr_accessor :request_method
|
205
205
|
|
206
|
-
def find_on_request_methods(request
|
206
|
+
def find_on_request_methods(request)
|
207
207
|
if @request_method
|
208
208
|
request_method_satisfied = false
|
209
209
|
request_value = request.send(request_method)
|
@@ -212,23 +212,19 @@ class HttpRouter
|
|
212
212
|
regexp === request_value
|
213
213
|
end
|
214
214
|
request_method_satisfied = true if next_node
|
215
|
-
next_node &&= next_node.last.find_on_request_methods(request
|
215
|
+
next_node &&= next_node.last.find_on_request_methods(request)
|
216
216
|
return next_node if next_node
|
217
217
|
end
|
218
218
|
if @lookup and next_node = @lookup[request_value]
|
219
219
|
request_method_satisfied = true
|
220
|
-
next_node = next_node.find_on_request_methods(request
|
220
|
+
next_node = next_node.find_on_request_methods(request)
|
221
221
|
return next_node if next_node
|
222
222
|
end
|
223
223
|
if @catchall
|
224
224
|
request_method_satisfied = true
|
225
|
-
next_node = @catchall.find_on_request_methods(request
|
225
|
+
next_node = @catchall.find_on_request_methods(request)
|
226
226
|
return next_node if next_node
|
227
227
|
end
|
228
|
-
if @request_method == :request_method
|
229
|
-
alternate_request_methods.concat(@lookup.keys)
|
230
|
-
alternate_request_methods.request_method_found ||= request_method_satisfied
|
231
|
-
end
|
232
228
|
end
|
233
229
|
|
234
230
|
if @arbitrary_node
|
data/lib/http_router/root.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Root < Node
|
3
|
+
HttpRequestMethods = %w(HEAD GET HEAD POST DELETE PUT)
|
4
|
+
|
3
5
|
class AlternativeRequestMethods < Array
|
4
6
|
attr_accessor :request_method_found
|
5
7
|
end
|
@@ -10,26 +12,21 @@ class HttpRouter
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def find(request)
|
13
|
-
path = request.path_info.dup
|
14
|
-
parts = router.split(path)
|
15
|
-
parts << '' if path[path.size - 1] == ?/
|
16
15
|
params = []
|
17
|
-
|
18
|
-
|
19
|
-
process_response(
|
20
|
-
find_on_parts(request, parts, params, alternate_request_methods),
|
21
|
-
parts,
|
22
|
-
params,
|
23
|
-
request,
|
24
|
-
alternate_request_methods
|
25
|
-
)
|
16
|
+
parts = get_parts(request)
|
17
|
+
node = find_on_parts(request, parts, params)
|
18
|
+
process_response(node, parts, params, request)
|
26
19
|
end
|
27
|
-
|
20
|
+
|
21
|
+
def get_parts(request)
|
22
|
+
parts = router.split(request.path_info.dup)
|
23
|
+
parts << '' if request.path_info[-1] == ?/
|
24
|
+
parts
|
25
|
+
end
|
26
|
+
|
28
27
|
private
|
29
|
-
def process_response(node, parts, params, request
|
30
|
-
if node
|
31
|
-
node
|
32
|
-
elsif node && node.value
|
28
|
+
def process_response(node, parts, params, request)
|
29
|
+
if node && node.value
|
33
30
|
if parts.empty?
|
34
31
|
Response.matched(node.value, params, request.path_info)
|
35
32
|
elsif node.value.route.partially_match?
|
@@ -39,10 +36,17 @@ class HttpRouter
|
|
39
36
|
nil
|
40
37
|
end
|
41
38
|
else
|
42
|
-
|
39
|
+
alternate_methods = (HttpRequestMethods - [request.request_method]).select do |alternate_method|
|
40
|
+
test_request = request.dup
|
41
|
+
test_request.env['REQUEST_METHOD'] = alternate_method
|
42
|
+
node = find_on_parts(test_request, get_parts(request), [])
|
43
|
+
node && node.value
|
44
|
+
end
|
45
|
+
|
46
|
+
if alternate_methods.empty?
|
43
47
|
nil
|
44
48
|
else
|
45
|
-
Response.unmatched(405, {"Allow" =>
|
49
|
+
Response.unmatched(405, {"Allow" => alternate_methods.join(", ")})
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/http_router/route.rb
CHANGED
@@ -301,23 +301,23 @@ class HttpRouter
|
|
301
301
|
paths = HttpRouter::OptionalCompiler.new(@path).paths
|
302
302
|
paths.map do |path|
|
303
303
|
splitting_indexes = []
|
304
|
-
|
304
|
+
variable_position = 0
|
305
305
|
counter = 0
|
306
306
|
original_path = path.dup
|
307
307
|
split_path = router.split(path)
|
308
|
-
|
308
|
+
position = 0
|
309
309
|
new_path = split_path.map do |part|
|
310
|
-
|
310
|
+
processed_parts = case part
|
311
311
|
when /^:([a-zA-Z_0-9]*)$/
|
312
312
|
v_name = ($1.empty? ? anonymous_variable(counter += 1) : $1).to_sym
|
313
313
|
router.variable(v_name, @matches_with[v_name])
|
314
314
|
when /^\*([a-zA-Z_0-9]*)$/
|
315
|
-
if
|
315
|
+
if position != split_path.size - 1
|
316
316
|
v_name = ($1.empty? ? anonymous_variable(counter += 1) : $1).to_sym
|
317
|
-
splitting_indexes <<
|
318
|
-
remaining_path_parts = split_path[
|
317
|
+
splitting_indexes << variable_position
|
318
|
+
remaining_path_parts = split_path[position + 1, split_path.size]
|
319
319
|
look_ahead_variable = remaining_path_parts.find{|p| p[0] == ?: || p[0] == ?*}
|
320
|
-
remaining_matcher = split_path[
|
320
|
+
remaining_matcher = split_path[position + 1, look_ahead_variable ? remaining_path_parts.index(look_ahead_variable) : split_path.size].join('/')
|
321
321
|
remaining_path_parts.index(look_ahead_variable) if look_ahead_variable
|
322
322
|
router.variable(v_name, /^(#{@matches_with[v_name] || '[^\/]*?'}\/)+(?=#{Regexp.quote(remaining_matcher)})/)
|
323
323
|
else
|
@@ -327,9 +327,9 @@ class HttpRouter
|
|
327
327
|
else
|
328
328
|
generate_interstitial_parts(part)
|
329
329
|
end
|
330
|
-
|
331
|
-
|
332
|
-
|
330
|
+
variable_position += Array(processed_parts).select{|part| part.is_a?(Variable)}.size
|
331
|
+
position += 1
|
332
|
+
processed_parts
|
333
333
|
end
|
334
334
|
new_path.flatten!
|
335
335
|
Path.new(self, original_path, new_path, splitting_indexes.empty? ? nil : splitting_indexes)
|
data/lib/http_router/version.rb
CHANGED
data/spec/misc_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe "HttpRouter" do
|
|
9
9
|
route = @router.add('/:test', :conditions => {:request_method => %w{HEAD GET}, :host => 'host1'}, :default_values => {:page => 1}, :matching => {:test => /\d+/}, :name => :foobar).to :test
|
10
10
|
@router.recognize(Rack::MockRequest.env_for('http://host2/variable', :method => 'POST')).should be_nil
|
11
11
|
@router.recognize(Rack::MockRequest.env_for('http://host1/variable', :method => 'POST')).should be_nil
|
12
|
-
@router.recognize(Rack::MockRequest.env_for('http://host2/123', :method => 'POST')).
|
12
|
+
@router.recognize(Rack::MockRequest.env_for('http://host2/123', :method => 'POST')).should be_nil
|
13
13
|
@router.recognize(Rack::MockRequest.env_for('http://host1/123', :method => 'POST')).matched?.should be_false
|
14
14
|
@router.recognize(Rack::MockRequest.env_for('http://host1/123', :method => 'GET' )).route.dest.should == :test
|
15
15
|
@router.url(:foobar, '123').should == '/123?page=1'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 11
|
10
|
+
version: 0.3.11
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Hull
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-08 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -64,7 +64,7 @@ dependencies:
|
|
64
64
|
type: :development
|
65
65
|
version_requirements: *id003
|
66
66
|
- !ruby/object:Gem::Dependency
|
67
|
-
name:
|
67
|
+
name: code_stats
|
68
68
|
prerelease: false
|
69
69
|
requirement: &id004 !ruby/object:Gem::Requirement
|
70
70
|
none: false
|
@@ -78,7 +78,7 @@ dependencies:
|
|
78
78
|
type: :development
|
79
79
|
version_requirements: *id004
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
|
-
name:
|
81
|
+
name: rake
|
82
82
|
prerelease: false
|
83
83
|
requirement: &id005 !ruby/object:Gem::Requirement
|
84
84
|
none: false
|
@@ -92,7 +92,7 @@ dependencies:
|
|
92
92
|
type: :development
|
93
93
|
version_requirements: *id005
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
95
|
+
name: sinatra
|
96
96
|
prerelease: false
|
97
97
|
requirement: &id006 !ruby/object:Gem::Requirement
|
98
98
|
none: false
|
@@ -106,21 +106,36 @@ dependencies:
|
|
106
106
|
type: :development
|
107
107
|
version_requirements: *id006
|
108
108
|
- !ruby/object:Gem::Dependency
|
109
|
-
name:
|
109
|
+
name: rbench
|
110
110
|
prerelease: false
|
111
111
|
requirement: &id007 !ruby/object:Gem::Requirement
|
112
112
|
none: false
|
113
113
|
requirements:
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
hash:
|
116
|
+
hash: 3
|
117
117
|
segments:
|
118
118
|
- 0
|
119
|
-
|
120
|
-
- 11
|
121
|
-
version: 0.0.11
|
119
|
+
version: "0"
|
122
120
|
type: :development
|
123
121
|
version_requirements: *id007
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: bundler
|
124
|
+
prerelease: false
|
125
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 977940573
|
131
|
+
segments:
|
132
|
+
- 1
|
133
|
+
- 0
|
134
|
+
- 0
|
135
|
+
- rc4
|
136
|
+
version: 1.0.0.rc4
|
137
|
+
type: :development
|
138
|
+
version_requirements: *id008
|
124
139
|
description: This library allows you to recognize and build URLs in a Rack application. As well it contains an interface for use within Sinatra.
|
125
140
|
email: joshbuddy@gmail.com
|
126
141
|
executables: []
|
@@ -135,7 +150,6 @@ files:
|
|
135
150
|
- Gemfile
|
136
151
|
- README.rdoc
|
137
152
|
- Rakefile
|
138
|
-
- Tumbler
|
139
153
|
- benchmarks/gen2.rb
|
140
154
|
- benchmarks/generation_bm.rb
|
141
155
|
- benchmarks/rack_mount.rb
|
@@ -154,7 +168,6 @@ files:
|
|
154
168
|
- examples/unnamed_variable.ru
|
155
169
|
- examples/variable.ru
|
156
170
|
- examples/variable_with_regex.ru
|
157
|
-
- ext/gem_rake.rb
|
158
171
|
- http_router.gemspec
|
159
172
|
- lib/ext/rack/rack_mapper.rb
|
160
173
|
- lib/ext/rack/rack_urlmap.rb
|
data/Tumbler
DELETED
data/ext/gem_rake.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
module Bundler
|
2
|
-
class GemHelper
|
3
|
-
|
4
|
-
def self.install_tasks
|
5
|
-
dir = caller.find{|c| /Rakefile:/}[/^(.*?)\/Rakefile:/, 1]
|
6
|
-
GemHelper.new(dir).install
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_reader :spec_path, :base, :name
|
10
|
-
|
11
|
-
def initialize(base, name = nil)
|
12
|
-
@base = base
|
13
|
-
@name = name || interpolate_name
|
14
|
-
@spec_path = File.join(@base, "#{@name}.gemspec")
|
15
|
-
end
|
16
|
-
|
17
|
-
def install
|
18
|
-
desc 'Build your gem into the pkg directory'
|
19
|
-
task 'build' do
|
20
|
-
build_gem
|
21
|
-
end
|
22
|
-
|
23
|
-
desc 'Install your gem into the pkg directory'
|
24
|
-
task 'install' do
|
25
|
-
install_gem
|
26
|
-
end
|
27
|
-
|
28
|
-
desc 'Push your gem to rubygems'
|
29
|
-
task 'push' do
|
30
|
-
push_gem
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def build_gem
|
35
|
-
file_name = nil
|
36
|
-
sh("gem build #{spec_path}") {
|
37
|
-
file_name = File.basename(built_gem_path)
|
38
|
-
FileUtils.mkdir_p(File.join(base, 'pkg'))
|
39
|
-
FileUtils.mv(built_gem_path, 'pkg')
|
40
|
-
}
|
41
|
-
File.join(base, 'pkg', file_name)
|
42
|
-
end
|
43
|
-
|
44
|
-
def install_gem
|
45
|
-
built_gem_path = build_gem
|
46
|
-
sh("gem install #{built_gem_path}")
|
47
|
-
end
|
48
|
-
|
49
|
-
def push_gem
|
50
|
-
guard_clean
|
51
|
-
guard_already_tagged
|
52
|
-
tag_version {
|
53
|
-
git_push
|
54
|
-
rubygem_push(build_gem)
|
55
|
-
}
|
56
|
-
end
|
57
|
-
|
58
|
-
protected
|
59
|
-
def rubygem_push(path)
|
60
|
-
sh("gem push #{path}")
|
61
|
-
end
|
62
|
-
|
63
|
-
def built_gem_path
|
64
|
-
Dir[File.join(base, "#{name}-*.gem")].sort_by{|f| File.mtime(f)}.last
|
65
|
-
end
|
66
|
-
|
67
|
-
def interpolate_name
|
68
|
-
gemspecs = Dir[File.join(base, "*.gemspec")]
|
69
|
-
raise "Unable to determine name from existing gemspec." unless gemspecs.size == 1
|
70
|
-
|
71
|
-
File.basename(gemspecs.first)[/^(.*)\.gemspec$/, 1]
|
72
|
-
end
|
73
|
-
|
74
|
-
def git_push
|
75
|
-
sh "git push --all"
|
76
|
-
sh "git push --tags"
|
77
|
-
end
|
78
|
-
|
79
|
-
def guard_already_tagged
|
80
|
-
sh('git tag').split(/\n/).include?(current_version_tag) and raise("This tag has already been committed to the repo.")
|
81
|
-
end
|
82
|
-
|
83
|
-
def guard_clean
|
84
|
-
clean? or raise("There are files that need to be committed first.")
|
85
|
-
end
|
86
|
-
|
87
|
-
def clean?
|
88
|
-
sh("git ls-files -dm").split("\n").size.zero?
|
89
|
-
end
|
90
|
-
|
91
|
-
def tag_version
|
92
|
-
sh "git tag #{current_version_tag}"
|
93
|
-
yield if block_given?
|
94
|
-
rescue
|
95
|
-
sh "git tag -d #{current_version_tag}"
|
96
|
-
raise
|
97
|
-
end
|
98
|
-
|
99
|
-
def current_version
|
100
|
-
raise("Version file could not be found at #{version_file_path}") unless File.exist?(version_file_path)
|
101
|
-
File.read(version_file_path)[/V(ERSION|ersion)\s*=\s*(["'])(.*?)\2/, 3]
|
102
|
-
end
|
103
|
-
|
104
|
-
def version_file_path
|
105
|
-
File.join(base, 'lib', name, 'version.rb')
|
106
|
-
end
|
107
|
-
|
108
|
-
def current_version_tag
|
109
|
-
"v#{current_version}"
|
110
|
-
end
|
111
|
-
|
112
|
-
def sh(cmd, &block)
|
113
|
-
output, code = sh_with_code(cmd, &block)
|
114
|
-
code == 0 ? output : raise(output)
|
115
|
-
end
|
116
|
-
|
117
|
-
def sh_with_code(cmd, &block)
|
118
|
-
output = ''
|
119
|
-
Dir.chdir(base) {
|
120
|
-
output = `#{cmd}`
|
121
|
-
block.call if block and $? == 0
|
122
|
-
}
|
123
|
-
[output, $?]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|