smallcage 0.1.7 → 0.1.8

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.
@@ -1,5 +1,7 @@
1
1
  module SmallCage::Commands
2
2
  class Update
3
+ include SmallCage
4
+
3
5
  def self.execute(opts)
4
6
  self.new(opts).execute
5
7
  end
@@ -15,73 +17,80 @@ module SmallCage::Commands
15
17
  raise "target directory or file does not exist.: " + target.to_s
16
18
  end
17
19
 
18
- @loader = SmallCage::Loader.new(target)
19
- @renderer = SmallCage::Renderer.new(@loader)
20
+ @loader = Loader.new(target)
21
+ @renderer = Renderer.new(@loader)
22
+ @list = UpdateList.create(@loader.root, target)
23
+ render_smc_files
24
+ expire_old_files @list.expire
25
+ @list.save
26
+
27
+ count = @list.update_count
28
+ elapsed = Time.now - start
29
+ puts "-- #{count} files. #{"%.3f" % elapsed} sec." +
30
+ " #{"%.3f" % (count == 0 ? 0 : elapsed/count)} sec/file." unless @opts[:quiet]
31
+ end
20
32
 
21
- urilist = render_smc_files
22
- rendered = urilist.length
23
- if list_file.exist?
24
- urilist = delete_expired_files(urilist)
33
+ def expire_old_files(uris)
34
+ root = @loader.root
35
+ uris.each do |uri|
36
+ file = root + uri[1..-1]
37
+ if file.exist?
38
+ puts "D #{uri}" unless @opts[:quiet]
39
+ file.delete
40
+ end
25
41
  end
26
- save_list(urilist)
27
- elapsed = Time.now - start
28
-
29
- puts "-- #{rendered} files. #{"%.3f" % elapsed} sec. #{"%.3f" % (elapsed/rendered)} sec/file." unless @opts[:quiet]
30
42
  end
43
+ private :expire_old_files
31
44
 
32
45
  def render_smc_files
33
- urilist = []
34
46
  @loader.each_smc_obj do |obj|
35
- urilist << obj["uri"].smc
36
- mark = obj["path"].exist? ? "U " : "A "
37
47
  render_smc_obj(obj)
38
- puts mark + obj["uri"] unless @opts[:quiet]
39
48
  end
40
- return urilist
41
49
  end
42
50
  private :render_smc_files
43
51
 
44
52
  def render_smc_obj(obj)
45
- result = @renderer.render(obj["template"], obj)
46
- result = after_rendering_filters(obj, result)
47
- output_result(obj, result)
53
+ uris = @renderer.render(obj["template"] + ".uri", obj)
54
+ if uris
55
+ render_multi(obj, uris.split(/\r\n|\r|\n/))
56
+ else
57
+ render_single(obj)
58
+ end
48
59
  end
49
60
  private :render_smc_obj
50
61
 
51
- def delete_expired_files(urilist)
52
- old_urilist = load_list
53
- root = @loader.root
54
- target = SmallCage::DocumentPath.new(root, @loader.target)
55
- target_uri = target.uri
56
- target_uri += "/" if target.path.directory? and target_uri[-1] != ?/
57
- if @loader.target.file?
58
- old_urilist << target_uri unless old_urilist.include?(target_uri)
59
- return old_urilist
60
- end
61
-
62
- target_uris = []
63
- not_target_uris = []
64
- old_urilist.each do |uri|
65
- if uri.index(target_uri) == 0
66
- target_uris << uri
67
- else
68
- not_target_uris << uri
69
- end
70
- end
62
+ def render_single(obj, mtime = nil)
63
+ mark = obj["path"].exist? ? "U " : "A "
64
+ mtime ||= obj["path"].smc.stat.mtime.to_i
65
+ result = @renderer.render(obj["template"], obj)
66
+ result = after_rendering_filters(obj, result)
67
+ output_result(obj, result)
68
+ puts mark + obj["uri"] unless @opts[:quiet]
71
69
 
72
- deletelist = target_uris - urilist
70
+ # create new uri String to remove smc instance-specific method.
71
+ @list.update(obj["uri"].smc, mtime, String.new(obj["uri"]))
72
+ end
73
+ private :render_single
73
74
 
