takelage 0.13.3 → 0.14.0

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/takelage.rb +37 -14
  3. data/lib/takelage/bit/check/cli.rb +1 -1
  4. data/lib/takelage/bit/check/{module.rb → workspace.rb} +2 -2
  5. data/lib/takelage/bit/clipboard/cli.rb +9 -3
  6. data/lib/takelage/bit/clipboard/copy.rb +140 -0
  7. data/lib/takelage/bit/clipboard/lib.rb +153 -0
  8. data/lib/takelage/bit/clipboard/paste.rb +58 -0
  9. data/lib/takelage/bit/clipboard/pull.rb +38 -0
  10. data/lib/takelage/bit/clipboard/push.rb +37 -0
  11. data/lib/takelage/bit/scope/add.rb +55 -0
  12. data/lib/takelage/bit/scope/cli.rb +7 -3
  13. data/lib/takelage/bit/scope/inbit.rb +13 -0
  14. data/lib/takelage/bit/scope/list.rb +41 -0
  15. data/lib/takelage/bit/scope/new.rb +44 -0
  16. data/lib/takelage/default.yml +4 -3
  17. data/lib/takelage/docker/check/cli.rb +1 -1
  18. data/lib/takelage/docker/check/{module.rb → running.rb} +2 -2
  19. data/lib/takelage/docker/container/check/cli.rb +4 -2
  20. data/lib/takelage/docker/container/check/existing.rb +31 -0
  21. data/lib/takelage/docker/container/check/network.rb +31 -0
  22. data/lib/takelage/docker/container/check/orphaned.rb +31 -0
  23. data/lib/takelage/docker/container/cli.rb +35 -34
  24. data/lib/takelage/docker/container/command.rb +33 -0
  25. data/lib/takelage/docker/container/daemon.rb +13 -0
  26. data/lib/takelage/docker/container/lib.rb +149 -0
  27. data/lib/takelage/docker/container/login.rb +46 -0
  28. data/lib/takelage/docker/container/nuke.rb +39 -0
  29. data/lib/takelage/docker/container/purge.rb +30 -0
  30. data/lib/takelage/docker/image/check/cli.rb +4 -4
  31. data/lib/takelage/docker/image/check/{module.rb → outdated.rb} +4 -5
  32. data/lib/takelage/docker/image/cli.rb +4 -4
  33. data/lib/takelage/docker/image/tag/check/cli.rb +4 -3
  34. data/lib/takelage/docker/image/tag/check/{module.rb → local.rb} +2 -34
  35. data/lib/takelage/docker/image/tag/check/remote.rb +38 -0
  36. data/lib/takelage/docker/image/tag/latest/cli.rb +5 -3
  37. data/lib/takelage/docker/image/tag/latest/local.rb +20 -0
  38. data/lib/takelage/docker/image/tag/latest/{module.rb → remote.rb} +2 -18
  39. data/lib/takelage/docker/image/tag/list/cli.rb +3 -2
  40. data/lib/takelage/docker/image/tag/list/local.rb +19 -0
  41. data/lib/takelage/docker/image/tag/list/{module.rb → remote.rb} +2 -17
  42. data/lib/takelage/docker/image/{module.rb → update.rb} +2 -2
  43. data/lib/takelage/docker/socket/cli.rb +6 -2
  44. data/lib/takelage/docker/socket/host.rb +25 -0
  45. data/lib/takelage/docker/socket/lib.rb +88 -0
  46. data/lib/takelage/docker/socket/scheme.rb +46 -0
  47. data/lib/takelage/docker/socket/start.rb +34 -0
  48. data/lib/takelage/docker/socket/stop.rb +55 -0
  49. data/lib/takelage/git/check/clean.rb +46 -0
  50. data/lib/takelage/git/check/cli.rb +3 -1
  51. data/lib/takelage/git/check/master.rb +26 -0
  52. data/lib/takelage/git/check/workspace.rb +33 -0
  53. data/lib/takelage/self/cli.rb +1 -1
  54. data/lib/takelage/self/{module.rb → list.rb} +2 -2
  55. data/lib/takelage/version +1 -1
  56. metadata +38 -15
  57. data/lib/takelage/bit/clipboard/module.rb +0 -401
  58. data/lib/takelage/bit/scope/module.rb +0 -122
  59. data/lib/takelage/docker/container/check/module.rb +0 -81
  60. data/lib/takelage/docker/container/module.rb +0 -295
  61. data/lib/takelage/docker/socket/module.rb +0 -227
  62. data/lib/takelage/git/check/module.rb +0 -93
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 991db33478b195724cc3055a8abd16c2a28bab6ea08d14fd875d738bf3a4bef1
4
- data.tar.gz: 918a401d9124057bcd84544cbcc83e177a163f9dce65fcc4fc9c8ef58d1a0cd7
3
+ metadata.gz: '058d42cc592fd9c1509aab8d8796069b1f1699453b88cfffbc93af9dfb1d09c0'
4
+ data.tar.gz: 45763ae032cd559e55dc636d857de7ef87a0dd4b6c0e1b3292f350d787388e0b
5
5
  SHA512:
