arduino_ci 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +48 -336
- data/cpp/arduino/Arduino.h +4 -68
- data/cpp/arduino/Godmode.cpp +14 -0
- data/cpp/arduino/Godmode.h +32 -12
- data/cpp/arduino/SPI.h +150 -0
- data/cpp/arduino/ci/Table.h +8 -0
- data/exe/arduino_ci_remote.rb +88 -33
- data/exe/arduino_ci_remote.rb.orig +216 -0
- data/exe/ensure_arduino_installation.rb +5 -0
- data/lib/arduino_ci/arduino_cmd.rb +40 -32
- data/lib/arduino_ci/arduino_cmd_linux.rb +2 -20
- data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -18
- data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
- data/lib/arduino_ci/arduino_downloader.rb +4 -0
- data/lib/arduino_ci/arduino_downloader_linux.rb +2 -0
- data/lib/arduino_ci/arduino_downloader_windows.rb +2 -0
- data/lib/arduino_ci/arduino_installation.rb +6 -3
- data/lib/arduino_ci/ci_config.rb +13 -3
- data/lib/arduino_ci/cpp_library.rb +129 -52
- data/lib/arduino_ci/host.rb +10 -4
- data/lib/arduino_ci/version.rb +1 -1
- metadata +11 -11
- data/lib/arduino_ci/arduino_downloader.rb.orig +0 -219
- data/lib/arduino_ci/arduino_downloader_linux.rb.orig +0 -79
- data/lib/arduino_ci/arduino_downloader_osx.rb.orig +0 -88
- data/lib/arduino_ci/arduino_installation.rb.orig +0 -116
- data/lib/arduino_ci/display_manager.rb +0 -192
@@ -1,116 +0,0 @@
|
|
1
|
-
require "arduino_ci/host"
|
2
|
-
require "arduino_ci/arduino_cmd_osx"
|
3
|
-
require "arduino_ci/arduino_cmd_linux"
|
4
|
-
require "arduino_ci/arduino_cmd_linux_builder"
|
5
|
-
require "arduino_ci/arduino_downloader_linux"
|
6
|
-
require "arduino_ci/arduino_downloader_osx"
|
7
|
-
|
8
|
-
DESIRED_ARDUINO_IDE_VERSION = "1.8.5".freeze
|
9
|
-
|
10
|
-
module ArduinoCI
|
11
|
-
|
12
|
-
# Manage the OS-specific install location of Arduino
|
13
|
-
class ArduinoInstallation
|
14
|
-
|
15
|
-
class << self
|
16
|
-
|
17
|
-
# attempt to find a workable Arduino executable across platforms
|
18
|
-
#
|
19
|
-
# Autolocation assumed to be an expensive operation
|
20
|
-
# @return [ArduinoCI::ArduinoCmd] an instance of the command or nil if it can't be found
|
21
|
-
def autolocate
|
22
|
-
ret = nil
|
23
|
-
case Host.os
|
24
|
-
when :osx then
|
25
|
-
ret = autolocate_osx
|
26
|
-
when :linux then
|
27
|
-
<<<<<<< HEAD
|
28
|
-
loc = ArduinoDownloaderLinux.autolocation
|
29
|
-
return nil if loc.nil?
|
30
|
-
ret = ArduinoCmdLinux.new
|
31
|
-
ret.base_cmd = [loc]
|
32
|
-
=======
|
33
|
-
loc = ArduinoDownloaderLinux.autolocated_executable
|
34
|
-
return nil if loc.nil?
|
35
|
-
ret = ArduinoCmdLinux.new
|
36
|
-
ret.base_cmd = [loc]
|
37
|
-
# when :windows then
|
38
|
-
# ArduinoDownloaderWindows.autolocation
|
39
|
-
# return nil if loc.nil?
|
40
|
-
# ret = ArduinoCmdWindows.new
|
41
|
-
# ret.base_cmd = [loc]
|
42
|
-
>>>>>>> Refactor force_install code in preparation for windows CI
|
43
|
-
end
|
44
|
-
ret
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [ArduinoCI::ArduinoCmdOSX] an instance of the command or nil if it can't be found
|
48
|
-
def autolocate_osx
|
49
|
-
<<<<<<< HEAD
|
50
|
-
osx_root = ArduinoDownloaderOSX.autolocation
|
51
|
-
=======
|
52
|
-
osx_root = ArduinoDownloaderOSX.autolocated_installation
|
53
|
-
return nil if osx_root.nil?
|
54
|
-
>>>>>>> Refactor force_install code in preparation for windows CI
|
55
|
-
return nil unless File.exist? osx_root
|
56
|
-
|
57
|
-
launchers = [
|
58
|
-
# try a hack that skips splash screen
|
59
|
-
# from https://github.com/arduino/Arduino/issues/1970#issuecomment-321975809
|
60
|
-
[
|
61
|
-
"java",
|
62
|
-
"-cp", "#{osx_root}/Java/*",
|
63
|
-
"-DAPP_DIR=#{osx_root}/Java",
|
64
|
-
"-Dfile.encoding=UTF-8",
|
65
|
-
"-Dapple.awt.UIElement=true",
|
66
|
-
"-Xms128M",
|
67
|
-
"-Xmx512M",
|
68
|
-
"processing.app.Base",
|
69
|
-
],
|
70
|
-
# failsafe way
|
71
|
-
[File.join(osx_root, "MacOS", "Arduino")]
|
72
|
-
]
|
73
|
-
|
74
|
-
# create return and find a command launcher that works
|
75
|
-
ret = ArduinoCmdOSX.new
|
76
|
-
launchers.each do |launcher|
|
77
|
-
# test whether this method successfully launches the IDE
|
78
|
-
# note that "successful launch" involves a command that will fail,
|
79
|
-
# because that's faster than any command which succeeds. what we
|
80
|
-
# don't want to see is a java error.
|
81
|
-
args = launcher + ["--bogus-option"]
|
82
|
-
result = Host.run_and_capture(*args)
|
83
|
-
if result[:err].include? "Error: unknown option: --bogus-option"
|
84
|
-
ret.base_cmd = launcher
|
85
|
-
return ret
|
86
|
-
end
|
87
|
-
end
|
88
|
-
nil
|
89
|
-
end
|
90
|
-
|
91
|
-
# Attempt to find a workable Arduino executable across platforms, and install it if we don't
|
92
|
-
# @return [ArduinoCI::ArduinoCmd] an instance of a command
|
93
|
-
def autolocate!
|
94
|
-
candidate = autolocate
|
95
|
-
return candidate unless candidate.nil?
|
96
|
-
|
97
|
-
# force the install
|
98
|
-
force_install
|
99
|
-
autolocate
|
100
|
-
end
|
101
|
-
|
102
|
-
# Forcibly install Arduino from the web
|
103
|
-
# @return [bool] Whether the command succeeded
|
104
|
-
def force_install
|
105
|
-
worker_class = case Host.os
|
106
|
-
when :osx then ArduinoDownloaderOSX
|
107
|
-
# when :windows then force_install_windows
|
108
|
-
when :linux then ArduinoDownloaderLinux
|
109
|
-
end
|
110
|
-
worker = worker_class.new(DESIRED_ARDUINO_IDE_VERSION)
|
111
|
-
worker.execute
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
@@ -1,192 +0,0 @@
|
|
1
|
-
require 'arduino_ci/host'
|
2
|
-
require 'singleton'
|
3
|
-
require 'timeout'
|
4
|
-
|
5
|
-
DESIRED_DISPLAY = ":1.0".freeze
|
6
|
-
|
7
|
-
module ArduinoCI
|
8
|
-
|
9
|
-
# When arduino commands run, they need a graphical display.
|
10
|
-
# This class handles the setup of that display, if needed.
|
11
|
-
class DisplayManager
|
12
|
-
include Singleton
|
13
|
-
|
14
|
-
# @return [bool] whether the display manager is currently active
|
15
|
-
attr_reader :enabled
|
16
|
-
|
17
|
-
# @return [bool] whether to log messages to the terminal
|
18
|
-
attr_accessor :debug
|
19
|
-
|
20
|
-
def initialize
|
21
|
-
@existing = existing_display?
|
22
|
-
@enabled = false
|
23
|
-
@pid = nil
|
24
|
-
@debug = false
|
25
|
-
|
26
|
-
# pipes for input and output
|
27
|
-
@xv_pipe_out_wr = nil
|
28
|
-
@xv_pipe_err_wr = nil
|
29
|
-
@xv_pipe_out = nil
|
30
|
-
@xv_pipe_err = nil
|
31
|
-
end
|
32
|
-
|
33
|
-
# attempt to determine if the machine is running a graphical display (i.e. not Travis)
|
34
|
-
# @return [bool] whether there is already a GUI that can accept windows
|
35
|
-
def existing_display?
|
36
|
-
return true if RUBY_PLATFORM.include? "darwin"
|
37
|
-
return true if Host.os == :windows
|
38
|
-
return false if ENV["DISPLAY"].nil?
|
39
|
-
return true if ENV["DISPLAY"].include? ":"
|
40
|
-
false
|
41
|
-
end
|
42
|
-
|
43
|
-
# check whether a process is alive
|
44
|
-
# https://stackoverflow.com/a/32513298/2063546
|
45
|
-
# @param pid [Int] the process ID
|
46
|
-
# @return [bool]
|
47
|
-
def alive?(pid)
|
48
|
-
Process.kill(0, pid)
|
49
|
-
true
|
50
|
-
rescue
|
51
|
-
false
|
52
|
-
end
|
53
|
-
|
54
|
-
# check whether an X server is taking connections
|
55
|
-
# @param display [String] the display variable as it would be specified in the environment
|
56
|
-
# @return [bool]
|
57
|
-
def xserver_exist?(display)
|
58
|
-
system({ "DISPLAY" => display }, "xdpyinfo", out: File::NULL, err: File::NULL)
|
59
|
-
end
|
60
|
-
|
61
|
-
# wait for the xvfb command to launch
|
62
|
-
# @param display [String] the value of the DISPLAY env var
|
63
|
-
# @param pid [Int] the process of Xvfb
|
64
|
-
# @param timeout [Int] the timeout in seconds
|
65
|
-
# @return [Bool] whether we detected a launch
|
66
|
-
def xvfb_launched?(display, pid, timeout)
|
67
|
-
Timeout.timeout(timeout) do
|
68
|
-
loop do
|
69
|
-
unless alive? pid
|
70
|
-
puts "Xvfb process has died"
|
71
|
-
return false
|
72
|
-
end
|
73
|
-
x = xserver_exist? display
|
74
|
-
puts "xdpyinfo reports X server status as #{x}" if debug
|
75
|
-
return true if x
|
76
|
-
sleep(0.1)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
rescue Timeout::Error
|
80
|
-
false
|
81
|
-
end
|
82
|
-
|
83
|
-
# enable a virtual display
|
84
|
-
def enable
|
85
|
-
if @existing
|
86
|
-
puts "DisplayManager enable: no-op for what appears to be an existing display" if debug
|
87
|
-
@enabled = true
|
88
|
-
return
|
89
|
-
end
|
90
|
-
|
91
|
-
return unless @pid.nil? # TODO: disable first?
|
92
|
-
@xv_pipe_out.close unless @xv_pipe_out.nil?
|
93
|
-
@xv_pipe_err.close unless @xv_pipe_err.nil?
|
94
|
-
|
95
|
-
# open Xvfb
|
96
|
-
xvfb_cmd = [
|
97
|
-
"Xvfb",
|
98
|
-
"+extension", "RANDR",
|
99
|
-
":1",
|
100
|
-
"-ac",
|
101
|
-
"-screen", "0",
|
102
|
-
"1280x1024x16",
|
103
|
-
]
|
104
|
-
puts "Xvfb launching" if debug
|
105
|
-
|
106
|
-
@xv_pipe_out, @xv_pipe_out_wr = IO.pipe
|
107
|
-
@xv_pipe_err, @xv_pipe_err_wr = IO.pipe
|
108
|
-
pipe = IO.popen(xvfb_cmd, stdout: @xv_pipe_out_wr, err: @xv_pipe_err_wr)
|
109
|
-
@pid = pipe.pid
|
110
|
-
@enabled = xvfb_launched?(DESIRED_DISPLAY, @pid, 30)
|
111
|
-
end
|
112
|
-
|
113
|
-
# disable the virtual display
|
114
|
-
def disable
|
115
|
-
if @existing
|
116
|
-
puts "DisplayManager disable: no-op for what appears to be an existing display" if debug
|
117
|
-
return @enabled = false
|
118
|
-
end
|
119
|
-
|
120
|
-
return @enabled = false if @pid.nil?
|
121
|
-
|
122
|
-
# https://www.whatastruggle.com/timeout-a-subprocess-in-ruby
|
123
|
-
begin
|
124
|
-
Timeout.timeout(30) do
|
125
|
-
Process.kill("TERM", @pid)
|
126
|
-
puts "Xvfb TERMed" if debug
|
127
|
-
end
|
128
|
-
rescue Timeout::Error
|
129
|
-
Process.kill(9, @pid)
|
130
|
-
puts "Xvfb KILLed" if debug
|
131
|
-
ensure
|
132
|
-
Process.wait @pid
|
133
|
-
@enabled = false
|
134
|
-
@pid = nil
|
135
|
-
|
136
|
-
@xv_pipe_out_wr.close
|
137
|
-
@xv_pipe_err_wr.close
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
# Enable a virtual display for the duration of the given block
|
142
|
-
# @yield [environment] The code to execute within the display environment
|
143
|
-
# @yieldparam [Hash] the environment variables relating to the display
|
144
|
-
def with_display
|
145
|
-
was_enabled = @enabled
|
146
|
-
enable unless was_enabled
|
147
|
-
begin
|
148
|
-
yield environment
|
149
|
-
ensure
|
150
|
-
disable unless was_enabled
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def wrap_run(work_fn, *args, **kwargs)
|
155
|
-
ret = nil
|
156
|
-
# do some work to extract & merge environment variables if they exist
|
157
|
-
has_env = !args.empty? && args[0].class == Hash
|
158
|
-
with_display do |env_vars|
|
159
|
-
env_vars = {} if env_vars.nil?
|
160
|
-
env_vars.merge!(args[0]) if has_env
|
161
|
-
actual_args = has_env ? args[1..-1] : args # need to shift over if we extracted args
|
162
|
-
full_cmd = env_vars.empty? ? actual_args : [env_vars] + actual_args
|
163
|
-
ret = work_fn.call(*full_cmd, **kwargs)
|
164
|
-
end
|
165
|
-
ret
|
166
|
-
end
|
167
|
-
|
168
|
-
# run a command in a display, outputting to stdout
|
169
|
-
# @return [bool]
|
170
|
-
def run_and_output(*args, **kwargs)
|
171
|
-
wrap_run((proc { |*a, **k| Host.run_and_output(*a, **k) }), *args, **kwargs)
|
172
|
-
end
|
173
|
-
|
174
|
-
# run a command in a display, capturing output
|
175
|
-
# @return [bool]
|
176
|
-
def run_and_capture(*args, **kwargs)
|
177
|
-
wrap_run((proc { |*a, **k| Host.run_and_capture(*a, **k) }), *args, **kwargs)
|
178
|
-
end
|
179
|
-
|
180
|
-
# @return [Hash] the environment variables for the display
|
181
|
-
def environment
|
182
|
-
return nil unless @existing || @enabled
|
183
|
-
return { "EXISTING_DISPLAY" => "YES" } if @existing
|
184
|
-
{ "DISPLAY" => DESIRED_DISPLAY }
|
185
|
-
end
|
186
|
-
|
187
|
-
# On finalize, ensure child process is ended
|
188
|
-
def self.finalize
|
189
|
-
disable
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|