jets 1.0.1 → 1.0.2

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -3
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +23 -1
  6. data/jets.gemspec +1 -2
  7. data/lib/jets.rb +5 -11
  8. data/lib/jets/builders/gem_replacer.rb +12 -96
  9. data/lib/jets/builders/ruby_packager.rb +3 -4
  10. data/lib/jets/builders/tidy.rb +9 -0
  11. data/lib/jets/commands.rb +1 -0
  12. data/lib/jets/commands/base.rb +10 -1
  13. data/lib/jets/commands/gems.rb +25 -0
  14. data/lib/jets/commands/help/gems/check.md +7 -0
  15. data/lib/jets/commands/help/import/rails.md +3 -3
  16. data/lib/jets/commands/import.rb +4 -0
  17. data/lib/jets/commands/import/base.rb +10 -0
  18. data/lib/jets/commands/import/cheatsheet.rb +35 -0
  19. data/lib/jets/commands/import/rail.rb +7 -0
  20. data/lib/jets/commands/import/sequence.rb +63 -47
  21. data/lib/jets/commands/import/templates/submodules-cheatsheet.md +89 -0
  22. data/lib/jets/db.rb +9 -0
  23. data/lib/jets/version.rb +1 -1
  24. data/vendor/jets-gems/Gemfile +6 -0
  25. data/vendor/jets-gems/Gemfile.lock +39 -0
  26. data/vendor/jets-gems/LICENSE.txt +21 -0
  27. data/vendor/jets-gems/README.md +19 -0
  28. data/vendor/{lambdagem → jets-gems}/Rakefile +2 -2
  29. data/vendor/jets-gems/bin/console +14 -0
  30. data/vendor/jets-gems/bin/setup +8 -0
  31. data/vendor/jets-gems/jets-gems.gemspec +30 -0
  32. data/vendor/jets-gems/lib/jets-gems.rb +1 -0
  33. data/vendor/jets-gems/lib/jets/gems.rb +16 -0
  34. data/vendor/jets-gems/lib/jets/gems/check.rb +156 -0
  35. data/vendor/jets-gems/lib/jets/gems/exist.rb +54 -0
  36. data/vendor/jets-gems/lib/jets/gems/extract.rb +7 -0
  37. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/base.rb +25 -6
  38. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/gem.rb +10 -8
  39. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/ruby.rb +6 -7
  40. data/vendor/jets-gems/lib/jets/gems/report.rb +53 -0
  41. data/vendor/jets-gems/lib/jets/gems/version.rb +5 -0
  42. data/vendor/jets-gems/spec/jets/gems_spec.rb +5 -0
  43. data/vendor/jets-gems/spec/spec_helper.rb +14 -0
  44. metadata +41 -53
  45. data/vendor/lambdagem/CHANGELOG.md +0 -27
  46. data/vendor/lambdagem/Gemfile +0 -6
  47. data/vendor/lambdagem/Gemfile.lock +0 -73
  48. data/vendor/lambdagem/Guardfile +0 -12
  49. data/vendor/lambdagem/LICENSE.txt +0 -22
  50. data/vendor/lambdagem/README.md +0 -139
  51. data/vendor/lambdagem/exe/lambdagem +0 -14
  52. data/vendor/lambdagem/lambdagem.gemspec +0 -32
  53. data/vendor/lambdagem/lib/lambdagem.rb +0 -18
  54. data/vendor/lambdagem/lib/lambdagem/base.rb +0 -53
  55. data/vendor/lambdagem/lib/lambdagem/build.rb +0 -202
  56. data/vendor/lambdagem/lib/lambdagem/clean.rb +0 -8
  57. data/vendor/lambdagem/lib/lambdagem/cli.rb +0 -62
  58. data/vendor/lambdagem/lib/lambdagem/command.rb +0 -38
  59. data/vendor/lambdagem/lib/lambdagem/exist.rb +0 -50
  60. data/vendor/lambdagem/lib/lambdagem/extract.rb +0 -8
  61. data/vendor/lambdagem/lib/lambdagem/extract/class_methods.rb +0 -50
  62. data/vendor/lambdagem/lib/lambdagem/help.rb +0 -9
  63. data/vendor/lambdagem/lib/lambdagem/help/all.md +0 -11
  64. data/vendor/lambdagem/lib/lambdagem/help/build.md +0 -14
  65. data/vendor/lambdagem/lib/lambdagem/help/clean.md +0 -5
  66. data/vendor/lambdagem/lib/lambdagem/help/extract_gem.md +0 -5
  67. data/vendor/lambdagem/lib/lambdagem/help/extract_ruby.md +0 -5
  68. data/vendor/lambdagem/lib/lambdagem/help/package.md +0 -20
  69. data/vendor/lambdagem/lib/lambdagem/help/upload.md +0 -7
  70. data/vendor/lambdagem/lib/lambdagem/package.rb +0 -33
  71. data/vendor/lambdagem/lib/lambdagem/upload.rb +0 -39
  72. data/vendor/lambdagem/lib/lambdagem/util.rb +0 -30
  73. data/vendor/lambdagem/lib/lambdagem/version.rb +0 -3
  74. data/vendor/lambdagem/spec/lib/build_spec.rb +0 -32
  75. data/vendor/lambdagem/spec/lib/cli_spec.rb +0 -24
  76. data/vendor/lambdagem/spec/lib/upload_spec.rb +0 -25
  77. data/vendor/lambdagem/spec/spec_helper.rb +0 -24
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Trap ^C
4
- Signal.trap("INT") {
5
- puts "\nCtrl-C detected. Exiting..."
6
- sleep 1
7
- exit
8
- }
9
-
10
- $:.unshift(File.expand_path("../../lib", __FILE__))
11
- require "lambdagem"
12
- require "lambdagem/cli"
13
-
14
- Lambdagem::CLI.start(ARGV)
@@ -1,32 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "lambdagem/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "lambdagem"
8
- spec.version = Lambdagem::VERSION
9
- spec.authors = ["Tung Nguyen"]
10
- spec.email = ["tongueroo@gmail.com"]
11
- spec.description = %q{Gem builder}
12
- spec.summary = %q{Gem builder}
13
- spec.homepage = "https://github.com/tongueroo/lambdagem"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.bindir = 'exe'
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_dependency "thor"
23
- spec.add_dependency "hashie"
24
- spec.add_dependency "colorize"
25
- spec.add_dependency "aws-sdk-s3"
26
- spec.add_dependency "gems"
27
-
28
- spec.add_development_dependency "bundler"
29
- spec.add_development_dependency "rake"
30
- spec.add_development_dependency "rspec"
31
- spec.add_development_dependency "byebug"
32
- end
@@ -1,18 +0,0 @@
1
- $:.unshift(File.expand_path("../", __FILE__))
2
- require "lambdagem/version"
3
- require "byebug" if ENV['USER'] == 'tung'
4
-
5
- module Lambdagem
6
- autoload :Command, "lambdagem/command"
7
- autoload :Help, "lambdagem/help"
8
- autoload :CLI, "lambdagem/cli"
9
- autoload :Base, "lambdagem/base"
10
- autoload :Build, "lambdagem/build"
11
- autoload :Package, "lambdagem/package"
12
- autoload :Upload, "lambdagem/upload"
13
- autoload :Extract, "lambdagem/extract"
14
- autoload :Clean, "lambdagem/clean"
15
- autoload :Exist, "lambdagem/exist"
16
- autoload :Util, "lambdagem/util"
17
- extend Util
18
- end
@@ -1,53 +0,0 @@
1
- require 'fileutils'
2
- require 'colorize'
3
-
4
- class Lambdagem::Base
5
- include Lambdagem::Util
6
-
7
- attr_reader :s3_bucket, :lambdagems_url
8
- def initialize(name, options={})
9
- @name = name
10
- @options = options
11
-
12
- @build_root = options[:build_root] || "/tmp/lambdagem"
13
- @artifacts_root = "#{@build_root}/artifacts"
14
- @s3_bucket = options[:s3] || 'lambdagems'
15
- @lambdagems_url = options[:lambdagems_url] || "https://gems.lambdagems.com"
16
- end
17
-
18
- # The gems are stored in a ruby version folder that always has a patch version of
19
- # 0. So 2.5.1 => 2.5.0
20
- def minor_ruby_version
21
- major, minor = RUBY_VERSION.split('.')[0..1]
22
- [major, minor, "0"].join('.')
23
- end
24
-
25
- # The ruby version folder always has a 0 for the patch version.
26
- # Example: 2.4.2 => 2.4.0
27
- def ruby_version_folder
28
- major, minor, patch = RUBY_VERSION.split('.')
29
- [major, minor, '0'].join('.')
30
- end
31
-
32
- # Current jets version is 2.5.0, will use that for gems and ruby
33
- # when users are using ruby 2.5.1.
34
- # When the jets ruby version is updated we update this also.
35
- def jets_ruby_version
36
- major, minor, patch = RUBY_VERSION.split('.')
37
- [major, minor, '0'].join('.')
38
- end
39
-
40
- # Input: byebug-9.1.0
41
- # Output: byebug
42
- def gem_name
43
- @name.gsub(/-(\d+\.\d+\.\d+.*)/,'')
44
- end
45
-
46
- # Input: byebug-9.1.0
47
- # Output: 9.1.0
48
- # Can return nil if version not found
49
- def gem_version
50
- md = @name.match(/-(\d+\.\d+\.\d+.*)/)
51
- md[1] if md
52
- end
53
- end
@@ -1,202 +0,0 @@
1
- require 'bundler'
2
-
3
- # Terms:
4
- # name: the gem name the user passed in, could have version number could not
5
- # full_gem_name: has both gem name and version number. IE: byebug-0.9.1
6
- # gem_name: strips the version. IE: byebug
7
- # gem_version: version only. IE: 0.9.1
8
- class Lambdagem::Build < Lambdagem::Base
9
- def build
10
- puts "Building #{@name} in #{@build_root}"
11
- return if @options[:noop]
12
-
13
- clean
14
- create_gemfile
15
- bundle_install
16
- # upload not just the top-level gem but also the dependent gems
17
- # in case there are dependent gems that also require compilation
18
- all_gems.each do |full_gem_name|
19
- artifact_location = prepare_gem(full_gem_name)
20
- # artifact is going to be tmp/artifacts/bundled
21
- # the article contains the bundled directory so we can expand it all
22
- # out together.
23
- puts "Artifacts location: #{artifact_location}"
24
- puts "Gem artifact path: #{gem_artifact_path(full_gem_name)}"
25
- puts "If you have system library dependencies add them under the artifacts location before running: lambdagem package #{full_gem_name}"
26
- end
27
- end
28
-
29
- def all_gems
30
- names = all_extensions.map { |path| File.basename(path) }
31
- names.uniq
32
- end
33
-
34
- # Finds the paths that have compiled extensions.
35
- #
36
- # Examples of return:
37
- # linux:
38
- # ["tmp/bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/byebug-9.1.0"]
39
- # macosx:
40
- # ["tmp/bundled/gems/ruby/2.4.0/extensions/x86_64-darwin-16/2.4.0-static/byebug-9.1.0"]
41
- def all_extensions
42
- Dir.glob("#{@build_root}/bundled/gems/ruby/*/extensions/*/*/*").to_a.uniq
43
- end
44
-
45
- def clean
46
- FileUtils.rm_rf(@build_root)
47
- end
48
-
49
- def create_gemfile
50
- content =<<-EOL
51
- source "https://rubygems.org"
52
- EOL
53
- if gem_version
54
- content << %Q|gem "#{gem_name}", "#{gem_version}"\n|
55
- else
56
- content << %Q|gem "#{gem_name}"\n|
57
- end
58
-
59
- gemfile_path = "#{@build_root}/Gemfile"
60
- FileUtils.mkdir_p(File.dirname(gemfile_path))
61
- IO.write(gemfile_path, content)
62
- puts "Generated: #{gemfile_path}"
63
- end
64
-
65
- def bundle_install
66
- Bundler.with_clean_env do
67
- command = "cd #{@build_root} && bundle install --path bundled/gems"
68
- puts "=> #{command}"
69
- success = system(command)
70
- abort('Bundle install failed, exiting.') unless success
71
- end
72
- end
73
-
74
- # Do not want to copy everything underneath bundled/gems/ruby/2.5.0 or else
75
- # we end up with a bunch of extra files that might screw up an current
76
- # install of ruby when we extract out the files and overwrite things.
77
- #
78
- # Instead only copy the folders that we want to be a part of the tarball
79
- # into another directory first. This is called the artifacts directory.
80
- #
81
- # Example of the 2 folder we want to keep is:
82
- #
83
- # tmp/bundled/gems/ruby/2.5.0/gems/byebug-9.1.0
84
- # tmp/bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/byebug-9.1.0
85
- #
86
- # Returns the path to the ruby minor version folder that contains all the of gem.
87
- # Example: tmp/artifacts/2.5.0
88
- def prepare_gem(full_gem_name)
89
- gem_path = built_gem_path(full_gem_name)
90
- ext_path = built_ext_path(full_gem_name)
91
- copy_artifacts(gem_path)
92
- copy_artifacts(ext_path) if ext_path
93
- # copy specifications: required for bundler to work
94
- specs_path = specifications_path(full_gem_name)
95
- copy_spec(specs_path)
96
-
97
- tidy_gem(full_gem_name)
98
-
99
- "#{@artifacts_root}/#{full_gem_name}/bundled"
100
- end
101
-
102
- # Clean up some unneeded files to try to keep the package size down
103
- def tidy_gem(full_gem_name)
104
- gem_artifact_path = gem_artifact_path(full_gem_name)
105
-
106
- # remove top level tests and cache folders
107
- Dir.glob("#{gem_artifact_path}/*").each do |path|
108
- next unless File.directory?(path)
109
- folder = File.basename(path)
110
- if %w[test tests spec features benchmark cache doc].include?(folder)
111
- FileUtils.rm_rf(path)
112
- end
113
- end
114
-
115
- Dir.glob("#{gem_artifact_path}/**/*").each do |path|
116
- next unless File.file?(path)
117
- ext = File.extname(path)
118
- if %w[.rdoc .md .markdown].include?(ext) or
119
- path =~ /LICENSE|CHANGELOG|README/
120
- FileUtils.rm_f(path)
121
- end
122
- end
123
- end
124
-
125
- def gem_artifact_path(full_gem_name)
126
- "#{@artifacts_root}/#{full_gem_name}/bundled/gems/ruby/#{ruby_version_folder}/gems/#{full_gem_name}"
127
- end
128
-
129
- # original_path example: tmp/bundled/gems/ruby/2.5.0/gems/byebug-9.1.0
130
- def copy_artifacts(original_path)
131
- leaf_path = recreate_leaves_structure(@artifacts_root, original_path)
132
- FileUtils.cp_r(original_path, leaf_path)
133
- end
134
-
135
- # Mirrors the some of the leave path structure of the original structure.
136
- # This works for specific folders that have the gem name at the end only.
137
- # This is not a generic method.
138
- #
139
- # Example 1:
140
- # dest: tmp/artifacts
141
- # original_path: tmp/bundled/gems/ruby/2.5.0/gems/byebug-9.1.0
142
- #
143
- # Recreated structure:
144
- # created: tmp/artifacts/byebug-9.1.0/bundled/gems/ruby/2.5.0/gems
145
- #
146
- # Example 2:
147
- # dest: tmp/artifacts
148
- # original_path: tmp/bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/byebug-9.1.0
149
- #
150
- # Recreated structure:
151
- # created: tmp/artifacts/byebug-9.1.0/bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static
152
- #
153
- #
154
- # Returns created leaf path folder. If the original path was a file this
155
- # will be the parent folder.
156
- #
157
- # Example:
158
- #
159
- # folder/a.txt => leaf path is folder
160
- # folder/folder2 => leaf path is folder/folder2
161
- #
162
- def recreate_leaves_structure(dest_dir, original_path)
163
- # strip the leading tmp/bundled/gems/ruby/
164
- # and the trailing gem_name
165
- full_gem_name = File.basename(original_path)
166
- new_path = original_path.sub("#{@build_root}/", "") # script build root
167
- leaf_path = "#{dest_dir}/#{full_gem_name}/#{new_path}"
168
- leaf_path = File.dirname(leaf_path)
169
- FileUtils.mkdir_p(leaf_path)
170
- leaf_path
171
- end
172
-
173
- # bundled/gems/ruby/2.5.0/gems/byebug-9.1.0
174
- def built_gem_path(full_gem_name)
175
- "#{@build_root}/bundled/gems/ruby/#{minor_ruby_version}/gems/#{full_gem_name}"
176
- end
177
-
178
- # bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/byebug-9.1.0
179
- # |
180
- # could change
181
- def built_ext_path(full_gem_name)
182
- # infer the path because think 2.5.0-static can probably change
183
- # Note, RUBY_PLATFORM x86_64-darwin17 in a Dir.glob patter does not always
184
- # result in a match
185
- pattern = "#{@build_root}/bundled/gems/ruby/#{minor_ruby_version}/extensions/*/*/#{full_gem_name}"
186
- # path should be something like this:
187
- # tmp/bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/byebug-9.1.0
188
- path = Dir.glob(pattern).first
189
- end
190
-
191
- def specifications_path(full_gem_name)
192
- "#{@build_root}/bundled/gems/ruby/#{minor_ruby_version}/specifications/#{full_gem_name}.gemspec"
193
- end
194
-
195
- def copy_spec(original_path)
196
- full_gem_name = File.basename(original_path, ".gemspec")
197
- new_path = original_path.gsub(%r{.*bundled/}, "bundled/") # strip build_root
198
- new_path = "#{@artifacts_root}/#{full_gem_name}/#{new_path}"
199
- FileUtils.mkdir_p(File.dirname(new_path))
200
- FileUtils.cp(original_path, new_path)
201
- end
202
- end
@@ -1,8 +0,0 @@
1
- module Lambdagem
2
- class Clean < Base
3
- def run
4
- FileUtils.rm_rf("#{@build_root}/downloads")
5
- puts "Cleared out tmp/downloads cache."
6
- end
7
- end
8
- end
@@ -1,62 +0,0 @@
1
- require "thor"
2
-
3
- module Lambdagem
4
-
5
- class CLI < Command
6
- class_option :verbose, type: :boolean
7
- class_option :noop, type: :boolean
8
-
9
- desc "build NAME", "build gem"
10
- long_desc Help.text(:build)
11
- def build(name)
12
- Build.new(name, options).build
13
- end
14
-
15
- desc "package NAME", "package gem into tarball"
16
- long_desc Help.text(:package)
17
- def package(name)
18
- Package.new(name, options).build
19
- end
20
-
21
- desc "upload NAME", "uploads gem to s3"
22
- long_desc Help.text(:upload)
23
- option :s3, required: true, desc: "s3 bucket name"
24
- def upload(name)
25
- Upload.new(name, options).upload
26
- end
27
-
28
- desc "all NAME", "builds, packages and uploads to s3"
29
- long_desc Help.text(:all)
30
- option :s3, required: true, desc: "s3 bucket name"
31
- def all(name)
32
- build(name)
33
- package(name)
34
- upload(name)
35
- end
36
-
37
- extract_options = Proc.new do
38
- option :s3, required: true, desc: "s3 bucket name", default: "lambdagems"
39
- option :clean, type: :boolean, desc: "remove the cache"
40
- end
41
-
42
- desc "extract_gem NAME", "downloads gem from s3 and extracts it"
43
- long_desc Help.text(:extract)
44
- extract_options.call
45
- def extract_gem(name)
46
- Extract::Gem.new(name, options.merge(exit_on_error: true)).run
47
- end
48
-
49
- desc "extract_ruby NAME", "downloads ruby from s3 and extracts it"
50
- long_desc Help.text(:extract_ruby)
51
- extract_options.call
52
- def extract_ruby(name)
53
- Extract::Ruby.new(name, options.merge(exit_on_error: true)).run
54
- end
55
-
56
- desc "clean", "cleans up tmp/downloads cache"
57
- long_desc Help.text(:clean)
58
- def clean
59
- Clean.new(options).run
60
- end
61
- end
62
- end
@@ -1,38 +0,0 @@
1
- require "thor"
2
-
3
- # Override thor's long_desc identation behavior
4
- # https://github.com/erikhuda/thor/issues/398
5
- class Thor
6
- module Shell
7
- class Basic
8
- def print_wrapped(message, options = {})
9
- message = "\n#{message}" unless message[0] == "\n"
10
- stdout.puts message
11
- end
12
- end
13
- end
14
- end
15
-
16
- module Lambdagem
17
- class Command < Thor
18
- class << self
19
- def dispatch(m, args, options, config)
20
- # Allow calling for help via:
21
- # lambdagem command help
22
- # lambdagem command -h
23
- # lambdagem command --help
24
- # lambdagem command -D
25
- #
26
- # as well thor's normal way:
27
- #
28
- # lambdagem help command
29
- help_flags = Thor::HELP_MAPPINGS + ["help"]
30
- if args.length > 1 && !(args & help_flags).empty?
31
- args -= help_flags
32
- args.insert(-2, "help")
33
- end
34
- super
35
- end
36
- end
37
- end
38
- end
@@ -1,50 +0,0 @@
1
- class Lambdagem::Exist < Lambdagem::Base
2
- def initialize(options)
3
- @options = options
4
- end
5
-
6
- # We check all the availability before even downloading so we can provide a
7
- # full list of gems they might want to research all at once instead of incrementally
8
- #
9
- # Examples:
10
- #
11
- # check(single_gem)
12
- # check(list, of, gems)
13
- def check(*gem_names)
14
- gem_names = gem_names.flatten
15
- exists = gem_names.inject({}) do |hash, gem_name|
16
- exist = url_exists?(gem_url(gem_name))
17
- hash[gem_name] = exist
18
- hash.merge(hash)
19
- end
20
-
21
- exists.values.all? {|v| v } # all_exist
22
- end
23
-
24
- # Example url:
25
- # https://gems.lambdagems.com/gems/2.5.0/byebug/byebug-9.1.0-x86_64-linux.tgz
26
- def url_exists?(url)
27
- url = URI.parse(url)
28
- req = Net::HTTP.new(url.host, url.port).tap do |http|
29
- http.use_ssl = true
30
- end
31
- res = req.request_head(url.path)
32
- res.code == "200"
33
- rescue SocketError, OpenURI::HTTPError
34
- false
35
- end
36
-
37
- def lambdagems_url
38
- s3_bucket = @options[:s3] || "lambdagems"
39
- s3_url = "https://s3.amazonaws.com/#{s3_bucket}"
40
- @options[:lambdagems_url] || s3_url
41
- end
42
-
43
- # gem_name: byebug-9.1.0
44
- # Example url:
45
- # https://gems.lambdagems.com/gems/2.5.0/byebug/byebug-9.1.0-x86_64-linux.tgz
46
- def gem_url(gem_name)
47
- folder = gem_name.gsub(/-(\d+\.\d+\.\d+.*)/,'') # folder: byebug
48
- "#{lambdagems_url}/gems/#{jets_ruby_version}/#{folder}/#{gem_name}-x86_64-linux.tgz"
49
- end
50
- end