rubygems-requirements-system 0.0.1

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 (32) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +141 -0
  3. data/Rakefile +35 -0
  4. data/doc/text/gpl-3.txt +674 -0
  5. data/doc/text/lgpl-3.txt +165 -0
  6. data/doc/text/news.md +5 -0
  7. data/lib/rubygems-requirements-system/executable-finder.rb +87 -0
  8. data/lib/rubygems-requirements-system/installer.rb +122 -0
  9. data/lib/rubygems-requirements-system/os-release.rb +59 -0
  10. data/lib/rubygems-requirements-system/package.rb +17 -0
  11. data/lib/rubygems-requirements-system/platform/alpine-linux.rb +44 -0
  12. data/lib/rubygems-requirements-system/platform/alt-linux.rb +52 -0
  13. data/lib/rubygems-requirements-system/platform/amazon-linux-2.rb +50 -0
  14. data/lib/rubygems-requirements-system/platform/amazon-linux-2023.rb +40 -0
  15. data/lib/rubygems-requirements-system/platform/arch-linux.rb +43 -0
  16. data/lib/rubygems-requirements-system/platform/base.rb +135 -0
  17. data/lib/rubygems-requirements-system/platform/conda.rb +43 -0
  18. data/lib/rubygems-requirements-system/platform/debian.rb +67 -0
  19. data/lib/rubygems-requirements-system/platform/fedora.rb +44 -0
  20. data/lib/rubygems-requirements-system/platform/freebsd.rb +43 -0
  21. data/lib/rubygems-requirements-system/platform/gentoo-linux.rb +50 -0
  22. data/lib/rubygems-requirements-system/platform/homebrew.rb +43 -0
  23. data/lib/rubygems-requirements-system/platform/macports.rb +43 -0
  24. data/lib/rubygems-requirements-system/platform/pld-linux.rb +43 -0
  25. data/lib/rubygems-requirements-system/platform/red-hat-enterprise-linux.rb +67 -0
  26. data/lib/rubygems-requirements-system/platform/suse.rb +51 -0
  27. data/lib/rubygems-requirements-system/platform/ubuntu.rb +41 -0
  28. data/lib/rubygems-requirements-system/platform/unknown.rb +31 -0
  29. data/lib/rubygems-requirements-system/platform.rb +72 -0
  30. data/lib/rubygems-requirements-system/version.rb +18 -0
  31. data/lib/rubygems_plugin.rb +21 -0
  32. metadata +94 -0
