makit 0.0.5 → 0.0.6

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/makit/apache.rb +32 -32
  3. data/lib/makit/cli/clean.rb +14 -14
  4. data/lib/makit/cli/clone.rb +59 -59
  5. data/lib/makit/cli/init.rb +38 -38
  6. data/lib/makit/cli/main.rb +33 -33
  7. data/lib/makit/cli/make.rb +54 -54
  8. data/lib/makit/cli/new.rb +37 -37
  9. data/lib/makit/cli/nuget_cache.rb +38 -38
  10. data/lib/makit/cli/pull.rb +31 -31
  11. data/lib/makit/cli/setup.rb +71 -71
  12. data/lib/makit/cli/work.rb +21 -21
  13. data/lib/makit/command_runner.rb +321 -318
  14. data/lib/makit/commands.rb +21 -21
  15. data/lib/makit/content/default_gitignore.rb +5 -5
  16. data/lib/makit/content/default_rakefile.rb +11 -11
  17. data/lib/makit/content/gem_rakefile.rb +14 -14
  18. data/lib/makit/data.rb +50 -50
  19. data/lib/makit/directories.rb +140 -140
  20. data/lib/makit/directory.rb +153 -153
  21. data/lib/makit/dotnet.rb +83 -83
  22. data/lib/makit/environment.rb +123 -123
  23. data/lib/makit/files.rb +47 -47
  24. data/lib/makit/git.rb +66 -66
  25. data/lib/makit/gitlab_runner.rb +60 -60
  26. data/lib/makit/humanize.rb +89 -89
  27. data/lib/makit/logging.rb +96 -96
  28. data/lib/makit/markdown.rb +75 -75
  29. data/lib/makit/mp/basic_object_mp.rb +16 -16
  30. data/lib/makit/mp/project_mp.rb +160 -156
  31. data/lib/makit/mp/string_mp.rb +107 -107
  32. data/lib/makit/nuget.rb +57 -57
  33. data/lib/makit/protoc.rb +61 -61
  34. data/lib/makit/serializer.rb +115 -115
  35. data/lib/makit/storage.rb +131 -131
  36. data/lib/makit/symbols.rb +149 -149
  37. data/lib/makit/tasks.rb +67 -67
  38. data/lib/makit/tree.rb +37 -37
  39. data/lib/makit/v1/makit.v1_pb.rb +4 -3
  40. data/lib/makit/v1/makit.v1_services_pb.rb +25 -25
  41. data/lib/makit/version.rb +12 -12
  42. data/lib/makit/wix.rb +95 -95
  43. data/lib/makit/zip.rb +17 -17
  44. data/lib/makit.rb +243 -243
  45. metadata +3 -3
