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
@@ -1,20 +1,30 @@
1
+ # encoding: utf-8
2
+
1
3
  # Main
2
4
  module CommandExec
3
5
  # Classed concerning pdflatex exceptions
4
6
  module Exceptions
5
7
  # Class used to indicate that a command
6
8
  # could not be found in file system
7
- class CommandNotFound < RuntimeError
8
- end
9
+ class CommandNotFound < RuntimeError; end
10
+
11
+ # Class used to indicate that a command
12
+ # is not flagged as executable
13
+ #
14
+ # @example Counter measure for this error
15
+ # chmod +x <executable>
16
+ class CommandNotExecutable < RuntimeError; end
17
+
18
+ # Class used to indicate that a command
19
+ # is not a file
20
+ class CommandIsNotAFile < RuntimeError; end
9
21
 
10
22
  # Class used to indicate that a command run
11
23
  # ended with a failure
12
- class ExecuteCommandFailed < RuntimeError
13
- end
24
+ class CommandExecutionFailed < RuntimeError; end
14
25
 
15
26
  # Class used to indicate that a logfile
16
27
  # could not be found in file system
17
- class LogfileNotFound < RuntimeError
18
- end
28
+ class LogfileNotFound < RuntimeError; end
19
29
  end
20
30
  end
@@ -0,0 +1,263 @@
1
+ #encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ # Shared methods for fields
6
+ module FieldHelper
7
+
8
+ # Initialize helper
9
+ #
10
+ # will be used from array and hash via super call although there's no
11
+ # inheritance.
12
+ # See for more information http://stackoverflow.com/questions/1645398/ruby-include-question
13
+ def initialize
14
+ @end_time = []
15
+ @executable = []
16
+ @log_file = []
17
+ @pid = []
18
+ @reason_for_failure = []
19
+ @return_code = []
20
+ @start_time = []
21
+ @status = []
22
+ @stderr = []
23
+ @stdout = []
24
+ end
25
+
26
+ private
27
+
28
+ # Return the available header names
29
+ #
30
+ # @return [Hash] the names of the headers
31
+ #
32
+ # * :status [String]: 'STATUS'
33
+ # * :return_code [String]: 'RETURN CODE'
34
+ # * :log_file [String]: 'LOG FILE'
35
+ # * :stderr [String]: 'STDERR'
36
+ # * :stdout [String]: 'STDOUT'
37
+ # * :pid [String]: 'PID'
38
+ # * :reason\_for\_failure [String]: 'REASON FOR FAILURE'
39
+ # * :executable [String]: 'EXECUTABLE'
40
+ #
41
+ def header_names
42
+ {
43
+ headers: {
44
+ names: {
45
+ status: 'STATUS',
46
+ return_code: 'RETURN CODE',
47
+ log_file: 'LOG FILE',
48
+ stderr: 'STDERR',
49
+ stdout: 'STDOUT',
50
+ pid: 'PID',
51
+ reason_for_failure: 'REASON FOR FAILURE',
52
+ executable: 'EXECUTABLE',
53
+ start_time: 'START TIME',
54
+ end_time: 'END TIME',
55
+ },
56
+ }
57
+ }
58
+ end
59
+
60
+ # Return the available fields for output
61
+ #
62
+ # @return [Hash] the available fields with the corresponding instance
63
+ # variable
64
+ def available_fields
65
+ {
66
+ :status => @status,
67
+ :return_code => @return_code,
68
+ :stderr => @stderr,
69
+ :stdout => @stdout,
70
+ :log_file => @log_file,
71
+ :pid => @pid,
72
+ :reason_for_failure => @reason_for_failure,
73
+ :executable => @executable,
74
+ :start_time => @start_time,
75
+ :end_time => @end_time,
76
+ }
77
+ end
78
+
79
+ # Return the default fields for output
80
+ #
81
+ # @return [Array] the names of the fields which should be outputted by
82
+ # default
83
+ def default_fields
84
+ [:status,
85
+ :return_code,
86
+ :stderr,
87
+ :stdout,
88
+ :log_file,
89
+ :pid,
90
+ :reason_for_failure,
91
+ :executable,
92
+ :start_time,
93
+ :end_time,
94
+ ]
95
+ end
96
+
97
+ # Set the status of the command
98
+ #
99
+ # @param [String,Symbol] value
100
+ # Set the status of the command based on input.
101
+ #
102
+ # @param [Hash] options
103
+ # Options for status
104
+ #
105
+ # @option options [True,False] :color
106
+ # Should the output be colored
107
+ #
108
+ # @return [Array]
109
+ # the formatted status. It returns `OK` (in bold and green) if status is
110
+ # `:success` and `FAILED` (in bold and red) if status is `:failed`.
111
+ #
112
+ def prepare_status(value,options={})
113
+
114
+ case value.to_s
115
+ when 'success'
116
+ @status[0] = message_success(color: options[:color])
117
+ when 'failed'
118
+ @status[0] = message_failure(color: options[:color])
119
+ else
120
+ @status[0] = message_failure(color: options[:color])
121
+ end
122
+
123
+ @status
124
+ end
125
+
126
+ # Returns the success message
127
+ #
128
+ # @param [Hash] options
129
+ # options
130
+ #
131
+ # @option options [True,False] :color
132
+ # should the message return in color
133
+ #
134
+ # @return [String] the message
135
+ def message_success(options={})
136
+ message = 'OK'
137
+
138
+ if options[:color]
139
+ return message.green.bold
140
+ else
141
+ return message
142
+ end
143
+ end
144
+
145
+ # Returns the failure message
146
+ #
147
+ # @param [Hash] options
148
+ # options
149
+ #
150
+ # @option options [True,False] :color
151
+ # should the message return in color
152
+ #
153
+ # @return [String] the message
154
+ def message_failure(options)
155
+ message = 'FAILED'
156
+
157
+ if options[:color]
158
+ return message.red.bold
159
+ else
160
+ return message
161
+ end
162
+ end
163
+
164
+ public
165
+
166
+ # Set the content of the log file
167
+ #
168
+ # @param content [Array,String]
169
+ # The content of log file
170
+ #
171
+ # @return [Array] the content of the log file
172
+ def log_file(*content)
173
+ @log_file += content.flatten
174
+ end
175
+
176
+ # Set the return code of the command
177
+ #
178
+ # @param value [Number,String]
179
+ # Set the return code(s) of the command.
180
+ #
181
+ # @return [Array] the return code
182
+ def return_code(value)
183
+ @return_code[0] = value.to_s
184
+
185
+ @return_code
186
+ end
187
+
188
+ # Set the content of stdout
189
+ #
190
+ # @param content [Array,String]
191
+ # The content of stdout
192
+ #
193
+ # @return [Array]
194
+ def stdout(*content)
195
+ @stdout += content.flatten
196
+ end
197
+
198
+ # Set the content of stderr
199
+ #
200
+ # @param content [Array,String]
201
+ # The content of stderr
202
+ #
203
+ # @return [Array]
204
+ def stderr(*content)
205
+ @stderr += content.flatten
206
+ end
207
+
208
+ # Set the pid of the command
209
+ #
210
+ # @param value [Number,String]
211
+ # Set the pid of the command.
212
+ #
213
+ # @return [Array]
214
+ def pid(value)
215
+ @pid[0] = value.to_s
216
+
217
+ @pid
218
+ end
219
+
220
+ # Set the reason for failure
221
+ #
222
+ # @param content [Array, String]
223
+ # Set the reason for failure.
224
+ #
225
+ # @return [Array]
226
+ def reason_for_failure(*content)
227
+ @reason_for_failure += content.flatten
228
+ end
229
+
230
+ # Set the path to the executable of the command
231
+ #
232
+ # @param [String] value
233
+ # the path to the executable
234
+ #
235
+ # @return [Array]
236
+ # the executable
237
+ def executable(value)
238
+ @executable[0] = value
239
+ end
240
+
241
+ # Set the start time of command execution
242
+ #
243
+ # @param [Time] value
244
+ # the start time of command execution
245
+ #
246
+ # @return [Array]
247
+ # the start time
248
+ def start_time(value)
249
+ @start_time[0] = value
250
+ end
251
+
252
+ # Set the end time of command execution
253
+ #
254
+ # @param [Time] value
255
+ # the end time of command execution
256
+ #
257
+ # @return [Array]
258
+ # the end time
259
+ def end_time(value)
260
+ @end_time[0] = value
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,158 @@
1
+ # encoding: utf-8
2
+
3
+ #Main
4
+ module CommandExec
5
+ #Formatting output
6
+ module Formatter
7
+ #Style array
8
+ class Array
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
+ # Create new array formatter
20
+ #
21
+ # @param [Hash] options
22
+ # Options for formatter
23
+ #
24
+ # @option options [Hash] :headers
25
+ # It is used to configure how the headers will be formatted
26
+ #
27
+ # There are several sub-options:
28
+ #
29
+ # * :names [Hash]: What should be output as name for the header (filled via deep_merge and FieldHelper-Module)
30
+ # * :prefix [String]: What is placed before the header ('=' * 5)
31
+ # * :suffix [String]: What is placed after the header ('=' * 5)
32
+ # * :halign [Symbol]: How to align the header: :center [default], :left, :right
33
+ # * :show (Boolean): Should the header be shown (true)
34
+ #
35
+ # @option options [Symbol] :logger
36
+ # Logger to output information. Needs to have the same interface like
37
+ # the ruby `Logger`-class.
38
+ #
39
+ def initialize(options={})
40
+ @options = {
41
+ headers: {
42
+ names: {},
43
+ prefix: '=' * 5,
44
+ suffix: '=' * 5,
45
+ halign: :center,
46
+ show: true,
47
+ },
48
+ logger: Logger.new($stdout),
49
+ }.deep_merge(header_names.deep_merge(options))
50
+
51
+ @headers_options = @options[:headers]
52
+ @logger = @options[:logger]
53
+
54
+ super()
55
+ end
56
+
57
+ def status(value)
58
+ prepare_status(value, color: true)
59
+ end
60
+
61
+ private
62
+
63
+ # Get the maximum length over all headers
64
+ #
65
+ # @return [Number] the maxium header length
66
+ def max_header_length
67
+ @max_header_length ||= @headers_options[:names].values.inject(0) { |max_length, name| max_length < name.length ? name.length : max_length }
68
+ end
69
+
70
+ # Align header names
71
+ #
72
+ # @param [String] name
73
+ # the name which should be aligned
74
+ #
75
+ # @param max_length [Number]
76
+ # the maximum length which is used to align the name
77
+ #
78
+ # @param orientation [Symbol]
79
+ # how to align the header name
80
+ #
81
+ # @return [String] the aligned header name
82
+ def halign(name, max_length, orientation)
83
+
84
+ name = name.to_s
85
+
86
+ case orientation
87
+ when :center
88
+ name.center(max_length)
89
+ when :left
90
+ name.ljust(max_length)
91
+ when :right
92
+ name.rjust(max_length)
93
+ else
94
+ name.center(max_length)
95
+ end
96
+ end
97
+
98
+ # Format header but only if given header is defined.
99
+ #
100
+ # @param [Symbol] header
101
+ # the name of the header. It has to be defined in opts[:names]
102
+ #
103
+ # @param [Hash] options
104
+ # used to change format options like `prefix`, `suffix` etc. after the
105
+ # creation of the `Formatter::Array`-object. Those options defined at the
106
+ # creation of the `Formatter`-object are default and can be overwritten
107
+ # using this `Hash`.
108
+ #
109
+ # @return [String] the formatted header
110
+ def format_header(header,options={})
111
+ opts = @headers_options.deep_merge options
112
+
113
+ output=""
114
+ unless opts[:names][header] == ""
115
+ output += "#{opts[:prefix]} " unless opts[:prefix].blank?
116
+ output += halign(opts[:names][header], max_header_length, opts[:halign])
117
+ output += " #{opts[:suffix]}" unless opts[:suffix].blank?
118
+ end
119
+
120
+ output
121
+ end
122
+
123
+ # Build the data structure for output
124
+ #
125
+ # @param [Array] fields
126
+ # which fields should be outputted
127
+ #
128
+ # @return [Array]
129
+ # the formatted output
130
+ def prepare_output(fields=[])
131
+ out = []
132
+ fields = fields.flatten
133
+
134
+ fields = default_fields if fields.blank?
135
+
136
+ fields.each do |var|
137
+ out << format_header(var,@headers_options) if @headers_options[:show] = true and available_fields.has_key?(var)
138
+ out += available_fields[var] if available_fields.has_key?(var)
139
+ end
140
+
141
+ out
142
+ end
143
+
144
+ public
145
+
146
+ # Output the prepared output
147
+ #
148
+ # @param [Array,Symbol) fields
149
+ # the fields which should be outputted
150
+ #
151
+ # @return [Array]
152
+ # the formatted output
153
+ def output(*fields)
154
+ prepare_output(fields.flatten)
155
+ end
156
+ end
157
+ end
158
+ end