6
- metadata.gz: 76985cf34c08ac197fcf252c35aeef45075bba7549eab29fe0ae273e42ddd29ede87a5f556d8b9c2e649781152022be4b472de0a0f2755da4efbc5096622efbe
7
- data.tar.gz: a8c9a36f133db5617aa918a52101f2507ed86be0cea8cad9bdea1157ffc82608eaaa65309a5c6a00ce3fa0300c2836d5c53650ea9fa5a7ad2465b0e3b000343b
6
+ metadata.gz: 733b0d40ac76a2caece5cf6f6a52252d5bd9dad690bd6df0258dab21268b43cf9f109e5e54f5ce8b3599ee392ba3f9bb3d65e7a7fcaa4a1daadee560c7ce7469
7
+ data.tar.gz: ef4b53f6bb4cd250095e02472357933d2d29f6049d0b29269782f5730694aaffefbb89ac252f37f816e3e4c03c89184debf07e061b564e46615b75110abc20b1
data/lib/takelage.rb CHANGED
@@ -20,41 +20,64 @@ require_relative 'takelage/lib/system'
20
20
  require_relative 'takelage/lib/config'
21
21
  require_relative 'takelage/lib/project'
22
22
 
23
- require_relative 'takelage/git/check/module'
23
+ require_relative 'takelage/git/check/clean'
24
+ require_relative 'takelage/git/check/master'
25
+ require_relative 'takelage/git/check/workspace'
24
26
  require_relative 'takelage/git/check/cli'
25
27
  require_relative 'takelage/git/cli'
26
- require_relative 'takelage/bit/check/module'
28
+ require_relative 'takelage/bit/check/workspace'
27
29
  require_relative 'takelage/bit/check/cli'
28
- require_relative 'takelage/bit/scope/module'
30
+ require_relative 'takelage/bit/scope/add'
31
+ require_relative 'takelage/bit/scope/inbit'
32
+ require_relative 'takelage/bit/scope/list'
33
+ require_relative 'takelage/bit/scope/new'
29
34
  require_relative 'takelage/bit/scope/cli'
30
- require_relative 'takelage/bit/clipboard/module'
35
+ require_relative 'takelage/bit/clipboard/lib'
36
+ require_relative 'takelage/bit/clipboard/copy'
37
+ require_relative 'takelage/bit/clipboard/paste'
38
+ require_relative 'takelage/bit/clipboard/pull'
39
+ require_relative 'takelage/bit/clipboard/push'
31
40
  require_relative 'takelage/bit/clipboard/cli'
32
41
  require_relative 'takelage/bit/cli'
33
42
  require_relative 'takelage/completion/cli'
34
- require_relative 'takelage/docker/check/module'
43
+ require_relative 'takelage/docker/check/running'
35
44
  require_relative 'takelage/docker/check/cli'
36
- require_relative 'takelage/docker/socket/module'
45
+ require_relative 'takelage/docker/socket/lib'
46
+ require_relative 'takelage/docker/socket/host'
47
+ require_relative 'takelage/docker/socket/scheme'
48
+ require_relative 'takelage/docker/socket/start'
49
+ require_relative 'takelage/docker/socket/stop'
37
50
  require_relative 'takelage/docker/socket/cli'
