command_exec 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/Gemfile +6 -2
  2. data/Gemfile.lock +42 -18
  3. data/README.md +707 -72
  4. data/RELEASE_NOTES.md +62 -0
  5. data/Rakefile +40 -9
  6. data/TODO.md +8 -2
  7. data/command_exec.gemspec +3 -2
  8. data/gemfiles/Gemfile.default +28 -0
  9. data/gemfiles/Gemfile.travis +16 -0
  10. data/gemfiles/Gemfile.travis.lock +48 -0
  11. data/lib/command_exec.rb +22 -2
  12. data/lib/command_exec/command.rb +307 -157
  13. data/lib/command_exec/exceptions.rb +16 -6
  14. data/lib/command_exec/field_helper.rb +263 -0
  15. data/lib/command_exec/formatter/array.rb +158 -0
  16. data/lib/command_exec/formatter/hash.rb +78 -0
  17. data/lib/command_exec/formatter/json.rb +22 -0
  18. data/lib/command_exec/formatter/string.rb +22 -0
  19. data/lib/command_exec/formatter/xml.rb +22 -0
  20. data/lib/command_exec/formatter/yaml.rb +22 -0
  21. data/lib/command_exec/logger.rb +9 -0
  22. data/lib/command_exec/process.rb +294 -0
  23. data/lib/command_exec/spec_helper_module.rb +52 -0
  24. data/lib/command_exec/version.rb +1 -1
  25. data/script/console +8 -0
  26. data/spec/command/command_spec.rb +413 -117
  27. data/spec/command/test_data/echo_test +3 -0
  28. data/spec/command/test_data/exit_status_test +2 -0
  29. data/spec/command/test_data/log_file_test +3 -0
  30. data/spec/command/test_data/logger_test +2 -0
  31. data/spec/command/test_data/not_raise_error_test +4 -0
  32. data/spec/command/test_data/not_throw_error_test +4 -0
  33. data/spec/command/test_data/output_test +6 -0
  34. data/spec/command/test_data/raise_error_test +6 -0
  35. data/spec/command/test_data/runner_open3_test +4 -0
  36. data/spec/command/test_data/runner_system_test +4 -0
  37. data/spec/command/test_data/stderr_test +4 -0
  38. data/spec/command/test_data/stdout_multiple_lines_test +4 -0
  39. data/spec/command/test_data/stdout_test +4 -0
  40. data/spec/command/test_data/throw_error_test +6 -0
  41. data/spec/command/test_data/true_test +2 -0
  42. data/spec/formatter/array_spec.rb +215 -0
  43. data/spec/formatter/hash_spec.rb +117 -0
  44. data/spec/formatter/json_spec.rb +21 -0
  45. data/spec/formatter/xml_spec.rb +33 -0
  46. data/spec/formatter/yaml_spec.rb +21 -0
  47. data/spec/process/process_spec.rb +329 -0
  48. data/spec/spec_helper.rb +15 -4
  49. metadata +79 -5
