arduino_ci 0.1.10 → 0.1.11
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.
- 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
|