machinery-tool 1.22.1 → 1.22.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.git_revision +1 -1
- data/NEWS +10 -0
- data/bin/machinery +1 -1
- data/lib/analyze_changed_config_files_diffs_task.rb +6 -6
- data/lib/autoyast.rb +2 -2
- data/lib/build_task.rb +10 -7
- data/lib/cli.rb +1005 -801
- data/lib/compare_task.rb +11 -7
- data/lib/comparison.rb +2 -2
- data/lib/config_base.rb +1 -1
- data/lib/config_task.rb +1 -1
- data/lib/containerize_task.rb +3 -3
- data/lib/containerized_app.rb +1 -1
- data/lib/copy_task.rb +1 -1
- data/lib/current_user.rb +1 -1
- data/lib/deploy_task.rb +6 -4
- data/lib/diff_widget.rb +67 -63
- data/lib/docker_system.rb +12 -8
- data/lib/dpkg_database.rb +1 -1
- data/lib/element_filter.rb +7 -4
- data/lib/exceptions.rb +23 -5
- data/lib/export_task.rb +1 -1
- data/lib/exporter.rb +1 -1
- data/lib/file_diff.rb +1 -1
- data/lib/file_scope.rb +1 -1
- data/lib/file_validator.rb +7 -4
- data/lib/filter.rb +97 -93
- data/lib/filter_option_parser.rb +2 -2
- data/lib/hint.rb +64 -59
- data/lib/html.rb +1 -1
- data/lib/inspect_task.rb +12 -12
- data/lib/inspector.rb +3 -3
- data/lib/json_validation_error_cleaner.rb +1 -1
- data/lib/json_validator.rb +4 -4
- data/lib/kiwi_config.rb +8 -4
- data/lib/list_task.rb +10 -9
- data/lib/local_system.rb +11 -5
- data/lib/logged_cheetah.rb +1 -1
- data/lib/man_task.rb +10 -6
- data/lib/managed_files_database.rb +1 -1
- data/lib/manifest.rb +5 -5
- data/lib/migration.rb +16 -10
- data/lib/mountpoints.rb +1 -1
- data/lib/move_task.rb +1 -1
- data/lib/remote_system.rb +7 -7
- data/lib/remove_task.rb +1 -1
- data/lib/renderer.rb +177 -172
- data/lib/rpm.rb +4 -4
- data/lib/rpm_database.rb +1 -1
- data/lib/scope.rb +2 -2
- data/lib/scope_file_access_archive.rb +1 -1
- data/lib/scope_file_access_flat.rb +1 -1
- data/lib/scope_file_store.rb +1 -1
- data/lib/serve_html_task.rb +6 -2
- data/lib/server.rb +19 -12
- data/lib/show_task.rb +10 -6
- data/lib/static_html.rb +1 -1
- data/lib/system.rb +10 -10
- data/lib/system_description.rb +14 -13
- data/lib/system_description_memory_store.rb +1 -1
- data/lib/system_description_store.rb +9 -9
- data/lib/tarball.rb +8 -2
- data/lib/upgrade_format_task.rb +11 -6
- data/lib/validate_task.rb +2 -2
- data/lib/version.rb +1 -1
- data/lib/workload_mapper.rb +2 -2
- data/lib/workload_mapper_dsl.rb +1 -1
- data/lib/zypper.rb +40 -17
- data/machinery-helper/machinery_helper.go +35 -16
- data/machinery-helper/version.go +1 -1
- data/man/generated/machinery.1.gz +0 -0
- data/manual/site/sitemap.xml +24 -24
- data/plugins/changed_config_files/changed_config_files_inspector.rb +59 -56
- data/plugins/changed_config_files/changed_config_files_model.rb +23 -21
- data/plugins/changed_config_files/changed_config_files_renderer.rb +56 -52
- data/plugins/changed_managed_files/changed_managed_files_inspector.rb +52 -50
- data/plugins/changed_managed_files/changed_managed_files_model.rb +23 -21
- data/plugins/changed_managed_files/changed_managed_files_renderer.rb +43 -39
- data/plugins/environment/environment_inspector.rb +25 -23
- data/plugins/environment/environment_model.rb +5 -3
- data/plugins/groups/groups_inspector.rb +30 -28
- data/plugins/groups/groups_model.rb +18 -17
- data/plugins/groups/groups_renderer.rb +29 -25
- data/plugins/os/os_inspector.rb +120 -118
- data/plugins/os/os_model.rb +139 -134
- data/plugins/os/os_renderer.rb +13 -9
- data/plugins/packages/packages_inspector.rb +99 -86
- data/plugins/packages/packages_model.rb +35 -34
- data/plugins/packages/packages_renderer.rb +47 -39
- data/plugins/patterns/patterns_inspector.rb +70 -68
- data/plugins/patterns/patterns_model.rb +19 -18
- data/plugins/patterns/patterns_renderer.rb +36 -32
- data/plugins/repositories/repositories_inspector.rb +162 -156
- data/plugins/repositories/repositories_model.rb +50 -49
- data/plugins/repositories/repositories_renderer.rb +48 -44
- data/plugins/repositories/schema/system-description-repositories.schema-v10.json +0 -1
- data/plugins/services/services_inspector.rb +187 -176
- data/plugins/services/services_model.rb +37 -36
- data/plugins/services/services_renderer.rb +28 -24
- data/plugins/unmanaged_files/unmanaged_files_inspector.rb +102 -99
- data/plugins/unmanaged_files/unmanaged_files_model.rb +64 -56
- data/plugins/unmanaged_files/unmanaged_files_renderer.rb +44 -40
- data/plugins/users/users_inspector.rb +67 -65
- data/plugins/users/users_model.rb +37 -36
- data/plugins/users/users_renderer.rb +31 -27
- data/schema/migrations/migrate1to2.rb +1 -1
- data/schema/migrations/migrate2to3.rb +1 -1
- data/schema/migrations/migrate3to4.rb +1 -1
- data/schema/migrations/migrate4to5.rb +1 -1
- data/schema/migrations/migrate5to6.rb +1 -1
- data/schema/migrations/migrate6to7.rb +1 -1
- data/schema/migrations/migrate7to8.rb +1 -1
- data/schema/migrations/migrate8to9.rb +1 -1
- data/schema/migrations/migrate9to10.rb +1 -1
- metadata +2 -2
data/lib/mountpoints.rb
CHANGED
@@ -31,7 +31,7 @@
|
|
31
31
|
# local file systems with permanent data (e.g. ext3, btrfs, xfs)
|
32
32
|
|
33
33
|
|
34
|
-
class MountPoints
|
34
|
+
class Machinery::MountPoints
|
35
35
|
attr_reader :mounts
|
36
36
|
REMOTE_FILE_SYSTEMS = ["autofs", "cifs", "nfs", "nfs4"]
|
37
37
|
SPECIAL_FILE_SYSTEMS = ["proc", "sysfs", "devtmpfs", "tmpfs", "fuse.gvfs-fuse-daemon"]
|
data/lib/move_task.rb
CHANGED
data/lib/remote_system.rb
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
# To contact SUSE about this file by physical or electronic mail,
|
16
16
|
# you may find current contact information at www.suse.com
|
17
17
|
|
18
|
-
class RemoteSystem < System
|
18
|
+
class Machinery::RemoteSystem < Machinery::System
|
19
19
|
attr_reader :host, :remote_user, :ssh_port, :ssh_identity_file
|
20
20
|
|
21
21
|
def type
|
@@ -85,7 +85,7 @@ class RemoteSystem < System
|
|
85
85
|
if options[:disable_logging]
|
86
86
|
cheetah_class = Cheetah
|
87
87
|
else
|
88
|
-
cheetah_class = LoggedCheetah
|
88
|
+
cheetah_class = Machinery::LoggedCheetah
|
89
89
|
end
|
90
90
|
|
91
91
|
sudo = ["sudo", "-n"] if options[:privileged] && sudo_required?
|
@@ -120,7 +120,7 @@ class RemoteSystem < System
|
|
120
120
|
stdin: filelist.join("\n")
|
121
121
|
]
|
122
122
|
begin
|
123
|
-
LoggedCheetah.run(*cmd)
|
123
|
+
Machinery::LoggedCheetah.run(*cmd)
|
124
124
|
rescue Cheetah::ExecutionFailed => e
|
125
125
|
raise Machinery::Errors::RsyncFailed.new(
|
126
126
|
"Could not rsync files from host '#{host}'.\n" \
|
@@ -130,7 +130,7 @@ class RemoteSystem < System
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def check_retrieve_files_dependencies
|
133
|
-
LocalSystem.validate_existence_of_command("rsync", "rsync")
|
133
|
+
Machinery::LocalSystem.validate_existence_of_command("rsync", "rsync")
|
134
134
|
check_requirement("rsync", "--version")
|
135
135
|
end
|
136
136
|
|
@@ -161,7 +161,7 @@ class RemoteSystem < System
|
|
161
161
|
]
|
162
162
|
|
163
163
|
begin
|
164
|
-
LoggedCheetah.run(*cmd)
|
164
|
+
Machinery::LoggedCheetah.run(*cmd)
|
165
165
|
rescue Cheetah::ExecutionFailed => e
|
166
166
|
raise Machinery::Errors::InjectFileFailed.new(
|
167
167
|
"Could not inject file '#{source}' to host '#{host}'.\nError: #{e}"
|
@@ -187,7 +187,7 @@ class RemoteSystem < System
|
|
187
187
|
# Tries to run the noop-command(:) on the remote system as root (without a password or passphrase)
|
188
188
|
# and raises an Machinery::Errors::SshConnectionFailed exception when it's not successful.
|
189
189
|
def check_connection
|
190
|
-
LoggedCheetah.run(*build_command(:ssh), "-q", "-o", "BatchMode=yes",
|
190
|
+
Machinery::LoggedCheetah.run(*build_command(:ssh), "-q", "-o", "BatchMode=yes",
|
191
191
|
"#{remote_user}@#{host}", ":")
|
192
192
|
rescue Cheetah::ExecutionFailed
|
193
193
|
raise Machinery::Errors::SshConnectionFailed.new(
|
@@ -200,7 +200,7 @@ class RemoteSystem < System
|
|
200
200
|
|
201
201
|
def check_sudo
|
202
202
|
check_requirement("sudo", "-h")
|
203
|
-
LoggedCheetah.run(*build_command(:ssh), "-q", "-o", "BatchMode=yes",
|
203
|
+
Machinery::LoggedCheetah.run(*build_command(:ssh), "-q", "-o", "BatchMode=yes",
|
204
204
|
"#{remote_user}@#{host}", "sudo", "id")
|
205
205
|
rescue Cheetah::ExecutionFailed => e
|
206
206
|
if e.stderr && e.stderr.include?("password is required")
|
data/lib/remove_task.rb
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
# To contact SUSE about this file by physical or electronic mail,
|
16
16
|
# you may find current contact information at www.suse.com
|
17
17
|
|
18
|
-
class RemoveTask
|
18
|
+
class Machinery::RemoveTask
|
19
19
|
def remove(store, names, options = {})
|
20
20
|
if options[:all]
|
21
21
|
removed_descriptions = store.list
|
data/lib/renderer.rb
CHANGED
@@ -48,7 +48,7 @@
|
|
48
48
|
#
|
49
49
|
# Accordingly a simple renderer for the "packages" scope could look like this:
|
50
50
|
#
|
51
|
-
# class PackagesRenderer < Renderer
|
51
|
+
# class PackagesRenderer < Machinery::Ui::Renderer
|
52
52
|
# def content(description)
|
53
53
|
# return if description.packages.empty?
|
54
54
|
#
|
@@ -59,216 +59,221 @@
|
|
59
59
|
# end
|
60
60
|
# end
|
61
61
|
# end
|
62
|
-
|
62
|
+
module Machinery
|
63
|
+
class Ui
|
64
|
+
class Renderer
|
63
65
|
|
64
|
-
|
66
|
+
class InvalidStructureError < StandardError; end
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
+
attr_accessor :system_description
|
69
|
+
attr_accessor :buffer
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
+
abstract_method :content
|
72
|
+
abstract_method :compare_content_changed
|
71
73
|
|
72
|
-
|
74
|
+
@@renderers = []
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
class << self
|
77
|
+
def inherited(klass)
|
78
|
+
@@renderers << klass
|
79
|
+
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
def all
|
82
|
+
@@renderers.map(&:new)
|
83
|
+
end
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
+
def for(scope)
|
86
|
+
class_name = "Machinery::Ui::#{scope.split("_").map(&:capitalize).join}Renderer"
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
+
begin
|
89
|
+
Object.const_get(class_name).new
|
90
|
+
rescue NameError
|
91
|
+
end
|
92
|
+
end
|
88
93
|
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def scope
|
93
|
-
# Return the un-camelcased name of the inspector,
|
94
|
-
# e.g. "foo_bar" for "FooBarInspector"
|
95
|
-
scope = self.class.name.match(/^(.*)Renderer$/)[1]
|
96
|
-
scope.gsub(/([^A-Z])([A-Z])/, "\\1_\\2").downcase
|
97
|
-
end
|
98
94
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
@stack = []
|
105
|
-
|
106
|
-
if system_description[scope]
|
107
|
-
header = display_name
|
108
|
-
meta = system_description[scope].meta
|
109
|
-
|
110
|
-
if meta
|
111
|
-
header += " [#{meta.hostname}]"
|
112
|
-
date = Time.parse(meta.modified).localtime
|
113
|
-
date_human = date.strftime "%Y-%m-%d %H:%M:%S"
|
114
|
-
header += " (#{date_human})"
|
95
|
+
def scope
|
96
|
+
# Return the un-camelcased name of the inspector,
|
97
|
+
# e.g. "foo_bar" for "FooBarInspector"
|
98
|
+
scope = self.class.name.match(/^Machinery::Ui::(.*)Renderer$/)[1]
|
99
|
+
scope.gsub(/([^A-Z])([A-Z])/, "\\1_\\2").downcase
|
115
100
|
end
|
116
101
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
@buffer
|
125
|
-
end
|
126
|
-
|
127
|
-
# Renders the result of a comparison of two system descriptions.
|
128
|
-
def render_comparison(comparison, options = {})
|
129
|
-
@options = options
|
130
|
-
@buffer = ""
|
131
|
-
@indent = 0
|
132
|
-
@stack = []
|
133
|
-
|
134
|
-
show_heading = if options[:show_all]
|
135
|
-
comparison.only_in1 || comparison.only_in2 || comparison.changed || comparison.common
|
136
|
-
else
|
137
|
-
comparison.only_in1 || comparison.only_in2 || comparison.changed
|
138
|
-
end
|
139
|
-
|
140
|
-
heading(display_name) if show_heading
|
102
|
+
# Renders one system description using the specialized `content` method
|
103
|
+
def render(system_description, options = {})
|
104
|
+
@options = options
|
105
|
+
@buffer = ""
|
106
|
+
@indent = 2
|
107
|
+
@stack = []
|
141
108
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
render_comparison_common(comparison.as_description(:common)) if @options[:show_all]
|
146
|
-
@buffer
|
147
|
-
end
|
109
|
+
if system_description[scope]
|
110
|
+
header = display_name
|
111
|
+
meta = system_description[scope].meta
|
148
112
|
|
149
|
-
|
150
|
-
|
113
|
+
if meta
|
114
|
+
header += " [#{meta.hostname}]"
|
115
|
+
date = Time.parse(meta.modified).localtime
|
116
|
+
date_human = date.strftime "%Y-%m-%d %H:%M:%S"
|
117
|
+
header += " (#{date_human})"
|
118
|
+
end
|
151
119
|
|
152
|
-
|
153
|
-
|
154
|
-
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
155
|
-
end
|
120
|
+
heading(header)
|
121
|
+
end
|
156
122
|
|
157
|
-
|
158
|
-
puts "In both with different attributes ('#{comparison.name1}' <> '#{comparison.name2}'):"
|
159
|
-
indent { compare_content_changed(comparison.changed) }
|
160
|
-
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
161
|
-
end
|
123
|
+
content(system_description)
|
162
124
|
|
163
|
-
|
164
|
-
return unless description[scope]
|
125
|
+
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
165
126
|
|
166
|
-
|
167
|
-
|
168
|
-
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
169
|
-
end
|
127
|
+
@buffer
|
128
|
+
end
|
170
129
|
|
171
|
-
|
172
|
-
|
173
|
-
|
130
|
+
# Renders the result of a comparison of two system descriptions.
|
131
|
+
def render_comparison(comparison, options = {})
|
132
|
+
@options = options
|
133
|
+
@buffer = ""
|
134
|
+
@indent = 0
|
135
|
+
@stack = []
|
136
|
+
|
137
|
+
show_heading = if options[:show_all]
|
138
|
+
comparison.only_in1 || comparison.only_in2 || comparison.changed || comparison.common
|
139
|
+
else
|
140
|
+
comparison.only_in1 || comparison.only_in2 || comparison.changed
|
141
|
+
end
|
142
|
+
|
143
|
+
heading(display_name) if show_heading
|
144
|
+
|
145
|
+
render_comparison_only_in(comparison.as_description(:one))
|
146
|
+
render_comparison_only_in(comparison.as_description(:two))
|
147
|
+
render_comparison_changed(comparison) if comparison.changed
|
148
|
+
render_comparison_common(comparison.as_description(:common)) if @options[:show_all]
|
149
|
+
@buffer
|
150
|
+
end
|
174
151
|
|
175
|
-
|
176
|
-
|
177
|
-
end
|
152
|
+
def render_comparison_only_in(description)
|
153
|
+
return if !description[scope] || description[scope].elements.try(:empty?)
|
178
154
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
missing_descriptions = Array.new
|
155
|
+
puts "Only in '#{description.name}':"
|
156
|
+
indent { compare_content_only_in(description) }
|
157
|
+
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
158
|
+
end
|
184
159
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
end
|
160
|
+
def render_comparison_changed(comparison)
|
161
|
+
puts "In both with different attributes ('#{comparison.name1}' <> '#{comparison.name2}'):"
|
162
|
+
indent { compare_content_changed(comparison.changed) }
|
163
|
+
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
164
|
+
end
|
191
165
|
|
192
|
-
|
193
|
-
|
194
|
-
indent { puts "Unable to compare, no data in '#{missing_descriptions.join("', '")}'" }
|
195
|
-
end
|
196
|
-
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
166
|
+
def render_comparison_common(description)
|
167
|
+
return unless description[scope]
|
197
168
|
|
198
|
-
|
199
|
-
|
169
|
+
puts "Common to both systems:"
|
170
|
+
indent { compare_content_common(description) }
|
171
|
+
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
172
|
+
end
|
200
173
|
|
201
|
-
|
174
|
+
def compare_content_only_in(description)
|
175
|
+
content(description)
|
176
|
+
end
|
202
177
|
|
203
|
-
|
204
|
-
|
205
|
-
|
178
|
+
def compare_content_common(description)
|
179
|
+
content(description)
|
180
|
+
end
|
206
181
|
|
207
|
-
|
208
|
-
|
209
|
-
|
182
|
+
def render_comparison_missing_scope(description1, description2)
|
183
|
+
@buffer = ""
|
184
|
+
@indent = 0
|
185
|
+
@stack = []
|
186
|
+
missing_descriptions = Array.new
|
187
|
+
|
188
|
+
unless description1[scope]
|
189
|
+
missing_descriptions << description1.name
|
190
|
+
end
|
191
|
+
unless description2[scope]
|
192
|
+
missing_descriptions << description2.name
|
193
|
+
end
|
194
|
+
|
195
|
+
if missing_descriptions.count == 1
|
196
|
+
@buffer += "# #{display_name}\n"
|
197
|
+
indent { puts "Unable to compare, no data in '#{missing_descriptions.join("', '")}'" }
|
198
|
+
end
|
199
|
+
@buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
|
200
|
+
|
201
|
+
@buffer
|
202
|
+
end
|
210
203
|
|
211
|
-
|
212
|
-
unless block_given?
|
213
|
-
raise InvalidStructureError.new(
|
214
|
-
"'list' was called without a block"
|
215
|
-
)
|
216
|
-
end
|
204
|
+
protected
|
217
205
|
|
218
|
-
|
206
|
+
def heading(s)
|
207
|
+
@buffer += "# #{s}\n\n"
|
208
|
+
end
|
219
209
|
|
220
|
-
|
221
|
-
|
222
|
-
indent do
|
223
|
-
block.call
|
210
|
+
def puts(s)
|
211
|
+
print_indented Machinery.scrub(s)
|
224
212
|
end
|
225
|
-
else
|
226
|
-
block.call
|
227
|
-
end
|
228
|
-
@buffer += "\n" unless @buffer.end_with?("\n\n") || options[:sublist]
|
229
213
|
|
230
|
-
|
231
|
-
|
214
|
+
def list(name = nil, options = {}, &block)
|
215
|
+
unless block_given?
|
216
|
+
raise InvalidStructureError.new(
|
217
|
+
"'list' was called without a block"
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
@stack << :list
|
222
|
+
|
223
|
+
if name && !name.empty?
|
224
|
+
print_indented "#{name}:"
|
225
|
+
indent do
|
226
|
+
block.call
|
227
|
+
end
|
228
|
+
else
|
229
|
+
block.call
|
230
|
+
end
|
231
|
+
@buffer += "\n" unless @buffer.end_with?("\n\n") || options[:sublist]
|
232
|
+
|
233
|
+
@stack.pop
|
234
|
+
end
|
232
235
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
236
|
+
def item(s, &block)
|
237
|
+
unless @stack.last == :list
|
238
|
+
raise InvalidStructureError.new(
|
239
|
+
"'item' was called outside of a list block"
|
240
|
+
)
|
241
|
+
end
|
242
|
+
|
243
|
+
print_indented "* #{Machinery.scrub(s)}"
|
244
|
+
|
245
|
+
if block_given?
|
246
|
+
@stack << :item
|
247
|
+
indent do
|
248
|
+
block.call
|
249
|
+
end
|
250
|
+
@buffer += "\n"
|
251
|
+
@stack.pop
|
252
|
+
end
|
253
|
+
end
|
239
254
|
|
240
|
-
|
255
|
+
private
|
241
256
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
257
|
+
def print_indented(s)
|
258
|
+
s.split("\n", -1).each do |line|
|
259
|
+
@buffer += if line.empty?
|
260
|
+
"\n"
|
261
|
+
else
|
262
|
+
" " * @indent + line + "\n"
|
263
|
+
end
|
264
|
+
end
|
246
265
|
end
|
247
|
-
@buffer += "\n"
|
248
|
-
@stack.pop
|
249
|
-
end
|
250
|
-
end
|
251
266
|
|
252
|
-
|
267
|
+
def indent
|
268
|
+
@indent += 2
|
269
|
+
yield
|
270
|
+
@indent -= 2
|
271
|
+
end
|
253
272
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
@buffer += "\n"
|
258
|
-
else
|
259
|
-
@buffer += " " * @indent + line + "\n"
|
273
|
+
def na_note(s)
|
274
|
+
Machinery::Ui.puts "Note: 'N/A' represents a missing #{s} which could not\n" \
|
275
|
+
"be gathered during inspection.\n"
|
260
276
|
end
|
261
277
|
end
|
262
278
|
end
|
263
|
-
|
264
|
-
def indent
|
265
|
-
@indent += 2
|
266
|
-
yield
|
267
|
-
@indent -= 2
|
268
|
-
end
|
269
|
-
|
270
|
-
def na_note(s)
|
271
|
-
Machinery::Ui.puts "Note: 'N/A' represents a missing #{s} which could not\n" \
|
272
|
-
"be gathered during inspection.\n"
|
273
|
-
end
|
274
279
|
end
|