74
- deletelist.each do |uri|
75
- delfile = SmallCage::DocumentPath.new(root, root + ("." + uri)).outfile
76
- next unless delfile.path.file?
77
-
78
- File.delete(delfile.path)
79
- puts "D #{delfile.uri}" unless @opts[:quiet]
75
+ def render_multi(obj, uris)
76
+ obj['uris'] ||= uris
77
+ uris = uris.map {|uri| uri.strip }
78
+ smcuri = obj['uri'].smc
79
+ smcpath = obj['path'].smc
80
+ base = obj['path'].parent
81
+ mtime = smcpath.stat.mtime.to_i
82
+ uris.each_with_index do |uri, index|
83
+ next if uri.empty?
84
+ docpath = DocumentPath.create_with_uri(@loader.root, uri, base)
85
+ next if docpath.path.directory?
86
+ FileUtils.mkpath(docpath.path.parent)
87
+ obj['uri'] = DocumentPath.add_smc_method(docpath.uri, smcuri)
88
+ obj['path'] = DocumentPath.add_smc_method(docpath.path, smcpath)
89
+ obj['cursor'] = index
90
+ render_single(obj, mtime)
80
91
  end
81
-
82
- return (not_target_uris + urilist).sort
83
92
  end
84
- private :delete_expired_files
93
+ private :render_multi
85
94
 
86
95
  def after_rendering_filters(obj, result)
87
96
  filters = @loader.filters("after_rendering_filters")
@@ -92,36 +101,12 @@ module SmallCage::Commands
92
101
  end
93
102
  private :after_rendering_filters
94
103
 
95
- def save_list(urilist)
96
- f = list_file
97
- FileUtils.makedirs(f.parent)
98
- open(f, "w") do |io|
99
- io << "version: " + SmallCage::VERSION::STRING + "\n"
100
- urilist.each do |u|
101
- io << u + "\n"
102
- end
103
- end
104
- end
105
- private :save_list
106
-
107
- def load_list
108
- txt = File.read(list_file)
109
- result = txt.split(/\n/)
110
- result.shift
111
- return result
112
- end
113
- private :load_list
114
-
115
- def list_file
116
- @loader.root + "./_smc/tmp/list.txt"
117
- end
118
- private :list_file
119
-
120
104
  def output_result(obj, str)
121
105
  open(obj["path"], "w") do |io|
122
106
  io << str
123
107
  end
124
108
  end
125
109
  private :output_result
110
+
126
111
  end
127
112
  end
@@ -4,7 +4,7 @@ module SmallCage
4
4
  attr_reader :root, :uri, :path
5
5
 
6
6
  def initialize(root, path)
7
- @root = Pathname.new(root).realpath;
7
+ @root = Pathname.new(root).realpath
8
8
 
9
9
  @path = Pathname.new(path)
10
10
  if @path.exist?
@@ -42,5 +42,29 @@ module SmallCage
42
42
  return self.new(root,path).uri
43
43
  end
44
44
 
45
+ def self.create_with_uri(root, uri, base = nil)
46
+ base ||= root
47
+ if uri[0] == ?/
48
+ path = root + uri[1..-1] # absolute URI
49
+ else
50
+ path = base + uri # relative URI
51
+ end
52
+ return self.new(root, path)
53
+ end
54
+
55
+ def self.add_smc_method(obj, value)
56
+ obj.instance_eval do
57
+ @__smallcage ||= {}
58
+ @__smallcage[:smc] = value
59
+ end
60
+
61
+ def obj.smc
62
+ return @__smallcage.nil? ? nil : @__smallcage[:smc]
63
+ end
64
+
65
+ return obj
66
+ end
67
+
68
+
45
69
  end
46
- end
70
+ end
@@ -36,7 +36,7 @@ module SmallCage
36
36
  def load(path)
37
37
  raise "Not found: #{path}" unless path.exist?
38
38
 
39
- docpath = SmallCage::DocumentPath.new(@root, path)
39
+ docpath = DocumentPath.new(@root, path)
40
40
 
