perennial 0.2.2.2 → 1.0.0.1
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.
- 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
|