arduino_ci 0.1.21 → 1.0.0
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 +49 -20
- data/REFERENCE.md +625 -0
- data/cpp/arduino/Arduino.h +1 -1
- data/cpp/arduino/AvrMath.h +117 -17
- data/cpp/arduino/Client.h +27 -0
- data/cpp/arduino/EEPROM.h +64 -0
- data/cpp/arduino/Godmode.cpp +38 -19
- data/cpp/arduino/Godmode.h +88 -22
- data/cpp/arduino/HardwareSerial.h +9 -28
- data/cpp/arduino/IPAddress.h +59 -0
- data/cpp/arduino/MockEventQueue.h +86 -0
- data/cpp/arduino/PinHistory.h +64 -24
- data/cpp/arduino/Print.h +9 -12
- data/cpp/arduino/Printable.h +8 -0
- data/cpp/arduino/SPI.h +11 -3
- data/cpp/arduino/Server.h +5 -0
- data/cpp/arduino/Udp.h +27 -0
- data/cpp/arduino/Wire.h +234 -0
- data/cpp/arduino/avr/io.h +10 -1
- data/cpp/arduino/avr/pgmspace.h +76 -46
- data/cpp/arduino/ci/StreamTape.h +36 -0
- data/cpp/unittest/OstreamHelpers.h +4 -0
- data/exe/arduino_ci.rb +400 -0
- data/exe/arduino_ci_remote.rb +2 -385
- data/exe/arduino_library_location.rb +2 -2
- data/lib/arduino_ci.rb +1 -0
- data/lib/arduino_ci/arduino_backend.rb +218 -0
- data/lib/arduino_ci/arduino_downloader.rb +42 -72
- data/lib/arduino_ci/arduino_downloader_linux.rb +17 -55
- data/lib/arduino_ci/arduino_downloader_osx.rb +21 -33
- data/lib/arduino_ci/arduino_downloader_windows.rb +11 -53
- data/lib/arduino_ci/arduino_installation.rb +18 -80
- data/lib/arduino_ci/ci_config.rb +12 -7
- data/lib/arduino_ci/cpp_library.rb +262 -48
- data/lib/arduino_ci/host.rb +59 -4
- data/lib/arduino_ci/library_properties.rb +96 -0
- data/lib/arduino_ci/version.rb +1 -1
- data/misc/default.yml +55 -4
- metadata +18 -83
- data/cpp/arduino/Arduino.h.orig +0 -143
- data/cpp/arduino/ci/Queue.h +0 -73
- data/exe/libasan.rb +0 -29
- data/lib/arduino_ci/arduino_cmd.rb +0 -328
- data/lib/arduino_ci/arduino_cmd_linux.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -19
- data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
@@ -2,6 +2,6 @@
|
|
2
2
|
require 'arduino_ci'
|
3
3
|
|
4
4
|
# locate and/or forcibly install Arduino, keep stdout clean
|
5
|
-
@
|
5
|
+
@backend = ArduinoCI::ArduinoInstallation.autolocate!($stderr)
|
6
6
|
|
7
|
-
puts @
|
7
|
+
puts @backend.lib_dir
|
data/lib/arduino_ci.rb
CHANGED
@@ -2,6 +2,7 @@ require "arduino_ci/version"
|
|
2
2
|
require "arduino_ci/arduino_installation"
|
3
3
|
require "arduino_ci/cpp_library"
|
4
4
|
require "arduino_ci/ci_config"
|
5
|
+
require "arduino_ci/library_properties"
|
5
6
|
|
6
7
|
# ArduinoCI contains classes for automated testing of Arduino code on the command line
|
7
8
|
# @author Ian Katz <ianfixes@gmail.com>
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# workaround for https://github.com/arduino/Arduino/issues/3535
|
6
|
+
WORKAROUND_LIB = "USBHost".freeze
|
7
|
+
|
8
|
+
module ArduinoCI
|
9
|
+
|
10
|
+
# To report errors that we can't resolve or possibly even explain
|
11
|
+
class ArduinoExecutionError < StandardError; end
|
12
|
+
|
13
|
+
# Wrap the Arduino executable. This requires, in some cases, a faked display.
|
14
|
+
class ArduinoBackend
|
15
|
+
|
16
|
+
# We never even use this in code, it's just here for reference because the backend is picky about it. Used for testing
|
17
|
+
# @return [String] the only allowable name for the arduino-cli config file.
|
18
|
+
CONFIG_FILE_NAME = "arduino-cli.yaml".freeze
|
19
|
+
|
20
|
+
# the actual path to the executable on this platform
|
21
|
+
# @return [Pathname]
|
22
|
+
attr_accessor :binary_path
|
23
|
+
|
24
|
+
# If a custom config is deired (i.e. for testing), specify it here.
|
25
|
+
# Note https://github.com/arduino/arduino-cli/issues/753 : the --config-file option
|
26
|
+
# is really the director that contains the file
|
27
|
+
# @return [Pathname]
|
28
|
+
attr_accessor :config_dir
|
29
|
+
|
30
|
+
# @return [String] STDOUT of the most recently-run command
|
31
|
+
attr_reader :last_out
|
32
|
+
|
33
|
+
# @return [String] STDERR of the most recently-run command
|
34
|
+
attr_reader :last_err
|
35
|
+
|
36
|
+
# @return [String] the most recently-run command
|
37
|
+
attr_reader :last_msg
|
38
|
+
|
39
|
+
# @return [Array<String>] Additional URLs for the boards manager
|
40
|
+
attr_reader :additional_urls
|
41
|
+
|
42
|
+
def initialize(binary_path)
|
43
|
+
@binary_path = binary_path
|
44
|
+
@config_dir = nil
|
45
|
+
@additional_urls = []
|
46
|
+
@last_out = ""
|
47
|
+
@last_err = ""
|
48
|
+
@last_msg = ""
|
49
|
+
end
|
50
|
+
|
51
|
+
def _wrap_run(work_fn, *args, **kwargs)
|
52
|
+
# do some work to extract & merge environment variables if they exist
|
53
|
+
has_env = !args.empty? && args[0].class == Hash
|
54
|
+
env_vars = has_env ? args[0] : {}
|
55
|
+
actual_args = has_env ? args[1..-1] : args # need to shift over if we extracted args
|
56
|
+
custom_config = @config_dir.nil? ? [] : ["--config-file", @config_dir.to_s]
|
57
|
+
full_args = [binary_path.to_s, "--format", "json"] + custom_config + actual_args
|
58
|
+
full_cmd = env_vars.empty? ? full_args : [env_vars] + full_args
|
59
|
+
|
60
|
+
shell_vars = env_vars.map { |k, v| "#{k}=#{v}" }.join(" ")
|
61
|
+
@last_msg = " $ #{shell_vars} #{full_args.join(' ')}"
|
62
|
+
work_fn.call(*full_cmd, **kwargs)
|
63
|
+
end
|
64
|
+
|
65
|
+
# build and run the arduino command
|
66
|
+
def run_and_output(*args, **kwargs)
|
67
|
+
_wrap_run((proc { |*a, **k| Host.run_and_output(*a, **k) }), *args, **kwargs)
|
68
|
+
end
|
69
|
+
|
70
|
+
# run a command and capture its output
|
71
|
+
# @return [Hash] {:out => String, :err => String, :success => bool}
|
72
|
+
def run_and_capture(*args, **kwargs)
|
73
|
+
ret = _wrap_run((proc { |*a, **k| Host.run_and_capture(*a, **k) }), *args, **kwargs)
|
74
|
+
@last_err = ret[:err]
|
75
|
+
@last_out = ret[:out]
|
76
|
+
ret
|
77
|
+
end
|
78
|
+
|
79
|
+
def capture_json(*args, **kwargs)
|
80
|
+
ret = run_and_capture(*args, **kwargs)
|
81
|
+
ret[:json] = JSON.parse(ret[:out])
|
82
|
+
ret
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get a dump of the entire config
|
86
|
+
# @return [Hash] The configuration
|
87
|
+
def config_dump
|
88
|
+
capture_json("config", "dump")[:json]
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [String] the path to the Arduino libraries directory
|
92
|
+
def lib_dir
|
93
|
+
Pathname.new(config_dump["directories"]["user"]) + "libraries"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Board manager URLs
|
97
|
+
# @return [Array<String>] The additional URLs used by the board manager
|
98
|
+
def board_manager_urls
|
99
|
+
config_dump["board_manager"]["additional_urls"] + @additional_urls
|
100
|
+
end
|
101
|
+
|
102
|
+
# Set board manager URLs
|
103
|
+
# @return [Array<String>] The additional URLs used by the board manager
|
104
|
+
def board_manager_urls=(all_urls)
|
105
|
+
raise ArgumentError("all_urls should be an array, got #{all_urls.class}") unless all_urls.is_a? Array
|
106
|
+
|
107
|
+
@additional_urls = all_urls
|
108
|
+
end
|
109
|
+
|
110
|
+
# check whether a board is installed
|
111
|
+
# we do this by just selecting a board.
|
112
|
+
# the arduino binary will error if unrecognized and do a successful no-op if it's installed
|
113
|
+
# @param boardname [String] The board to test
|
114
|
+
# @return [bool] Whether the board is installed
|
115
|
+
def board_installed?(boardname)
|
116
|
+
# capture_json("core", "list")[:json].find { |b| b["ID"] == boardname } # nope, this is for the family
|
117
|
+
run_and_capture("board", "details", "--fqbn", boardname)[:success]
|
118
|
+
end
|
119
|
+
|
120
|
+
# install a board by name
|
121
|
+
# @param name [String] the board name
|
122
|
+
# @return [bool] whether the command succeeded
|
123
|
+
def install_boards(boardfamily)
|
124
|
+
result = run_and_capture("core", "install", boardfamily)
|
125
|
+
result[:success]
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [Hash] information about installed libraries via the CLI
|
129
|
+
def installed_libraries
|
130
|
+
capture_json("lib", "list")[:json]
|
131
|
+
end
|
132
|
+
|
133
|
+
# @param path [String] The sketch to compile
|
134
|
+
# @param boardname [String] The board to use
|
135
|
+
# @return [bool] whether the command succeeded
|
136
|
+
def compile_sketch(path, boardname)
|
137
|
+
ext = File.extname path
|
138
|
+
unless ext.casecmp(".ino").zero?
|
139
|
+
@last_msg = "Refusing to compile sketch with '#{ext}' extension -- rename it to '.ino'!"
|
140
|
+
return false
|
141
|
+
end
|
142
|
+
unless File.exist? path
|
143
|
+
@last_msg = "Can't compile Sketch at nonexistent path '#{path}'!"
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
ret = run_and_capture("compile", "--fqbn", boardname, "--warnings", "all", "--dry-run", path.to_s)
|
147
|
+
ret[:success]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Guess the name of a library
|
151
|
+
# @param path [Pathname] The path to the library (installed or not)
|
152
|
+
# @return [String] the probable library name
|
153
|
+
def name_of_library(path)
|
154
|
+
src_path = path.realpath
|
155
|
+
properties_file = src_path + CppLibrary::LIBRARY_PROPERTIES_FILE
|
156
|
+
return src_path.basename.to_s unless properties_file.exist?
|
157
|
+
return src_path.basename.to_s if LibraryProperties.new(properties_file).name.nil?
|
158
|
+
|
159
|
+
LibraryProperties.new(properties_file).name
|
160
|
+
end
|
161
|
+
|
162
|
+
# Create a handle to an Arduino library by name
|
163
|
+
# @param name [String] The library "real name"
|
164
|
+
# @return [CppLibrary] The library object
|
165
|
+
def library_of_name(name)
|
166
|
+
raise ArgumentError, "name is not a String (got #{name.class})" unless name.is_a? String
|
167
|
+
|
168
|
+
CppLibrary.new(name, self)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create a handle to an Arduino library by path
|
172
|
+
# @param path [Pathname] The path to the library
|
173
|
+
# @return [CppLibrary] The library object
|
174
|
+
def library_of_path(path)
|
175
|
+
# the path must exist... and if it does, brute-force search the installed libs for it
|
176
|
+
realpath = path.realpath # should produce error if the path doesn't exist to begin with
|
177
|
+
entry = installed_libraries.find { |l| Pathname.new(l["library"]["install_dir"]).realpath == realpath }
|
178
|
+
probable_name = entry["real_name"].nil? ? realpath.basename.to_s : entry["real_name"]
|
179
|
+
CppLibrary.new(probable_name, self)
|
180
|
+
end
|
181
|
+
|
182
|
+
# install a library from a path on the local machine (not via library manager), by symlink or no-op as appropriate
|
183
|
+
# @param path [Pathname] library to use
|
184
|
+
# @return [CppLibrary] the installed library, or nil
|
185
|
+
def install_local_library(path)
|
186
|
+
src_path = path.realpath
|
187
|
+
library_name = name_of_library(path)
|
188
|
+
cpp_library = library_of_name(library_name)
|
189
|
+
destination_path = cpp_library.path
|
190
|
+
|
191
|
+
# things get weird if the sketchbook contains the library.
|
192
|
+
# check that first
|
193
|
+
if cpp_library.installed?
|
194
|
+
# maybe the project has always lived in the libraries directory, no need to symlink
|
195
|
+
return cpp_library if destination_path == src_path
|
196
|
+
|
197
|
+
uhoh = "There is already a library '#{library_name}' in the library directory (#{destination_path})"
|
198
|
+
# maybe it's a symlink? that would be OK
|
199
|
+
if Host.symlink?(destination_path)
|
200
|
+
current_destination_target = Host.readlink(destination_path)
|
201
|
+
return cpp_library if current_destination_target == src_path
|
202
|
+
|
203
|
+
@last_msg = "#{uhoh} and it's symlinked to #{current_destination_target} (expected #{src_path})"
|
204
|
+
return nil
|
205
|
+
end
|
206
|
+
|
207
|
+
@last_msg = "#{uhoh}. It may need to be removed manually."
|
208
|
+
return nil
|
209
|
+
end
|
210
|
+
|
211
|
+
# install the library
|
212
|
+
libraries_dir = destination_path.parent
|
213
|
+
libraries_dir.mkpath unless libraries_dir.exist?
|
214
|
+
Host.symlink(src_path, destination_path)
|
215
|
+
cpp_library
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'pathname'
|
2
3
|
require 'net/http'
|
3
4
|
require 'open-uri'
|
4
5
|
require 'zip'
|
@@ -10,10 +11,10 @@ module ArduinoCI
|
|
10
11
|
# Manage the OS-specific download & install of Arduino
|
11
12
|
class ArduinoDownloader
|
12
13
|
|
13
|
-
# @param
|
14
|
+
# @param desired_version [string] Version string e.g. 1.8.7
|
14
15
|
# @param output [IO] $stdout, $stderr, File.new(/dev/null, 'w'), etc. where console output will be sent
|
15
|
-
def initialize(
|
16
|
-
@
|
16
|
+
def initialize(desired_version, output = $stdout)
|
17
|
+
@desired_version = desired_version
|
17
18
|
@output = output
|
18
19
|
end
|
19
20
|
|
@@ -30,7 +31,7 @@ module ArduinoCI
|
|
30
31
|
|
31
32
|
# The autolocated executable of the installation
|
32
33
|
#
|
33
|
-
# @return [
|
34
|
+
# @return [Pathname] or nil
|
34
35
|
def self.autolocated_executable
|
35
36
|
# Arbitrarily, I'm going to pick the force installed location first
|
36
37
|
# if it exists. I'm not sure why we would have both, but if we did
|
@@ -39,70 +40,54 @@ module ArduinoCI
|
|
39
40
|
locations.find { |loc| !loc.nil? && File.exist?(loc) }
|
40
41
|
end
|
41
42
|
|
42
|
-
# The
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
# Arbitrarily, I'm going to pick the force installed location first
|
47
|
-
# if it exists. I'm not sure why we would have both, but if we did
|
48
|
-
# a force install then let's make sure we actually use it.
|
49
|
-
locations = [self.force_install_location, self.existing_installation]
|
50
|
-
locations.find { |loc| !loc.nil? && File.exist?(loc) }
|
43
|
+
# The executable Arduino file in an existing installation, or nil
|
44
|
+
# @return [Pathname]
|
45
|
+
def self.existing_executable
|
46
|
+
self.must_implement(__method__)
|
51
47
|
end
|
52
48
|
|
53
|
-
# The
|
49
|
+
# The local file (dir) name of the desired IDE package (zip/tar/etc)
|
54
50
|
# @return [string]
|
55
|
-
def
|
56
|
-
self.must_implement(__method__)
|
51
|
+
def package_file
|
52
|
+
self.class.must_implement(__method__)
|
57
53
|
end
|
58
54
|
|
59
|
-
# The
|
55
|
+
# The local filename of the extracted IDE package (zip/tar/etc)
|
60
56
|
# @return [string]
|
61
|
-
def self.
|
57
|
+
def self.extracted_file
|
62
58
|
self.must_implement(__method__)
|
63
59
|
end
|
64
60
|
|
65
61
|
# The executable Arduino file in a forced installation, or nil
|
66
|
-
# @return [
|
62
|
+
# @return [Pathname]
|
67
63
|
def self.force_installed_executable
|
68
|
-
|
64
|
+
Pathname.new(ENV['HOME']) + self.extracted_file
|
69
65
|
end
|
70
66
|
|
71
67
|
# The technology that will be used to complete the download
|
72
68
|
# (for logging purposes)
|
73
69
|
# @return [string]
|
74
|
-
def downloader
|
70
|
+
def self.downloader
|
75
71
|
"open-uri"
|
76
72
|
end
|
77
73
|
|
78
74
|
# The technology that will be used to extract the download
|
79
75
|
# (for logging purposes)
|
80
76
|
# @return [string]
|
81
|
-
def extracter
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
# The URL of the desired IDE package (zip/tar/etc) for this platform
|
86
|
-
# @return [string]
|
87
|
-
def package_url
|
88
|
-
"https://downloads.arduino.cc/#{package_file}"
|
77
|
+
def self.extracter
|
78
|
+
self.must_implement(__method__)
|
89
79
|
end
|
90
80
|
|
91
|
-
#
|
92
|
-
# @return [
|
93
|
-
def
|
94
|
-
self.
|
81
|
+
# Extract the package_file to extracted_file
|
82
|
+
# @return [bool] whether successful
|
83
|
+
def self.extract(_package_file)
|
84
|
+
self.must_implement(__method__)
|
95
85
|
end
|
96
86
|
|
97
|
-
# The
|
87
|
+
# The URL of the desired IDE package (zip/tar/etc) for this platform
|
98
88
|
# @return [string]
|
99
|
-
def
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
# @return [String] The location where a forced install will go
|
104
|
-
def self.force_install_location
|
105
|
-
File.join(ENV['HOME'], 'arduino_ci_ide')
|
89
|
+
def package_url
|
90
|
+
"https://github.com/arduino/arduino-cli/releases/download/#{@desired_version}/#{package_file}"
|
106
91
|
end
|
107
92
|
|
108
93
|
# Download the package_url to package_file
|
@@ -130,26 +115,10 @@ module ArduinoCI
|
|
130
115
|
@output.puts "\nArduino force-install failed downloading #{package_url}: #{e}"
|
131
116
|
end
|
132
117
|
|
133
|
-
#
|
134
|
-
# @return [bool] whether successful
|
135
|
-
def extract
|
136
|
-
Zip::File.open(package_file) do |zip|
|
137
|
-
batch_size = [1, (zip.size / 100).to_i].max
|
138
|
-
dots = 0
|
139
|
-
zip.each do |file|
|
140
|
-
@output.print "." if (dots % batch_size).zero?
|
141
|
-
file.restore_permissions = true
|
142
|
-
file.extract { accept_all }
|
143
|
-
dots += 1
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Move the extracted package file from extracted_file to the force_install_location
|
118
|
+
# Move the extracted package file from extracted_file to the force_installed_executable
|
149
119
|
# @return [bool] whether successful
|
150
120
|
def install
|
151
|
-
|
152
|
-
FileUtils.mv extracted_file, self.class.force_install_location
|
121
|
+
FileUtils.mv self.class.extracted_file.to_s, self.class.force_installed_executable.to_s
|
153
122
|
end
|
154
123
|
|
155
124
|
# Forcibly install Arduino on linux from the web
|
@@ -161,39 +130,40 @@ module ArduinoCI
|
|
161
130
|
return false
|
162
131
|
end
|
163
132
|
|
133
|
+
arduino_package = "Arduino #{@desired_version} package"
|
164
134
|
attempts = 0
|
165
135
|
|
166
136
|
loop do
|
167
|
-
if File.exist?
|
168
|
-
@output.puts "
|
137
|
+
if File.exist?(package_file)
|
138
|
+
@output.puts "#{arduino_package} seems to have been downloaded already at #{package_file}" if attempts.zero?
|
169
139
|
break
|
170
140
|
elsif attempts >= DOWNLOAD_ATTEMPTS
|
171
141
|
break @output.puts "After #{DOWNLOAD_ATTEMPTS} attempts, failed to download #{package_url}"
|
172
142
|
else
|
173
|
-
@output.print "Attempting to download
|
143
|
+
@output.print "Attempting to download #{arduino_package} with #{self.class.downloader}"
|
174
144
|
download
|
175
145
|
@output.puts
|
176
146
|
end
|
177
147
|
attempts += 1
|
178
148
|
end
|
179
149
|
|
180
|
-
if File.exist?
|
181
|
-
@output.puts "
|
182
|
-
elsif File.exist?
|
183
|
-
@output.print "Extracting archive with #{extracter}"
|
184
|
-
extract
|
150
|
+
if File.exist?(self.class.extracted_file)
|
151
|
+
@output.puts "#{arduino_package} seems to have been extracted already at #{self.class.extracted_file}"
|
152
|
+
elsif File.exist?(package_file)
|
153
|
+
@output.print "Extracting archive with #{self.class.extracter}"
|
154
|
+
self.class.extract(package_file)
|
185
155
|
@output.puts
|
186
156
|
end
|
187
157
|
|
188
|
-
if File.exist?
|
189
|
-
@output.puts "
|
190
|
-
elsif File.exist?
|
158
|
+
if File.exist?(self.class.force_installed_executable)
|
159
|
+
@output.puts "#{arduino_package} seems to have been installed already at #{self.class.force_installed_executable}"
|
160
|
+
elsif File.exist?(self.class.extracted_file)
|
191
161
|
install
|
192
162
|
else
|
193
|
-
@output.puts "Could not find extracted archive (tried #{extracted_file})"
|
163
|
+
@output.puts "Could not find extracted archive (tried #{self.class.extracted_file})"
|
194
164
|
end
|
195
165
|
|
196
|
-
File.exist?
|
166
|
+
File.exist?(self.class.force_installed_executable)
|
197
167
|
end
|
198
168
|
|
199
169
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require "arduino_ci/arduino_downloader"
|
2
2
|
|
3
|
-
USE_BUILDER = false
|
4
|
-
|
5
3
|
module ArduinoCI
|
6
4
|
|
7
5
|
# Manage the linux download & install of Arduino
|
@@ -10,13 +8,25 @@ module ArduinoCI
|
|
10
8
|
# The local filename of the desired IDE package (zip/tar/etc)
|
11
9
|
# @return [string]
|
12
10
|
def package_file
|
13
|
-
"#{
|
11
|
+
"arduino-cli_#{@desired_version}_Linux_64bit.tar.gz"
|
12
|
+
end
|
13
|
+
|
14
|
+
# The local file (dir) name of the extracted IDE package (zip/tar/etc)
|
15
|
+
# @return [string]
|
16
|
+
def self.extracted_file
|
17
|
+
"arduino-cli"
|
18
|
+
end
|
19
|
+
|
20
|
+
# The executable Arduino file in an existing installation, or nil
|
21
|
+
# @return [string]
|
22
|
+
def self.existing_executable
|
23
|
+
Host.which("arduino-cli")
|
14
24
|
end
|
15
25
|
|
16
26
|
# Make any preparations or run any checks prior to making changes
|
17
27
|
# @return [string] Error message, or nil if success
|
18
28
|
def prepare
|
19
|
-
reqs = [extracter]
|
29
|
+
reqs = [self.class.extracter]
|
20
30
|
reqs.each do |req|
|
21
31
|
return "#{req} does not appear to be installed!" unless Host.which(req)
|
22
32
|
end
|
@@ -26,62 +36,14 @@ module ArduinoCI
|
|
26
36
|
# The technology that will be used to extract the download
|
27
37
|
# (for logging purposes)
|
28
38
|
# @return [string]
|
29
|
-
def extracter
|
39
|
+
def self.extracter
|
30
40
|
"tar"
|
31
41
|
end
|
32
42
|
|
33
43
|
# Extract the package_file to extracted_file
|
34
44
|
# @return [bool] whether successful
|
35
|
-
def extract
|
36
|
-
system(extracter, "xf", package_file)
|
37
|
-
end
|
38
|
-
|
39
|
-
# The local file (dir) name of the extracted IDE package (zip/tar/etc)
|
40
|
-
# @return [string]
|
41
|
-
def extracted_file
|
42
|
-
"arduino-#{@desired_ide_version}"
|
43
|
-
end
|
44
|
-
|
45
|
-
# The path to the directory of an existing installation, or nil
|
46
|
-
# @return [string]
|
47
|
-
def self.existing_installation
|
48
|
-
exe = self.existing_executable
|
49
|
-
return nil if exe.nil?
|
50
|
-
|
51
|
-
File.dirname(exe) # it's not really this
|
52
|
-
# but for this platform it doesn't really matter
|
53
|
-
end
|
54
|
-
|
55
|
-
# The executable Arduino file in an existing installation, or nil
|
56
|
-
# @return [string]
|
57
|
-
def self.existing_executable
|
58
|
-
if USE_BUILDER
|
59
|
-
# builder_name = "arduino-builder"
|
60
|
-
# cli_place = Host.which(builder_name)
|
61
|
-
# unless cli_place.nil?
|
62
|
-
# ret = ArduinoCmdLinuxBuilder.new
|
63
|
-
# ret.base_cmd = [cli_place]
|
64
|
-
# return ret
|
65
|
-
# end
|
66
|
-
end
|
67
|
-
Host.which("arduino")
|
68
|
-
end
|
69
|
-
|
70
|
-
# The executable Arduino file in a forced installation, or nil
|
71
|
-
# @return [string]
|
72
|
-
def self.force_installed_executable
|
73
|
-
if USE_BUILDER
|
74
|
-
# forced_builder = File.join(ArduinoCmdLinuxBuilder.force_install_location, builder_name)
|
75
|
-
# if File.exist?(forced_builder)
|
76
|
-
# ret = ArduinoCmdLinuxBuilder.new
|
77
|
-
# ret.base_cmd = [forced_builder]
|
78
|
-
# return ret
|
79
|
-
# end
|
80
|
-
end
|
81
|
-
forced_arduino = File.join(self.force_install_location, "arduino")
|
82
|
-
return forced_arduino if File.exist? forced_arduino
|
83
|
-
|
84
|
-
nil
|
45
|
+
def self.extract(package_file)
|
46
|
+
system(extracter, "xf", package_file, extracted_file)
|
85
47
|
end
|
86
48
|
|
87
49
|
end
|