makit 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) 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_gitignore.txt +222 -0
  17. data/lib/makit/content/default_rakefile.rb +11 -11
  18. data/lib/makit/content/gem_rakefile.rb +14 -14
  19. data/lib/makit/data.rb +50 -50
  20. data/lib/makit/directories.rb +140 -140
  21. data/lib/makit/directory.rb +153 -153
  22. data/lib/makit/dotnet.rb +83 -83
  23. data/lib/makit/environment.rb +123 -123
  24. data/lib/makit/files.rb +47 -47
  25. data/lib/makit/git.rb +66 -66
  26. data/lib/makit/gitlab_runner.rb +60 -60
  27. data/lib/makit/humanize.rb +89 -89
  28. data/lib/makit/logging.rb +96 -96
  29. data/lib/makit/markdown.rb +75 -75
  30. data/lib/makit/mp/basic_object_mp.rb +16 -16
  31. data/lib/makit/mp/project_mp.rb +160 -156
  32. data/lib/makit/mp/string_mp.rb +107 -107
  33. data/lib/makit/nuget.rb +57 -57
  34. data/lib/makit/protoc.rb +61 -61
  35. data/lib/makit/serializer.rb +115 -115
  36. data/lib/makit/storage.rb +131 -131
  37. data/lib/makit/symbols.rb +149 -149
  38. data/lib/makit/tasks.rb +67 -67
  39. data/lib/makit/tree.rb +37 -37
  40. data/lib/makit/v1/makit.v1_pb.rb +4 -3
  41. data/lib/makit/v1/makit.v1_services_pb.rb +25 -25
  42. data/lib/makit/version.rb +12 -12
  43. data/lib/makit/wix.rb +95 -95
  44. data/lib/makit/zip.rb +17 -17
  45. data/lib/makit.rb +243 -243
  46. metadata +4 -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