38
- require_relative 'takelage/docker/image/tag/list/module'
51
+ require_relative 'takelage/docker/image/tag/list/local'
52
+ require_relative 'takelage/docker/image/tag/list/remote'
39
53
  require_relative 'takelage/docker/image/tag/list/cli'
40
- require_relative 'takelage/docker/image/tag/latest/module'
54
+ require_relative 'takelage/docker/image/tag/latest/local'
55
+ require_relative 'takelage/docker/image/tag/latest/remote'
41
56
  require_relative 'takelage/docker/image/tag/latest/cli'
42
- require_relative 'takelage/docker/image/tag/check/module'
57
+ require_relative 'takelage/docker/image/tag/check/local'
58
+ require_relative 'takelage/docker/image/tag/check/remote'
43
59
  require_relative 'takelage/docker/image/tag/check/cli'
44
60
  require_relative 'takelage/docker/image/tag/cli'
45
- require_relative 'takelage/docker/image/check/module'
61
+ require_relative 'takelage/docker/image/check/outdated'
46
62
  require_relative 'takelage/docker/image/check/cli'
47
- require_relative 'takelage/docker/image/module'
63
+ require_relative 'takelage/docker/image/update'
48
64
  require_relative 'takelage/docker/image/cli'
49
- require_relative 'takelage/docker/container/check/module'
65
+ require_relative 'takelage/docker/container/check/existing'
66
+ require_relative 'takelage/docker/container/check/network'
67
+ require_relative 'takelage/docker/container/check/orphaned'
50
68
  require_relative 'takelage/docker/container/check/cli'
51
- require_relative 'takelage/docker/container/module'
69
+ require_relative 'takelage/docker/container/lib'
70
+ require_relative 'takelage/docker/container/command'
71
+ require_relative 'takelage/docker/container/daemon'
72
+ require_relative 'takelage/docker/container/login'
73
+ require_relative 'takelage/docker/container/nuke'
74
+ require_relative 'takelage/docker/container/purge'
52
75
  require_relative 'takelage/docker/container/cli'
53
76
  require_relative 'takelage/docker/cli'
54
77
  require_relative 'takelage/info/project/cli'
55
78
  require_relative 'takelage/info/cli'
56
79
  require_relative 'takelage/self/config/cli'
57
- require_relative 'takelage/self/module'
80
+ require_relative 'takelage/self/list'
58
81
  require_relative 'takelage/self/cli'
59
82
 
60
83
  # Facilitate the takelage devops workflow.
@@ -6,7 +6,7 @@ module Takelage
6
6
  include LoggingModule
7
7
  include SystemModule
8
8
  include ConfigModule
9
- include BitCheckModule
9
+ include BitCheckWorkspace
10
10
 
11
11
  #
12
12
  # bit check workspace
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # takelage bit check module
4
- module BitCheckModule
3
+ # takelage bit check workspace
4
+ module BitCheckWorkspace
5
5
  # Backend method for bit check workspace.
6
6
  # @return [Boolean] is this a bit workspace?
7
7
  def bit_check_workspace
@@ -6,9 +6,15 @@ module Takelage
6
6
  include LoggingModule
7
7
  include ConfigModule
8
8
  include SystemModule
9
- include GitCheckModule
10
- include BitCheckModule
11
- include BitClipboardModule
9
+ include GitCheckClean
10
+ include GitCheckMaster
11
+ include GitCheckWorkspace
12
+ include BitCheckWorkspace
13
+ include BitClipboardLib
14
+ include BitClipboardCopy
15
+ include BitClipboardPaste
16
+ include BitClipboardPull
17
+ include BitClipboardPush
12
18
 
13
19
  #
