perennial 0.2.2.2 → 1.0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/perennial +1 -2
- data/lib/perennial/application.rb +65 -22
- data/lib/perennial/core_ext/attribute_accessors.rb +25 -0
- data/lib/perennial/core_ext/hash_key_conversions.rb +26 -0
- data/lib/perennial/core_ext/inflections.rb +33 -0
- data/lib/perennial/core_ext/misc.rb +33 -43
- data/lib/perennial/core_ext/proxy.rb +16 -0
- data/lib/perennial/core_ext.rb +4 -1
- data/lib/perennial/daemon.rb +9 -2
- data/lib/perennial/delegateable.rb +48 -0
- data/lib/perennial/dispatchable.rb +67 -24
- data/lib/perennial/generator.rb +43 -8
- data/lib/perennial/loader.rb +5 -1
- data/lib/perennial/logger.rb +14 -4
- data/lib/perennial/nash.rb +217 -0
- data/lib/perennial/option_parser.rb +3 -3
- data/lib/perennial/reloading.rb +45 -0
- data/lib/perennial/settings.rb +59 -31
- data/lib/perennial.rb +7 -5
- data/templates/application.erb +3 -2
- data/templates/rakefile.erb +1 -0
- metadata +10 -17
- data/test/dispatchable_test.rb +0 -129
- data/test/hookable_test.rb +0 -61
- data/test/loader_test.rb +0 -1
- data/test/loggable_test.rb +0 -38
- data/test/logger_test.rb +0 -57
- data/test/settings_test.rb +0 -99
- data/test/test_helper.rb +0 -38
- data/vendor/fakefs/LICENSE +0 -20
- data/vendor/fakefs/README.markdown +0 -37
- data/vendor/fakefs/Rakefile +0 -3
- data/vendor/fakefs/lib/fakefs.rb +0 -448
- data/vendor/fakefs/test/fakefs_test.rb +0 -511
- data/vendor/fakefs/test/verify.rb +0 -27
data/lib/perennial/generator.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'open-uri'
|
2
2
|
require 'fileutils'
|
3
3
|
require 'erb'
|
4
|
+
require 'readline'
|
4
5
|
|
5
6
|
module Perennial
|
6
7
|
class Generator
|
@@ -32,12 +33,46 @@ module Perennial
|
|
32
33
|
def initialize(destination, opts = {})
|
33
34
|
@destination_path = destination
|
34
35
|
@template_path = opts[:template_path] || File.join(Settings.library_root, "templates")
|
35
|
-
|
36
|
+
@silent = !!opts[:silent]
|
37
|
+
describe "Initializing generator in #{destination}"
|
36
38
|
end
|
37
39
|
|
38
|
-
|
40
|
+
# Helpers for testing file state
|
41
|
+
|
42
|
+
def fu
|
43
|
+
FileUtils
|
44
|
+
end
|
45
|
+
|
46
|
+
def chmod(permissions, path)
|
47
|
+
describe "Changing permissions for #{path} to #{permissions}"
|
48
|
+
FileUtils.chmod(permissions, expand_destination_path(path))
|
49
|
+
end
|
50
|
+
|
51
|
+
def file?(path)
|
52
|
+
describe "Checking if #{path} is a file"
|
53
|
+
File.file?(expand_destination_path(path))
|
54
|
+
end
|
55
|
+
|
56
|
+
def executable?(path)
|
57
|
+
describe "Checking if #{path} is an executable"
|
58
|
+
File.executable?(expand_destination_path(path))
|
59
|
+
end
|
60
|
+
|
61
|
+
def directory?(path)
|
62
|
+
describe "Checking if #{path} is a directory"
|
63
|
+
File.directory?(expand_destination_path(path))
|
64
|
+
end
|
65
|
+
|
66
|
+
alias folder? directory?
|
67
|
+
|
68
|
+
def exists?(path)
|
69
|
+
describe "Checking if #{path} exists"
|
70
|
+
File.exits?(expand_destination_path(path))
|
71
|
+
end
|
72
|
+
|
73
|
+
def download(from, to, append = false)
|
39
74
|
describe "Downloading #{from}"
|
40
|
-
file to, open(from).read
|
75
|
+
file to, open(from).read, append
|
41
76
|
end
|
42
77
|
|
43
78
|
def folders(*args)
|
@@ -47,20 +82,20 @@ module Perennial
|
|
47
82
|
end
|
48
83
|
end
|
49
84
|
|
50
|
-
def file(name, contents)
|
85
|
+
def file(name, contents, append = false)
|
51
86
|
dest_folder = File.dirname(name)
|
52
87
|
folders(dest_folder) unless File.directory?(expand_destination_path(dest_folder))
|
53
88
|
describe "Creating file #{name}"
|
54
|
-
File.open(expand_destination_path(name), "w+") do |f|
|
89
|
+
File.open(expand_destination_path(name), "#{append ? "a" : "w"}+") do |f|
|
55
90
|
f.write(contents)
|
56
91
|
end
|
57
92
|
end
|
58
93
|
|
59
|
-
def template(source, destination, environment = {})
|
94
|
+
def template(source, destination, environment = {}, append = false)
|
60
95
|
describe "Processing template #{source}"
|
61
96
|
raw_template = File.read(expand_template_path(source))
|
62
97
|
processed_template = ERB.new(raw_template).result(binding_for(environment))
|
63
|
-
file destination, processed_template
|
98
|
+
file destination, processed_template, append
|
64
99
|
end
|
65
100
|
|
66
101
|
protected
|
@@ -82,7 +117,7 @@ module Perennial
|
|
82
117
|
end
|
83
118
|
|
84
119
|
def describe(action)
|
85
|
-
puts "
|
120
|
+
puts "[generator] #{action}" unless @silent
|
86
121
|
end
|
87
122
|
|
88
123
|
end
|
data/lib/perennial/loader.rb
CHANGED
@@ -53,7 +53,10 @@ module Perennial
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def current_controller
|
56
|
-
@current_controller ||=
|
56
|
+
@current_controller ||= begin
|
57
|
+
c = @@controllers[@@current_type.to_sym]
|
58
|
+
c.is_a?(String) ? eval(c) : c
|
59
|
+
end
|
57
60
|
end
|
58
61
|
|
59
62
|
protected
|
@@ -70,6 +73,7 @@ module Perennial
|
|
70
73
|
handler_directory = Settings.root / "handlers"
|
71
74
|
if File.directory?(handler_directory)
|
72
75
|
Dir[handler_directory / "**" / "*.rb"].each do |handler|
|
76
|
+
Perennial::Reloading.watch(handler, handler_directory)
|
73
77
|
require handler
|
74
78
|
end
|
75
79
|
end
|
data/lib/perennial/logger.rb
CHANGED
@@ -5,8 +5,9 @@ module Perennial
|
|
5
5
|
|
6
6
|
cattr_accessor :logger, :log_name
|
7
7
|
|
8
|
-
@@log_name
|
9
|
-
@@setup
|
8
|
+
@@log_name = "perennial.log"
|
9
|
+
@@setup = false
|
10
|
+
@@default_logger_path = nil
|
10
11
|
|
11
12
|
class << self
|
12
13
|
|
@@ -19,9 +20,18 @@ module Perennial
|
|
19
20
|
setup!
|
20
21
|
end
|
21
22
|
|
23
|
+
def default_logger_path=(value)
|
24
|
+
@@default_logger_path = value
|
25
|
+
# Rereun setup if setup is already done.
|
26
|
+
setup! if setup?
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_logger_path
|
30
|
+
@@default_logger_path || (Settings.root / "log" / @@log_name.to_str)
|
31
|
+
end
|
32
|
+
|
22
33
|
def setup!
|
23
|
-
|
24
|
-
@@logger = new(log_path, Settings.log_level, Settings.verbose?)
|
34
|
+
@@logger = new(self.default_logger_path, Settings.log_level, Settings.verbose?)
|
25
35
|
@@setup = true
|
26
36
|
end
|
27
37
|
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Perennial
|
3
|
+
# A ninja hash. Like OpenStruct, but better
|
4
|
+
class Nash
|
5
|
+
|
6
|
+
def self.load_file(path)
|
7
|
+
n = self.new
|
8
|
+
if File.file?(path) && File.readable?(path)
|
9
|
+
contents = YAML.load_file(path)
|
10
|
+
end
|
11
|
+
if contents.is_a?(Hash)
|
12
|
+
contents.to_nash
|
13
|
+
else
|
14
|
+
new(:data => contents).normalized
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :table
|
19
|
+
|
20
|
+
def initialize(initial = {})
|
21
|
+
@table = {}
|
22
|
+
initial.to_hash.each_pair { |k,v| self[k] = v }
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
@table[real_key(key)]
|
27
|
+
end
|
28
|
+
|
29
|
+
def []=(key, *values)
|
30
|
+
@table.send(:[]=, real_key(key), *values)
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to?(name, rec = nil)
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def id
|
38
|
+
self.has_key?(:id) ? self.id : super
|
39
|
+
end
|
40
|
+
|
41
|
+
def dup
|
42
|
+
Nash.new(self.table)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_hash
|
46
|
+
@table.dup
|
47
|
+
end
|
48
|
+
|
49
|
+
def keys
|
50
|
+
@table.keys
|
51
|
+
end
|
52
|
+
|
53
|
+
def values
|
54
|
+
@table.values
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_key?(key)
|
58
|
+
@table.has_key? real_key(key)
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_value?(value)
|
62
|
+
@table.has_value? value
|
63
|
+
end
|
64
|
+
|
65
|
+
def each_pair
|
66
|
+
@table.each_pair { |k, v| yield k, v }
|
67
|
+
end
|
68
|
+
|
69
|
+
def each_key
|
70
|
+
@table.each_key { |k| yield k }
|
71
|
+
end
|
72
|
+
|
73
|
+
def each_value
|
74
|
+
@table.each_value { |v| yield v }
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete(key)
|
78
|
+
@table.delete(real_key(key))
|
79
|
+
end
|
80
|
+
|
81
|
+
def merge!(hash_or_nash)
|
82
|
+
hash_or_nash.to_hash.each_pair do |k, v|
|
83
|
+
self[k] = v
|
84
|
+
end
|
85
|
+
return self
|
86
|
+
end
|
87
|
+
|
88
|
+
def merge(hash_or_nash)
|
89
|
+
dup.merge! hash_or_nash
|
90
|
+
end
|
91
|
+
|
92
|
+
def reverse_merge!(hash_or_nash)
|
93
|
+
replace Nash.new(hash_or_nash).merge!(self)
|
94
|
+
end
|
95
|
+
|
96
|
+
def reverse_merge(hash_or_nash)
|
97
|
+
dup.reverse_merge(hash_or_nash)
|
98
|
+
end
|
99
|
+
|
100
|
+
def replace(nash)
|
101
|
+
if nash.is_a?(self.class)
|
102
|
+
@table = nash.table
|
103
|
+
else
|
104
|
+
@table = {}
|
105
|
+
nash.to_hash.each_pair { |k, v| self[k] = v }
|
106
|
+
end
|
107
|
+
return self
|
108
|
+
end
|
109
|
+
|
110
|
+
def blank?
|
111
|
+
@table.blank?
|
112
|
+
end
|
113
|
+
|
114
|
+
def present?
|
115
|
+
@table.present?
|
116
|
+
end
|
117
|
+
|
118
|
+
def inspect
|
119
|
+
str = ""
|
120
|
+
if Thread.current[:inspect_stack].nil?
|
121
|
+
Thread.current[:inspect_stack] = [self]
|
122
|
+
str = _inspect
|
123
|
+
Thread.current[:inspect_stack] = nil
|
124
|
+
else
|
125
|
+
if Thread.current[:inspect_stack].include?(self)
|
126
|
+
return "..."
|
127
|
+
else
|
128
|
+
Thread.current[:inspect_stack] << self
|
129
|
+
str = _inspect
|
130
|
+
Thread.current[:inspect_stack].pop
|
131
|
+
end
|
132
|
+
end
|
133
|
+
return str
|
134
|
+
end
|
135
|
+
|
136
|
+
def _inspect
|
137
|
+
str = "#<Perennial::Nash:#{(object_id * 2).to_s(16)}"
|
138
|
+
if !blank?
|
139
|
+
str << " "
|
140
|
+
str << table.map { |k, v| "#{k}=#{v.inspect}" }.join(", ")
|
141
|
+
end
|
142
|
+
str << ">"
|
143
|
+
return str
|
144
|
+
end
|
145
|
+
|
146
|
+
def hash
|
147
|
+
@table.hash
|
148
|
+
end
|
149
|
+
|
150
|
+
def normalized(n = nil)
|
151
|
+
item = nil
|
152
|
+
if Thread.current[:normalized].nil?
|
153
|
+
n = self.class.new
|
154
|
+
Thread.current[:normalized] = {self => n}
|
155
|
+
item = normalize_nash(n)
|
156
|
+
Thread.current[:normalized] = nil
|
157
|
+
else
|
158
|
+
if Thread.current[:normalized].has_key?(self)
|
159
|
+
return Thread.current[:normalized][self]
|
160
|
+
else
|
161
|
+
n = self.class.new
|
162
|
+
Thread.current[:normalized][self] = n
|
163
|
+
item = normalize_nash(n)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
item
|
167
|
+
end
|
168
|
+
|
169
|
+
protected
|
170
|
+
|
171
|
+
def normalize_nash(n = self.class.new)
|
172
|
+
each_pair do |k, v|
|
173
|
+
n[k] = normalize_item(v)
|
174
|
+
end
|
175
|
+
return n
|
176
|
+
end
|
177
|
+
|
178
|
+
def normalize_item(i)
|
179
|
+
case i
|
180
|
+
when Hash
|
181
|
+
self.class.new(i).normalized
|
182
|
+
when Array
|
183
|
+
i.map { |v| normalize_item(v) }
|
184
|
+
when self.class
|
185
|
+
i.normalized
|
186
|
+
else
|
187
|
+
i
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def method_missing(name, *args, &blk)
|
192
|
+
name = name.to_s
|
193
|
+
case name.to_s[-1]
|
194
|
+
when ??
|
195
|
+
self[name[0..-2]].present?
|
196
|
+
when ?=
|
197
|
+
send(:[]=, real_key(name[0..-2]), *args)
|
198
|
+
when ?!
|
199
|
+
self[name[0..-2]] = self.class.new
|
200
|
+
else
|
201
|
+
self[name]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def real_key(name)
|
206
|
+
name.to_sym
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class Hash
|
214
|
+
def to_nash
|
215
|
+
Perennial::Nash.new(self)
|
216
|
+
end
|
217
|
+
end
|
@@ -52,9 +52,9 @@ module Perennial
|
|
52
52
|
def add_defaults!
|
53
53
|
return if defined?(@defaults_added) && @defaults_added
|
54
54
|
logger_levels = Logger::LEVELS.keys.map { |k| k.to_s }
|
55
|
-
add(:daemon, 'Runs this application as a daemon') { Settings.daemon = true }
|
56
|
-
add(:verbose, 'Runs this application verbosely, writing to STDOUT') { Settings.verbose = true }
|
57
|
-
add(:log_level, "Sets this applications log level, one of: #{logger_levels.join(", ")}") do |level|
|
55
|
+
add(:daemon, 'Runs this application as a daemon', :shortcut => "d") { Settings.daemon = true }
|
56
|
+
add(:verbose, 'Runs this application verbosely, writing to STDOUT', :shortcut => "v") { Settings.verbose = true }
|
57
|
+
add(:log_level, "Sets this applications log level, one of: #{logger_levels.join(", ")}", :shortcut => "l") do |level|
|
58
58
|
if logger_levels.include?(level)
|
59
59
|
Settings.log_level = level.to_sym
|
60
60
|
else
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Perennial
|
2
|
+
class Reloading
|
3
|
+
|
4
|
+
cattr_accessor :mapping, :mtimes
|
5
|
+
self.mapping = {}
|
6
|
+
self.mtimes = {}
|
7
|
+
|
8
|
+
def self.watch(file, relative_to = File.dirname(file))
|
9
|
+
file = File.expand_path(file)
|
10
|
+
raise ArgumentError, "You must provide the path to a file" unless File.file?(file)
|
11
|
+
relative = file.gsub(/^#{File.expand_path(relative_to)}\//, '')
|
12
|
+
name = relative.gsub(/\.rb$/, '').split("/").map { |part|part.camelize }.join("::")
|
13
|
+
self.mapping[name] = file
|
14
|
+
self.mtimes[file] = File.mtime(file)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reload!
|
18
|
+
self.mapping.each_pair do |constant, file|
|
19
|
+
next unless File.mtime(file) > self.mtimes[file]
|
20
|
+
begin
|
21
|
+
# Get a relative name and namespace
|
22
|
+
parts = constant.split("::")
|
23
|
+
name = parts.pop
|
24
|
+
ns = parts.inject(Object) { |a, c| a.const_get(c) }
|
25
|
+
# Notify object pre-reload.
|
26
|
+
final = ns.const_get(name)
|
27
|
+
final.reloading! if final.respond_to?(:reloading!)
|
28
|
+
final = nil
|
29
|
+
# Remove the constant
|
30
|
+
ns.send(:remove_const, name)
|
31
|
+
load(file)
|
32
|
+
# Notify the object it was reloaded...
|
33
|
+
final = ns.const_get(name)
|
34
|
+
final.reloaded! if final.respond_to?(:reloaded!)
|
35
|
+
# Finally, update the mtime
|
36
|
+
self.mtimes[file] = File.mtime(file)
|
37
|
+
rescue Exception => e
|
38
|
+
logger.fatal "Exception reloading #{file} (for #{constant})"
|
39
|
+
Perennial::ExceptionTracker.log(e)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/perennial/settings.rb
CHANGED
@@ -4,10 +4,13 @@ module Perennial
|
|
4
4
|
class Settings
|
5
5
|
|
6
6
|
cattr_accessor :configuration, :log_level, :verbose, :daemon
|
7
|
-
|
8
|
-
@@
|
9
|
-
@@
|
10
|
-
@@
|
7
|
+
|
8
|
+
@@configuration = Perennial::Nash.new
|
9
|
+
@@verbose = false
|
10
|
+
@@log_level = :info
|
11
|
+
@@daemon = false
|
12
|
+
@@default_settings_path = nil
|
13
|
+
@@lookup_key_path = ["default"]
|
11
14
|
|
12
15
|
class << self
|
13
16
|
|
@@ -39,57 +42,82 @@ module Perennial
|
|
39
42
|
@@setup ||= false
|
40
43
|
end
|
41
44
|
|
45
|
+
def default_settings_path
|
46
|
+
@@default_settings_path || (root / "config" / "settings.yml")
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_settings_path=(value)
|
50
|
+
@@default_settings_path = value
|
51
|
+
setup! if setup?
|
52
|
+
end
|
53
|
+
|
54
|
+
def lookup_key_path
|
55
|
+
@@lookup_key_path ||= []
|
56
|
+
end
|
57
|
+
|
58
|
+
def lookup_key_path=(value)
|
59
|
+
@@lookup_key_path = value
|
60
|
+
end
|
61
|
+
|
42
62
|
def setup(options = {})
|
43
63
|
self.setup!(options) unless setup?
|
44
64
|
end
|
45
65
|
|
46
66
|
def setup!(options = {})
|
47
|
-
@@configuration
|
48
|
-
settings_file =
|
67
|
+
@@configuration ||= Perennial::Nash.new
|
68
|
+
settings_file = self.default_settings_path
|
49
69
|
if File.exist?(settings_file)
|
50
70
|
loaded_yaml = YAML.load(File.read(settings_file))
|
51
|
-
@@configuration.merge!
|
71
|
+
@@configuration.merge!(lookup_settings_from(loaded_yaml))
|
52
72
|
end
|
53
73
|
@@configuration.merge! options
|
54
|
-
|
55
|
-
|
56
|
-
mod = generate_settings_accessor_mixin
|
57
|
-
extend mod
|
58
|
-
include mod
|
74
|
+
# Finally, normalize settings
|
75
|
+
@@configuration = @@configuration.normalized
|
59
76
|
@@setup = true
|
60
77
|
end
|
61
78
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
79
|
+
def update!(attributes = {})
|
80
|
+
return if attributes.blank?
|
81
|
+
settings_file = self.default_settings_path
|
82
|
+
settings = File.exist?(settings_file) ? YAML.load(File.read(settings_file)) : {}
|
83
|
+
namespaced_settings = lookup_settings_from(settings)
|
84
|
+
namespaced_settings.merge! attributes.stringify_keys
|
85
|
+
File.open(settings_file, "w+") { |f| f.write(settings.to_yaml) }
|
86
|
+
setup!
|
87
|
+
return true
|
65
88
|
end
|
66
89
|
|
67
|
-
def
|
68
|
-
|
69
|
-
self.configuration[key.to_sym] = value
|
70
|
-
return value
|
90
|
+
def to_hash
|
91
|
+
@@configuration.to_hash
|
71
92
|
end
|
72
93
|
|
73
|
-
def
|
74
|
-
self.
|
94
|
+
def method_missing(name, *args, &blk)
|
95
|
+
self.setup! unless self.setup?
|
96
|
+
@@configuration.send(name, *args, &blk)
|
97
|
+
end
|
98
|
+
|
99
|
+
def respond_to?(name, rec = nil)
|
100
|
+
true
|
75
101
|
end
|
76
102
|
|
77
103
|
protected
|
78
104
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
define_method(k) do
|
83
|
-
return Settings.configuration[k]
|
84
|
-
end
|
85
|
-
define_method("#{k}=") do |val|
|
86
|
-
Settings.configuration[k] = val
|
87
|
-
end
|
88
|
-
end
|
105
|
+
def lookup_settings_from(settings_hash)
|
106
|
+
lookup_key_path.inject(settings_hash) do |h, k|
|
107
|
+
h[k.to_s] ||= {}
|
89
108
|
end
|
90
109
|
end
|
91
110
|
|
92
111
|
end
|
112
|
+
|
113
|
+
def method_missing(name, *args, &blk)
|
114
|
+
self.class.setup
|
115
|
+
@@configuration.send(name, *args, &blk)
|
116
|
+
end
|
117
|
+
|
118
|
+
def respond_to?(name, rec = nil)
|
119
|
+
true
|
120
|
+
end
|
93
121
|
|
94
122
|
end
|
95
123
|
end
|
data/lib/perennial.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Append the perennial lib folder onto the load path to make it
|
2
2
|
# nicer to require perennial-related libraries.
|
3
|
-
|
3
|
+
perennial_dir = File.dirname(__FILE__)
|
4
|
+
$LOAD_PATH.unshift(perennial_dir) unless $LOAD_PATH.include?(perennial_dir)
|
4
5
|
|
5
6
|
require 'pathname'
|
6
7
|
require 'perennial/core_ext'
|
@@ -8,11 +9,12 @@ require 'perennial/exceptions'
|
|
8
9
|
|
9
10
|
module Perennial
|
10
11
|
|
11
|
-
VERSION = "0.
|
12
|
+
VERSION = "1.0.0.1"
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
has_library :dispatchable, :hookable, :loader, :logger, :nash,
|
15
|
+
:loggable, :manifest, :settings, :argument_parser,
|
16
|
+
:option_parser, :application, :generator, :daemon,
|
17
|
+
:delegateable, :reloading
|
16
18
|
|
17
19
|
def self.included(parent)
|
18
20
|
parent.extend(Manifest::Mixin)
|
data/templates/application.erb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
lib_path = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
2
3
|
require 'perennial'
|
3
4
|
|
4
5
|
module <%= @application_module %>
|
@@ -7,7 +8,7 @@ module <%= @application_module %>
|
|
7
8
|
VERSION = "0.0.1"
|
8
9
|
|
9
10
|
manifest do |m, l|
|
10
|
-
Settings.root =
|
11
|
+
Settings.root = __FILE__.to_pathname.dirname.dirname
|
11
12
|
# Initialize your controllers, e.g:
|
12
13
|
# l.register_controller :client, <%= @application_module %>::Client
|
13
14
|
end
|
data/templates/rakefile.erb
CHANGED
@@ -26,6 +26,7 @@ task :gemspec do
|
|
26
26
|
s.summary = ""
|
27
27
|
s.files = FileList["{bin,vendor,lib,test}/**/*"].to_a
|
28
28
|
s.platform = Gem::Platform::RUBY
|
29
|
+
s.add_dependency "Sutto-perennial", ">= <%= Perennial::VERSION %>"
|
29
30
|
end
|
30
31
|
File.open("<%= @application_path %>.gemspec", "w+") { |f| f.puts spec.to_ruby }
|
31
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perennial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darcy Laycock
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-25 00:00:00 +08:00
|
13
13
|
default_executable: perennial
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,19 +23,17 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- bin/perennial
|
26
|
-
- vendor/fakefs/lib/fakefs.rb
|
27
|
-
- vendor/fakefs/LICENSE
|
28
|
-
- vendor/fakefs/Rakefile
|
29
|
-
- vendor/fakefs/README.markdown
|
30
|
-
- vendor/fakefs/test/fakefs_test.rb
|
31
|
-
- vendor/fakefs/test/verify.rb
|
32
26
|
- lib/perennial/application.rb
|
33
27
|
- lib/perennial/argument_parser.rb
|
34
28
|
- lib/perennial/core_ext/attribute_accessors.rb
|
35
29
|
- lib/perennial/core_ext/blank.rb
|
30
|
+
- lib/perennial/core_ext/hash_key_conversions.rb
|
31
|
+
- lib/perennial/core_ext/inflections.rb
|
36
32
|
- lib/perennial/core_ext/misc.rb
|
33
|
+
- lib/perennial/core_ext/proxy.rb
|
37
34
|
- lib/perennial/core_ext.rb
|
38
35
|
- lib/perennial/daemon.rb
|
36
|
+
- lib/perennial/delegateable.rb
|
39
37
|
- lib/perennial/dispatchable.rb
|
40
38
|
- lib/perennial/exceptions.rb
|
41
39
|
- lib/perennial/generator.rb
|
@@ -44,23 +42,18 @@ files:
|
|
44
42
|
- lib/perennial/loggable.rb
|
45
43
|
- lib/perennial/logger.rb
|
46
44
|
- lib/perennial/manifest.rb
|
45
|
+
- lib/perennial/nash.rb
|
47
46
|
- lib/perennial/option_parser.rb
|
47
|
+
- lib/perennial/reloading.rb
|
48
48
|
- lib/perennial/settings.rb
|
49
49
|
- lib/perennial.rb
|
50
|
-
- test/dispatchable_test.rb
|
51
|
-
- test/hookable_test.rb
|
52
|
-
- test/loader_test.rb
|
53
|
-
- test/loggable_test.rb
|
54
|
-
- test/logger_test.rb
|
55
|
-
- test/settings_test.rb
|
56
|
-
- test/test_helper.rb
|
57
50
|
- templates/application.erb
|
58
51
|
- templates/boot.erb
|
59
52
|
- templates/rakefile.erb
|
60
53
|
- templates/setup.erb
|
61
54
|
- templates/test.erb
|
62
55
|
- templates/test_helper.erb
|
63
|
-
has_rdoc:
|
56
|
+
has_rdoc: false
|
64
57
|
homepage: http://sutto.net/
|
65
58
|
licenses: []
|
66
59
|
|
@@ -84,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
77
|
requirements: []
|
85
78
|
|
86
79
|
rubyforge_project:
|
87
|
-
rubygems_version: 1.3.
|
80
|
+
rubygems_version: 1.3.2
|
88
81
|
signing_key:
|
89
82
|
specification_version: 3
|
90
83
|
summary: A simple (generally event-oriented) application library for Ruby
|