raykit 0.0.467 → 0.0.468

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,345 +1,341 @@
1
- # frozen_string_literal: true
2
-
3
- require "rake/clean"
4
- require "digest"
5
- RAKE_DIRECTORY = Rake.application.original_dir
6
-
7
- module Raykit
8
- class Project
9
- attr_accessor :name, :description, :timer, :verbose, :target
10
-
11
- @directory
12
- @version
13
- @remote
14
- @repository
15
- @git_directory
16
- @timeout
17
- @values
18
- @commands
19
-
20
- # @log
21
- # @commit_message_filename
22
-
23
- # TODO: refactor to remove the defaults
24
- def initialize(name = "", description = "", version = "")
25
- @description = description if description.length.positive?
26
- @version = version if version.length.positive?
27
- @timeout = 1000 * 60 * 15
28
- @verbose = false
29
- @timer = Raykit::Timer.new
30
- @remote = ""
31
- @commit_message_filename = "commit_message.tmp"
32
- if Dir.exist?(RAKE_DIRECTORY)
33
- @directory = RAKE_DIRECTORY
34
- if Dir.exist?("#{RAKE_DIRECTORY}/.git") && Dir.exist?(@directory)
35
- @git_directory = Raykit::Git::Directory.new(@directory)
36
- @remote = @git_directory.remote
37
- end
38
- else
39
- @directory = ""
40
- end
41
-
42
- # @log=Log.new("#{RAKE_DIRECTORY}/tmp/raykit.log")
43
- if (name.length.positive?)
44
- @name = name
45
- else
46
- if defined?(NAME)
47
- @name = NAME
48
- else
49
- slns = Dir.glob("*.sln")
50
- if slns.length == 1
51
- @name = slns[0].gsub(".sln", "")
52
- else
53
- gemspecs = Dir.glob("*.gemspec")
54
- if gemspecs.length == 1
55
- @name = gemspecs[0].gsub(".gemspec", "")
56
- else
57
- remote_parts = @remote.split("/")
58
- @name = remote_parts[-1].gsub(".git", "") if remote_parts.length.positive?
59
- end
60
- end
61
- end
62
- end
63
- @repository = Raykit::Git::Repository.new(@remote)
64
- @values = Hash::new()
65
- @commands = Array::new()
66
- end
67
-
68
- def get_dev_dir(subdir)
69
- Raykit::Environment.get_dev_dir(subdir)
70
- end
71
-
72
- attr_reader :log, :directory, :remote
73
-
74
- # def target
75
- # @target
76
- # end
77
- def target_md5
78
- return Digest::MD5.file(target).to_s.strip if !target.nil? && File.exist?(target)
79
-
80
- ""
81
- end
82
-
83
- def branch
84
- return "main" if @git_directory.nil?
85
- @git_directory.branch
86
- end
87
-
88
- def values
89
- @values
90
- end
91
-
92
- # latest local commit
93
- def latest_commit
94
- return "" if detached?
95
- Dir.chdir(@directory) do
96
- text = `git log -n 1`
97
- scan = text.scan(/commit (\w+)\s/)
98
- return scan[0][0].to_s
99
- end
100
- end
101
-
102
- def outstanding_commit?
103
- Dir.chdir(@directory) do
104
- return true unless `git status`.include?("nothing to commit")
105
- end
106
- false
107
- end
108
-
109
- def outstanding_tag?
110
- # puts `git log -n 1`
111
- # !latest_tag_commit.eql?(latest_commit)
112
- # commit 2e4cb6d6c0721e16cd06afee85b7cdc27354921b (HEAD -> master, tag: 0.0.180, origin/master, origin/HEAD)
113
- outstanding_commit? || !`git log -n 1`.include?("tag:")
114
- end
115
-
116
- def read_only?
117
- return true if !File.exist?(".git") || detached?
118
- return false
119
- end
120
-
121
- def detached?
122
- return true if @git_directory.nil?
123
- @git_directory.detached?
124
- end
125
-
126
- def has_diff?(filename)
127
- Dir.chdir(@directory) do
128
- text = `git diff #{filename}`.strip
129
- return true if text.length.positive?
130
- end
131
- end
132
-
133
- def version
134
- if @version.nil?
135
- # Dir.chdir(@directory) do
136
- # if(Dir.glob("*.gemspec").length > 0)
137
- # @version=`bump current`.gsub('Current version:','').strip
138
- # else
139
- # @version=Raykit::VersionHelper.detect(@name,@verbose)
140
- # end
141
- @version = Raykit::Version.detect(@name, @verbose)
142
- # end
143
- end
144
- @version
145
- end
146
-
147
- def set_version(version)
148
- @version = version
149
- end
150
-
151
- # def update_version
152
- # @version=Raykit::Version.detect(@name,@verbose)
153
- # end
154
-
155
- def latest_tag
156
- `git describe --abbrev=0`.strip
157
- end
158
-
159
- def latest_tag_commit
160
- `git show-ref -s #{latest_tag}`.strip
161
- end
162
-
163
- def latest_tag_md5
164
- text = `git tag #{latest_tag} -n3`
165
- scan = text.scan(/md5=(\w{32})/)
166
- return scan[0][0].to_s.strip if scan.length.positive? && scan[0].length.positive?
167
-
168
- ""
169
- end
170
-
171
- def last_modified_filename
172
- Dir.chdir(@directory) do
173
- Dir.glob("**/*.*").select { |f| File.file?(f) }.max_by { |f| File.mtime(f) }
174
- end
175
- end
176
-
177
- def size
178
- Dir.chdir(@directory) do
179
- text = `git count-objects -v -H`
180
- if matches = text.match(/size: ([. \w]+)$/)
181
- matches[1]
182
- else
183
- text
184
- end
185
- end
186
- end
187
-
188
- def size_pack
189
- Dir.chdir(@directory) do
190
- text = `git count-objects -v -H`
191
- if matches = text.match(/size-pack: ([. \w]+)$/)
192
- matches[1]
193
- else
194
- text
195
- end
196
- end
197
- end
198
-
199
- def elapsed
200
- elapsed = @timer.elapsed
201
- if elapsed < 1.0
202
- "#{format("%.1f", @timer.elapsed)}s"
203
- else
204
- "#{format("%.0f", @timer.elapsed)}s"
205
- end
206
- end
207
-
208
- def info
209
- ljust = 35
210
- puts ""
211
- puts "PROJECT.name".ljust(ljust) + Rainbow(PROJECT.name).yellow.bright
212
- puts "PROJECT.version".ljust(ljust) + Rainbow(PROJECT.version).yellow.bright
213
- puts "PROJECT.remote".ljust(ljust) + Rainbow(PROJECT.remote).yellow.bright
214
- puts "PROJECT.branch".ljust(ljust) + Rainbow(PROJECT.branch).yellow.bright
215
- puts "PROJECT.detached?".ljust(ljust) + Rainbow(PROJECT.detached?).yellow.bright
216
- # puts "PROJECT.target".ljust(ljust) + Rainbow(PROJECT.target).yellow.bright
217
- # puts "PROJECT.target_md5".ljust(ljust) + Rainbow(PROJECT.target_md5).yellow.bright
218
- puts "PROJECT.latest_tag".ljust(ljust) + Rainbow(PROJECT.latest_tag).yellow.bright
219
- puts "PROJECT.latest_tag_commit".ljust(ljust) + Rainbow(PROJECT.latest_tag_commit).yellow.bright
220
- puts "PROJECT.latest_tag_md5".ljust(ljust) + Rainbow(PROJECT.latest_tag_md5).yellow.bright
221
- puts "PROJECT.latest_commit".ljust(ljust) + Rainbow(PROJECT.latest_commit).yellow.bright
222
- puts "PROJECT.last_modified_filename".ljust(ljust) + Rainbow(PROJECT.last_modified_filename).yellow.bright
223
- # puts "PROJECT.elapsed".ljust(ljust) + Rainbow(PROJECT.elapsed).yellow.bright
224
- puts "PROJECT.size".ljust(ljust) + Rainbow(PROJECT.size).yellow.bright
225
- puts "PROJECT.size_pack".ljust(ljust) + Rainbow(PROJECT.size_pack).yellow.bright
226
- puts "PROJECT.outstanding_commit?".ljust(ljust) + Rainbow(PROJECT.outstanding_commit?).yellow.bright
227
- puts "PROJECT.outstanding_tag?".ljust(ljust) + Rainbow(PROJECT.outstanding_tag?).yellow.bright
228
- puts ""
229
- self
230
- end
231
-
232
- def to_markdown()
233
- md = "# #{@name}"
234
- md += get_markdown_nvp("Name", "Value", " ")
235
- md += get_markdown_nvp("-", "-", "-")
236
- md += get_markdown_nvp("Version", "#{@version}", " ")
237
- md += get_markdown_nvp("Machine", "#{Raykit::Environment::machine}", " ")
238
- md += get_markdown_nvp("User", "#{Raykit::Environment::user}", " ")
239
- @values.each do |key, value|
240
- md += get_markdown_nvp(key, value, " ")
241
- end
242
- @commands.each do |cmd|
243
- md = md + "\n" + cmd.to_markdown
244
- end
245
- md
246
- end
247
-
248
- def get_markdown_nvp(key, value, pad_char)
249
- "\n| " + key.to_s.ljust(36, pad_char) + "| " + value.to_s.ljust(36, pad_char)
250
- end
251
-
252
- def summary
253
- info if @verbose
254
- puts "[#{elapsed}] #{Rainbow(@name).yellow.bright} #{Rainbow(version).yellow.bright}"
255
- end
256
-
257
- def commit_message_filename
258
- warn "[DEPRECATION] 'commit_message_filename' is deprecated."
259
- @commit_message_filename
260
- end
261
-
262
- def commit(commit_message)
263
- warn "[DEPRECATION] 'commit_message_filename' is deprecated. Use a run command for better transparency."
264
- Dir.chdir(@directory) do
265
- if File.exist?(".gitignore")
266
- status = `git status`
267
- if status.include?("Changes not staged for commit:")
268
- run("git add --all")
269
- if GIT_DIRECTORY.outstanding_commit?
270
- if File.exist?(@commit_message_filename)
271
- run("git commit --file #{@commit_message_filename}")
272
- File.delete(@commit_message_filename)
273
- else
274
- run("git commit -m'#{commit_message}'")
275
- end
276
- end
277
- end
278
- else
279
- puts "warning: .gitignore not found."
280
- end
281
- end
282
- self
283
- end
284
-
285
- def push
286
- Dir.chdir(@directory) do
287
- status = `git status`
288
- if status.include?('use "git push"')
289
- run("git push")
290
- end
291
- end
292
- self
293
- end
294
-
295
- def pull
296
- Dir.chdir(@directory) do
297
- run("git pull")
298
- end
299
- self
300
- end
301
-
302
- def tag
303
- warn "[DEPRECATION] 'tag' is deprecated. Use run command(s) for better transparency."
304
- Dir.chdir(@directory) do
305
- specific_tag = `git tag -l #{@version}`.strip
306
- puts Rainbow("git tag - #{@version}").green if @verbose
307
- puts `git tag -l #{@version}` if @verbose
308
- if specific_tag.length.zero?
309
- puts "tag #{@version} not detected." if @verbose
310
- tag = `git describe --abbrev=0 --tags`.strip
311
- if @version != tag
312
- puts "latest tag #{@tag}" if @verbose
313
- run("git tag #{@version} -m'#{@version}'")
314
- run("git push origin #{@version}")
315
- # push
316
- end
317
- elsif @verbose
318
- puts "already has tag #{specific_tag}"
319
- end
320
- end
321
- self
322
- end
323
-
324
- def run(command, quit_on_failure = true)
325
- if command.is_a?(Array)
326
- command.each { |subcommand| run(subcommand, quit_on_failure) }
327
- else
328
- cmd = Command.new(command).set_timeout(@timeout).run
329
- cmd.summary
330
- elapsed_str = Timer.get_elapsed_str(cmd.elapsed, 0)
331
- if !cmd.exitstatus.nil? && cmd.exitstatus.zero?
332
- else
333
- # display error details
334
- cmd.details
335
- if quit_on_failure
336
- abort
337
- end
338
- end
339
- cmd.save
340
- @commands << cmd
341
- cmd
342
- end
343
- end
344
- end
345
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "rake/clean"
4
+ require "digest"
5
+ RAKE_DIRECTORY = Rake.application.original_dir
6
+
7
+ module Raykit
8
+ class Project
9
+ attr_accessor :name, :description, :version, :timer, :verbose, :target
10
+
11
+ @directory
12
+ #@version
13
+ @remote
14
+ @repository
15
+ @git_directory
16
+ @timeout
17
+ @values
18
+ @commands
19
+
20
+ # @log
21
+ # @commit_message_filename
22
+
23
+ # TODO: refactor to remove the defaults
24
+ def initialize(name = "", description = "", version = "")
25
+ @description = description if description.length.positive?
26
+ @version = version if version.length.positive?
27
+ @timeout = 1000 * 60 * 15
28
+ @verbose = false
29
+ @timer = Raykit::Timer.new
30
+ @remote = ""
31
+ @commit_message_filename = "commit_message.tmp"
32
+ if Dir.exist?(RAKE_DIRECTORY)
33
+ @directory = RAKE_DIRECTORY
34
+ if Dir.exist?("#{RAKE_DIRECTORY}/.git") && Dir.exist?(@directory)
35
+ @git_directory = Raykit::Git::Directory.new(@directory)
36
+ @remote = @git_directory.remote
37
+ end
38
+ else
39
+ @directory = ""
40
+ end
41
+
42
+ # @log=Log.new("#{RAKE_DIRECTORY}/tmp/raykit.log")
43
+ if (name.length.positive?)
44
+ @name = name
45
+ else
46
+ if defined?(NAME)
47
+ @name = NAME
48
+ else
49
+ slns = Dir.glob("*.sln")
50
+ if slns.length == 1
51
+ @name = slns[0].gsub(".sln", "")
52
+ else
53
+ gemspecs = Dir.glob("*.gemspec")
54
+ if gemspecs.length == 1
55
+ @name = gemspecs[0].gsub(".gemspec", "")
56
+ else
57
+ remote_parts = @remote.split("/")
58
+ @name = remote_parts[-1].gsub(".git", "") if remote_parts.length.positive?
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ @version = Raykit::Version.detect(@name, true) if version.length.zero?
65
+
66
+ @repository = Raykit::Git::Repository.new(@remote)
67
+ @values = Hash::new()
68
+ @commands = Array::new()
69
+ end
70
+
71
+ def get_dev_dir(subdir)
72
+ Raykit::Environment.get_dev_dir(subdir)
73
+ end
74
+
75
+ attr_reader :log, :directory, :remote
76
+
77
+ # def target
78
+ # @target
79
+ # end
80
+ def target_md5
81
+ return Digest::MD5.file(target).to_s.strip if !target.nil? && File.exist?(target)
82
+
83
+ ""
84
+ end
85
+
86
+ def branch
87
+ return "main" if @git_directory.nil?
88
+ @git_directory.branch
89
+ end
90
+
91
+ def values
92
+ @values
93
+ end
94
+
95
+ # latest local commit
96
+ def latest_commit
97
+ return "" if detached?
98
+ Dir.chdir(@directory) do
99
+ text = `git log -n 1`
100
+ scan = text.scan(/commit (\w+)\s/)
101
+ return scan[0][0].to_s
102
+ end
103
+ end
104
+
105
+ def outstanding_commit?
106
+ Dir.chdir(@directory) do
107
+ return true unless `git status`.include?("nothing to commit")
108
+ end
109
+ false
110
+ end
111
+
112
+ def outstanding_tag?
113
+ # puts `git log -n 1`
114
+ # !latest_tag_commit.eql?(latest_commit)
115
+ # commit 2e4cb6d6c0721e16cd06afee85b7cdc27354921b (HEAD -> master, tag: 0.0.180, origin/master, origin/HEAD)
116
+ outstanding_commit? || !`git log -n 1`.include?("tag:")
117
+ end
118
+
119
+ def read_only?
120
+ return true if !File.exist?(".git") || detached?
121
+ return false
122
+ end
123
+
124
+ def detached?
125
+ return true if @git_directory.nil?
126
+ @git_directory.detached?
127
+ end
128
+
129
+ def has_diff?(filename)
130
+ Dir.chdir(@directory) do
131
+ text = `git diff #{filename}`.strip
132
+ return true if text.length.positive?
133
+ end
134
+ end
135
+
136
+ #def version
137
+ # if @version.nil?
138
+ # @version = Raykit::Version.detect(@name, @verbose)
139
+ # end
140
+ # @version
141
+ #end
142
+
143
+ def set_version(version)
144
+ @version = version
145
+ end
146
+
147
+ # def update_version
148
+ # @version=Raykit::Version.detect(@name,@verbose)
149
+ # end
150
+
151
+ def latest_tag
152
+ `git describe --abbrev=0`.strip
153
+ end
154
+
155
+ def latest_tag_commit
156
+ `git show-ref -s #{latest_tag}`.strip
157
+ end
158
+
159
+ def latest_tag_md5
160
+ text = `git tag #{latest_tag} -n3`
161
+ scan = text.scan(/md5=(\w{32})/)
162
+ return scan[0][0].to_s.strip if scan.length.positive? && scan[0].length.positive?
163
+
164
+ ""
165
+ end
166
+
167
+ def last_modified_filename
168
+ Dir.chdir(@directory) do
169
+ Dir.glob("**/*.*").select { |f| File.file?(f) }.max_by { |f| File.mtime(f) }
170
+ end
171
+ end
172
+
173
+ def size
174
+ Dir.chdir(@directory) do
175
+ text = `git count-objects -v -H`
176
+ if matches = text.match(/size: ([. \w]+)$/)
177
+ matches[1]
178
+ else
179
+ text
180
+ end
181
+ end
182
+ end
183
+
184
+ def size_pack
185
+ Dir.chdir(@directory) do
186
+ text = `git count-objects -v -H`
187
+ if matches = text.match(/size-pack: ([. \w]+)$/)
188
+ matches[1]
189
+ else
190
+ text
191
+ end
192
+ end
193
+ end
194
+
195
+ def elapsed
196
+ elapsed = @timer.elapsed
197
+ if elapsed < 1.0
198
+ "#{format("%.1f", @timer.elapsed)}s"
199
+ else
200
+ "#{format("%.0f", @timer.elapsed)}s"
201
+ end
202
+ end
203
+
204
+ def info
205
+ ljust = 35
206
+ puts ""
207
+ puts "PROJECT.name".ljust(ljust) + Rainbow(PROJECT.name).yellow.bright
208
+ puts "PROJECT.version".ljust(ljust) + Rainbow(PROJECT.version).yellow.bright
209
+ puts "PROJECT.remote".ljust(ljust) + Rainbow(PROJECT.remote).yellow.bright
210
+ puts "PROJECT.branch".ljust(ljust) + Rainbow(PROJECT.branch).yellow.bright
211
+ puts "PROJECT.detached?".ljust(ljust) + Rainbow(PROJECT.detached?).yellow.bright
212
+ # puts "PROJECT.target".ljust(ljust) + Rainbow(PROJECT.target).yellow.bright
213
+ # puts "PROJECT.target_md5".ljust(ljust) + Rainbow(PROJECT.target_md5).yellow.bright
214
+ puts "PROJECT.latest_tag".ljust(ljust) + Rainbow(PROJECT.latest_tag).yellow.bright
215
+ puts "PROJECT.latest_tag_commit".ljust(ljust) + Rainbow(PROJECT.latest_tag_commit).yellow.bright
216
+ puts "PROJECT.latest_tag_md5".ljust(ljust) + Rainbow(PROJECT.latest_tag_md5).yellow.bright
217
+ puts "PROJECT.latest_commit".ljust(ljust) + Rainbow(PROJECT.latest_commit).yellow.bright
218
+ puts "PROJECT.last_modified_filename".ljust(ljust) + Rainbow(PROJECT.last_modified_filename).yellow.bright
219
+ # puts "PROJECT.elapsed".ljust(ljust) + Rainbow(PROJECT.elapsed).yellow.bright
220
+ puts "PROJECT.size".ljust(ljust) + Rainbow(PROJECT.size).yellow.bright
221
+ puts "PROJECT.size_pack".ljust(ljust) + Rainbow(PROJECT.size_pack).yellow.bright
222
+ puts "PROJECT.outstanding_commit?".ljust(ljust) + Rainbow(PROJECT.outstanding_commit?).yellow.bright
223
+ puts "PROJECT.outstanding_tag?".ljust(ljust) + Rainbow(PROJECT.outstanding_tag?).yellow.bright
224
+ puts ""
225
+ self
226
+ end
227
+
228
+ def to_markdown()
229
+ md = "# #{@name}"
230
+ md += get_markdown_nvp("Name", "Value", " ")
231
+ md += get_markdown_nvp("-", "-", "-")
232
+ md += get_markdown_nvp("Version", "#{@version}", " ")
233
+ md += get_markdown_nvp("Machine", "#{Raykit::Environment::machine}", " ")
234
+ md += get_markdown_nvp("User", "#{Raykit::Environment::user}", " ")
235
+ @values.each do |key, value|
236
+ md += get_markdown_nvp(key, value, " ")
237
+ end
238
+ @commands.each do |cmd|
239
+ md = md + "\n" + cmd.to_markdown
240
+ end
241
+ md
242
+ end
243
+
244
+ def get_markdown_nvp(key, value, pad_char)
245
+ "\n| " + key.to_s.ljust(36, pad_char) + "| " + value.to_s.ljust(36, pad_char)
246
+ end
247
+
248
+ def summary
249
+ info if @verbose
250
+ puts "[#{elapsed}] #{Rainbow(@name).yellow.bright} #{Rainbow(version).yellow.bright}"
251
+ end
252
+
253
+ def commit_message_filename
254
+ warn "[DEPRECATION] 'commit_message_filename' is deprecated."
255
+ @commit_message_filename
256
+ end
257
+
258
+ def commit(commit_message)
259
+ warn "[DEPRECATION] 'commit_message_filename' is deprecated. Use a run command for better transparency."
260
+ Dir.chdir(@directory) do
261
+ if File.exist?(".gitignore")
262
+ status = `git status`
263
+ if status.include?("Changes not staged for commit:")
264
+ run("git add --all")
265
+ if GIT_DIRECTORY.outstanding_commit?
266
+ if File.exist?(@commit_message_filename)
267
+ run("git commit --file #{@commit_message_filename}")
268
+ File.delete(@commit_message_filename)
269
+ else
270
+ run("git commit -m'#{commit_message}'")
271
+ end
272
+ end
273
+ end
274
+ else
275
+ puts "warning: .gitignore not found."
276
+ end
277
+ end
278
+ self
279
+ end
280
+
281
+ def push
282
+ Dir.chdir(@directory) do
283
+ status = `git status`
284
+ if status.include?('use "git push"')
285
+ run("git push")
286
+ end
287
+ end
288
+ self
289
+ end
290
+
291
+ def pull
292
+ Dir.chdir(@directory) do
293
+ run("git pull")
294
+ end
295
+ self
296
+ end
297
+
298
+ def tag
299
+ warn "[DEPRECATION] 'tag' is deprecated. Use run command(s) for better transparency."
300
+ Dir.chdir(@directory) do
301
+ specific_tag = `git tag -l #{@version}`.strip
302
+ puts Rainbow("git tag - #{@version}").green if @verbose
303
+ puts `git tag -l #{@version}` if @verbose
304
+ if specific_tag.length.zero?
305
+ puts "tag #{@version} not detected." if @verbose
306
+ tag = `git describe --abbrev=0 --tags`.strip
307
+ if @version != tag
308
+ puts "latest tag #{@tag}" if @verbose
309
+ run("git tag #{@version} -m'#{@version}'")
310
+ run("git push origin #{@version}")
311
+ # push
312
+ end
313
+ elsif @verbose
314
+ puts "already has tag #{specific_tag}"
315
+ end
316
+ end
317
+ self
318
+ end
319
+
320
+ def run(command, quit_on_failure = true)
321
+ if command.is_a?(Array)
322
+ command.each { |subcommand| run(subcommand, quit_on_failure) }
323
+ else
324
+ cmd = Command.new(command).set_timeout(@timeout).run
325
+ cmd.summary
326
+ elapsed_str = Timer.get_elapsed_str(cmd.elapsed, 0)
327
+ if !cmd.exitstatus.nil? && cmd.exitstatus.zero?
328
+ else
329
+ # display error details
330
+ cmd.details
331
+ if quit_on_failure
332
+ abort
333
+ end
334
+ end
335
+ cmd.save
336
+ @commands << cmd
337
+ cmd
338
+ end
339
+ end
340
+ end
341
+ end