14
20
  # bit copy
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ # takelage bit clipboard copy
4
+ module BitClipboardCopy
5
+ # Backend method for bit copy.
6
+ def bit_clipboard_copy(dir, scope)
7
+ # remove trailing slash
8
+ dir = dir.chomp('/')
9
+
10
+ log.debug "Running bit copy \"#{dir}\" to \"#{scope}\""
11
+
12
+ return false unless _bit_clipboard_lib_prepare_workspace
13
+
14
+ unless File.directory? dir
15
+ log.error "The directory \"#{dir}\" does not exist"
16
+ return false
17
+ end
18
+
19
+ _bit_clipboard_copy_dir dir, scope
20
+ end
21
+
22
+ private
23
+
24
+ # rubocop:disable Metrics/MethodLength
25
+ def _bit_clipboard_copy_dir(dir, scope)
26
+ log.debug "Adding the directory \"#{dir}\" as a tagged bit component"
27
+
28
+ return false unless _bit_clipboard_copy_dir_scope_exists? scope
29
+
30
+ return false if _bit_clipboard_copy_readme_bit_exists_in_subdir? dir
31
+
32
+ id = _bit_clipboard_lib_id(dir)
33
+
34
+ _bit_clipboard_copy_touch_readme_bit dir
35
+ _bit_clipboard_copy_add_dir id, dir
36
+ _bit_clipboard_copy_tag_dir id
37
+ _bit_clipboard_copy_export_to_scope scope
38
+ _bit_clipbpard_lib_remove_bit_artifacts
39
+ _bit_clipboard_lib_sync_workspace
40
+
41
+ log.info "Copied directory \"#{dir}\" as bit component \"#{id}\" " \
42
+ "to bit remote scope \"#{scope}\""
43
+ end
44
+ # rubocop:enable Metrics/MethodLength
45
+
46
+ # touch README.bit if necessary
47
+ def _bit_clipboard_copy_touch_readme_bit(dir)
48
+ readme_bit = "#{dir}/README.bit"
49
+ return if File.file? readme_bit
50
+
51
+ log.info "Creating \"README.bit\" in \"#{dir}\""
52
+ File.open(readme_bit, 'w') {}
53
+ end
54
+
55
+ # check if a README.bit file exists in a subdirectory
56
+ def _bit_clipboard_copy_readme_bit_exists_in_subdir?(dir)
57
+ Dir.glob("#{dir}/**/README.bit").each do |file|
58
+ unless file == "#{dir}/README.bit"
59
+ log.error 'Nested README.bit file detected'
60
+ return true
61
+ end
62
+ end
63
+
64
+ false
65
+ end
66
+
67
+ # Check if bit scope exists
68
+ def _bit_clipboard_copy_dir_scope_exists?(scope)
69
+ bit_dev = config.active['bit_dev_user']
70
+
71
+ # check if scope is a candidate for a bit.dev remote scope
72
+ if scope.start_with? bit_dev + '.'
73
+ return false unless _bit_clipboard_bit_dev_scope_exists scope
74
+ else
75
+ return false unless _bit_clipboard_custom_scope_exists scope
76
+ end
77
+
78
+ true
79
+ end
80
+
81
+ # check if bit.dev remote scope exists
82
+ def _bit_clipboard_bit_dev_scope_exists(scope)
83
+ cmd_bit_list_scope = format(
84
+ config.active['cmd_bit_clipboard_copy_bit_list_scope'],
85
+ scope: scope
86
+ )
87
+
88
+ status = try cmd_bit_list_scope
89
+
90
+ return true if status.exitstatus.zero?
91
+
92
+ log.error "No bit.dev remote scope \"#{scope}\" found"
93
+ false
94
+ end
95
+
96
+ # check if bit remote scope is added to local workspace
97
+ def _bit_clipboard_custom_scope_exists(scope)
98
+ cmd_bit_list_remotes =
99
+ config.active['cmd_bit_clipboard_copy_bit_list_remotes']
100
+
101
+ stdout_str = run cmd_bit_list_remotes
102
+
103
+ return true if /.*\s+#{scope}\s+.*/m.match? stdout_str
104
+
105
+ log.error "No bit remote scope \"#{scope}\" " \
106
+ 'found in local bit workspace'
107
+ false
108
+ end
109
+
110
+ # bit tag dir
111
+ def _bit_clipboard_copy_add_dir(id, dir)
112
+ cmd_bit_add_dir = format(
113
+ config.active['cmd_bit_clipboard_copy_bit_add_dir'],
114
+ id: id,
115
+ dir: dir
116
+ )
117
+
118
+ run cmd_bit_add_dir
119
+ end
120
+
121
+ # bit tag dir
122
+ def _bit_clipboard_copy_tag_dir(id)
123
+ cmd_bit_tag_id = format(
124
+ config.active['cmd_bit_clipboard_copy_bit_tag_id'],
125
+ id: id
126
+ )
127
+
128
+ run cmd_bit_tag_id
129
+ end
130
+
131
+ # bit export component to bit remote scope
132
+ def _bit_clipboard_copy_export_to_scope(scope)
133
+ cmd_bit_export_to_scope = format(
134
+ config.active['cmd_bit_clipboard_copy_bit_export_to_scope'],
135
+ scope: scope
136
+ )
137
+
138
+ run cmd_bit_export_to_scope
139
+ end
140
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ # takelage bit clipboard lib
4
+ module BitClipboardLib
5
+ private
6
+
7
+ # Prepare workspace for bit clipboard.
8
+ def _bit_clipboard_lib_prepare_workspace
9
+ unless bit_check_workspace
10
+ log.error 'No bit workspace'
11
+ return false
12
+ end
13
+
14
+ return true unless git_check_workspace
15
+
16
+ _bit_clipboard_lib_prepare_git_workspace
17
+ end
18
+
19
+ # Prepare git workspace for bit clipboard.
20
+ def _bit_clipboard_lib_prepare_git_workspace
21
+ unless git_check_master
22
+ log.error 'Not on git master branch'
23
+ return false
24
+ end
25
+
26
+ unless git_check_clean
27
+ log.error 'No clean git workspace'
28
+ return false
29
+ end
30
+
31
+ _bit_clipboard_lib_git_pull
32
+ end
33
+
34
+ # Remove bit artifacts.
35
+ def _bit_clipbpard_lib_remove_bit_artifacts
36
+ log.debug 'Removing bit artifacts'
37
+
38
+ # Remove node_modules directory.
39
+ FileUtils.remove_entry_secure('node_modules', force: true)
40
+
41
+ # Remove index.bit files recursively.
42
+ Dir.glob('./**/index.bit').each do |file|
43
+ FileUtils.remove_entry_secure(file, force: true)
44
+ end
45
+
46
+ # Remove package.json file.
47
+ FileUtils.remove_entry_secure('package.json', force: true)
48
+ end
49
+
50
+ # Sync workspace with upstream.
51
+ def _bit_clipboard_lib_sync_workspace
52
+ log.debug 'Syncing git workspace'
53
+
54
+ _rakefile, path = Rake.application.find_rakefile_location
55
+ bitmap = "#{path}/.bitmap"
56
+
57
+ _bit_clipboard_lib_git_add bitmap
58
+ _bit_clipboard_lib_git_commit bitmap
59
+ _bit_clipboard_lib_git_push
60
+ end
61
+
62
+ # git add .bitmap
63
+ def _bit_clipboard_lib_git_add(bitmap)
64
+ log.debug "Adding \"#{bitmap}\" to git"
65
+
66
+ cmd_bit_clipboard_git_add = format(
67
+ config.active['cmd_bit_clipboard_git_add'],
68
+ file: bitmap
69
+ )
70
+ run cmd_bit_clipboard_git_add
71
+ end
72
+
73
+ # git commit -m "Update .bitmap"
74
+ def _bit_clipboard_lib_git_commit(bitmap)
75
+ message = 'Update .bitmap'
76
+
77
+ log.debug "Committing \"#{bitmap}\" to git"
78
+
79
+ cmd_bit_clipboard_git_commit = format(
80
+ config.active['cmd_bit_clipboard_git_commit'],
81
+ message: message
82
+ )
83
+
84
+ run cmd_bit_clipboard_git_commit
85
+ end
86
+
87
+ # git push origin master
88
+ def _bit_clipboard_lib_git_push
89
+ log.debug 'Pushing master branch to origin'
90
+
91
+ cmd_bit_clipboard_git_push =
92
+ config.active['cmd_bit_clipboard_git_push']
93
+
94
+ run cmd_bit_clipboard_git_push
95
+ end
96
+
97
+ # git pull
98
+ def _bit_clipboard_lib_git_pull
99
+ log.debug 'Updating git workspace'
100
+ cmd_bit_clipboard_git_pull =
101
+ config.active['cmd_bit_clipboard_git_pull']
102
+
103
+ result_git_pull = try cmd_bit_clipboard_git_pull
104
+
105
+ return true unless result_git_pull
106
+
107
+ log.error 'Unable to update git workspace'
108
+ false
109
+ end
110
+
111
+ # Genereate .gitignore if bitignore is present
112
+ def _bit_clipboard_lib_handle_bitignore
113
+ log.debug 'Handling bitgnore files'
114
+
115
+ # find all bitgnore files
116
+ Dir.glob('./**/bitignore').each do |file|
117
+ # get directory of bitignore file
118
+ dir = File.dirname file
119
+
120
+ # build gitignore filepath
121
+ gitignore_file = "#{dir}/.gitignore"
122
+
123
+ unless File.exist? gitignore_file
124
+ log.debug "Creating \".gitignore\" in \"#{dir}\""
125
+ File.open(gitignore_file, 'w') { |gitignore| gitignore.write('*') }
126
+ end
127
+ end
128
+ end
129
+
130
+ # Generate bit component ID.
131
+ def _bit_clipboard_lib_id(name)
132
+ id = ''
133
+
134
+ # bit restrictions:
135
+ # component names can only contain alphanumeric,
136
+ # lowercase characters, and the following ["-", "_", "$", "!", "/"]
137
+
138
+ # convert directory name to lowercase characters
139
+ dir_downcase = name.downcase
140
+
141
+ # construct array of allowed characters
142
+ allowed_chars = [*('a'..'z'), *('0'..'9'), '-', '_', '$', '!', '/']
143
+
144
+ # iterate over directory or file name
145
+ # and replace invalid characters with underscore
146
+ dir_downcase.split('').each do |char|
147
+ id += allowed_chars.include?(char) ? char : '_'
148
+ end
149
+
150
+ log.debug "Generated bit id \"#{id}\" from \"#{name}\""
151
+ id
152
+ end
153
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # takelage bit clipboard paste
4
+ module BitClipboardPaste
5
+ # Backend method for bit paste.
6
+ def bit_clipboard_paste(cid, dir)
7
+ log.debug "Running bit paste \"#{cid}\" to \"#{dir}\""
8
+
9
+ return false unless _bit_clipboard_lib_prepare_workspace
10
+
11
+ return false unless _bit_clipboard_paste_cid_exists? cid
12
+
13
+ _bit_clipboard_paste_import_cid cid, dir
14
+ _bit_clipboard_lib_handle_bitignore
15
+ _bit_clipbpard_lib_remove_bit_artifacts
16
+ _bit_clipboard_lib_sync_workspace
17
+
18
+ log.info "Pasted bit component \"#{cid}\" to directory \"#{dir}\""
19
+ true
20
+ end
21
+
22
+ private
23
+
24
+ # paste bit component into directory
25
+ def _bit_clipboard_paste_import_cid(cid, dir)
26
+ cmd_bit_import_cid = format(
27
+ config.active['cmd_bit_clipboard_paste_bit_import_cid'],
28
+ cid: cid,
29
+ dir: dir
30
+ )
31
+
32
+ run cmd_bit_import_cid
33
+ end
34
+
35
+ def _bit_clipboard_paste_cid_exists?(cid)
36
+ scope = cid.scan(%r{([^/]*).*}).first.first
37
+
38
+ log.debug "Checking if scope \"#{scope}\" " \
39
+ "contains component id \"#{cid}\""
40
+
41
+ bit_list_scope = _bit_clipboard_paste_cid_exists_list_scope scope
42
+
43
+ return true if bit_list_scope.include? '"id": "' + cid + '",'
44
+
45
+ log.error "No remote component \"#{cid}\""
46
+ false
47
+ end
48
+
49
+ # get components in remote scope
50
+ def _bit_clipboard_paste_cid_exists_list_scope(scope)
51
+ cmd_bit_list_scope = format(
52
+ config.active['cmd_bit_clipboard_paste_bit_list_scope'],
53
+ scope: scope
54
+ )
55
+
56
+ run cmd_bit_list_scope
57
+ end
58
+ end