cocoapods 0.16.4 → 0.17.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +108 -0
- data/README.md +3 -3
- data/bin/pod +1 -1
- data/lib/cocoapods.rb +31 -31
- data/lib/cocoapods/command.rb +62 -107
- data/lib/cocoapods/command/inter_process_communication.rb +103 -0
- data/lib/cocoapods/command/list.rb +45 -44
- data/lib/cocoapods/command/outdated.rb +28 -25
- data/lib/cocoapods/command/project.rb +90 -0
- data/lib/cocoapods/command/push.rb +50 -32
- data/lib/cocoapods/command/repo.rb +125 -155
- data/lib/cocoapods/command/search.rb +23 -12
- data/lib/cocoapods/command/setup.rb +103 -64
- data/lib/cocoapods/command/spec.rb +329 -90
- data/lib/cocoapods/config.rb +197 -44
- data/lib/cocoapods/downloader.rb +47 -34
- data/lib/cocoapods/executable.rb +98 -41
- data/lib/cocoapods/external_sources.rb +325 -0
- data/lib/cocoapods/file_list.rb +8 -1
- data/lib/cocoapods/gem_version.rb +7 -0
- data/lib/cocoapods/generator/acknowledgements.rb +71 -7
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
- data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
- data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
- data/lib/cocoapods/generator/documentation.rb +153 -37
- data/lib/cocoapods/generator/prefix_header.rb +82 -0
- data/lib/cocoapods/generator/target_header.rb +58 -0
- data/lib/cocoapods/generator/xcconfig.rb +130 -0
- data/lib/cocoapods/hooks/installer_representation.rb +123 -0
- data/lib/cocoapods/hooks/library_representation.rb +79 -0
- data/lib/cocoapods/hooks/pod_representation.rb +74 -0
- data/lib/cocoapods/installer.rb +398 -147
- data/lib/cocoapods/installer/analyzer.rb +556 -0
- data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
- data/lib/cocoapods/installer/file_references_installer.rb +179 -0
- data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
- data/lib/cocoapods/installer/target_installer.rb +307 -112
- data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
- data/lib/cocoapods/library.rb +195 -0
- data/lib/cocoapods/open_uri.rb +16 -14
- data/lib/cocoapods/project.rb +175 -52
- data/lib/cocoapods/resolver.rb +151 -164
- data/lib/cocoapods/sandbox.rb +276 -54
- data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
- data/lib/cocoapods/sandbox/headers_store.rb +96 -0
- data/lib/cocoapods/sandbox/path_list.rb +178 -0
- data/lib/cocoapods/sources_manager.rb +218 -0
- data/lib/cocoapods/user_interface.rb +82 -18
- data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
- data/lib/cocoapods/validator.rb +379 -0
- metadata +74 -55
- data/lib/cocoapods/command/install.rb +0 -55
- data/lib/cocoapods/command/linter.rb +0 -317
- data/lib/cocoapods/command/update.rb +0 -25
- data/lib/cocoapods/dependency.rb +0 -285
- data/lib/cocoapods/downloader/git.rb +0 -276
- data/lib/cocoapods/downloader/http.rb +0 -99
- data/lib/cocoapods/downloader/mercurial.rb +0 -26
- data/lib/cocoapods/downloader/subversion.rb +0 -42
- data/lib/cocoapods/local_pod.rb +0 -620
- data/lib/cocoapods/lockfile.rb +0 -274
- data/lib/cocoapods/platform.rb +0 -127
- data/lib/cocoapods/podfile.rb +0 -551
- data/lib/cocoapods/source.rb +0 -223
- data/lib/cocoapods/specification.rb +0 -579
- data/lib/cocoapods/specification/set.rb +0 -175
- data/lib/cocoapods/specification/statistics.rb +0 -112
- data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
- data/lib/cocoapods/version.rb +0 -26
data/lib/cocoapods/config.rb
CHANGED
@@ -1,79 +1,232 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
|
3
1
|
module Pod
|
2
|
+
|
3
|
+
# Stores the global configuration of CocoaPods.
|
4
|
+
#
|
4
5
|
class Config
|
5
|
-
def self.instance
|
6
|
-
@instance ||= new
|
7
|
-
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# The default settings for the configuration.
|
8
|
+
#
|
9
|
+
# Users can specify custom settings in `~/.cocoapods/config.yaml`.
|
10
|
+
# An example of the contents of this file might look like:
|
11
|
+
#
|
12
|
+
# ---
|
13
|
+
# skip_repo_update: true
|
14
|
+
# generate_docs: false
|
15
|
+
# install_docs: false
|
16
|
+
#
|
17
|
+
DEFAULTS = {
|
18
|
+
:verbose => false,
|
19
|
+
:silent => false,
|
20
|
+
:skip_repo_update => false,
|
21
|
+
:aggressive_cache => false,
|
22
|
+
|
23
|
+
:clean => true,
|
24
|
+
:generate_docs => true,
|
25
|
+
:install_docs => true,
|
26
|
+
:integrate_targets => true,
|
27
|
+
:skip_repo_update => true,
|
28
|
+
:new_version_message => true,
|
29
|
+
}
|
30
|
+
|
31
|
+
#--------------------------------------#
|
32
|
+
|
33
|
+
# @!group UI
|
34
|
+
|
35
|
+
# @return [Bool] Whether CocoaPods should provide detailed output about the
|
36
|
+
# performed actions.
|
37
|
+
#
|
38
|
+
attr_accessor :verbose
|
39
|
+
alias_method :verbose?, :verbose
|
40
|
+
|
41
|
+
# @return [Bool] Whether CocoaPods should produce not output.
|
42
|
+
#
|
43
|
+
attr_accessor :silent
|
44
|
+
alias_method :silent?, :silent
|
45
|
+
|
46
|
+
# @return [Bool] Whether the generated documentation should be installed to
|
47
|
+
# Xcode.
|
48
|
+
#
|
49
|
+
attr_accessor :new_version_message
|
50
|
+
alias_method :new_version_message?, :new_version_message
|
51
|
+
|
52
|
+
#--------------------------------------#
|
12
53
|
|
13
|
-
|
14
|
-
|
15
|
-
|
54
|
+
# @!group Installation
|
55
|
+
|
56
|
+
# @return [Bool] Whether the installer should clean after the installation.
|
57
|
+
#
|
58
|
+
attr_accessor :clean
|
59
|
+
alias_method :clean?, :clean
|
60
|
+
|
61
|
+
# @return [Bool] Whether the documentation should be generated for the
|
62
|
+
# installed Pods.
|
63
|
+
#
|
64
|
+
attr_accessor :generate_docs
|
65
|
+
alias_method :generate_docs?, :generate_docs
|
66
|
+
|
67
|
+
# @return [Bool] Whether the generated documentation should be installed to
|
68
|
+
# Xcode.
|
69
|
+
#
|
70
|
+
attr_accessor :install_docs
|
71
|
+
alias_method :install_docs?, :install_docs
|
72
|
+
|
73
|
+
# @return [Bool] Whether CocoaPods should integrate a user target and build
|
74
|
+
# the workspace or just create the Pods project.
|
75
|
+
#
|
16
76
|
attr_accessor :integrate_targets
|
17
|
-
|
77
|
+
alias_method :integrate_targets?, :integrate_targets
|
18
78
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
alias_method
|
24
|
-
|
25
|
-
|
26
|
-
|
79
|
+
|
80
|
+
# @return [Bool] Whether the installer should skip the repos update.
|
81
|
+
#
|
82
|
+
attr_accessor :skip_repo_update
|
83
|
+
alias_method :skip_repo_update?, :skip_repo_update
|
84
|
+
|
85
|
+
# @return [Bool] Whether the downloader should use more aggressive caching
|
86
|
+
# options.
|
87
|
+
#
|
88
|
+
attr_accessor :aggressive_cache
|
89
|
+
alias_method :aggressive_cache?, :aggressive_cache
|
90
|
+
|
91
|
+
#--------------------------------------#
|
92
|
+
|
93
|
+
# @!group Initialization
|
27
94
|
|
28
95
|
def initialize
|
29
|
-
|
30
|
-
|
31
|
-
|
96
|
+
configure_with(DEFAULTS)
|
97
|
+
|
98
|
+
if user_settings_file.exist?
|
99
|
+
require 'yaml'
|
100
|
+
user_settings = YAML.load_file(user_settings_file)
|
101
|
+
configure_with(user_settings)
|
102
|
+
end
|
32
103
|
end
|
33
104
|
|
34
|
-
def
|
35
|
-
@
|
105
|
+
def verbose
|
106
|
+
@verbose && !silent
|
36
107
|
end
|
37
108
|
|
38
|
-
|
39
|
-
|
109
|
+
#--------------------------------------#
|
110
|
+
|
111
|
+
# @!group Paths
|
112
|
+
|
113
|
+
# @return [Pathname] the directory where the CocoaPods sources are stored.
|
114
|
+
#
|
115
|
+
def repos_dir
|
116
|
+
@repos_dir ||= Pathname.new(ENV['HOME'] + "/.cocoapods")
|
40
117
|
end
|
41
118
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@project_podfile
|
119
|
+
attr_writer :repos_dir
|
120
|
+
|
121
|
+
# @return [Pathname] the root of the CocoaPods installation where the
|
122
|
+
# Podfile is located.
|
123
|
+
#
|
124
|
+
def installation_root
|
125
|
+
@installation_root ||= Pathname.pwd
|
50
126
|
end
|
51
127
|
|
52
|
-
|
53
|
-
|
128
|
+
attr_writer :installation_root
|
129
|
+
alias :project_root :installation_root
|
130
|
+
|
131
|
+
# @return [Pathname] The root of the sandbox.
|
132
|
+
#
|
133
|
+
def sandbox_root
|
134
|
+
@sandbox_root ||= installation_root + 'Pods'
|
54
135
|
end
|
55
136
|
|
56
|
-
|
57
|
-
|
137
|
+
attr_writer :sandbox_root
|
138
|
+
alias :project_pods_root :sandbox_root
|
139
|
+
|
140
|
+
# @return [Sandbox] The sandbox of the current project.
|
141
|
+
#
|
142
|
+
def sandbox
|
143
|
+
@sandbox ||= Sandbox.new(sandbox_root)
|
58
144
|
end
|
59
145
|
|
60
146
|
# @return [Podfile] The Podfile to use for the current execution.
|
61
147
|
#
|
62
148
|
def podfile
|
63
|
-
@podfile ||=
|
64
|
-
Podfile.from_file(project_podfile) if project_podfile.exist?
|
65
|
-
end
|
149
|
+
@podfile ||= Podfile.from_file(podfile_path) if podfile_path.exist?
|
66
150
|
end
|
67
151
|
attr_writer :podfile
|
68
152
|
|
69
153
|
# @return [Lockfile] The Lockfile to use for the current execution.
|
70
154
|
#
|
71
155
|
def lockfile
|
72
|
-
@lockfile ||=
|
73
|
-
|
156
|
+
@lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path.exist?
|
157
|
+
end
|
158
|
+
|
159
|
+
#--------------------------------------#
|
160
|
+
|
161
|
+
# @!group Helpers
|
162
|
+
|
163
|
+
# private
|
164
|
+
|
165
|
+
# @return [Pathname] The path of the file which contains the user settings.
|
166
|
+
#
|
167
|
+
def user_settings_file
|
168
|
+
Pathname.new(ENV['HOME'] + "/.cocoapods/config.yaml")
|
169
|
+
end
|
170
|
+
|
171
|
+
# Sets the values of the attributes with the given hash.
|
172
|
+
#
|
173
|
+
# @param [Hash{String,Symbol => Object}] values_by_key
|
174
|
+
# The values of the attributes grouped by key.
|
175
|
+
#
|
176
|
+
# @return [void]
|
177
|
+
#
|
178
|
+
def configure_with(values_by_key)
|
179
|
+
values_by_key.each do |key, value|
|
180
|
+
self.instance_variable_set("@#{key}", value)
|
74
181
|
end
|
75
182
|
end
|
76
183
|
|
184
|
+
# Returns the path of the Podfile.
|
185
|
+
#
|
186
|
+
# @note The Podfile can be named either `CocoaPods.podfile` or `Podfile`.
|
187
|
+
# The first is preferred as it allows to specify an OS X UTI.
|
188
|
+
#
|
189
|
+
def podfile_path
|
190
|
+
unless @podfile_path
|
191
|
+
path = installation_root + 'Podfile.yaml'
|
192
|
+
path = installation_root + 'Podfile' unless path.exist?
|
193
|
+
@podfile_path = path
|
194
|
+
end
|
195
|
+
@podfile_path
|
196
|
+
end
|
197
|
+
|
198
|
+
# Returns the path of the Lockfile.
|
199
|
+
#
|
200
|
+
# @note The Lockfile is named `Podfile.lock`.
|
201
|
+
#
|
202
|
+
def lockfile_path
|
203
|
+
@lockfile_path ||= installation_root + 'Podfile.lock'
|
204
|
+
end
|
205
|
+
|
206
|
+
#--------------------------------------#
|
207
|
+
|
208
|
+
# @return [Config] the current config instance creating one if needed.
|
209
|
+
#
|
210
|
+
def self.instance
|
211
|
+
@instance ||= new
|
212
|
+
end
|
213
|
+
|
214
|
+
# Sets the current config instance. If set to nil the config will be
|
215
|
+
# recreated when needed.
|
216
|
+
#
|
217
|
+
# @param [Config, Nil] the instance.
|
218
|
+
#
|
219
|
+
# @return [void]
|
220
|
+
#
|
221
|
+
def self.instance=(instance)
|
222
|
+
@instance = instance
|
223
|
+
end
|
224
|
+
|
225
|
+
#-------------------------------------------------------------------------#
|
226
|
+
|
227
|
+
# Provides support for accessing the configuration instance in other
|
228
|
+
# scopes.
|
229
|
+
#
|
77
230
|
module Mixin
|
78
231
|
def config
|
79
232
|
Config.instance
|
data/lib/cocoapods/downloader.rb
CHANGED
@@ -1,45 +1,58 @@
|
|
1
|
-
require '
|
1
|
+
require 'cocoapods-downloader'
|
2
2
|
|
3
3
|
module Pod
|
4
|
-
|
5
|
-
|
6
|
-
autoload :GitHub, 'cocoapods/downloader/git'
|
7
|
-
autoload :Mercurial, 'cocoapods/downloader/mercurial'
|
8
|
-
autoload :Subversion, 'cocoapods/downloader/subversion'
|
9
|
-
autoload :Http, 'cocoapods/downloader/http'
|
4
|
+
module Downloader
|
5
|
+
class Base
|
10
6
|
|
11
|
-
|
7
|
+
override_api do
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :target_path, :url, :options
|
9
|
+
def execute_command(executable, command, raise_on_failure = false)
|
10
|
+
Executable.execute_command(executable, command, raise_on_failure)
|
11
|
+
end
|
19
12
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
# Indicates that an action will be performed. The action is passed as a
|
14
|
+
# block.
|
15
|
+
#
|
16
|
+
# @param [String] message
|
17
|
+
# The message associated with the action.
|
18
|
+
#
|
19
|
+
# @yield The action, this block is always executed.
|
20
|
+
#
|
21
|
+
# @return [void]
|
22
|
+
#
|
23
|
+
def ui_action(message)
|
24
|
+
UI.section(" > #{message}", '', 1) do
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
end
|
24
28
|
|
25
|
-
|
29
|
+
# Indicates that a minor action will be performed. The action is passed
|
30
|
+
# as a block.
|
31
|
+
#
|
32
|
+
# @param [String] message
|
33
|
+
# The message associated with the action.
|
34
|
+
#
|
35
|
+
# @yield The action, this block is always executed.
|
36
|
+
#
|
37
|
+
# @return [void]
|
38
|
+
#
|
39
|
+
def ui_sub_action(message)
|
40
|
+
UI.section(" > #{message}", '', 2) do
|
41
|
+
yield
|
42
|
+
end
|
43
|
+
end
|
26
44
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
45
|
+
# Prints an UI message.
|
46
|
+
#
|
47
|
+
# @param [String] message
|
48
|
+
# The message associated with the action.
|
49
|
+
#
|
50
|
+
# @return [void]
|
51
|
+
#
|
52
|
+
def ui_message(message)
|
53
|
+
UI.puts message
|
34
54
|
end
|
35
|
-
|
36
|
-
Mercurial.new(target_path, url, options)
|
37
|
-
elsif url = options.delete(:svn)
|
38
|
-
Subversion.new(target_path, url, options)
|
39
|
-
elsif url = options.delete(:http)
|
40
|
-
Http.new(target_path, url, options)
|
41
|
-
else
|
42
|
-
raise "Unsupported download strategy `#{options.inspect}'."
|
55
|
+
|
43
56
|
end
|
44
57
|
end
|
45
58
|
end
|
data/lib/cocoapods/executable.rb
CHANGED
@@ -1,61 +1,118 @@
|
|
1
|
-
require 'open4'
|
2
|
-
|
3
1
|
module Pod
|
2
|
+
|
3
|
+
# Module which provides support for running executables.
|
4
|
+
#
|
5
|
+
# In a class it can be used as:
|
6
|
+
#
|
7
|
+
# extend Executable
|
8
|
+
# executable :git
|
9
|
+
#
|
10
|
+
# This will create two methods `git` and `git!` both accept a command but
|
11
|
+
# the later will raise on non successful executions. The methods return the
|
12
|
+
# output of the command.
|
13
|
+
#
|
4
14
|
module Executable
|
15
|
+
|
16
|
+
# Creates the methods for the executable with the given name.
|
17
|
+
#
|
18
|
+
# @param [Symbol] name
|
19
|
+
# the name of the executable.
|
20
|
+
#
|
21
|
+
# @return [void]
|
22
|
+
#
|
23
|
+
def executable(name)
|
24
|
+
|
25
|
+
define_method(name) do |command|
|
26
|
+
Executable.execute_command(name, command, false)
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method(name.to_s + "!") do |command|
|
30
|
+
Executable.execute_command(name, command, true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Executes the given command displaying it if in verbose mode.
|
35
|
+
#
|
36
|
+
# @param [String] bin
|
37
|
+
# The binary to use.
|
38
|
+
#
|
39
|
+
# @param [String] command
|
40
|
+
# The command to send to the binary.
|
41
|
+
#
|
42
|
+
# @param [Bool] raise_on_failure
|
43
|
+
# Whether it should raise if the command fails.
|
44
|
+
#
|
45
|
+
# @raise If the executable could not be located.
|
46
|
+
#
|
47
|
+
# @raise If the command fails and the `raise_on_failure` is set to true.
|
48
|
+
#
|
49
|
+
# @return [String] the output of the command (STDOUT and STDERR).
|
50
|
+
#
|
51
|
+
# @todo Find a way to display the live output of the commands.
|
52
|
+
#
|
53
|
+
def self.execute_command(executable, command, raise_on_failure)
|
54
|
+
|
55
|
+
bin = `which #{executable}`.strip
|
56
|
+
raise Informative, "Unable to locate the executable `#{executable}`" if bin.empty?
|
57
|
+
|
58
|
+
require 'open4'
|
59
|
+
|
60
|
+
full_command = "#{bin} #{command}"
|
61
|
+
|
62
|
+
if Config.instance.verbose?
|
63
|
+
UI.message("$ #{full_command}")
|
64
|
+
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
|
65
|
+
else
|
66
|
+
stdout, stderr = Indenter.new, Indenter.new
|
67
|
+
end
|
68
|
+
|
69
|
+
options = {:stdout => stdout, :stderr => stderr, :status => true}
|
70
|
+
status = Open4.spawn(full_command, options)
|
71
|
+
output = stdout.join("\n") + stderr.join("\n")
|
72
|
+
unless status.success?
|
73
|
+
if raise_on_failure
|
74
|
+
raise Informative, "#{name} #{command}\n\n#{output}"
|
75
|
+
else
|
76
|
+
UI.message("[!] Failed: #{full_command}".red)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
output
|
80
|
+
end
|
81
|
+
|
82
|
+
#-------------------------------------------------------------------------#
|
83
|
+
|
84
|
+
# Helper class that allows to write to an {IO} instance taking into account
|
85
|
+
# the UI indentation lever.
|
86
|
+
#
|
5
87
|
class Indenter < ::Array
|
6
|
-
include Config::Mixin
|
7
88
|
|
89
|
+
# @return [Fixnum] The indentation level of the UI.
|
90
|
+
#
|
8
91
|
attr_accessor :indent
|
92
|
+
|
93
|
+
# @return [IO] the {IO} to which the output should be printed.
|
94
|
+
#
|
9
95
|
attr_accessor :io
|
10
96
|
|
97
|
+
# @param [IO] io @see io
|
98
|
+
#
|
11
99
|
def initialize(io = nil)
|
12
100
|
@io = io
|
13
101
|
@indent = ' ' * UI.indentation_level
|
14
102
|
end
|
15
103
|
|
104
|
+
# Stores a portion of the output and prints it to the {IO} instance.
|
105
|
+
#
|
106
|
+
# @param [String] value
|
107
|
+
# the output to print.
|
108
|
+
#
|
109
|
+
# @return [void]
|
110
|
+
#
|
16
111
|
def <<(value)
|
17
112
|
super
|
18
113
|
ensure
|
19
114
|
@io << "#{ indent }#{ value }" if @io
|
20
115
|
end
|
21
116
|
end
|
22
|
-
|
23
|
-
def executable(name)
|
24
|
-
bin = `which #{name}`.strip
|
25
|
-
base_method = "base_" << name.to_s
|
26
|
-
define_method(base_method) do |command, should_raise|
|
27
|
-
if bin.empty?
|
28
|
-
raise Informative, "Unable to locate the executable `#{name}'"
|
29
|
-
end
|
30
|
-
full_command = "#{bin} #{command}"
|
31
|
-
if Config.instance.verbose?
|
32
|
-
UI.message("$ #{full_command}")
|
33
|
-
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
|
34
|
-
else
|
35
|
-
stdout, stderr = Indenter.new, Indenter.new
|
36
|
-
end
|
37
|
-
status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
|
38
|
-
|
39
|
-
output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
|
40
|
-
unless status.success?
|
41
|
-
if should_raise
|
42
|
-
raise Informative, "#{name} #{command}\n\n#{output}"
|
43
|
-
else
|
44
|
-
UI.message("[!] Failed: #{full_command}".red)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
output
|
48
|
-
end
|
49
|
-
|
50
|
-
define_method(name) do |command|
|
51
|
-
send(base_method, command, false)
|
52
|
-
end
|
53
|
-
|
54
|
-
define_method(name.to_s + "!") do |command|
|
55
|
-
send(base_method, command, true)
|
56
|
-
end
|
57
|
-
|
58
|
-
private name
|
59
|
-
end
|
60
117
|
end
|
61
118
|
end
|