runo 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -118
- data/bin/runo +4 -29
- data/lib/dummy.rb +0 -0
- metadata +12 -278
- data/lib/_error.rb +0 -14
- data/lib/_field.rb +0 -260
- data/lib/_i18n.rb +0 -144
- data/lib/_parser.rb +0 -256
- data/lib/_path.rb +0 -86
- data/lib/_storage/_storage.rb +0 -215
- data/lib/_storage/file.rb +0 -201
- data/lib/_storage/sequel.rb +0 -174
- data/lib/_storage/temp.rb +0 -73
- data/lib/_widget/action_create.rb +0 -23
- data/lib/_widget/action_login.rb +0 -22
- data/lib/_widget/action_signup.rb +0 -16
- data/lib/_widget/action_update.rb +0 -16
- data/lib/_widget/crumb.rb +0 -24
- data/lib/_widget/done.rb +0 -16
- data/lib/_widget/login.rb +0 -25
- data/lib/_widget/me.rb +0 -31
- data/lib/_widget/message.rb +0 -51
- data/lib/_widget/navi.rb +0 -88
- data/lib/_widget/submit.rb +0 -49
- data/lib/_widget/view_ym.rb +0 -77
- data/lib/_workflow/_workflow.rb +0 -89
- data/lib/_workflow/attachment.rb +0 -50
- data/lib/_workflow/blog.rb +0 -28
- data/lib/_workflow/contact.rb +0 -23
- data/lib/_workflow/forum.rb +0 -26
- data/lib/_workflow/register.rb +0 -39
- data/lib/meta/_meta.rb +0 -20
- data/lib/meta/group.rb +0 -19
- data/lib/meta/id.rb +0 -59
- data/lib/meta/owner.rb +0 -21
- data/lib/meta/timestamp.rb +0 -118
- data/lib/runo.rb +0 -396
- data/lib/scalar/checkbox.rb +0 -68
- data/lib/scalar/file.rb +0 -144
- data/lib/scalar/img.rb +0 -112
- data/lib/scalar/password.rb +0 -58
- data/lib/scalar/radio.rb +0 -47
- data/lib/scalar/select.rb +0 -47
- data/lib/scalar/text.rb +0 -38
- data/lib/scalar/textarea.rb +0 -35
- data/lib/scalar/textarea_pre.rb +0 -14
- data/lib/scalar/textarea_wiki.rb +0 -173
- data/lib/set/_set.rb +0 -196
- data/lib/set/dynamic.rb +0 -177
- data/lib/set/static.rb +0 -102
- data/lib/set/static_folder.rb +0 -96
- data/locale/en/index.po +0 -242
- data/locale/index.pot +0 -243
- data/locale/ja/index.po +0 -242
- data/locale/lazy_parser.rb +0 -54
- data/skel/config.ru +0 -27
- data/skel/skin/_users/00000000_frank-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_frank-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_frank.yaml +0 -12
- data/skel/skin/_users/00000000_root-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_root-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_root.yaml +0 -11
- data/skel/skin/_users/css/users.css +0 -21
- data/skel/skin/_users/css/users.less +0 -25
- data/skel/skin/_users/done.html +0 -42
- data/skel/skin/_users/index.html +0 -46
- data/skel/skin/_users/index.yaml +0 -3
- data/skel/skin/_users/summary.html +0 -40
- data/skel/skin/css/base.css +0 -93
- data/skel/skin/css/base.less +0 -139
- data/skel/skin/css/coax.css +0 -199
- data/skel/skin/css/coax.less +0 -244
- data/skel/skin/examples/blog/20091214_0001.yaml +0 -8
- data/skel/skin/examples/blog/20100630_0001.yaml +0 -8
- data/skel/skin/examples/blog/20100630_0002.yaml +0 -14
- data/skel/skin/examples/blog/20100701_0001.yaml +0 -8
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f_small.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002.yaml +0 -19
- data/skel/skin/examples/blog/frank/20100701_0001.yaml +0 -10
- data/skel/skin/examples/blog/frank/index.yaml +0 -4
- data/skel/skin/examples/blog/index.html +0 -51
- data/skel/skin/examples/blog/rss.xml +0 -18
- data/skel/skin/examples/contact/20100701_0001-file.txt +0 -1
- data/skel/skin/examples/contact/20100701_0001.yaml +0 -15
- data/skel/skin/examples/contact/20100701_0002.yaml +0 -8
- data/skel/skin/examples/contact/20100701_0003.yaml +0 -9
- data/skel/skin/examples/contact/index.html +0 -47
- data/skel/skin/examples/contact/js/contact.js +0 -13
- data/skel/skin/examples/contact/summary.html +0 -54
- data/skel/skin/examples/forum/20100701_0001.yaml +0 -41
- data/skel/skin/examples/forum/20100701_0002.yaml +0 -25
- data/skel/skin/examples/forum/index.html +0 -68
- data/skel/skin/examples/forum/summary.html +0 -47
- data/skel/skin/examples/index.html +0 -73
- data/skel/skin/index.html +0 -39
- data/skel/skin/js/base.js +0 -50
- data/t/locale/de/index.po +0 -19
- data/t/locale/en-GB/index.po +0 -25
- data/t/locale/ja/index.po +0 -30
- data/t/skin/_users/00000000_test.yaml +0 -3
- data/t/skin/_users/index.html +0 -13
- data/t/skin/foo/20091120_0001.yaml +0 -7
- data/t/skin/foo/bar/20091120_0001.yaml +0 -5
- data/t/skin/foo/bar/index.yaml +0 -5
- data/t/skin/foo/baz/css/baz.css +0 -1
- data/t/skin/foo/css/foo.css +0 -1
- data/t/skin/foo/index.html +0 -14
- data/t/skin/foo/index.yaml +0 -7
- data/t/skin/foo/not_css/foo.css +0 -1
- data/t/skin/foo/qux/index.html +0 -8
- data/t/skin/foo/qux/moo/index.html +0 -6
- data/t/skin/foo/sub-20100306_0001.yaml +0 -3
- data/t/skin/index.yaml +0 -3
- data/t/skin/t_attachment/index.html +0 -13
- data/t/skin/t_contact/done.html +0 -6
- data/t/skin/t_contact/index.html +0 -9
- data/t/skin/t_file/index.html +0 -16
- data/t/skin/t_img/index.html +0 -14
- data/t/skin/t_img/test.jpg +0 -0
- data/t/skin/t_select/index.html +0 -9
- data/t/skin/t_store/index.html +0 -9
- data/t/skin/t_summary/20100326_0001.yaml +0 -3
- data/t/skin/t_summary/create.html +0 -9
- data/t/skin/t_summary/index.html +0 -9
- data/t/skin/t_summary/summary.html +0 -9
- data/t/t.rb +0 -27
- data/t/test_checkbox.rb +0 -273
- data/t/test_field.rb +0 -330
- data/t/test_file.rb +0 -900
- data/t/test_id.rb +0 -215
- data/t/test_img.rb +0 -328
- data/t/test_meta.rb +0 -57
- data/t/test_parser.rb +0 -1516
- data/t/test_password.rb +0 -188
- data/t/test_radio.rb +0 -226
- data/t/test_role.rb +0 -249
- data/t/test_runo.rb +0 -768
- data/t/test_runo_call.rb +0 -1281
- data/t/test_runo_i18n.rb +0 -325
- data/t/test_select.rb +0 -182
- data/t/test_set_complex.rb +0 -527
- data/t/test_set_dynamic.rb +0 -1504
- data/t/test_set_folder.rb +0 -515
- data/t/test_set_permit.rb +0 -246
- data/t/test_set_static.rb +0 -468
- data/t/test_storage.rb +0 -915
- data/t/test_text.rb +0 -125
- data/t/test_textarea.rb +0 -138
- data/t/test_timestamp.rb +0 -473
- data/t/test_workflow.rb +0 -367
data/lib/_path.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# Author:: Akira FUNAI
|
4
|
-
# Copyright:: Copyright (c) 2009 Akira FUNAI
|
5
|
-
|
6
|
-
module Runo::Path
|
7
|
-
|
8
|
-
module_function
|
9
|
-
|
10
|
-
def tid_of(path)
|
11
|
-
path[Runo::REX::TID]
|
12
|
-
end
|
13
|
-
|
14
|
-
def steps_of(path)
|
15
|
-
_dirname(path).gsub(Runo::REX::PATH_ID, '').split('/').select {|step_or_cond|
|
16
|
-
step_or_cond != '' &&
|
17
|
-
step_or_cond !~ Regexp.union(Runo::REX::COND, Runo::REX::COND_D, Runo::REX::TID)
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
def base_of(path)
|
22
|
-
base = Runo::Set::Static::Folder.root.item steps_of(path)
|
23
|
-
if base.is_a? Runo::Set::Static::Folder
|
24
|
-
base.item('main') || base.find {|item| item.is_a? Runo::Set::Dynamic } || base
|
25
|
-
else
|
26
|
-
base
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def conds_of(path)
|
31
|
-
dir = _dirname path.gsub(Runo::REX::PATH_ID, '')
|
32
|
-
conds = $& ? {:id => sprintf('%.8d_%.4d', $1, $2)} : {}
|
33
|
-
|
34
|
-
dir.split('/').inject(conds) {|conds, step_or_cond|
|
35
|
-
if step_or_cond =~ Runo::REX::COND
|
36
|
-
conds[$1.intern] = $2
|
37
|
-
elsif step_or_cond =~ Runo::REX::COND_D
|
38
|
-
conds[:d] = $&
|
39
|
-
end
|
40
|
-
conds
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
def action_of(path)
|
45
|
-
a = _basename(path).to_s[/^[a-z]+/]
|
46
|
-
a.intern if a && a != 'index'
|
47
|
-
end
|
48
|
-
|
49
|
-
def sub_action_of(path)
|
50
|
-
a = _basename(path).to_s[/_([a-z]+)/, 1]
|
51
|
-
a.intern if a
|
52
|
-
end
|
53
|
-
|
54
|
-
def path_of(conds)
|
55
|
-
conds = {} unless conds.is_a? ::Hash
|
56
|
-
(
|
57
|
-
(conds.keys - [:order, :p, :id]) |
|
58
|
-
([:order, :p, :id] & conds.keys)
|
59
|
-
).collect {|cid|
|
60
|
-
if cid == :id
|
61
|
-
ids = Array(conds[:id]).collect {|id|
|
62
|
-
(id =~ /_(#{Runo::REX::ID_SHORT})$/) ? $1 : (id if Runo::REX::ID)
|
63
|
-
}.compact
|
64
|
-
if (ids.size == 1) && (ids.first =~ Runo::REX::ID)
|
65
|
-
'%s/%d/' % [$1, $2.to_i]
|
66
|
-
elsif ids.size > 0
|
67
|
-
"id=#{ids.join ','}/"
|
68
|
-
end
|
69
|
-
elsif cid == :d
|
70
|
-
conds[:id] ? '' : "#{conds[:d]}/"
|
71
|
-
else
|
72
|
-
"#{cid}=#{Array(conds[cid]).join ','}/"
|
73
|
-
end
|
74
|
-
}.join.sub(%r{/p=1/$}, '/')
|
75
|
-
end
|
76
|
-
|
77
|
-
def _dirname(path) # returns '/foo/bar/' for '/foo/bar/'
|
78
|
-
path[%r{^.*/}] || ''
|
79
|
-
end
|
80
|
-
|
81
|
-
def _basename(path) # returns nil for '/foo/bar/'
|
82
|
-
path[%r{[^/]+$}]
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
data/lib/_storage/_storage.rb
DELETED
@@ -1,215 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# Author:: Akira FUNAI
|
4
|
-
# Copyright:: Copyright (c) 2009 Akira FUNAI
|
5
|
-
|
6
|
-
class Runo::Storage
|
7
|
-
|
8
|
-
def self.instance(sd)
|
9
|
-
if folder = sd[:folder]
|
10
|
-
if folder != sd[:parent]
|
11
|
-
Temp.new sd
|
12
|
-
else
|
13
|
-
klass = Runo['storage']['default'].capitalize
|
14
|
-
self.const_get(klass).new sd
|
15
|
-
end
|
16
|
-
else
|
17
|
-
Temp.new sd
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.available?
|
22
|
-
false
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :sd
|
26
|
-
|
27
|
-
def initialize(sd)
|
28
|
-
@sd = sd
|
29
|
-
end
|
30
|
-
|
31
|
-
def persistent?
|
32
|
-
true
|
33
|
-
end
|
34
|
-
|
35
|
-
def order
|
36
|
-
@sd[:order]
|
37
|
-
end
|
38
|
-
|
39
|
-
def select(conds = {})
|
40
|
-
_cast conds
|
41
|
-
item_ids = _select(conds)
|
42
|
-
item_ids = _sort(item_ids, conds)
|
43
|
-
item_ids = _page(item_ids, conds)
|
44
|
-
((conds[:order] || order) =~ /^-/) ? item_ids.reverse : item_ids
|
45
|
-
end
|
46
|
-
|
47
|
-
def build(v)
|
48
|
-
self
|
49
|
-
end
|
50
|
-
|
51
|
-
def clear
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
def store(id, v)
|
56
|
-
id
|
57
|
-
end
|
58
|
-
|
59
|
-
def delete(id)
|
60
|
-
id
|
61
|
-
end
|
62
|
-
|
63
|
-
def navi(conds)
|
64
|
-
conds[:p] = '1' unless conds[:p] || conds[:id] || (@sd[:p_size].to_i < 1)
|
65
|
-
navi = {}
|
66
|
-
(([:id, :p, :d] & conds.keys) | conds.keys).each {|cid|
|
67
|
-
next unless conds[cid] && respond_to?("_sibs_#{cid}", true)
|
68
|
-
sibs = __send__("_sibs_#{cid}", conds)
|
69
|
-
|
70
|
-
c = (c.is_a?(::Array) && c.size < 2) ? conds[cid].first : conds[cid]
|
71
|
-
if i = sibs.index(c)
|
72
|
-
if !navi[:prev] && i > 0
|
73
|
-
navi[:prev] = conds.merge(cid => sibs[i - 1])
|
74
|
-
if ![:id, :p].include? cid
|
75
|
-
navi[:prev][:id] = _select_without(:id, navi[:prev]).last if conds[:id]
|
76
|
-
navi[:prev][:p] = _p_count(navi[:prev]).to_s if conds[:p]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
if !navi[:next] && i < (sibs.size - 1)
|
80
|
-
navi[:next] = conds.merge(cid => sibs[i + 1])
|
81
|
-
if ![:id, :p].include? cid
|
82
|
-
navi[:next][:id] = _select_without(:id, navi[:next]).first if conds[:id]
|
83
|
-
navi[:next][:p] = '1' if conds[:p]
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
navi[:sibs] ||= {cid => sibs} if navi[:prev] || navi[:next]
|
88
|
-
|
89
|
-
break if navi[:prev] && navi[:next]
|
90
|
-
}
|
91
|
-
|
92
|
-
navi
|
93
|
-
end
|
94
|
-
|
95
|
-
def last(cid, conds)
|
96
|
-
__send__("_sibs_#{cid}", conds).last
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
def _cast(conds)
|
102
|
-
([:d, :id, :p] & conds.keys).each {|cid|
|
103
|
-
case cid
|
104
|
-
when :d
|
105
|
-
conds[:d] = conds[:d].first if conds[:d].is_a? ::Array
|
106
|
-
conds[:d] = conds[:d].to_s
|
107
|
-
conds[:d] = last(:d, conds) if conds[:d] =~ /9999(99)?(99)?/
|
108
|
-
conds[:d] = nil unless conds[:d] =~ Runo::REX::COND_D
|
109
|
-
when :id
|
110
|
-
conds[:id] = Array(conds[:id]).collect {|id|
|
111
|
-
case id
|
112
|
-
when '99999999_9999', 'last'
|
113
|
-
last(:id, conds)
|
114
|
-
when /\A#{Runo::REX::ID_SHORT}\z/
|
115
|
-
"00000000_#{id}"
|
116
|
-
when Runo::REX::ID, Runo::REX::ID_NEW
|
117
|
-
id
|
118
|
-
end
|
119
|
-
}.uniq.compact
|
120
|
-
when :p
|
121
|
-
conds[:p] = conds[:p].first if conds[:p].is_a? ::Array
|
122
|
-
conds[:p] = conds[:p].to_s
|
123
|
-
conds[:p] = last(:p, conds) if conds[:p] == 'last'
|
124
|
-
conds[:p] = nil unless conds[:p] =~ /^\d+$/
|
125
|
-
end
|
126
|
-
}
|
127
|
-
conds
|
128
|
-
end
|
129
|
-
|
130
|
-
def _select(conds)
|
131
|
-
if conds[:id]
|
132
|
-
_select_by_id(conds) | (@sd.instance_variable_get(:@item_object).keys & Array(conds[:id]))
|
133
|
-
elsif cid = (conds.keys - [:order, :p]).first
|
134
|
-
m = "_select_by_#{cid}"
|
135
|
-
respond_to?(m, true) ? __send__(m, conds) : []
|
136
|
-
else
|
137
|
-
_select_all(conds) | @sd.instance_variable_get(:@item_object).keys
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def _sort(item_ids, conds)
|
142
|
-
item_ids.sort
|
143
|
-
end
|
144
|
-
|
145
|
-
def _page(item_ids, conds)
|
146
|
-
size = @sd[:p_size].to_i
|
147
|
-
return item_ids if size < 1
|
148
|
-
|
149
|
-
page = conds[:p].to_i
|
150
|
-
page = 1 if page < 1
|
151
|
-
Array item_ids[(page - 1) * size, size]
|
152
|
-
end
|
153
|
-
|
154
|
-
def _sibs_id(conds)
|
155
|
-
_select_without(:id, conds)
|
156
|
-
end
|
157
|
-
|
158
|
-
def _sibs_p(conds)
|
159
|
-
p_count = _p_count(conds)
|
160
|
-
p_count ? (1..p_count).collect {|i| i.to_s } : []
|
161
|
-
end
|
162
|
-
|
163
|
-
def _sibs_d(conds)
|
164
|
-
rex_d = /^\d{#{conds[:d].length}}/
|
165
|
-
_select_without(:id, :p, :d, conds).collect {|id| id[rex_d] }.uniq.compact
|
166
|
-
end
|
167
|
-
|
168
|
-
def _select_without(*cids)
|
169
|
-
conds = cids.pop.dup
|
170
|
-
cids.each {|cid| conds.delete cid }
|
171
|
-
_sort(_select(conds), conds)
|
172
|
-
end
|
173
|
-
|
174
|
-
def _p_count(conds)
|
175
|
-
(_select_without(:id, :p, conds).size / @sd[:p_size].to_f).ceil unless @sd[:p_size].to_f == 0
|
176
|
-
end
|
177
|
-
|
178
|
-
def cast_ids(ids)
|
179
|
-
Array(ids).collect {|i|
|
180
|
-
id = (i =~ /^[a-z]/) ? "00000000_#{i}" : i
|
181
|
-
id if id =~ Runo::REX::ID
|
182
|
-
}.compact
|
183
|
-
end
|
184
|
-
|
185
|
-
def new_id(v = {})
|
186
|
-
return "00000000_#{v['_id']}" if v.is_a?(::Hash) && v['_id'] =~ /\A#{Runo::REX::ID_SHORT}\z/
|
187
|
-
|
188
|
-
if v.is_a?(::Hash) && v['_timestamp'] && v['_timestamp']['published'].is_a?(::Time)
|
189
|
-
d = v['_timestamp']['published'].strftime '%Y%m%d'
|
190
|
-
else
|
191
|
-
d = Time.now.strftime '%Y%m%d'
|
192
|
-
end
|
193
|
-
if max_in_d = _select(:d => d).sort.last
|
194
|
-
max_in_d.succ
|
195
|
-
else
|
196
|
-
d + '_0001'
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def new_id?(id, v)
|
201
|
-
if id == :new_id
|
202
|
-
true
|
203
|
-
elsif !v.is_a?(::Hash)
|
204
|
-
false
|
205
|
-
elsif id =~ /_#{Runo::REX::ID_SHORT}\z/
|
206
|
-
v['_id'] =~ /\A#{Runo::REX::ID_SHORT}\z/ &&
|
207
|
-
id != new_id(v)
|
208
|
-
else
|
209
|
-
v['_timestamp'] &&
|
210
|
-
v['_timestamp']['published'].is_a?(::Time) &&
|
211
|
-
id !~ /\A#{v['_timestamp']['published'].strftime('%Y%m%d')}/
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
data/lib/_storage/file.rb
DELETED
@@ -1,201 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# Author:: Akira FUNAI
|
4
|
-
# Copyright:: Copyright (c) 2009 Akira FUNAI
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'yaml'
|
8
|
-
require 'ya2yaml'
|
9
|
-
require 'fileutils'
|
10
|
-
|
11
|
-
class Runo::Storage::File < Runo::Storage
|
12
|
-
|
13
|
-
def self.traverse(dir = '/', root = Runo['storage']['File']['data_dir'], &block)
|
14
|
-
::Dir.glob(::File.join(root, dir, '*')).sort.collect {|file|
|
15
|
-
ftype = ::File.ftype file
|
16
|
-
base_name = ::File.basename file
|
17
|
-
id, ext = base_name.split('.', 2)
|
18
|
-
id = "main-#{id}" if id =~ Runo::REX::ID
|
19
|
-
full_name = ::File.join(dir, id).gsub(::File::SEPARATOR, '-')
|
20
|
-
|
21
|
-
if ftype == 'file' && id.sub(/^([^\d\-]+-)+/, '') =~ Runo::REX::ID
|
22
|
-
val = nil
|
23
|
-
::File.open(file, 'r') {|f|
|
24
|
-
f.flock ::File::LOCK_SH
|
25
|
-
f.binmode
|
26
|
-
val = f.read
|
27
|
-
f.flock ::File::LOCK_UN
|
28
|
-
}
|
29
|
-
block.call(
|
30
|
-
:dir => dir,
|
31
|
-
:base_name => base_name,
|
32
|
-
:full_name => full_name,
|
33
|
-
:ext => ext,
|
34
|
-
:val => (ext == 'yaml' ? YAML.load(val) : val)
|
35
|
-
)
|
36
|
-
elsif ftype == 'directory' && base_name !~ /\A#{Runo::REX::DIR_STATIC}\z/
|
37
|
-
self.traverse(::File.join(dir, base_name), root, &block)
|
38
|
-
end
|
39
|
-
}.compact.flatten
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.load_skel
|
43
|
-
self.traverse('/', Runo['skin_dir']) {|entry|
|
44
|
-
dir = ::File.join(Runo['storage']['File']['data_dir'], entry[:dir])
|
45
|
-
unless ::File.exists? ::File.join(dir, entry[:base_name])
|
46
|
-
::FileUtils.mkpath(dir) unless ::File.directory? dir
|
47
|
-
::FileUtils.cp(
|
48
|
-
::File.join(Runo['skin_dir'], entry[:dir], entry[:base_name]),
|
49
|
-
::File.join(dir, entry[:base_name]),
|
50
|
-
{:preserve => true}
|
51
|
-
)
|
52
|
-
end
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.available?
|
57
|
-
Runo['storage']['File'] && Runo['storage']['File']['data_dir']
|
58
|
-
end
|
59
|
-
|
60
|
-
def initialize(sd)
|
61
|
-
super
|
62
|
-
unless @@loaded ||= false
|
63
|
-
entries = ::Dir.glob ::File.join(Runo['storage']['File']['data_dir'], '*')
|
64
|
-
self.class.load_skel if entries.empty?
|
65
|
-
@@loaded = true
|
66
|
-
end
|
67
|
-
@dir = ::File.join(Runo['storage']['File']['data_dir'], @sd[:folder][:dir])
|
68
|
-
::FileUtils.mkpath(@dir) unless ::File.directory? @dir
|
69
|
-
end
|
70
|
-
|
71
|
-
def val(id = nil)
|
72
|
-
if id
|
73
|
-
load id
|
74
|
-
else
|
75
|
-
# this could be HUGE.
|
76
|
-
_select_all({}).inject({}) {|v, id|
|
77
|
-
v[id] = load id
|
78
|
-
v
|
79
|
-
}
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def build(v)
|
84
|
-
clear
|
85
|
-
v.each {|id, v| store(id, v) }
|
86
|
-
self
|
87
|
-
end
|
88
|
-
|
89
|
-
def clear
|
90
|
-
glob.each {|file| ::File.unlink ::File.join(@dir, file) }
|
91
|
-
self
|
92
|
-
end
|
93
|
-
|
94
|
-
def store(id, v, ext = nil)
|
95
|
-
save(id, v, ext)
|
96
|
-
end
|
97
|
-
|
98
|
-
def delete(id)
|
99
|
-
remove_file(id) && id
|
100
|
-
end
|
101
|
-
|
102
|
-
def move(old_id, new_id)
|
103
|
-
rename_file(old_id, new_id) && new_id
|
104
|
-
end
|
105
|
-
|
106
|
-
private
|
107
|
-
|
108
|
-
def _select_by_id(conds)
|
109
|
-
glob(Array(conds[:id])).collect {|f| f[/\d.*/][Runo::REX::ID] }.compact
|
110
|
-
end
|
111
|
-
|
112
|
-
def _select_by_d(conds)
|
113
|
-
glob(conds[:d].to_s).collect {|f| f[/\.yaml$/] && f[/\d.*/][Runo::REX::ID] }.compact
|
114
|
-
end
|
115
|
-
|
116
|
-
def _select_all(conds)
|
117
|
-
glob.collect {|f| f[/\.yaml$/] && f[/\d.*/][Runo::REX::ID] }.compact
|
118
|
-
end
|
119
|
-
|
120
|
-
def glob(id = :all)
|
121
|
-
glob_pattern = "#{file_prefix}#{pattern_for id}.[a-z]*"
|
122
|
-
::Dir.chdir(@dir) { ::Dir.glob glob_pattern }
|
123
|
-
end
|
124
|
-
|
125
|
-
def file_prefix
|
126
|
-
(@sd[:name] == 'main') ? '' : @sd[:name].sub(/^main-/, '') + '-'
|
127
|
-
end
|
128
|
-
|
129
|
-
def pattern_for(id)
|
130
|
-
if id.is_a? Array
|
131
|
-
"{#{id.join ','}}"
|
132
|
-
elsif id == :all
|
133
|
-
'[0-9]*_*'
|
134
|
-
elsif id =~ /\A\d{4,8}\z/
|
135
|
-
"#{id}*"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def load(id)
|
140
|
-
v = nil
|
141
|
-
file = glob(Array(id)).sort.first
|
142
|
-
::File.open(::File.join(@dir, file), 'r') {|f|
|
143
|
-
f.flock ::File::LOCK_SH
|
144
|
-
f.binmode
|
145
|
-
v = f.read
|
146
|
-
f.flock ::File::LOCK_UN
|
147
|
-
} if file
|
148
|
-
(file[/\.yaml$/] ? YAML.load(v) : v) if v
|
149
|
-
end
|
150
|
-
|
151
|
-
def save(id, v, ext)
|
152
|
-
if new_id?(id, v)
|
153
|
-
old_id = id
|
154
|
-
id = new_id v
|
155
|
-
end
|
156
|
-
|
157
|
-
if ext
|
158
|
-
val = v
|
159
|
-
ext = 'y' if ext == 'yaml'
|
160
|
-
remove_file id
|
161
|
-
else
|
162
|
-
val = v.ya2yaml(:syck_compatible => true)
|
163
|
-
ext = 'yaml'
|
164
|
-
end
|
165
|
-
|
166
|
-
file = "#{file_prefix}#{id}.#{ext}"
|
167
|
-
if old_id && f = ::File.open(::File.join(@dir, file), 'a')
|
168
|
-
f.seek(0, IO::SEEK_END)
|
169
|
-
return if f.pos != 0 # duplicate id
|
170
|
-
move(old_id, id) unless old_id == :new_id
|
171
|
-
end
|
172
|
-
::File.open(::File.join(@dir, file), 'a') {|f|
|
173
|
-
f.flock ::File::LOCK_EX
|
174
|
-
f.binmode
|
175
|
-
f.seek 0
|
176
|
-
f.truncate 0
|
177
|
-
f << val
|
178
|
-
f.flock ::File::LOCK_UN
|
179
|
-
f.chmod 0664
|
180
|
-
} && id
|
181
|
-
end
|
182
|
-
|
183
|
-
def remove_file(id)
|
184
|
-
glob_pattern = "#{file_prefix}#{pattern_for Array(id)}[.-]*"
|
185
|
-
files = ::Dir.chdir(@dir) { ::Dir.glob glob_pattern } # may include child files
|
186
|
-
files.each {|file|
|
187
|
-
::File.unlink ::File.join(@dir, file)
|
188
|
-
}
|
189
|
-
end
|
190
|
-
|
191
|
-
def rename_file(old_id, new_id)
|
192
|
-
glob_pattern = "#{file_prefix}#{pattern_for Array(old_id)}*"
|
193
|
-
files = ::Dir.chdir(@dir) { ::Dir.glob glob_pattern } # may include child files
|
194
|
-
rex = /^\A#{file_prefix}#{old_id}/
|
195
|
-
files.each {|file|
|
196
|
-
to_file = file.sub(rex, "#{file_prefix}#{new_id}")
|
197
|
-
::File.rename(::File.join(@dir, file), ::File.join(@dir, to_file))
|
198
|
-
}
|
199
|
-
end
|
200
|
-
|
201
|
-
end
|