smallcage 0.2.6 → 0.2.7
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +3 -2
- data/lib/smallcage/application.rb +12 -236
- data/lib/smallcage/commands/auto.rb +46 -23
- data/lib/smallcage/commands/base.rb +5 -2
- data/lib/smallcage/commands/clean.rb +9 -8
- data/lib/smallcage/commands/export.rb +9 -14
- data/lib/smallcage/commands/import.rb +29 -29
- data/lib/smallcage/commands/manifest.rb +8 -10
- data/lib/smallcage/commands/server.rb +2 -2
- data/lib/smallcage/commands/update.rb +30 -17
- data/lib/smallcage/commands/uri.rb +6 -9
- data/lib/smallcage/document_path.rb +10 -12
- data/lib/smallcage/erb_base.rb +7 -3
- data/lib/smallcage/http_server.rb +10 -10
- data/lib/smallcage/loader.rb +57 -57
- data/lib/smallcage/misc.rb +1 -1
- data/lib/smallcage/options_parser.rb +251 -0
- data/lib/smallcage/renderer.rb +3 -4
- data/lib/smallcage/runner.rb +9 -9
- data/lib/smallcage/update_list.rb +50 -40
- data/lib/smallcage/version.rb +1 -1
- data/lib/smallcage.rb +1 -0
- data/spec/lib/smallcage/application_spec.rb +62 -43
- data/spec/lib/smallcage/commands/export_spec.rb +8 -8
- data/spec/lib/smallcage/commands/import_spec.rb +2 -2
- data/spec/lib/smallcage/commands/manifest_spec.rb +1 -1
- data/spec/lib/smallcage/commands/update_spec.rb +13 -13
- data/spec/lib/smallcage/document_path_spec.rb +4 -4
- data/spec/lib/smallcage/loader_spec.rb +3 -3
- data/spec/lib/smallcage/update_list_spec.rb +139 -118
- data/spec/spec_helper.rb +6 -0
- metadata +3 -2
@@ -1,22 +1,22 @@
|
|
1
1
|
module SmallCage::Commands
|
2
2
|
class Import
|
3
3
|
def self.execute(opts)
|
4
|
-
|
4
|
+
new(opts).execute
|
5
5
|
end
|
6
6
|
|
7
7
|
def initialize(opts)
|
8
8
|
@opts = opts
|
9
|
-
if @opts[:from] ==
|
10
|
-
@opts[:from] =
|
9
|
+
if @opts[:from] == 'default'
|
10
|
+
@opts[:from] = 'base,standard'
|
11
11
|
end
|
12
|
-
@project_dir = Pathname.new(__FILE__) +
|
12
|
+
@project_dir = Pathname.new(__FILE__) + '../../../../project'
|
13
13
|
end
|
14
14
|
|
15
|
-
def qp(str =
|
15
|
+
def qp(str = '')
|
16
16
|
print str unless @opts[:quiet]
|
17
17
|
end
|
18
18
|
|
19
|
-
def qps(str =
|
19
|
+
def qps(str = '')
|
20
20
|
puts str unless @opts[:quiet]
|
21
21
|
end
|
22
22
|
|
@@ -61,27 +61,27 @@ module SmallCage::Commands
|
|
61
61
|
failed = []
|
62
62
|
@entries.each do |e|
|
63
63
|
if e.overwrite?
|
64
|
-
qps
|
65
|
-
elsif !
|
66
|
-
qps
|
64
|
+
qps 'M /' + e.path
|
65
|
+
elsif !e.exist?
|
66
|
+
qps 'A /' + e.path
|
67
67
|
elsif e.to.directory?
|
68
68
|
# nothing
|
69
69
|
else
|
70
|
-
qps
|
70
|
+
qps '? /' + e.path
|
71
71
|
end
|
72
72
|
|
73
73
|
begin
|
74
74
|
e.import
|
75
75
|
rescue
|
76
76
|
failed << e
|
77
|
-
qps
|
77
|
+
qps 'F /' + e.path
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
unless failed.empty?
|
82
|
-
qps
|
82
|
+
qps 'FAILED:'
|
83
83
|
failed.each do |e|
|
84
|
-
qps
|
84
|
+
qps ' ' + e.path
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -90,7 +90,7 @@ module SmallCage::Commands
|
|
90
90
|
def local_entries(d)
|
91
91
|
result = []
|
92
92
|
Dir.chdir(d) do
|
93
|
-
Dir.glob(
|
93
|
+
Dir.glob('**/*') do |f|
|
94
94
|
e = ImportEntry.new
|
95
95
|
e.path = f
|
96
96
|
e.from = d + f
|
@@ -98,20 +98,20 @@ module SmallCage::Commands
|
|
98
98
|
result << e
|
99
99
|
end
|
100
100
|
end
|
101
|
-
|
101
|
+
result
|
102
102
|
end
|
103
103
|
private :local_entries
|
104
104
|
|
105
105
|
def external_entries(uri)
|
106
106
|
if uri !~ %r{/$}
|
107
|
-
uri +=
|
107
|
+
uri += '/'
|
108
108
|
end
|
109
|
-
mfuri = uri +
|
109
|
+
mfuri = uri + 'Manifest.html'
|
110
110
|
|
111
|
-
source = open(mfuri) {|io| io.read }
|
111
|
+
source = open(mfuri) { |io| io.read }
|
112
112
|
result = []
|
113
113
|
|
114
|
-
files = source.scan(%r{<li><a href="(./[^"]+)">(./[^<]+)</a></li>}) #"
|
114
|
+
files = source.scan(%r{<li><a href="(./[^"]+)">(./[^<]+)</a></li>}) # "
|
115
115
|
files.each do |f|
|
116
116
|
raise "illegal path:#{f[0]},#{f[1]}" if f[0] != f[1]
|
117
117
|
raise "illegal path:#{f[0]}" if f[0] =~ %r{/\.\.}
|
@@ -123,32 +123,32 @@ module SmallCage::Commands
|
|
123
123
|
result << e
|
124
124
|
end
|
125
125
|
|
126
|
-
|
126
|
+
result
|
127
127
|
end
|
128
128
|
private :external_entries
|
129
129
|
|
130
130
|
def confirm_entries
|
131
131
|
overwrite = []
|
132
132
|
|
133
|
-
qps
|
133
|
+
qps 'Create:'
|
134
134
|
@entries.each do |e|
|
135
135
|
if e.overwrite?
|
136
136
|
overwrite << e
|
137
|
-
elsif !
|
138
|
-
qps
|
137
|
+
elsif !e.exist?
|
138
|
+
qps ' /' + e.path
|
139
139
|
end
|
140
140
|
end
|
141
141
|
qps
|
142
142
|
|
143
143
|
unless overwrite.empty?
|
144
|
-
qps
|
144
|
+
qps 'Overwrite:'
|
145
145
|
overwrite.each do |e|
|
146
|
-
qps
|
146
|
+
qps ' /' + e.path
|
147
147
|
end
|
148
148
|
qps
|
149
149
|
end
|
150
150
|
|
151
|
-
|
151
|
+
y_or_n('Import these files?[Yn]: ', true)
|
152
152
|
end
|
153
153
|
private :confirm_entries
|
154
154
|
|
@@ -160,7 +160,7 @@ module SmallCage::Commands
|
|
160
160
|
return true
|
161
161
|
elsif yn =~ /^(n|no)$/i
|
162
162
|
return false
|
163
|
-
elsif yn ==
|
163
|
+
elsif yn == ''
|
164
164
|
return default
|
165
165
|
end
|
166
166
|
end
|
@@ -205,8 +205,8 @@ module SmallCage::Commands
|
|
205
205
|
FileUtils.makedirs(to)
|
206
206
|
else
|
207
207
|
FileUtils.makedirs(to.parent)
|
208
|
-
s = open(from) {|io| io.read }
|
209
|
-
open(to,
|
208
|
+
s = open(from) { |io| io.read }
|
209
|
+
open(to, 'w') { |io| io << s }
|
210
210
|
end
|
211
211
|
end
|
212
212
|
private :copy_external
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module SmallCage::Commands
|
2
2
|
class Manifest
|
3
3
|
def self.execute(opts)
|
4
|
-
|
4
|
+
new(opts).execute
|
5
5
|
end
|
6
6
|
|
7
7
|
def initialize(opts)
|
@@ -12,7 +12,7 @@ module SmallCage::Commands
|
|
12
12
|
entries = []
|
13
13
|
root = Pathname.new(@opts[:path])
|
14
14
|
Dir.chdir(root) do
|
15
|
-
Dir.glob(
|
15
|
+
Dir.glob('**/*') do |f|
|
16
16
|
entries << f
|
17
17
|
end
|
18
18
|
end
|
@@ -20,18 +20,16 @@ module SmallCage::Commands
|
|
20
20
|
tmp = []
|
21
21
|
entries.each do |f|
|
22
22
|
path = root + f
|
23
|
-
f =
|
24
|
-
if path.directory?
|
25
|
-
|
26
|
-
end
|
27
|
-
next if path.basename.to_s == "Manifest.html"
|
23
|
+
f = './' + f
|
24
|
+
f = f + '/' if path.directory?
|
25
|
+
next if path.basename.to_s == 'Manifest.html'
|
28
26
|
tmp << f
|
29
27
|
end
|
30
28
|
entries = tmp
|
31
29
|
|
32
|
-
template = File.dirname(__FILE__) +
|
33
|
-
source = ERB.new(File.read(template), nil,
|
34
|
-
open(root +
|
30
|
+
template = File.dirname(__FILE__) + '/../resources/Manifest.erb'
|
31
|
+
source = ERB.new(File.read(template), nil, '-').result(binding)
|
32
|
+
open(root + 'Manifest.html', 'w') do |io|
|
35
33
|
io << source
|
36
34
|
end
|
37
35
|
end
|
@@ -6,8 +6,8 @@ module SmallCage::Commands
|
|
6
6
|
|
7
7
|
server = SmallCage::HTTPServer.new(document_root, port)
|
8
8
|
|
9
|
-
sighandler = Proc.new {|signal| server.shutdown}
|
10
|
-
SmallCage::Application.add_signal_handler(
|
9
|
+
sighandler = Proc.new { |signal| server.shutdown }
|
10
|
+
SmallCage::Application.add_signal_handler(%w{INT TERM}, sighandler)
|
11
11
|
|
12
12
|
server.start
|
13
13
|
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
module SmallCage::Commands
|
2
|
+
#
|
3
|
+
# 'smc update' command
|
4
|
+
#
|
2
5
|
class Update
|
3
6
|
include SmallCage
|
4
7
|
|
5
8
|
def self.execute(opts)
|
6
|
-
|
9
|
+
new(opts).execute
|
7
10
|
end
|
8
11
|
|
9
12
|
def initialize(opts)
|
@@ -13,21 +16,22 @@ module SmallCage::Commands
|
|
13
16
|
def execute
|
14
17
|
start = Time.now
|
15
18
|
target = Pathname.new(@opts[:path])
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
+
|
20
|
+
fail 'target directory or file does not exist.: ' + target.to_s unless target.exist?
|
19
21
|
|
20
22
|
@loader = Loader.new(target)
|
21
23
|
@renderer = Renderer.new(@loader)
|
22
24
|
@list = UpdateList.create(@loader.root, target)
|
25
|
+
STDERR.puts 'WARN: Can\'t load tmp/list.yml file.' if @list.load_error
|
26
|
+
|
23
27
|
render_smc_files
|
24
28
|
expire_old_files @list.expire
|
25
29
|
@list.save
|
26
30
|
|
27
31
|
count = @list.update_count
|
28
32
|
elapsed = Time.now - start
|
29
|
-
puts "-- #{count} files. #{
|
30
|
-
" #{
|
33
|
+
puts "-- #{count} files. #{sprintf('%.3f', elapsed)} sec." +
|
34
|
+
" #{sprintf('%.3f', count == 0 ? 0 : elapsed / count)} sec/file." unless @opts[:quiet]
|
31
35
|
end
|
32
36
|
|
33
37
|
def expire_old_files(uris)
|
@@ -50,7 +54,7 @@ module SmallCage::Commands
|
|
50
54
|
private :render_smc_files
|
51
55
|
|
52
56
|
def render_smc_obj(obj)
|
53
|
-
uris = @renderer.render(obj[
|
57
|
+
uris = @renderer.render(obj['template'] + '.uri', obj)
|
54
58
|
if uris
|
55
59
|
render_multi(obj, uris.split(/\r\n|\r|\n/))
|
56
60
|
else
|
@@ -60,28 +64,37 @@ module SmallCage::Commands
|
|
60
64
|
private :render_smc_obj
|
61
65
|
|
62
66
|
def render_single(obj, mtime = nil)
|
63
|
-
mark
|
64
|
-
mtime
|
65
|
-
|
67
|
+
mark = obj['path'].exist? ? 'U ' : 'A '
|
68
|
+
mtime ||= obj['path'].smc.stat.mtime.to_i
|
69
|
+
|
70
|
+
if @opts[:fast]
|
71
|
+
last_mtime = @list.mtime(obj['uri'].smc)
|
72
|
+
if mtime == last_mtime
|
73
|
+
@list.update(obj['uri'].smc, mtime, String.new(obj['uri']))
|
74
|
+
return
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
result = @renderer.render(obj['template'], obj)
|
66
79
|
result = after_rendering_filters(obj, result)
|
67
80
|
output_result(obj, result)
|
68
|
-
puts mark + obj[
|
81
|
+
puts mark + obj['uri'] unless @opts[:quiet]
|
69
82
|
|
70
83
|
# create new uri String to remove smc instance-specific method.
|
71
|
-
@list.update(obj[
|
84
|
+
@list.update(obj['uri'].smc, mtime, String.new(obj['uri']))
|
72
85
|
end
|
73
86
|
private :render_single
|
74
87
|
|
75
88
|
def render_multi(obj, uris)
|
76
89
|
obj['uris'] ||= uris
|
77
|
-
uris = uris.map {|uri| uri.strip }
|
90
|
+
uris = uris.map { |uri| uri.strip }
|
78
91
|
smcuri = obj['uri'].smc
|
79
92
|
smcpath = obj['path'].smc
|
80
93
|
base = obj['path'].parent
|
81
94
|
mtime = smcpath.stat.mtime.to_i
|
82
95
|
uris.each_with_index do |uri, index|
|
83
96
|
next if uri.empty?
|
84
|
-
docpath
|
97
|
+
docpath = DocumentPath.create_with_uri(@loader.root, uri, base)
|
85
98
|
next if docpath.path.directory?
|
86
99
|
FileUtils.mkpath(docpath.path.parent)
|
87
100
|
obj['uri'] = DocumentPath.add_smc_method(docpath.uri, smcuri)
|
@@ -93,16 +106,16 @@ module SmallCage::Commands
|
|
93
106
|
private :render_multi
|
94
107
|
|
95
108
|
def after_rendering_filters(obj, result)
|
96
|
-
filters = @loader.filters(
|
109
|
+
filters = @loader.filters('after_rendering_filters')
|
97
110
|
filters.each do |f|
|
98
111
|
result = f.after_rendering_filter(obj, result)
|
99
112
|
end
|
100
|
-
|
113
|
+
result
|
101
114
|
end
|
102
115
|
private :after_rendering_filters
|
103
116
|
|
104
117
|
def output_result(obj, str)
|
105
|
-
open(obj[
|
118
|
+
open(obj['path'], 'w') do |io|
|
106
119
|
io << str
|
107
120
|
end
|
108
121
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
module SmallCage::Commands
|
2
2
|
class Uri
|
3
|
-
|
4
3
|
def self.execute(opts)
|
5
|
-
|
4
|
+
new(opts).execute
|
6
5
|
end
|
7
6
|
|
8
7
|
def initialize(opts)
|
@@ -11,9 +10,7 @@ module SmallCage::Commands
|
|
11
10
|
|
12
11
|
def execute
|
13
12
|
target = Pathname.new(@opts[:path])
|
14
|
-
unless target.exist?
|
15
|
-
raise "target directory or file does not exist.: " + target.to_s
|
16
|
-
end
|
13
|
+
fail 'target directory or file does not exist.: ' + target.to_s unless target.exist?
|
17
14
|
|
18
15
|
@loader = SmallCage::Loader.new(target)
|
19
16
|
@renderer = SmallCage::Renderer.new(@loader)
|
@@ -28,21 +25,21 @@ module SmallCage::Commands
|
|
28
25
|
private :print_uris
|
29
26
|
|
30
27
|
def print_default_or_template_uris(obj)
|
31
|
-
uris = @renderer.render(obj[
|
28
|
+
uris = @renderer.render(obj['template'] + '.uri', obj)
|
32
29
|
if uris
|
33
30
|
print_uri_templates(obj, uris.split(/\r\n|\r|\n/))
|
34
31
|
else
|
35
|
-
puts obj[
|
32
|
+
puts obj['uri']
|
36
33
|
end
|
37
34
|
end
|
38
35
|
private :print_default_or_template_uris
|
39
36
|
|
40
37
|
def print_uri_templates(obj, uris)
|
41
|
-
uris = uris.map {|uri| uri.strip }
|
38
|
+
uris = uris.map { |uri| uri.strip }
|
42
39
|
base = obj['path'].parent
|
43
40
|
uris.each_with_index do |uri, index|
|
44
41
|
if uri.empty?
|
45
|
-
puts
|
42
|
+
puts ''
|
46
43
|
else
|
47
44
|
docpath = SmallCage::DocumentPath.create_with_uri(@loader.root, uri, base)
|
48
45
|
puts docpath.uri
|
@@ -12,43 +12,41 @@ module SmallCage
|
|
12
12
|
@path = @path.cleanpath
|
13
13
|
end
|
14
14
|
|
15
|
-
if @path.to_s[0...@root.to_s.length] != @root.to_s
|
16
|
-
raise "Illegal path: #{path.to_s}"
|
17
|
-
end
|
15
|
+
fail "Illegal path: #{ path.to_s }" if @path.to_s[0...@root.to_s.length] != @root.to_s
|
18
16
|
|
19
17
|
if @path == @root
|
20
|
-
@uri =
|
18
|
+
@uri = '/'
|
21
19
|
else
|
22
20
|
@uri = @path.to_s[@root.to_s.length .. -1]
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
26
24
|
def smc?
|
27
|
-
|
25
|
+
@path.extname == '.smc'
|
28
26
|
end
|
29
27
|
|
30
28
|
def outfile
|
31
29
|
return nil unless smc?
|
32
|
-
|
30
|
+
self.class.new(@root, @path.to_s[0 .. -5])
|
33
31
|
end
|
34
32
|
|
35
33
|
def outuri
|
36
34
|
return nil unless smc?
|
37
|
-
|
35
|
+
uri[0 .. -5]
|
38
36
|
end
|
39
37
|
|
40
38
|
def self.to_uri(root, path)
|
41
|
-
|
39
|
+
new(root, path).uri
|
42
40
|
end
|
43
41
|
|
44
42
|
def self.create_with_uri(root, uri, base = nil)
|
45
43
|
base ||= root
|
46
|
-
if uri[0] ==
|
44
|
+
if uri[0, 1] == '/'
|
47
45
|
path = root + uri[1..-1] # absolute URI
|
48
46
|
else
|
49
47
|
path = base + uri # relative URI
|
50
48
|
end
|
51
|
-
|
49
|
+
new(root, path)
|
52
50
|
end
|
53
51
|
|
54
52
|
def self.add_smc_method(obj, value)
|
@@ -58,10 +56,10 @@ module SmallCage
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def obj.smc
|
61
|
-
|
59
|
+
@__smallcage.nil? ? nil : @__smallcage[:smc]
|
62
60
|
end
|
63
61
|
|
64
|
-
|
62
|
+
obj
|
65
63
|
end
|
66
64
|
end
|
67
65
|
end
|
data/lib/smallcage/erb_base.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
#
|
2
|
+
# ERB Base class
|
3
|
+
#
|
2
4
|
class SmallCage::ErbBase
|
3
5
|
def initialize(loader, renderer, obj)
|
4
6
|
@loader, @renderer, @obj = loader, renderer, obj
|
@@ -6,13 +8,15 @@ class SmallCage::ErbBase
|
|
6
8
|
|
7
9
|
def method_missing(*args)
|
8
10
|
if 1 < args.length
|
9
|
-
|
11
|
+
msg = 'method_missing called with more than one argument: ' +
|
12
|
+
"#{ @renderer.current_template } #{ args.inspect }"
|
13
|
+
fail NameError, msg
|
10
14
|
end
|
11
15
|
|
12
16
|
name = args[0].to_s
|
13
17
|
return @obj[name] unless @obj[name].nil?
|
14
18
|
|
15
19
|
# render if template file exists. or return nil.
|
16
|
-
|
20
|
+
@renderer.render(name, @obj)
|
17
21
|
end
|
18
22
|
end
|
@@ -11,11 +11,11 @@ module SmallCage
|
|
11
11
|
:AccessLog => []
|
12
12
|
})
|
13
13
|
|
14
|
-
WEBrick::HTTPServlet::FileHandler.remove_handler(
|
15
|
-
WEBrick::HTTPServlet::FileHandler.remove_handler(
|
14
|
+
WEBrick::HTTPServlet::FileHandler.remove_handler('cgi')
|
15
|
+
WEBrick::HTTPServlet::FileHandler.remove_handler('rhtml')
|
16
16
|
|
17
|
-
@server.mount(
|
18
|
-
@server.mount(
|
17
|
+
@server.mount('/_smc/update_uri', UpdateUriServlet)
|
18
|
+
@server.mount('/_smc/auto', AutoServlet)
|
19
19
|
end
|
20
20
|
|
21
21
|
def start
|
@@ -31,17 +31,17 @@ module SmallCage
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def reload
|
34
|
-
UpdateUriServlet.uri =
|
34
|
+
UpdateUriServlet.uri = ':reload'
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
|
39
39
|
class UpdateUriServlet < WEBrick::HTTPServlet::AbstractServlet
|
40
|
-
@@uri =
|
41
|
-
@@update_time =
|
40
|
+
@@uri = '/index.html'
|
41
|
+
@@update_time = ''
|
42
42
|
|
43
43
|
def do_GET(req, res)
|
44
|
-
res['content-type'] =
|
44
|
+
res['content-type'] = 'text/plain'
|
45
45
|
res.body = @@uri + "\n" + @@update_time
|
46
46
|
end
|
47
47
|
|
@@ -57,8 +57,8 @@ module SmallCage
|
|
57
57
|
|
58
58
|
class AutoServlet < WEBrick::HTTPServlet::AbstractServlet
|
59
59
|
def do_GET(req, res)
|
60
|
-
res['content-type'] =
|
61
|
-
html = File.dirname(__FILE__) +
|
60
|
+
res['content-type'] = 'text/html'
|
61
|
+
html = File.dirname(__FILE__) + '/resources/auto.html'
|
62
62
|
res.body = File.read(html)
|
63
63
|
end
|
64
64
|
end
|