41
41
  if path.file?
42
42
  return load_smc_file(docpath)
@@ -68,7 +68,7 @@ module SmallCage
68
68
  local_prop_file = docpath.path + LOCAL_PROP_FILE
69
69
  if dir_prop_file.file?
70
70
  path_smc = dir_prop_file
71
- uri_smc = SmallCage::DocumentPath.to_uri(@root, dir_prop_file)
71
+ uri_smc = DocumentPath.to_uri(@root, dir_prop_file)
72
72
  end
73
73
 
74
74
  result = create_base_smc_object(docpath.path, path_smc,
@@ -86,8 +86,8 @@ module SmallCage
86
86
  result["arrays"] = []
87
87
  result["strings"] = []
88
88
  result["body"] = nil
89
- result["path"] = add_smc_method(path_out, path_smc)
90
- result["uri"] = add_smc_method(uri_out, uri_smc )
89
+ result["path"] = DocumentPath.add_smc_method(path_out, path_smc)
90
+ result["uri"] = DocumentPath.add_smc_method(uri_out, uri_smc )
91
91
  return result
92
92
  end
93
93
  private :create_base_smc_object
@@ -170,13 +170,13 @@ module SmallCage
170
170
  next if f.directory?
171
171
  next if f.to_s =~ %r{/_smc/}
172
172
  next if f.to_s =~ %r{\.smc$}
173
- yield SmallCage::DocumentPath.new(@root, p + f)
173
+ yield DocumentPath.new(@root, p + f)
174
174
  end
175
175
  end
176
176
  else
177
177
  return if @target.to_s =~ %r{/_smc/}
178
178
  return if @target.to_s =~ %r{\.smc$}
179
- yield SmallCage::DocumentPath.new(@root, @target)
179
+ yield DocumentPath.new(@root, @target)
180
180
  end
181
181
  end
182
182
 
@@ -193,7 +193,7 @@ module SmallCage
193
193
 
194
194
 
195
195
  def load_erb_base
196
- result = Class.new(SmallCage::ErbBase)
196
+ result = Class.new(ErbBase)
197
197
  class << result
198
198
  def include_helpers(anon_module, mod_names)
199
199
  smc_module = anon_module.const_get("SmallCage")
@@ -272,19 +272,5 @@ module SmallCage
272
272
  end
273
273
  private :load_filters_config
274
274
 
275
- def add_smc_method(obj, value)
276
- obj.instance_eval do
277
- @__smallcage ||= {}
278
- @__smallcage[:smc] = value
279
- end
280
-
281
- def obj.smc
282
- return @__smallcage.nil? ? nil : @__smallcage[:smc]
283
- end
284
-
285
- return obj
286
- end
287
- private :add_smc_method
288
-
289
275
  end
290
276
  end
@@ -0,0 +1,143 @@
1
+ module SmallCage
2
+
3
+ # Updated files list model.
4
+ # Do not access File system exept list.yml.
5
+ class UpdateList
6
+ attr_reader :update_count
7
+
8
+ def self.create(root_path, target_path)
9
+ docpath = DocumentPath.new(root_path, target_path)
10
+ uri = docpath.uri
11
+ uri += "/" if docpath.path.directory? && uri[-1] != ?/
12
+ return self.new(root_path + "_smc/tmp/list.yml", uri)
13
+ end
14
+
15
+ # target_uri must be ends with / when target is directory.
16
+ def initialize(list_file, target_uri)
17
+ @list_file = list_file
18
+ @target_uri = target_uri
19
+ @expired_src = {}
20
+ @expired_dst = {}
21
+ @update_count = 0
22
+ load
23
+ end
24
+
25
+ def load
26
+ if @list_file.exist?
27
+ @data = YAML.load_file(@list_file)
28
+ else
29
+ @data = {}
30
+ end
31
+ @data["version"] ||= VERSION::STRING
32
+ @data["list"] ||= []
33
+
34
+ @map = {}
35
+ @data["list"].each do |item|
36
+ src = item["src"]
37
+ @map[src] = item
38
+ if target?(src)
39
+ @expired_src[src] = true
40
+ item["dst"].each do |d|
41
+ @expired_dst[d] = [true, src]
42
+ end
43
+ end
44
+ end
45
+ end
46
+ private :load
47
+
48
+ def target?(uri)
49
+ return uri[0...@target_uri.length] == @target_uri
50
+ end
51
+ private :target?
52
+
53
+ def save
54
+ FileUtils.mkpath(@list_file.parent)
55
+ @data["version"] = VERSION::STRING
56
+ open(@list_file, "w") do |io|
57
+ io << to_yaml
58
+ end
59
+ end
60
+
61
+ def to_yaml
62
+ return @data.to_yaml
63
+ end
64
+
65
+ def mtime(srcuri)
66
+ item = @map[srcuri]
67
+ return -1 unless item
68
+ return item["mtime"].to_i
69
+ end
70
+
71
+ def update(srcuri, mtime, dsturi)
72
+ update_list(srcuri, mtime, dsturi)
73
+ stop_expiration(srcuri, dsturi)
74
+ @update_count += 1
75
+ end
76
+
77
+ def update_list(srcuri, mtime, dsturi)
78
+ unless update_list_item(srcuri, mtime, dsturi)
79
+ add_list_item(srcuri, mtime, dsturi)
80
+ end
81
+ end
82
+ private :update_list
83
+
84
+ def update_list_item(srcuri, mtime, dsturi)
85
+ return false unless @map[srcuri]
86
+ item = @map[srcuri]
87
+ item["mtime"] = mtime.to_i
88
+ item["dst"] << dsturi unless item["dst"].include?(dsturi)
89
+ return true
90
+ end
91
+ private :update_list_item
92
+
93
+ def add_list_item(srcuri, mtime, dsturi)
94
+ item = {"src" => srcuri, "dst" => [dsturi], "mtime" => mtime.to_i}
95
+ @map[srcuri] = item
96
+ @data["list"] << item
97
+ end
98
+ private :add_list_item
99
+
100
+ def stop_expiration(srcuri, dsturi)
101
+ @expired_src.delete(srcuri)
102
+ @expired_dst[dsturi] = [false, srcuri]
103
+ end
104
+ private :stop_expiration
105
+
106
+ def expire
107
+ expire_src
108
+ result = expire_dst
109
+ return result
110
+ end
111
+
112
+ def expire_src
113
+ @expired_src.each do |srcuri,v|
114
+ mark_expired_src(srcuri)
115
+ end
116
+ @data["list"] = @data["list"].select {|item| ! item["expired"] }
117
+ end
118
+ private :expire_src
119
+
120
+ def mark_expired_src(srcuri)
121
+ @map[srcuri]["expired"] = true
122
+ @map[srcuri]["dst"].each do |dsturi|
123
+ next if @expired_dst[dsturi] && ! @expired_dst[dsturi][0]
124
+ @expired_dst[dsturi] = [true, srcuri]
125
+ end
126
+ end
127
+ private :mark_expired_src
128
+
129
+ def expire_dst
130
+ result = []
131
+ @expired_dst.each do |dsturi, stat|
132
+ next unless stat[0]
133
+ srcuri = stat[1]
134
+ item = @map[srcuri]
135
+ item["dst"].delete(dsturi)
136
+ result << dsturi
137
+ end
138
+ return result
139
+ end
140
+ private :expire_dst
141
+
142
+ end
143
+ end
@@ -2,7 +2,7 @@ module SmallCage #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 7
5
+ TINY = 8
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/smallcage.gemspec ADDED
@@ -0,0 +1,172 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{smallcage}
8
+ s.version = "0.1.8"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["SAITO Toshihiro", "gommmmmm", "KOSEKI Kengo"]
12
+ s.date = %q{2009-11-05}
13
+ s.default_executable = %q{smc}
14
+ s.description = %q{Lightweight CMS package.}
15
+ s.email = %q{smallcage@googlegroups.com}
16
+ s.executables = ["smc"]
17
+ s.extra_rdoc_files = [
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "History.txt",
23
+ "License.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/smc",
28
+ "lib/smallcage.rb",
29
+ "lib/smallcage/application.rb",
30
+ "lib/smallcage/commands/auto.rb",
31
+ "lib/smallcage/commands/base.rb",
32
+ "lib/smallcage/commands/clean.rb",
33
+ "lib/smallcage/commands/export.rb",
34
+ "lib/smallcage/commands/import.rb",
35
+ "lib/smallcage/commands/manifest.rb",
36
+ "lib/smallcage/commands/server.rb",
37
+ "lib/smallcage/commands/update.rb",
38
+ "lib/smallcage/document_path.rb",
39
+ "lib/smallcage/erb_base.rb",
40
+ "lib/smallcage/http_server.rb",
41
+ "lib/smallcage/loader.rb",
42
+ "lib/smallcage/misc.rb",
43
+ "lib/smallcage/renderer.rb",
44
+ "lib/smallcage/resources/Manifest.erb",
45
+ "lib/smallcage/resources/auto.html",
46
+ "lib/smallcage/runner.rb",
47
+ "lib/smallcage/update_list.rb",
48
+ "lib/smallcage/version.rb",
49
+ "project/base/_smc/helpers/base_helper.rb",
50
+ "project/base/_smc/helpers/site_helper.rb",
51
+ "project/base/_smc/templates/default.rhtml",
52
+ "project/base/_smc/templates/footer.rhtml",
53
+ "project/base/_smc/templates/header.rhtml",
54
+ "project/bluecloth/_smc/helpers/blue_cloth_helper.rb",
55
+ "project/bluecloth/_smc/templates/markdown.rhtml",
56
+ "project/cache/_smc/filters/cache_filter.rb",
57
+ "project/cache/_smc/filters/filters.yml",
58
+ "project/cache/_smc/rakelib/cache.rake",
59
+ "project/lang/_smc/helpers/lang_helper.rb",
60
+ "project/lang/_smc/templates/other_lang.rhtml",
61
+ "project/news/_smc/helpers/news_helper.rb",
62
+ "project/nkf/_smc/filters/filters.yml",
63
+ "project/nkf/_smc/filters/nkf_filter.rb",
64
+ "project/nkf/_smc/helpers/nkf_helper.rb",
65
+ "project/rake/_smc/Rakefile",
66
+ "project/rake/_smc/rakelib/csv.rake",
67
+ "project/rake/_smc/rakelib/svn.rake",
68
+ "project/redcloth/_smc/helpers/red_cloth_helper.rb",
69
+ "project/redcloth/_smc/templates/textile.rhtml",
70
+ "project/relpath/_smc/filters/filters.yml",
71
+ "project/relpath/_smc/filters/relpath_filter.rb",
72
+ "project/standard/_dir.smc",
73
+ "project/standard/_smc/helpers/menu_helper.rb",
74
+ "project/standard/_smc/templates/default.rhtml",
75
+ "project/standard/_smc/templates/footer.rhtml",
76
+ "project/standard/_smc/templates/header.rhtml",
77
+ "project/standard/_smc/templates/menu.rhtml",
78
+ "project/standard/_smc/templates/redirect.rhtml",
79
+ "project/standard/_smc/templates/sidebar.rhtml",
80
+ "project/standard/_smc/templates/topic_path.rhtml",
81
+ "project/standard/common/css/default.css",
82
+ "project/standard/common/css/print.css",
83
+ "project/standard/index.html.smc",
84
+ "project/standard/sample/_dir.smc",
85
+ "project/standard/sample/index.html.smc",
86
+ "project/standard/sample/redirect.html.smc",
87
+ "project/standard/sample/sub/_dir.smc",
88
+ "project/standard/sample/sub/contents.html.smc",
89
+ "project/standard/sample/sub/index.html.smc",
90
+ "project/tutorial/_smc/helpers/sample_helper.rb",
91
+ "project/tutorial/_smc/templates/default.rhtml",
92
+ "project/tutorial/_smc/templates/include1.rhtml",
93
+ "project/tutorial/_smc/templates/include2.rhtml",
94
+ "project/tutorial/sample.txt.smc",
95
+ "project/tutorial/sample2.txt.smc",
96
+ "project/tutorial2/_smc/helpers/priority_sample_helper.rb",
97
+ "project/tutorial2/_smc/templates/priorities.rhtml",
98
+ "project/tutorial2/_smc/templates/priority1.rhtml",
99
+ "project/tutorial2/_smc/templates/priority2.rhtml",
100
+ "project/tutorial2/_smc/templates/priority3.rhtml",
101
+ "project/tutorial2/_smc/templates/smc_variables.rhtml",
102
+ "project/tutorial2/tutorial2/_dir.smc",
103
+ "project/tutorial2/tutorial2/priorities.txt.smc",
104
+ "project/tutorial2/tutorial2/vars.txt.smc",
105
+ "smallcage.gemspec",
106
+ "spec/data/htdocs1/_dir.smc",
107
+ "spec/data/htdocs1/_smc/.gitignore",
108
+ "spec/data/htdocs1/_smc/filters/filters.yml",
109
+ "spec/data/htdocs1/a/b/c/index.html.smc",
110
+ "spec/data/htdocs2/_smc/filters/filters.yml",
111
+ "spec/data/htdocs2/_smc/templates/dummy.rhtml",
112
+ "spec/data/htdocs2/a/b/c/test.html",
113
+ "spec/data/htdocs2/a/b/test.html",
114
+ "spec/data/htdocs2/a/test.html.smc",
115
+ "spec/data/htdocs3/_dir.smc",
116
+ "spec/data/htdocs3/_local.smc",
117
+ "spec/data/htdocs3/_smc/.gitignore",
118
+ "spec/data/htdocs3/a/b/_dir.smc",
119
+ "spec/data/htdocs3/a/b/_local.smc",
120
+ "spec/data/htdocs3/a/b/c/_local.smc",
121
+ "spec/data/htdocs3/a/b/c/index.html.smc",
122
+ "spec/data/htdocs3/a/index.html.smc",
123
+ "spec/data/htdocs3/ab/index.html.smc",
124
+ "spec/data/htdocs3/abc/index.html.smc",
125
+ "spec/data/multifiles/_dir.smc",
126
+ "spec/data/multifiles/_smc/templates/default.rhtml",
127
+ "spec/data/multifiles/_smc/templates/items.rhtml",
128
+ "spec/data/multifiles/_smc/templates/items.uri.rhtml",
129
+ "spec/data/multifiles/items/index.html.smc",
130
+ "spec/data/updatelists/list1.yml",
131
+ "spec/document_path_spec.rb",
132
+ "spec/export_spec.rb",
133
+ "spec/import_spec.rb",
134
+ "spec/loader_spec.rb",
135
+ "spec/manifest_spec.rb",
136
+ "spec/misc_spec.rb",
137
+ "spec/smallcage_spec.rb",
138
+ "spec/spec.opts",
139
+ "spec/spec_helper.rb",
140
+ "spec/update_list_spec.rb",
141
+ "spec/update_spec.rb"
142
+ ]
143
+ s.homepage = %q{http://www.smallcage.org}
144
+ s.rdoc_options = ["--charset=UTF-8"]
145
+ s.require_paths = ["lib"]
146
+ s.rubyforge_project = %q{smallcage}
147
+ s.rubygems_version = %q{1.3.5}
148
+ s.summary = %q{Lightweight CMS package.}
149
+ s.test_files = [
150
+ "spec/document_path_spec.rb",
151
+ "spec/export_spec.rb",
152
+ "spec/import_spec.rb",
153
+ "spec/loader_spec.rb",
154
+ "spec/manifest_spec.rb",
155
+ "spec/misc_spec.rb",
156
+ "spec/smallcage_spec.rb",
157
+ "spec/spec_helper.rb",
158
+ "spec/update_list_spec.rb",
159
+ "spec/update_spec.rb"
160
+ ]
161
+
162
+ if s.respond_to? :specification_version then
163
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
164
+ s.specification_version = 3
165
+
166
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
167
+ else
168
+ end
169
+ else
170
+ end
171
+ end
172
+