@@ -1,318 +1,321 @@
1
- require "English"
2
- require "open3"
3
- require "socket"
4
- require "etc"
5
- require "logger"
6
-
7
- # This module provides classes for the Makit gem.
8
- module Makit
9
- # This class provide methods running commands.
10
- #
11
- class CommandRunner
12
- attr_accessor :show_output_on_success, :log_to_artifacts, :commands
13
-
14
- def initialize
15
- @show_output_on_success = false
16
- @log_to_artifacts = true
17
- @commands = []
18
- end
19
-
20
- def get_cache_filename(command)
21
- # test if the command_request is a Makit::V1::CommandRequest
22
- #if command_request.is_a? Makit::V1::CommandRequest || command_request.is_a? Makit::V1::Command
23
- # also replacing any path delimiters with an underscore
24
- int_hash = Digest::SHA256.hexdigest("{command.name}.#{command.arguments.join(" ")}")
25
- # int_hash
26
- #int_hash = command_request.to_hash
27
- hash_string = "#{int_hash}"[0, 8]
28
- cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
29
- "/commands/cache/#{hash_string}.pb"
30
- # create the directory if it does not already exist
31
- FileUtils.mkdir_p(File.dirname(cache_filename))
32
- cache_filename
33
- end
34
- # if there is a matching cached command result, that then the specified timestamp,
35
- # then return the cached result
36
- # otherwise run the command and save the result to a cache file
37
- # then return the result
38
- def cache_run(command_request, timestamp)
39
- # combine the command name and arguments into a single string
40
- # and use it to create a cache filename, making sure it is a valid filename,
41
- # by replacing all characters that are not valid in a filename with an underscore
42
- # also replacing any path delimiters with an underscore
43
- int_hash = command_request.to_hash
44
- hash_string = "#{int_hash}"[0, 8]
45
- cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
46
- "/commands/#{hash_string}.pb"
47
- puts "cache_filename: #{cache_filename}"
48
-
49
- #cache_filename = Makit::Directories::PROJECT_ARTIFACTS + "/commands/#{command_request.name}.#{command_request.arguments.join("_")}.#{timestamp.seconds}.pb"
50
- if File.exist?(cache_filename)
51
- puts "cache file date: #{File.mtime(cache_filename)}"
52
- if (File.mtime(cache_filename) > timestamp)
53
- puts "cache_filename exists and is newer than #{timestamp}"
54
- return Makit::Serializer.open(cache_filename, Makit::V1::Command)
55
- else
56
- puts "cache_filename exists, but is older than #{timestamp}"
57
- end
58
- end
59
-
60
- command = run(command_request)
61
- # make sure the cache directory exists
62
- FileUtils.mkdir_p(File.dirname(cache_filename))
63
- puts "saving command to cache_filename"
64
- Makit::Serializer.save_as(cache_filename, command)
65
- command
66
- end
67
-
68
- # Run a command and return a Makit::V1::Command.
69
- def run(command_request)
70
- raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
71
- command = execute(command_request)
72
- show_output = true
73
- exit_on_error = true
74
-
75
- log_to_artifacts(command) if @log_to_artifacts
76
- if command.exit_code != 0
77
- puts Makit::CommandRunner.get_command_summary(command) + " (exit code #{command.exit_code})".colorize(:default)
78
- puts " directory: #{command.directory}\n"
79
- puts " duration: #{command.duration.seconds} seconds\n"
80
- puts Makit::Humanize::indent_string(command.output, 2) if command.output.length > 0
81
- puts Makit::Humanize::indent_string(command.error, 2) if command.error.length > 0
82
- exit 1 if command_request.exit_on_error
83
- else
84
- puts Makit::CommandRunner.get_command_summary(command) + " (#{command.duration.seconds} seconds)".colorize(:cyan)
85
- puts Makit::Humanize::indent_string(command.output, 2).colorize(:default) if show_output_on_success
86
- end
87
-
88
- commands.push(command)
89
- command
90
- end
91
-
92
- def log_to_artifacts(command)
93
- #dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
94
- #FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
95
- #filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
96
- #log_filename = File.join(dir, "#{filename_friendly_timestamp}.json")
97
- log_filename = get_cache_filename(command)
98
- # serialize to protobuf json
99
- json = command.to_json
100
- pretty_json = JSON.pretty_generate(JSON.parse(json))
101
- File.write(log_filename, pretty_json)
102
- end
103
-
104
- # Run a command and return a Makit::V1::Command.
105
- def try(args)
106
- request = parse_command_request(args)
107
- request.exit_on_error = false
108
- run(request)
109
- #run2(args, false)
110
- end
111
-
112
- # Show the output of a command and return a Makit::V1::Command.
113
- def show(args)
114
- request = parse_args(args)
115
- command = execute(request)
116
-
117
- show_output = true
118
- exit_on_error = true
119
- Makit::LOGGER.info(Makit::CommandRunner.get_command_summary(command))
120
- show_output = true if command.exit_code != 0
121
- Makit::LOGGER.info(indent_string("\n#{command.output}\n#{command.error}\n".strip, 2)) if show_output
122
- exit(command.exit_code) if exit_on_error && command.exit_code != 0 # unless process_status.success?
123
- command
124
- end
125
-
126
- # Parse and return a Makit::V1::CommandRequest.
127
- def parse_command_request(source)
128
- return Makit::V1::CommandRequest.new(source) if source.is_a? Hash
129
- return source if source.is_a? Makit::V1::CommandRequest
130
- if source.is_a? String
131
- return parse_args(source)
132
- end
133
-
134
- raise "Invalid source" unless source.is_a? Makit::V1::CommandRequest
135
- end
136
-
137
- def parse_command_request_from_hash(hash)
138
- raise "Invalid hash" unless hash.is_a? Hash
139
- Makit::V1::CommandRequest.new(hash)
140
- end
141
-
142
- def parse_command_request_from_string(source)
143
- raise "Invalid source" unless source.is_a? String
144
- words = source.split(" ")
145
- hash = {
146
- name: words.shift,
147
- arguments: words,
148
- exit_on_error: true,
149
- }
150
- end
151
-
152
- # Parse the command line arguments into a Makit::V1::CommandRequest.
153
- def parse_args(args)
154
- #raise "No command specified" if args.empty?
155
- if args.is_a? Makit::V1::CommandRequest
156
- args
157
- else
158
- if args.is_a? String
159
- args = args.split(" ")
160
- if (args.length == 1)
161
- hash = {
162
- name: args[0],
163
- arguments: [],
164
- exit_on_error: true,
165
- }
166
- Makit::V1::CommandRequest.new(hash)
167
- else
168
- hash = {
169
- name: args.shift,
170
- arguments: args,
171
- exit_on_error: true,
172
- }
173
-
174
- Makit::V1::CommandRequest.new(hash)
175
- end
176
- else
177
- Makit::V1::CommandRequest.new(args)
178
- end
179
- end
180
- end
181
-
182
- def get_path_name(name)
183
- # replace all characters that a not valid in a filename with an underscore
184
- name.gsub(/[^0-9a-z]/i, "_")
185
- end
186
-
187
- # Given a Makit::V1::CommandRequest, execute the command and return a Makit::V1::Command.
188
- def execute(args)
189
- command_request = parse_args(args)
190
- command_request.directory = Dir.pwd if command_request.directory.nil?
191
- command_request.directory = Dir.pwd if command_request.directory.length == 0
192
- result = Makit::V1::Command.new(name: command_request.name)
193
- command_request.arguments.each do |arg|
194
- result.arguments.push(arg)
195
- end
196
- command = "#{command_request.name} #{command_request.arguments.join(" ")}"
197
- result.directory = command_request.directory
198
- start = Time.now
199
- filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
200
- log_filename = File.join(Makit::Directories::LOG, "#{filename_friendly_timestamp}.log")
201
-
202
- # assign a directory variable to the current working directory, if not specified,
203
- # otherwise assign the specified directory
204
- command_request.directory = Dir.pwd if command_request.directory.nil?
205
- command_request.directory = Dir.pwd if command_request.directory.length == 0
206
- raise "Invalid directory" unless Dir.exist?(command_request.directory)
207
-
208
- result.started_at = Google::Protobuf::Timestamp.new(seconds: start.to_i, nanos: start.nsec.to_i)
209
- ############# execute the command
210
- (output, error, exit_code) = execute_command(command, command_request.directory, command_request.timeout)
211
- result.output = output.force_encoding("ASCII-8BIT")
212
- result.error = error.force_encoding("ASCII-8BIT")
213
- result.exit_code = exit_code.nil? ? 0 : exit_code
214
-
215
- elapsed_time = Time.now - start
216
- seconds = elapsed_time.to_i
217
- nanos = ((elapsed_time - seconds) * 1_000_000_000).to_i
218
-
219
- result.duration = Google::Protobuf::Duration.new(seconds: seconds, nanos: nanos)
220
-
221
- result
222
- end
223
-
224
- # pure function to execute a command
225
- # returns (stdout, stderr, exit_code) or raise an exception
226
- def execute_command(command, directory, timeout)
227
- original_directory = Dir.pwd
228
- begin
229
- output = nil
230
- error = nil
231
- process_status = nil
232
- Dir.chdir(directory) do
233
- output, error, process_status = Open3.capture3(command)
234
- end
235
- return [output, error, process_status.exitstatus]
236
- rescue => e
237
- # restore the original working directory
238
- Dir.chdir(original_directory)
239
- message_parts = []
240
- message_parts << "failed to execute #{command}"
241
- message_parts << "directory: #{directory}"
242
- message_parts << "timeout: #{timeout}" unless timeout.nil?
243
- message_parts << "error: #{e.message}"
244
- message = message_parts.join("\n") + "\n"
245
- return ["", message, 1]
246
- #raise Makit::Error, message
247
- end
248
- end
249
-
250
- def execute_command_request(command_request)
251
- # if the command_request is not a Makit::V1::CommandRequest, raise an error
252
- raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
253
-
254
- args = Array.new
255
- command_request.arguments.each do |arg|
256
- args.push(arg)
257
- end
258
- result = Makit::V1::Command.new({
259
- name: command_request.name,
260
- arguments: args,
261
- started_at: Google::Protobuf::Timestamp.new({ seconds: Time.now.to_i, nanos: Time.now.nsec }),
262
- })
263
-
264
- begin
265
- rescue => e
266
- end
267
- end
268
-
269
- def indent_string(input_string, indent_spaces)
270
- indentation = " " * indent_spaces
271
- input_string.lines.map { |line| indentation + line }.join
272
- end
273
-
274
- def self.get_command_summary(command)
275
- symbol = Makit::Symbols.warning
276
- symbol = Makit::Symbols.checkmark if !command.exit_code.nil? && command.exit_code.zero?
277
- symbol = Makit::Symbols.error if command.exit_code != 0
278
- summary = "#{symbol} #{command.name.colorize(:yellow)} #{command.arguments.join(" ")}"
279
-
280
- if summary.length > 80
281
- summary = summary.to_lines(80, command.name.length + 3)
282
- end
283
-
284
- summary
285
- end
286
-
287
- def log_rake_commands
288
- dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
289
- FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
290
-
291
- # open a text file to write to
292
- File.open(File.join(dir, "rake.commands.txt"), "w") do |file|
293
- #rake_commands = commands.select { |command| command.name == "rake" }
294
- commands.each do |command|
295
- file.puts " " + Makit::CommandRunner.get_command_summary(command).strip_color_codes
296
- file.puts " start time: #{command.started_at}"
297
- file.puts command.output.strip_color_codes unless command.output.strip_color_codes.strip.length == 0
298
- file.puts command.error.strip_color_codes unless command.error.strip_color_codes.strip.length == 0
299
- file.puts " "
300
- end
301
- end
302
- end
303
- def log_slowest_commands
304
- dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
305
- FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
306
-
307
- # open a text file to write to
308
- File.open(File.join(dir, "slow.commands.txt"), "w") do |file|
309
- Makit::RUNNER.commands.sort_by { |command| (command.duration.seconds + (command.duration.nanos / 1_000_000_000.0)) }.reverse.first(5).each do |command|
310
- # Convert to float representation
311
- duration_in_float = command.duration.seconds + (command.duration.nanos / 1_000_000_000.0)
312
- #puts " #{command.name} took #{duration_in_float} seconds"
313
- file.puts " " + Makit::CommandRunner.get_command_summary(command).strip_color_codes + " (#{command.duration.seconds} seconds)"
314
- end
315
- end
316
- end
317
- end # class CommandRunner
318
- end # module Makit
1
+ require "English"
2
+ require "open3"
3
+ require "socket"
4
+ require "etc"
5
+ require "logger"
6
+
7
+ # This module provides classes for the Makit gem.
8
+ module Makit
9
+ # This class provide methods running commands.
10
+ #
11
+ class CommandRunner
12
+ attr_accessor :show_output_on_success, :log_to_artifacts, :commands
13
+
14
+ def initialize
15
+ @show_output_on_success = false
16
+ @log_to_artifacts = true
17
+ @commands = []
18
+ end
19
+
20
+ def get_cache_filename(command)
21
+ # test if the command_request is a Makit::V1::CommandRequest
22
+ #if command_request.is_a? Makit::V1::CommandRequest || command_request.is_a? Makit::V1::Command
23
+ # also replacing any path delimiters with an underscore
24
+ int_hash = Digest::SHA256.hexdigest("{command.name}.#{command.arguments.join(" ")}")
25
+ # int_hash
26
+ #int_hash = command_request.to_hash
27
+ hash_string = "#{int_hash}"[0, 8]
28
+ cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
29
+ "/commands/cache/#{hash_string}.pb"
30
+ # create the directory if it does not already exist
31
+ FileUtils.mkdir_p(File.dirname(cache_filename))
32
+ cache_filename
33
+ end
34
+
35
+ # if there is a matching cached command result, that then the specified timestamp,
36
+ # then return the cached result
37
+ # otherwise run the command and save the result to a cache file
38
+ # then return the result
39
+ def cache_run(command_request, timestamp)
40
+ # combine the command name and arguments into a single string
41
+ # and use it to create a cache filename, making sure it is a valid filename,
42
+ # by replacing all characters that are not valid in a filename with an underscore
43
+ # also replacing any path delimiters with an underscore
44
+ int_hash = command_request.to_hash
45
+ hash_string = "#{int_hash}"[0, 8]
46
+ cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
47
+ "/commands/#{hash_string}.pb"
48
+ #puts "cache_filename: #{cache_filename}"
49
+
50
+ #cache_filename = Makit::Directories::PROJECT_ARTIFACTS + "/commands/#{command_request.name}.#{command_request.arguments.join("_")}.#{timestamp.seconds}.pb"
51
+ if File.exist?(cache_filename)
52
+ #puts "cache file date: #{File.mtime(cache_filename)}"
53
+ if (File.mtime(cache_filename) > timestamp)
54
+ #puts "cache_filename exists and is newer than #{timestamp}"
55
+ return Makit::Serializer.open(cache_filename, Makit::V1::Command)
56
+ else
57
+ #puts "cache_filename exists, but is older than #{timestamp}"
58
+ end
59
+ end
60
+
61
+ command = run(command_request)
62
+ # make sure the cache directory exists
63
+ FileUtils.mkdir_p(File.dirname(cache_filename))
64
+ #puts "saving command to cache_filename"
65
+ Makit::Serializer.save_as(cache_filename, command)
66
+ commands.push(command)
67
+ command
68
+ end
69
+
70
+ # Run a command and return a Makit::V1::Command.
71
+ def run(command_request)
72
+ raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
73
+ command = execute(command_request)
74
+ show_output = true
75
+ exit_on_error = true
76
+
77
+ log_to_artifacts(command) if @log_to_artifacts
78
+ if command.exit_code != 0
79
+ puts Makit::CommandRunner.get_command_summary(command) + " (exit code #{command.exit_code})".colorize(:default)
80
+ puts " directory: #{command.directory}\n"
81
+ puts " duration: #{command.duration.seconds} seconds\n"
82
+ puts Makit::Humanize::indent_string(command.output, 2) if command.output.length > 0
83
+ puts Makit::Humanize::indent_string(command.error, 2) if command.error.length > 0
84
+ exit 1 if command_request.exit_on_error
85
+ else
86
+ puts Makit::CommandRunner.get_command_summary(command) + " (#{command.duration.seconds} seconds)".colorize(:cyan)
87
+ puts Makit::Humanize::indent_string(command.output, 2).colorize(:default) if show_output_on_success
88
+ end
89
+
90
+ commands.push(command)
91
+ command
92
+ end
93
+
94
+ def log_to_artifacts(command)
95
+ #dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
96
+ #FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
97
+ #filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
98
+ #log_filename = File.join(dir, "#{filename_friendly_timestamp}.json")
99
+ log_filename = get_cache_filename(command)
100
+ # serialize to protobuf json
101
+ json = command.to_json
102
+ pretty_json = JSON.pretty_generate(JSON.parse(json))
103
+ File.write(log_filename, pretty_json)
104
+ end
105
+
106
+ # Run a command and return a Makit::V1::Command.
107
+ def try(args)
108
+ request = parse_command_request(args)
109
+ request.exit_on_error = false
110
+ run(request)
111
+ #run2(args, false)
112
+ end
113
+
114
+ # Show the output of a command and return a Makit::V1::Command.
115
+ def show(args)
116
+ request = parse_args(args)
117
+ command = execute(request)
118
+
119
+ show_output = true
120
+ exit_on_error = true
121
+ Makit::LOGGER.info(Makit::CommandRunner.get_command_summary(command))
122
+ show_output = true if command.exit_code != 0
123
+ Makit::LOGGER.info(indent_string("\n#{command.output}\n#{command.error}\n".strip, 2)) if show_output
124
+ exit(command.exit_code) if exit_on_error && command.exit_code != 0 # unless process_status.success?
125
+ command
126
+ end
127
+
128
+ # Parse and return a Makit::V1::CommandRequest.
129
+ def parse_command_request(source)
130
+ return Makit::V1::CommandRequest.new(source) if source.is_a? Hash
131
+ return source if source.is_a? Makit::V1::CommandRequest
132
+ if source.is_a? String
133
+ return parse_args(source)
134
+ end
135
+
136
+ raise "Invalid source" unless source.is_a? Makit::V1::CommandRequest
137
+ end
138
+
139
+ def parse_command_request_from_hash(hash)
140
+ raise "Invalid hash" unless hash.is_a? Hash
141
+ Makit::V1::CommandRequest.new(hash)
142
+ end
143
+
144
+ def parse_command_request_from_string(source)
145
+ raise "Invalid source" unless source.is_a? String
146
+ words = source.split(" ")
147
+ hash = {
148
+ name: words.shift,
149
+ arguments: words,
150
+ exit_on_error: true,
151
+ }
152
+ end
153
+
154
+ # Parse the command line arguments into a Makit::V1::CommandRequest.
155
+ def parse_args(args)
156
+ #raise "No command specified" if args.empty?
157
+ if args.is_a? Makit::V1::CommandRequest
158
+ args
159
+ else
160
+ if args.is_a? String
161
+ args = args.split(" ")
162
+ if (args.length == 1)
163
+ hash = {
164
+ name: args[0],
165
+ arguments: [],
166
+ exit_on_error: true,
167
+ }
168
+ Makit::V1::CommandRequest.new(hash)
169
+ else
170
+ hash = {
171
+ name: args.shift,
172
+ arguments: args,
173
+ exit_on_error: true,
174
+ }
175
+
176
+ Makit::V1::CommandRequest.new(hash)
177
+ end
178
+ else
179
+ Makit::V1::CommandRequest.new(args)
180
+ end
181
+ end
182
+ end
183
+
184
+ def get_path_name(name)
185
+ # replace all characters that a not valid in a filename with an underscore
186
+ name.gsub(/[^0-9a-z]/i, "_")
187
+ end
188
+
189
+ # Given a Makit::V1::CommandRequest, execute the command and return a Makit::V1::Command.
190
+ def execute(args)
191
+ command_request = parse_args(args)
192
+ command_request.directory = Dir.pwd if command_request.directory.nil?
193
+ command_request.directory = Dir.pwd if command_request.directory.length == 0
194
+ result = Makit::V1::Command.new(name: command_request.name)
195
+ command_request.arguments.each do |arg|
196
+ result.arguments.push(arg)
197
+ end
198
+ command = "#{command_request.name} #{command_request.arguments.join(" ")}"
199
+ result.directory = command_request.directory
200
+ start = Time.now
201
+ filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
202
+ log_filename = File.join(Makit::Directories::LOG, "#{filename_friendly_timestamp}.log")
203
+
204
+ # assign a directory variable to the current working directory, if not specified,
205
+ # otherwise assign the specified directory
206
+ command_request.directory = Dir.pwd if command_request.directory.nil?
207
+ command_request.directory = Dir.pwd if command_request.directory.length == 0
208
+ raise "Invalid directory" unless Dir.exist?(command_request.directory)
209
+
210
+ result.started_at = Google::Protobuf::Timestamp.new(seconds: start.to_i, nanos: start.nsec.to_i)
211
+ ############# execute the command
212
+ (output, error, exit_code) = execute_command(command, command_request.directory, command_request.timeout)
213
+ result.output = output.force_encoding("ASCII-8BIT")
214
+ result.error = error.force_encoding("ASCII-8BIT")
215
+ result.exit_code = exit_code.nil? ? 0 : exit_code
216
+
217
+ elapsed_time = Time.now - start
218
+ seconds = elapsed_time.to_i
219
+ nanos = ((elapsed_time - seconds) * 1_000_000_000).to_i
220
+
221
+ result.duration = Google::Protobuf::Duration.new(seconds: seconds, nanos: nanos)
222
+
223
+ result
224
+ end
225
+
226
+ # pure function to execute a command
227
+ # returns (stdout, stderr, exit_code) or raise an exception
228
+ def execute_command(command, directory, timeout)
229
+ original_directory = Dir.pwd
230
+ begin
231
+ output = nil
232
+ error = nil
233
+ process_status = nil
234
+ Dir.chdir(directory) do
235
+ output, error, process_status = Open3.capture3(command)
236
+ end
237
+ return [output, error, process_status.exitstatus]
238
+ rescue => e
239
+ # restore the original working directory
240
+ Dir.chdir(original_directory)
241
+ message_parts = []
242
+ message_parts << "failed to execute #{command}"
243
+ message_parts << "directory: #{directory}"
244
+ message_parts << "timeout: #{timeout}" unless timeout.nil?
245
+ message_parts << "error: #{e.message}"
246
+ message = message_parts.join("\n") + "\n"
247
+ return ["", message, 1]
248
+ #raise Makit::Error, message
249
+ end
250
+ end
251
+
252
+ def execute_command_request(command_request)
253
+ # if the command_request is not a Makit::V1::CommandRequest, raise an error
254
+ raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
255
+
256
+ args = Array.new
257
+ command_request.arguments.each do |arg|
258
+ args.push(arg)
259
+ end
260
+ result = Makit::V1::Command.new({
261
+ name: command_request.name,
262
+ arguments: args,
263
+ started_at: Google::Protobuf::Timestamp.new({ seconds: Time.now.to_i, nanos: Time.now.nsec }),
264
+ })
265
+
266
+ begin
267
+ rescue => e
268
+ end
269
+ end
270
+
271
+ def indent_string(input_string, indent_spaces)
272
+ indentation = " " * indent_spaces
273
+ input_string.lines.map { |line| indentation + line }.join
274
+ end
275
+
276
+ def self.get_command_summary(command)
277
+ symbol = Makit::Symbols.warning
278
+ symbol = Makit::Symbols.checkmark if !command.exit_code.nil? && command.exit_code.zero?
279
+ symbol = Makit::Symbols.error if command.exit_code != 0
280
+ summary = "#{symbol} #{command.name.colorize(:yellow)} #{command.arguments.join(" ")}"
281
+
282
+ if summary.length > 80
283
+ summary = summary.to_lines(80, command.name.length + 3)
284
+ end
285
+
286
+ summary
287
+ end
288
+
289
+ def log_rake_commands
290
+ dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
291
+ FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
292
+
293
+ # open a text file to write to
294
+ File.open(File.join(dir, "rake.commands.txt"), "w") do |file|
295
+ #rake_commands = commands.select { |command| command.name == "rake" }
296
+ commands.each do |command|
297
+ file.puts " " + Makit::CommandRunner.get_command_summary(command).strip_color_codes
298
+ file.puts " start time: #{command.started_at}"
299
+ file.puts command.output.strip_color_codes unless command.output.strip_color_codes.strip.length == 0
300
+ file.puts command.error.strip_color_codes unless command.error.strip_color_codes.strip.length == 0
301
+ file.puts " "
302
+ end
303
+ end
304
+ end
305
+
306
+ def log_slowest_commands
307
+ dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
308
+ FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
309
+
310
+ # open a text file to write to
311
+ File.open(File.join(dir, "slow.commands.txt"), "w") do |file|
312
+ Makit::RUNNER.commands.sort_by { |command| (command.duration.seconds + (command.duration.nanos / 1_000_000_000.0)) }.reverse.first(5).each do |command|
313
+ # Convert to float representation
314
+ duration_in_float = command.duration.seconds + (command.duration.nanos / 1_000_000_000.0)
315
+ #puts " #{command.name} took #{duration_in_float} seconds"
316
+ file.puts " " + Makit::CommandRunner.get_command_summary(command).strip_color_codes + " (#{command.duration.seconds} seconds)"
317
+ end
318
+ end
319
+ end
320
+ end # class CommandRunner
321
+ end # module Makit