@@ -0,0 +1,135 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "fileutils"
17
+
18
+ require_relative "../executable-finder"
19
+ require_relative "../os-release"
20
+
21
+ module RubyGemsRequirementsSystem
22
+ module Platform
23
+ class Base
24
+ include Gem::UserInteraction
25
+
26
+ def target?(platform)
27
+ raise NotImpelementedError
28
+ end
29
+
30
+ def default_system_packages(packages)
31
+ nil
32
+ end
33
+
34
+ def install(requirement)
35
+ synchronize do
36
+ requirement.system_packages.any? do |package|
37
+ install_package(package) and requirement.satisfied?
38
+ end
39
+ end
40
+ end
41
+
42
+ private
43
+ def sudo
44
+ if have_priviledge?
45
+ nil
46
+ else
47
+ @sudo ||= ExecutableFinder.find("sudo")
48
+ end
49
+ end
50
+
51
+ def synchronize
52
+ if Gem.respond_to?(:state_home)
53
+ state_home = Gem.state_home
54
+ else
55
+ state_home =
56
+ ENV["XDG_STATE_HOME"] ||
57
+ File.join(Gem.user_home, ".local", "state")
58
+ end
59
+ lock_file_path = File.join(state_home,
60
+ "gem",
61
+ "requirements_system_lock")
62
+ FileUtils.mkdir_p(File.dirname(lock_file_path))
63
+ File.open(lock_file_path, "w") do |lock_file|
64
+ lock_file.flock(File::LOCK_EX)
65
+ yield
66
+ end
67
+ end
68
+
69
+ def super_user?
70
+ Process.uid.zero?
71
+ end
72
+
73
+ def need_super_user_priviledge?
74
+ raise NotImpelementedError
75
+ end
76
+
77
+ def have_priviledge?
78
+ return true unless need_super_user_priviledge?
79
+ super_user?
80
+ end
81
+
82
+ def install_package(package)
83
+ command_line = prepare_command_line(package)
84
+ if command_line
85
+ unless run_command_line(package, "prepare", command_line)
86
+ return false
87
+ end
88
+ end
89
+ run_command_line(package, "install", install_command_line(package))
90
+ end
91
+
92
+ def run_command_line(package, action, command_line)
93
+ failed_to_get_super_user_priviledge = false
94
+ command_line = install_command_line(package)
95
+ if have_priviledge?
96
+ succeeded = system(*command_line)
97
+ else
98
+ if sudo
99
+ prompt = "[sudo] password for %u to #{action} <#{package}>: "
100
+ command_line = [sudo, "-p", prompt, *command_line]
101
+ succeeded = system(*command_line)
102
+ else
103
+ succeeded = false
104
+ failed_to_get_super_user_priviledge = true
105
+ end
106
+ end
107
+ if failed_to_get_super_user_priviledge
108
+ result_message = "require super user privilege"
109
+ else
110
+ result_message = succeeded ? "succeeded" : "failed"
111
+ end
112
+ say("#{action.capitalize} '#{package}' system package: #{result_message}")
113
+
114
+ unless succeeded
115
+ escaped_command_line = command_line.collect do |part|
116
+ Shellwords.escape(part)
117
+ end
118
+ alert_warning("'#{package}' system package is required.")
119
+ alert_warning("Run the following command " +
120
+ "to #{action} required system package: " +
121
+ escaped_command.join(" "))
122
+ end
123
+ succeeded
124
+ end
125
+
126
+ def prepare_command_line(package)
127
+ nil
128
+ end
129
+
130
+ def install_command_line(package)
131
+ raise NotImpelementedError
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (C) 2023-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class Conda < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ ENV["CONDA_PREFIX"] && ExecutableFinder.exist?("conda")
26
+ end
27
+ end
28
+
29
+ def target?(platform)
30
+ platform == "conda"
31
+ end
32
+
33
+ private
34
+ def install_command_line(package)
35
+ ["conda", "install", "-c", "conda-forge", "-y", package]
36
+ end
37
+
38
+ def need_super_user_priviledge?
39
+ false
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,67 @@
1
+ # Copyright (C) 2013-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class Debian < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ case os_release.id
27
+ when "debian", "raspbian"
28
+ return true
29
+ else
30
+ return true if os_release.id_like.include?("debian")
31
+ end
32
+ false
33
+ end
34
+ end
35
+
36
+ def target?(platform)
37
+ case platform
38
+ when "debian", "raspbian"
39
+ true
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ private
46
+ def prepare_command_line(package)
47
+ ["apt-get", "update"]
48
+ end
49
+
50
+ def install_command_line(package)
51
+ [
52
+ "env",
53
+ "DEBIAN_FRONTEND=noninteractive",
54
+ "apt-get",
55
+ "install",
56
+ "-V",
57
+ "-y",
58
+ package,
59
+ ]
60
+ end
61
+
62
+ def need_super_user_priviledge?
63
+ true
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,44 @@
1
+ # Copyright (C) 2021-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "red-hat-enterprise-linux"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class Fedora < RedHatEnterpriseLinux
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ os_release.id == "fedora" or os_release.id_like.include?("fedora")
27
+ end
28
+ end
29
+
30
+ def target?(platform)
31
+ platform == "fedora" || super
32
+ end
33
+
34
+ private
35
+ def install_command_line(package)
36
+ ["dnf", "install", "-y", package]
37
+ end
38
+
39
+ def need_super_user_priviledge?
40
+ true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class FreeBSD < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ ExecutableFinder.exist?("pkg")
26
+ end
27
+ end
28
+
29
+ def target?(platform)
30
+ platform == "freebsd"
31
+ end
32
+
33
+ private
34
+ def install_command_line(package)
35
+ ["pkg", "install", "-y", package]
36
+ end
37
+
38
+ def need_super_user_priviledge?
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (C) 2022-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class GentooLinux < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ case os_release.id
27
+ when "gentoo"
28
+ return true
29
+ else
30
+ return true if os_release.id_like.include?("gentoo")
31
+ end
32
+ false
33
+ end
34
+ end
35
+
36
+ def target?(platform)
37
+ platform == "gentoo_linux"
38
+ end
39
+
40
+ private
41
+ def install_command_line(package)
42
+ ["emerge", "--getbinpkg", "--usepkg", package]
43
+ end
44
+
45
+ def need_super_user_priviledge?
46
+ true
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class Homebrew < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ ExecutableFinder.exist?("brew")
26
+ end
27
+ end
28
+
29
+ def target?(platform)
30
+ platform == "homebrew"
31
+ end
32
+
33
+ private
34
+ def install_command_line(package)
35
+ ["brew", "install", package]
36
+ end
37
+
38
+ def need_super_user_priviledge?
39
+ false
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class MacPorts < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ ExecutableFinder.exist?("port")
26
+ end
27
+ end
28
+
29
+ def target?(platform)
30
+ platform == "macports"
31
+ end
32
+
33
+ private
34
+ def install_command_line(package)
35
+ ["port", "install", "-y", package]
36
+ end
37
+
38
+ def need_super_user_priviledge?
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class PLDLinux < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ ExecutableFinder.exist?("poldek")
26
+ end
27
+ end
28
+
29
+ def target?(platform)
30
+ platform == "pld_linux"
31
+ end
32
+
33
+ private
34
+ def install_command_line(package)
35
+ ["poldek", "--up", "-u", package]
36
+ end
37
+
38
+ def need_super_user_priviledge?
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,67 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class RedHatEnterpriseLinux < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ os_release.id_like.include?("rhel")
27
+ end
28
+ end
29
+
30
+ def target?(platform)
31
+ case platform
32
+ when "rhel"
33
+ true
34
+ when "redhat" # For backward compatibility
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+ def default_system_packages(packages)
42
+ packages.collect {|package| "pkgconfig(#{package.id})"}
43
+ end
44
+
45
+ private
46
+
47
+ def install_command_line(package)
48
+ if major_version >= 9
49
+ ["dnf", "install", "--enablerepo=crb", "-y", package]
50
+ elsif major_version >= 8
51
+ ["dnf", "install", "--enablerepo=powertools", "-y", package]
52
+ else
53
+ ["yum", "install", "-y", package]
54
+ end
55
+ end
56
+
57
+ def need_super_user_priviledge?
58
+ true
59
+ end
60
+
61
+ def major_version
62
+ major_version_string = File.read("/etc/redhat-release")[/(\d+)/, 0]
63
+ Integer(major_version_string, 10)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (C) 2017-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "base"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class SUSE < Base
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ os_release.id_like.include?("suse")
27
+ end
28
+ end
29
+
30
+ def target?(platform)
31
+ case platform
32
+ when "suse"
33
+ true
34
+ when "fedora", "rhel", "redhat"
35
+ true # Most packages have the same name with Fedora/RHEL's one
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+ private
42
+ def install_command_line(package)
43
+ ["zypper", "--non-interactive", "install", package]
44
+ end
45
+
46
+ def need_super_user_priviledge?
47
+ true
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright (C) 2021-2025 Ruby-GNOME Project Team
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require_relative "debian"
17
+
18
+ module RubyGemsRequirementsSystem
19
+ module Platform
20
+ class Ubuntu < Debian
21
+ Platform.register(self)
22
+
23
+ class << self
24
+ def current_platform?
25
+ os_release = OSRelease.new
26
+ case os_release.id
27
+ when "ubuntu"
28
+ return true
29
+ else
30
+ return true if os_release.id_like.include?("ubuntu")
31
+ end
32
+ false
33
+ end
34
+ end
35
+
36
+ def target?(platform)
37
+ platform == "ubuntu" || super
38
+ end
39
+ end
40
+ end
41
+ end