@@ -0,0 +1,78 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style hash
8
+ class Hash
9
+
10
+ include FieldHelper
11
+
12
+ # @!attribute [r] output
13
+ # return the formatted output
14
+ attr_reader :output
15
+ # @!attribute [w] logger
16
+ # set the logger after object creation
17
+ attr_writer :logger
18
+
19
+ public
20
+
21
+ # Create new hash formatter
22
+ #
23
+ # @param [Hash] options
24
+ # Options for formatter
25
+ #
26
+ # @option options [Symbol] :logger
27
+ # Logger to output information. Needs to have the same interface like
28
+ # the ruby `Logger`-class.
29
+ def initialize(options={})
30
+ @options = {
31
+ logger: Logger.new($stdout),
32
+ }.deep_merge options
33
+
34
+ @logger = @options[:logger]
35
+
36
+ super()
37
+ end
38
+
39
+ def status(value)
40
+ prepare_status(value)
41
+ end
42
+
43
+ private
44
+
45
+ # Build the data structure for output
46
+ #
47
+ # @param [Array] fields
48
+ # which fields should be outputted
49
+ #
50
+ # @return [Hash]
51
+ # the formatted output
52
+ def prepare_output(fields=[])
53
+ out = {}
54
+
55
+ fields = default_fields if fields.blank?
56
+
57
+ fields.each do |f|
58
+ out[f] = available_fields[f] if available_fields.has_key?(f)
59
+ end
60
+
61
+ out
62
+ end
63
+
64
+ public
65
+
66
+ # Output the prepared output
67
+ #
68
+ # @param [Array,Symbol) fields
69
+ # the fields which should be outputted
70
+ #
71
+ # @return [Hash]
72
+ # the formatted output
73
+ def output(*fields)
74
+ prepare_output(fields.flatten)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,22 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style as json string
8
+ class JSON < CommandExec::Formatter::Hash
9
+
10
+ # convert the prepared output to json
11
+ #
12
+ # @param [Array,Symbol) fields
13
+ # the fields which should be outputted
14
+ #
15
+ # @return [String]
16
+ # the output formatted as json string
17
+ def output(*fields)
18
+ ::JSON.generate prepare_output(fields.flatten)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style as simple string
8
+ class String < CommandExec::Formatter::Array
9
+
10
+ # convert the prepared output to single string
11
+ #
12
+ # @param [Array,Symbol) fields
13
+ # the fields which should be outputted
14
+ #
15
+ # @return [String]
16
+ # the output formatted as simple string
17
+ def output(*fields)
18
+ prepare_output(fields.flatten).join("\n")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style as xml string
8
+ class XML < CommandExec::Formatter::Hash
9
+
10
+ # convert the prepared output to a xml string
11
+ #
12
+ # @param [Array,Symbol) fields
13
+ # the fields which should be outputted
14
+ #
15
+ # @return [String]
16
+ # the output formatted as a xml string
17
+ def output(*fields)
18
+ XmlSimple.xml_out(prepare_output(fields.flatten), 'RootName' => 'command', 'NoAttr' => true)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style as yaml string
8
+ class YAML < CommandExec::Formatter::Hash
9
+
10
+ # convert the prepared output to a yaml string
11
+ #
12
+ # @param [Array,Symbol) fields
13
+ # the fields which should be outputted
14
+ #
15
+ # @return [String]
16
+ # the output formatted as a xml string
17
+ def output(*fields)
18
+ Psych.dump prepare_output(fields.flatten)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ #ruby's logging class
3
+ class Logger
4
+ #container for extra severities
5
+ module Severity
6
+ #keep logger silent
7
+ SILENT = 999999
8
+ end
9
+ end
@@ -0,0 +1,294 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ # The class used to save the data about
6
+ # the executed command
7
+ class Process
8
+
9
+ include FieldHelper
10
+
11
+ # @!attribute [rw] executable
12
+ # Set/Get the executable of the command
13
+ attr_accessor :executable
14
+
15
+ # @!attribute [r] status
16
+ # Get the status of the command
17
+ #
18
+ # @!attribute [r] stdout
19
+ # Get stdout of the command
20
+ #
21
+ # @!attribute [r] stderr
22
+ # Get stderr of the command
23
+ #
24
+ # @!attribute [r] reason_for_failure
25
+ # Get the reason why `command_exec` thinks a command failed
26
+ #
27
+ # @!attribute [r] return_code
28
+ # Get the exit code of the command
29
+ #
30
+ # @!attribute [r] pid
31
+ # Get the pid of the command
32
+ #
33
+ # @!attribute [r] start_time
34
+ # Return the time when the execution of the command started
35
+ #
36
+ # @!attribute [r] end_time
37
+ # Return the time when the execution of the command finished
38
+ attr_reader :status, :log_file, :stdout, :stderr, :reason_for_failure, :return_code, :pid, :start_time, :end_time
39
+
40
+ # Create a process object
41
+ #
42
+ # @param [Hash] options
43
+ # options for the process
44
+ #
45
+ # @option options [Logger] lib_logger
46
+ # The logger which is used to output information generated by the
47
+ # library. The logger which is provided needs to be compatible with api
48
+ # of the Ruby `Logger`-class.
49
+ #
50
+ # @option options [Array] stderr
51
+ # content of stderr of the process
52
+ #
53
+ # @option options [Array] stdout
54
+ # content of stdout of the process
55
+ #
56
+ # @option options [Array] log_file
57
+ # content of the log file of the process
58
+ #
59
+ # @option options [Number,String] pid
60
+ # the pid of the process
61
+ #
62
+ # @option options [Number,String] return_code
63
+ # the exit status of the process
64
+ #
65
+ # @option options [Array] reason_for_failure
66
+ # the reason for failure
67
+ #
68
+ # @option options [Symbol] status
69
+ # execution was successful, failed
70
+ def initialize(options={})
71
+ @options = {
72
+ lib_logger: Logger.new($stderr),
73
+ stderr: [],
74
+ stdout: [],
75
+ log_file: [],
76
+ pid: nil,
77
+ return_code: nil,
78
+ reason_for_failure: [],
79
+ status: :success,
80
+ executable: nil,
81
+ }.merge options
82
+
83
+ @logger = @options[:lib_logger]
84
+
85
+ @stderr = @options[:stderr]
86
+ @stdout = @options[:stdout]
87
+ @status = @options[:status]
88
+ @log_file = @options[:log_file]
89
+ @pid = @options[:pid]
90
+ @reason_for_failure = @options[:reason_for_failure]
91
+ @return_code = @options[:return_code]
92
+ @executable = @options[:executable]
93
+
94
+ @start_time = nil
95
+ @end_time = nil
96
+ end
97
+
98
+ # Set the name of the log file
99
+ #
100
+ # @param [String] filename
101
+ # the name of the log file
102
+ def log_file=(filename=nil)
103
+ if filename.blank?
104
+ file = StringIO.new
105
+ @logger.debug "No file name for log file given. Using empty String"
106
+ else
107
+ begin
108
+ file = File.open(filename)
109
+ @logger.debug "read logfile \"#{file}\" "
110
+ rescue Errno::ENOENT
111
+ file = StringIO.new
112
+ @logger.warn "Logfile #{filename} not found!"
113
+ rescue Exception => e
114
+ file = StringIO.new
115
+ @logger.warn "An error happen while reading log_file \"#{filename}\": #{e.message}"
116
+ end
117
+ end
118
+
119
+ @log_file = file.readlines.map(&:chomp)
120
+ end
121
+
122
+ # Set the pid of the process
123
+ #
124
+ # @param [Number,String] value
125
+ def pid=(value)
126
+ @pid = value.to_s
127
+ end
128
+
129
+ # Set the value of stdout
130
+ #
131
+ # @param [Array, String] content
132
+ # the content of stdout
133
+ def stdout=(*content)
134
+ @stdout += content.flatten
135
+ end
136
+
137
+ # Set the value of stderr
138
+ #
139
+ # @param [Array, String] content
140
+ # the content of stderr
141
+ def stderr=(*content)
142
+ @stderr += content.flatten
143
+ end
144
+
145
+ # Set the status of command execution
146
+ #
147
+ # @param [Array, String] value
148
+ # the status
149
+ def status=(value)
150
+ case value.to_s
151
+ when 'success'
152
+ @status = :success
153
+ when 'failed'
154
+ @status = :failed
155
+ else
156
+ @status = :failed
157
+ end
158
+
159
+ @status
160
+ end
161
+
162
+ # Why the execution failed
163
+ #
164
+ # @param [String] content
165
+ # the reason for failure. When you run it mulitple times, the string is
166
+ # added at the end.
167
+ def reason_for_failure=(content)
168
+ @reason_for_failure << content.to_s
169
+ end
170
+
171
+ # Set the exit status of the command
172
+ #
173
+ # @param [Number,String] value
174
+ # the exit status of the command
175
+ def return_code=(value)
176
+ @return_code = value
177
+ end
178
+
179
+ # Set the path to the executable
180
+ #
181
+ # @param [Number,String] value
182
+ # the path to the executable of the command
183
+ def executable=(value)
184
+ @executable = value
185
+ end
186
+
187
+ # Set the start time of the command execution
188
+ #
189
+ # @param [Number,String] value
190
+ # the path to the executable of the command
191
+ def start_time=(value)
192
+ @start_time = value
193
+ end
194
+
195
+ # Set the end time of the command execution
196
+ #
197
+ # @param [Number,String] value
198
+ # the path to the executable of the command
199
+ def end_time=(value)
200
+ @end_time = value
201
+ end
202
+
203
+ def run_time
204
+ end_time - start_time
205
+ end
206
+
207
+ private
208
+
209
+ # Generate formatted output
210
+ #
211
+ # @param [Symbol,Array of Symbols] fields
212
+ # the field which should be part of the output
213
+ #
214
+ # @param [Formatter] formatter
215
+ # the formatter which is used to format the output
216
+ def output(*fields,formatter)
217
+
218
+ fields.flatten.each do |f|
219
+ formatter.public_send(f, available_fields[f])
220
+ end
221
+
222
+ formatter.output(fields.flatten)
223
+ end
224
+
225
+ public
226
+
227
+ # Output process data as array
228
+ #
229
+ # @param [Array of Symbols] fields
230
+ # the fields which should be outputed
231
+ #
232
+ # @param [Formatter] formatter (Formatter::Array.new)
233
+ # the formatter which is used the format the output
234
+ def to_a(fields=default_fields, formatter=Formatter::Array.new)
235
+ output(fields, formatter)
236
+ end
237
+
238
+ # Output process data as hash
239
+ #
240
+ # @param [Array of Symbols] fields
241
+ # the fields which should be outputed
242
+ #
243
+ # @param [Formatter] formatter (Formatter::Hash.new)
244
+ # the formatter which is used the format the output
245
+ def to_h(fields=default_fields, formatter=Formatter::Hash.new)
246
+ output(fields, formatter)
247
+ end
248
+
249
+ # Output process data as string
250
+ #
251
+ # @param [Array of Symbols] fields
252
+ # the fields which should be outputed
253
+ #
254
+ # @param [Formatter] formatter (Formatter::String.new)
255
+ # the formatter which is used the format the output
256
+ def to_s(fields=default_fields, formatter=Formatter::String.new)
257
+ output(fields, formatter)
258
+ end
259
+
260
+ # Output process data as xml
261
+ #
262
+ # @param [Array of Symbols] fields
263
+ # the fields which should be outputed
264
+ #
265
+ # @param [Formatter] formatter (Formatter::XML.new)
266
+ # the formatter which is used the format the output
267
+ def to_xml(fields=default_fields, formatter=Formatter::XML.new)
268
+ output(fields, formatter)
269
+ end
270
+
271
+ # Output process data as json
272
+ #
273
+ # @param [Array of Symbols] fields
274
+ # the fields which should be outputed
275
+ #
276
+ # @param [Formatter] formatter (Formatter::JSON.new)
277
+ # the formatter which is used the format the output
278
+ def to_json(fields=default_fields, formatter=Formatter::JSON.new)
279
+ output(fields, formatter)
280
+ end
281
+
282
+ # Output process data as yaml
283
+ #
284
+ # @param [Array of Symbols] fields
285
+ # the fields which should be outputed
286
+ #
287
+ # @param [Formatter] formatter (Formatter::YAML.new)
288
+ # the formatter which is used the format the output
289
+ def to_yaml(fields=default_fields, formatter=Formatter::YAML.new)
290
+ output(fields, formatter)
291
+ end
292
+ end
293
+ end
294
+