lenary-ginatra 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitattributes +2 -0
- data/.gitignore +13 -0
- data/.gitmodules +3 -0
- data/README.md +127 -0
- data/Rakefile +86 -0
- data/TODO.md +10 -0
- data/VERSION +1 -0
- data/bin/ginatra +60 -0
- data/bin/ginatra-daemon +81 -0
- data/bin/ginatra-directory +60 -0
- data/bin/ginatra-server +28 -0
- data/config.ru +7 -0
- data/features/pages.feature +33 -0
- data/features/step_definitions/page_steps.rb +36 -0
- data/features/support/env.rb +12 -0
- data/ginatra.gemspec +120 -0
- data/lib/ginatra.rb +185 -0
- data/lib/ginatra/config.rb +55 -0
- data/lib/ginatra/helpers.rb +112 -0
- data/lib/ginatra/repo.rb +50 -0
- data/lib/ginatra/repo_list.rb +53 -0
- data/lib/sinatra/partials.rb +17 -0
- data/public/favicon.ico +0 -0
- data/rackup.ru +7 -0
- data/repos/README.md +8 -0
- data/spec/repo_list_spec.rb +22 -0
- data/spec/repo_spec.rb +58 -0
- data/spec/spec_helper.rb +30 -0
- data/vendor/vegas/History.txt +18 -0
- data/vendor/vegas/LICENSE +22 -0
- data/vendor/vegas/Manifest.txt +5 -0
- data/vendor/vegas/README.rdoc +45 -0
- data/vendor/vegas/Rakefile +32 -0
- data/vendor/vegas/lib/vegas.rb +16 -0
- data/vendor/vegas/lib/vegas/runner.rb +270 -0
- data/vendor/vegas/test/test_app/bin/test_app +9 -0
- data/vendor/vegas/test/test_app/test_app.rb +10 -0
- data/vendor/vegas/test/test_apps.rb +22 -0
- data/vendor/vegas/test/test_helper.rb +59 -0
- data/vendor/vegas/test/test_vegas_runner.rb +8 -0
- data/vendor/vegas/vegas.gemspec +45 -0
- data/views/_actor_box.erb +13 -0
- data/views/_commit_info_box.erb +27 -0
- data/views/_header.erb +6 -0
- data/views/_tree_part.erb +11 -0
- data/views/atom.builder +32 -0
- data/views/blob.erb +9 -0
- data/views/commit.erb +20 -0
- data/views/index.erb +12 -0
- data/views/layout.erb +35 -0
- data/views/log.erb +64 -0
- data/views/tree.erb +24 -0
- metadata +158 -0
data/bin/ginatra-server
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
current_path = File.expand_path(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require "#{current_path}/../lib/ginatra"
|
6
|
+
require "#{current_path}/../vendor/vegas/lib/vegas"
|
7
|
+
Vegas::Runner.new(Ginatra::App, 'ginatra-server', :port => Ginatra::Config.port) do |runner, opts, app|
|
8
|
+
|
9
|
+
opts.banner = "Usage: ginatra-server [[options] start | stop | status]"
|
10
|
+
|
11
|
+
opts.separator " start - Start the Ginatra HTTP Server"
|
12
|
+
opts.separator " stop - Stop the Ginatra Server"
|
13
|
+
opts.separator " status - How's your Ginatra Server holding up?"
|
14
|
+
|
15
|
+
if ARGV[-1] == "start"
|
16
|
+
elsif ARGV[-1] == "stop"
|
17
|
+
runner.kill!
|
18
|
+
exit
|
19
|
+
elsif ARGV[-1] == "status"
|
20
|
+
runner.status
|
21
|
+
exit!
|
22
|
+
elsif ARGV.length == 0 || ARGV[-1] !~ /^(start|stop|status)$/
|
23
|
+
runner.options[:start] = false
|
24
|
+
at_exit { puts opts }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
data/config.ru
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Feature: Page
|
2
|
+
In order to use multiple repositories
|
3
|
+
As a browser
|
4
|
+
I want to see the home page
|
5
|
+
|
6
|
+
Scenario:
|
7
|
+
When I open '/'
|
8
|
+
Then I should see "Ginatra"
|
9
|
+
And I should see "View My Git Repositories"
|
10
|
+
And I should see "test"
|
11
|
+
And I should see "description file for this repository and set the description for it."
|
12
|
+
Scenario:
|
13
|
+
When I open '/test'
|
14
|
+
Then I should see "Ginatra"
|
15
|
+
And I should see "test"
|
16
|
+
And I should see "description file for this repository and set the description for it."
|
17
|
+
And I should see "Commits"
|
18
|
+
And I should see "(author)"
|
19
|
+
Scenario:
|
20
|
+
When I open '/test/commit/eefb4c3'
|
21
|
+
Then I should see "Ginatra"
|
22
|
+
And I should see "test"
|
23
|
+
And I should see "description file for this repository and set the description for it."
|
24
|
+
And I should see "Commit: eefb4c3"
|
25
|
+
And I should see "doh, thanks lenary for reminding me of the files i'd forgotten"
|
26
|
+
Scenario:
|
27
|
+
When I open '/test/tree/24f701fd'
|
28
|
+
Then I should see "Ginatra"
|
29
|
+
And I should see "test"
|
30
|
+
And I should see "description file for this repository and set the description for it."
|
31
|
+
And I should see "Tree: 24f701fd"
|
32
|
+
And I should see "README.md"
|
33
|
+
And I should see ".gitignore"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Given /^I am on '([^\']*)'$/ do |path|
|
2
|
+
get path
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I open '([^\']*)'$/ do |path|
|
6
|
+
get path
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I press "([^\"]*)"$/ do |button|
|
10
|
+
click_button(button)
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I follow "([^\"]*)"$/ do |link|
|
14
|
+
click_link(link)
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I fill in "([^\"]*)" with "([^\"]*)"$/ do |field, value|
|
18
|
+
fill_in(field, :with => value)
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^I should see "([^\"]*)"$/ do |text|
|
22
|
+
last_response.should contain(text)
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^I should not see "([^\"]*)"$/ do |text|
|
26
|
+
last_response.should_not contain(text)
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^I should be on (.+)$/ do |page_name|
|
30
|
+
URI.parse(current_url).path.should == path_to(page_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
Then /^Save and View$/ do
|
34
|
+
save_and_open_page
|
35
|
+
end
|
36
|
+
|
data/ginatra.gemspec
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ginatra}
|
8
|
+
s.version = "2.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Sam Elliott", "Ryan Bigg"]
|
12
|
+
s.date = %q{2009-08-26}
|
13
|
+
s.description = %q{Host your own git repository browser through the power of Sinatra and Grit}
|
14
|
+
s.email = %q{sam@lenary.co.uk}
|
15
|
+
s.executables = ["ginatra", "ginatra-daemon", "ginatra-directory", "ginatra-server"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitattributes",
|
21
|
+
".gitignore",
|
22
|
+
".gitmodules",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"TODO.md",
|
26
|
+
"VERSION",
|
27
|
+
"bin/ginatra",
|
28
|
+
"bin/ginatra-daemon",
|
29
|
+
"bin/ginatra-directory",
|
30
|
+
"bin/ginatra-server",
|
31
|
+
"config.ru",
|
32
|
+
"features/pages.feature",
|
33
|
+
"features/step_definitions/page_steps.rb",
|
34
|
+
"features/support/env.rb",
|
35
|
+
"ginatra.gemspec",
|
36
|
+
"lib/ginatra.rb",
|
37
|
+
"lib/ginatra/config.rb",
|
38
|
+
"lib/ginatra/helpers.rb",
|
39
|
+
"lib/ginatra/repo.rb",
|
40
|
+
"lib/ginatra/repo_list.rb",
|
41
|
+
"lib/sinatra/partials.rb",
|
42
|
+
"public/favicon.ico",
|
43
|
+
"public/img/add.png",
|
44
|
+
"public/img/diff.png",
|
45
|
+
"public/img/doc.png",
|
46
|
+
"public/img/rm.png",
|
47
|
+
"public/img/tree.png",
|
48
|
+
"public/src/blank.gif",
|
49
|
+
"public/src/colour.css",
|
50
|
+
"public/src/commit.css",
|
51
|
+
"public/src/default.css",
|
52
|
+
"public/src/ginatra.js",
|
53
|
+
"public/src/highlight.pack.js",
|
54
|
+
"public/src/iepngfix.htc",
|
55
|
+
"public/src/index.css",
|
56
|
+
"public/src/jquery-1.3.2.min.js",
|
57
|
+
"public/src/lists.css",
|
58
|
+
"public/src/reset.css",
|
59
|
+
"public/src/table.css",
|
60
|
+
"public/src/type.css",
|
61
|
+
"rackup.ru",
|
62
|
+
"repos/README.md",
|
63
|
+
"spec/repo_list_spec.rb",
|
64
|
+
"spec/repo_spec.rb",
|
65
|
+
"spec/spec_helper.rb",
|
66
|
+
"vendor/vegas/History.txt",
|
67
|
+
"vendor/vegas/LICENSE",
|
68
|
+
"vendor/vegas/Manifest.txt",
|
69
|
+
"vendor/vegas/README.rdoc",
|
70
|
+
"vendor/vegas/Rakefile",
|
71
|
+
"vendor/vegas/lib/vegas.rb",
|
72
|
+
"vendor/vegas/lib/vegas/runner.rb",
|
73
|
+
"vendor/vegas/test/test_app/bin/test_app",
|
74
|
+
"vendor/vegas/test/test_app/test_app.rb",
|
75
|
+
"vendor/vegas/test/test_apps.rb",
|
76
|
+
"vendor/vegas/test/test_helper.rb",
|
77
|
+
"vendor/vegas/test/test_vegas_runner.rb",
|
78
|
+
"vendor/vegas/vegas.gemspec",
|
79
|
+
"views/_actor_box.erb",
|
80
|
+
"views/_commit_info_box.erb",
|
81
|
+
"views/_header.erb",
|
82
|
+
"views/_tree_part.erb",
|
83
|
+
"views/atom.builder",
|
84
|
+
"views/blob.erb",
|
85
|
+
"views/commit.erb",
|
86
|
+
"views/index.erb",
|
87
|
+
"views/layout.erb",
|
88
|
+
"views/log.erb",
|
89
|
+
"views/tree.erb"
|
90
|
+
]
|
91
|
+
s.homepage = %q{http://lenary.github.com/ginatra}
|
92
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
93
|
+
s.require_paths = ["lib"]
|
94
|
+
s.rubygems_version = %q{1.3.4}
|
95
|
+
s.summary = %q{A Gitweb Clone in Sinatra and Grit}
|
96
|
+
s.test_files = [
|
97
|
+
"spec/repo_list_spec.rb",
|
98
|
+
"spec/repo_spec.rb",
|
99
|
+
"spec/spec_helper.rb"
|
100
|
+
]
|
101
|
+
|
102
|
+
if s.respond_to? :specification_version then
|
103
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
104
|
+
s.specification_version = 3
|
105
|
+
|
106
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
107
|
+
s.add_runtime_dependency(%q<sinatra>, [">= 0.9.4"])
|
108
|
+
s.add_runtime_dependency(%q<grit>, [">= 1.1.1"])
|
109
|
+
s.add_runtime_dependency(%q<coderay>, [">= 0.8.0"])
|
110
|
+
else
|
111
|
+
s.add_dependency(%q<sinatra>, [">= 0.9.4"])
|
112
|
+
s.add_dependency(%q<grit>, [">= 1.1.1"])
|
113
|
+
s.add_dependency(%q<coderay>, [">= 0.8.0"])
|
114
|
+
end
|
115
|
+
else
|
116
|
+
s.add_dependency(%q<sinatra>, [">= 0.9.4"])
|
117
|
+
s.add_dependency(%q<grit>, [">= 1.1.1"])
|
118
|
+
s.add_dependency(%q<coderay>, [">= 0.8.0"])
|
119
|
+
end
|
120
|
+
end
|
data/lib/ginatra.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'grit'
|
3
|
+
require 'coderay'
|
4
|
+
|
5
|
+
current_path = File.expand_path(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
module Ginatra; end
|
8
|
+
|
9
|
+
# Loading in reverse because RepoList needs to be loaded before MultiRepoList
|
10
|
+
Dir.glob("#{current_path}/ginatra/*.rb").reverse.each { |f| require f }
|
11
|
+
|
12
|
+
require "#{current_path}/sinatra/partials"
|
13
|
+
|
14
|
+
# Written myself. i know, what the hell?!
|
15
|
+
module Ginatra
|
16
|
+
|
17
|
+
class Error < StandardError; end
|
18
|
+
class CommitsError < Error; end
|
19
|
+
|
20
|
+
class InvalidCommit < Error
|
21
|
+
def initialize(id)
|
22
|
+
super("Could not find a commit with the id of #{id}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
current_path = File.expand_path(File.dirname(__FILE__))
|
27
|
+
VERSION = File.new("#{current_path}/../VERSION").read
|
28
|
+
|
29
|
+
class App < Sinatra::Base
|
30
|
+
|
31
|
+
configure do
|
32
|
+
current_path = File.expand_path(File.dirname(__FILE__))
|
33
|
+
Config.load!
|
34
|
+
set :port, Ginatra::Config[:port]
|
35
|
+
set :raise_errors, Proc.new { test? }
|
36
|
+
set :show_exceptions, Proc.new { development? }
|
37
|
+
set :dump_errors, true
|
38
|
+
set :logging, Proc.new { !test? }
|
39
|
+
set :static, true
|
40
|
+
set :public, "#{current_path}/../public"
|
41
|
+
set :views, "#{current_path}/../views"
|
42
|
+
end
|
43
|
+
|
44
|
+
helpers do
|
45
|
+
include Helpers
|
46
|
+
include ::Sinatra::Partials
|
47
|
+
end
|
48
|
+
|
49
|
+
error CommitsError do
|
50
|
+
'No commits were returned for ' + request.uri
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/' do
|
54
|
+
erb :index
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/:repo.atom' do
|
58
|
+
@repo = RepoList.find(params[:repo])
|
59
|
+
@commits = @repo.commits
|
60
|
+
return "" if @commits.empty?
|
61
|
+
etag(@commits.first.id)
|
62
|
+
builder :atom, :layout => nil
|
63
|
+
end
|
64
|
+
|
65
|
+
get '/:repo' do
|
66
|
+
@repo = RepoList.find(params[:repo])
|
67
|
+
@commits = @repo.commits
|
68
|
+
etag(@commits.first.id)
|
69
|
+
erb :log
|
70
|
+
end
|
71
|
+
|
72
|
+
get '/:repo/:ref.atom' do
|
73
|
+
@repo = RepoList.find(params[:repo])
|
74
|
+
@commits = @repo.commits(params[:ref])
|
75
|
+
return "" if @commits.empty?
|
76
|
+
etag(@commits.first.id)
|
77
|
+
builder :atom, :layout => nil
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/:repo/:ref' do
|
81
|
+
params[:page] = 1
|
82
|
+
@repo = RepoList.find(params[:repo])
|
83
|
+
@commits = @repo.commits(params[:ref])
|
84
|
+
etag(@commits.first.id)
|
85
|
+
erb :log
|
86
|
+
end
|
87
|
+
|
88
|
+
get '/:repo/commit/:commit.patch' do
|
89
|
+
response['Content-Type'] = "text/plain"
|
90
|
+
@repo = RepoList.find(params[:repo])
|
91
|
+
@repo.git.format_patch({}, "--stdout", "-1", params[:commit])
|
92
|
+
end
|
93
|
+
|
94
|
+
get '/:repo/commit/:commit' do
|
95
|
+
@repo = RepoList.find(params[:repo])
|
96
|
+
@commit = @repo.commit(params[:commit]) # can also be a ref
|
97
|
+
etag(@commit.id)
|
98
|
+
erb(:commit)
|
99
|
+
end
|
100
|
+
|
101
|
+
get '/:repo/archive/:tree.tar.gz' do
|
102
|
+
response['Content-Type'] = "application/x-tar-gz"
|
103
|
+
@repo = RepoList.find(params[:repo])
|
104
|
+
@repo.archive_tar_gz(params[:tree])
|
105
|
+
end
|
106
|
+
|
107
|
+
get '/:repo/tree/:tree' do
|
108
|
+
@repo = RepoList.find(params[:repo])
|
109
|
+
|
110
|
+
if (tag = @repo.git.method_missing('rev_parse', {}, '--verify', "#{params[:tree]}^{tree}")).empty?
|
111
|
+
# we don't have a tree.
|
112
|
+
not_found
|
113
|
+
else
|
114
|
+
etag(tag)
|
115
|
+
end
|
116
|
+
|
117
|
+
@tree = @repo.tree(params[:tree]) # can also be a ref (i think)
|
118
|
+
@path = {}
|
119
|
+
@path[:tree] = "/#{params[:repo]}/tree/#{params[:tree]}"
|
120
|
+
@path[:blob] = "/#{params[:repo]}/blob/#{params[:tree]}"
|
121
|
+
erb(:tree)
|
122
|
+
end
|
123
|
+
|
124
|
+
get '/:repo/tree/:tree/*' do # for when we specify a path
|
125
|
+
@repo = RepoList.find(params[:repo])
|
126
|
+
@tree = @repo.tree(params[:tree])/params[:splat].first # can also be a ref (i think)
|
127
|
+
if @tree.is_a?(Grit::Blob)
|
128
|
+
# we need @tree to be a tree. if it's a blob, send it to the blob page
|
129
|
+
# this allows people to put in the remaining part of the path to the file, rather than endless clicks like you need in github
|
130
|
+
redirect "/#{params[:repo]}/blob/#{params[:tree]}/#{params[:splat].first}"
|
131
|
+
else
|
132
|
+
etag(@tree.id)
|
133
|
+
@path = {}
|
134
|
+
@path[:tree] = "/#{params[:repo]}/tree/#{params[:tree]}/#{params[:splat].first}"
|
135
|
+
@path[:blob] = "/#{params[:repo]}/blob/#{params[:tree]}/#{params[:splat].first}"
|
136
|
+
erb(:tree)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
get '/:repo/blob/:blob' do
|
141
|
+
@repo = RepoList.find(params[:repo])
|
142
|
+
@blob = @repo.blob(params[:blob])
|
143
|
+
etag(@blob.id)
|
144
|
+
erb(:blob)
|
145
|
+
end
|
146
|
+
|
147
|
+
get '/:repo/blob/:tree/*' do
|
148
|
+
@repo = RepoList.find(params[:repo])
|
149
|
+
@blob = @repo.tree(params[:tree])/params[:splat].first
|
150
|
+
if @blob.is_a?(Grit::Tree)
|
151
|
+
# as above, we need @blob to be a blob. if it's a tree, send it to the tree page
|
152
|
+
# this allows people to put in the remaining part of the path to the folder, rather than endless clicks like you need in github
|
153
|
+
redirect "/#{params[:repo]}/tree/#{params[:tree]}/#{params[:splat].first}"
|
154
|
+
else
|
155
|
+
etag(@blob.id)
|
156
|
+
extension = params[:splat].first.split(".").last
|
157
|
+
@highlighter = case extension
|
158
|
+
when 'js'
|
159
|
+
'javascript'
|
160
|
+
when 'css'
|
161
|
+
'css'
|
162
|
+
end
|
163
|
+
|
164
|
+
@highlighter ||= 'ruby'
|
165
|
+
|
166
|
+
erb(:blob)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
get '/:repo/:ref/:page' do
|
171
|
+
pass unless params[:page] =~ /^(\d)+$/
|
172
|
+
params[:page] = params[:page].to_i
|
173
|
+
@repo = RepoList.find(params[:repo])
|
174
|
+
@commits = @repo.commits(params[:ref], 10, (params[:page] - 1) * 10)
|
175
|
+
@next_commits = !@repo.commits(params[:ref], 10, params[:page] * 10).empty?
|
176
|
+
if params[:page] - 1 > 0
|
177
|
+
@previous_commits = !@repo.commits(params[:ref], 10, (params[:page] - 1) * 10).empty?
|
178
|
+
end
|
179
|
+
@separator = @next_commits && @previous_commits
|
180
|
+
erb :log
|
181
|
+
end
|
182
|
+
|
183
|
+
end # App
|
184
|
+
|
185
|
+
end # Ginatra
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Ginatra
|
2
|
+
class Config
|
3
|
+
|
4
|
+
current_path = File.expand_path("#{File.dirname(__FILE__)}")
|
5
|
+
CONFIG_PATH = File.expand_path("~/.ginatra/config.yml")
|
6
|
+
DEFAULT_CONFIG = {
|
7
|
+
:git_dirs => [File.expand_path("#{current_path}/../../repos/*")],
|
8
|
+
:ignored_files => ['README.md'],
|
9
|
+
:description => "View My Git Repositories",
|
10
|
+
:port => 9797
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.setup! # Very Destructive Method. Use with care!
|
14
|
+
File.open(CONFIG_PATH, 'w') do |f|
|
15
|
+
YAML.dump(DEFAULT_CONFIG, f)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.load!
|
20
|
+
@config = {}
|
21
|
+
begin
|
22
|
+
@config = YAML.load_file(CONFIG_PATH)
|
23
|
+
rescue Errno::ENOENT
|
24
|
+
end
|
25
|
+
@config = DEFAULT_CONFIG.merge(@config)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.dump!
|
29
|
+
File.open(CONFIG_PATH, 'w') do |f|
|
30
|
+
YAML.dump(@config, f)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.method_missing(sym, *args, &block)
|
35
|
+
if @config.respond_to?(sym)
|
36
|
+
@config.send(sym, *args, &block)
|
37
|
+
elsif @config.has_key?(sym)
|
38
|
+
@config[sym]
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.respond_to?(name)
|
45
|
+
if @config.respond_to?(name)
|
46
|
+
true
|
47
|
+
elsif @config.has_key?(name)
|
48
|
+
true
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|